使用mysql_last_id()的竞争条件

时间:2012-01-09 22:56:55

标签: php mysql sql transactions lastinsertid

我花了大部分时间试图找到答案,但似乎没有一个在那里。我需要在表中创建一行的函数,从插入的行中检索自动增量,然后使用该值在第二个表中插入另一行。功能类似于以下php的东西:

$mysql_query("INSERT INTO table1 SET columns='values'");
$id = mysql_insert_id();
$mysql_query("INSERT INTO table2 SET id='$id', columns='values'");

我遇到的问题是,在我的应用程序中,所有类之间共享一个MySQL连接,所以我担心这可能会导致竞争条件,其中另一个类在运行第一个类之间插入一行和上面的第二行。

我能想到的最简单的解决方案是让任何使用mysql_insert_id()的函数打开一个新的,唯一的连接,但这似乎是一个巨大的不必要的开销。我玩过的其他答案包括插入一个唯一值(可能用UUID()创建)并使用它而不是自动增量值,或者可能将第一个插入和调用LAST_INSERT_ID()放入存储的函数(虽然我不确定这是否能解决可能的竞争条件)。

我一直在研究交易,看看它们是否有所帮助,但很少有关于mysql_insert_id()与它们交互的文档。我能说的最好,他们可能在这里没有帮助,因为与任何事务的锁没有冲突的另一个INSERT仍然可以执行并可能导致相同的竞争条件。

所以,假设我上述任何一个都没有错误(如果我是,请纠正我),确保100%第二个INSERT使用正确值的最佳方法是什么? / p>

2 个答案:

答案 0 :(得分:7)

php脚本的执行是线性的,而不是多线程的 所以,当一个物体与另一个物体同时被执行时,这是不可能的。

唯一可能的问题可能是持久连接。但似乎无论如何,两个单独的呼叫都不能使用相同的连接。即使它是持久的,如果它已经在使用 - 它不能被另一个脚本使用。因此,也没有问题。

答案 1 :(得分:0)

尝试使用if条件

示例

if(mysql_query(query)){
    $id = mysql_last_id();
    mysql_query(query using $id);
}