PHP mysql_query选择无法返回刚刚插入的行

时间:2013-09-06 15:46:49

标签: php mysql

在插入PHP后立即尝试选择一行时,我间歇性地发现问题。这个问题只会在每100-1000次发生一次。这是使用PHP 4.4,没有选项升级/能够使用PDO或mysqli。我正在考虑使用事务,但是两个查询都会执行,并且即使使用事务也会继续这样做,但是第二个查询会运行并返回空RS,所以我怀疑事务是否会影响它。

例如,选择一个包含两列的表:自动增量计数器和存储值。该值也必须是唯一的,但是在计数器上进行连接,而不是值。一次可以由多个用户输入值,所以我不能简单地相信最高的计数器给我刚刚插入的值。

    data:
    data_id int(11) UNIQUE AUTO_INCREMENT NOT NULL
    myData varchar(50) UNIQUE NOT NULL

现在每个用户都可以随时输入新的$ val,当他们输入时,还必须在状态表中输入一个条目。

    statuses:
    status_id int(11) UNIQUE AUTO_INCREMENT NOT NULL
    data_id int(11) NOT NULL
    status int(1) NOT NULL

我用来完成此任务的代码是:

// Get value
$insData = $_GET['VAL'];
// Insert value
$ins = mysql_query( "INSERT INTO data (myData) VALUES ('" . $insData . "')" )
    or die(mysql_error());
// Get value's id
$res = mysql_query( "SELECT data_id FROM data WHERE myData='" . $insData . "'" )
    or die(mysql_error());
// From here I would insert into the statuses table,
// but the new entry into the data table is sometimes not found!

每运行100-1000次代码,select将执行并且不返回任何行。数据插入将正确执行。我不相信这是可能的,因为插入或死亡迫使PHP等待返回值,以便它知道是否执行该行的'或die'部分。是否有可能PHP在执行完毕之前从insert命令收到了返回值,因此紧跟在insert之后的select语句无法返回任何行?那将来如何防止这种间歇性问题?

2 个答案:

答案 0 :(得分:0)

您尝试插入的数据(当您没有收到预期的错误消息时)是否存在重复记录(即匹配已存在于TABLE DATA中的记录)?

如果是,请参阅

具体来说,引自mysqlgatchas:

" ...进一步的特质似乎是这种行为:

CREATE TABLE insert_test2 (
id INT NOT NULL PRIMARY KEY,
txt VARCHAR(32)
);
INSERT INTO insert_test2 VALUES(1, 'foo');
INSERT INTO insert_test2 VALUES(2, 'bar');

现在看一下:

mysql> INSERT INTO insert_test2 VALUES(1, 'bar');
ERROR 1062: Duplicate entry '1' for key 1

正确行为......现在看一下:

mysql> INSERT INTO insert_test2 (id, txt) SELECT i.id, i.txt FROM insert_test i 
WHERE i.id=1;
Query OK, 0 rows affected (0.00 sec)
Records: 1  Duplicates: 1  Warnings: 0

mysql> SELECT * FROM insert_test2;
+----+------+
| id | txt  |
+----+------+
|  1 | foo  |
|  2 | bar  |
+----+------+
2 rows in set (0.00 sec)

此语句的预期行为将失败并出现与上述相同的错误;相反,它似乎是成功的,只有Duplicates:1通知表明该语句被有效忽略。

更新:在版本4.0.20以及可能的先前版本中,此语句返回预期的错误消息..."

答案 1 :(得分:0)

对于为什么偶尔失败,没有一个很好的解释,尽管如果你的桌子是MyISAM,那么我怀疑你有一些粗略的爬行到你的物理桌面结构。否则,您的非转义字符串中的值可能会导致查询无法找到刚刚插入的内容。

确定插入的最后一行的正确方法:

SELECT LAST_INSERT_ID();

或者这个:

SELECT @@LAST_INSERT_ID;

这些是等效的,并且总是会为您提供分配给> 插入的最后一行的自动增量列的值 - 即使另一个会话已经在您之后插入了数据。