0

在将行插入 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 次,选择就会执行并且不返回任何行。数据插入将正确执行。我不相信这是可能的,因为 insert 或 die 迫使 PHP 等待返回值,以便它知道是否执行该行的“or die”部分。PHP是否有可能在执行完成之前从插入命令收到返回值,因此紧跟在插入之后的选择语句无法返回任何行?将来如何防止这种间歇性问题?

4

2 回答 2

0

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

识别您插入的最后一行的正确方法是:

SELECT LAST_INSERT_ID();

或这个:

SELECT @@LAST_INSERT_ID;

这些是等价的,并且总是会给你分配给插入的最后一行的自动增量列的值——即使另一个会话在你之后插入了数据。

于 2013-09-06T16:38:39.637 回答
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 版本中,可能还有以前的版本,此语句返回预期的错误消息......”

于 2013-09-06T16:15:31.263 回答