在交易期间记录已删除

时间:2014-09-25 08:39:41

标签: php mysql sql transactions table-locking

我有一个每秒处理许多查询的系统。我使用mysqlPHP编码我的系统。

我的问题是mysqli事务仍然提交事务,即使其他用户同时删除了记录,我的所有表都使用InnoDB

这是我使用mysqli编写交易的方式:

mysqli_autocommit($dbc,FALSE);
$all_query_ok=true;

$q="INSERT INTO Transaction() VALUES()";
mysqli_query ($dbc,$q)?null:$all_query_ok=false;

$q="INSERT INTO Statement() VALUES()";
mysqli_query ($dbc,$q)?null:$all_query_ok=false;

if($all_query_ok==true){
    //all success
    mysqli_commit($dbc);
}else{
    //one of it failed , rollback everything.
    mysqli_rollback($dbc);
}

下面是另一个用户在其他脚本中同时执行的查询,最后弄乱了预期的系统行为,

$q="DELETE FROM Transaction...";
mysqli_query ($dbc,$q)?null:$all_query_ok=false;

请指教,我是否错误地实施了交易?我已阅读有关行级锁定的信息并认为innoDB确实在事务期间锁定了记录

4 个答案:

答案 0 :(得分:2)

我不知道您正在谈论哪种交易,但使用mysqli扩展程序我使用以下方法处理交易:

然后过程如下:

  1. 使用mysqli::begin_transaction
  2. 开始新的交易
  3. 执行SQL查询
  4. 成功使用mysqli::commit确认您在步骤2中执行查询时执行的查询所做的更改,在执行第2步中的查询时,使用mysqli::rollback还原所做的更改它们。
  5. 您可以将事务视为查询的临时缓存。它有点类似于PHP中带有ob_*函数的输出缓存。只要您没有刷新缓存的数据,屏幕上就不会发生任何事情。与事务相同:只要您没有提交任何内容(并且自动提交已关闭),数据库中就不会发生任何事情。

答案 1 :(得分:1)

我对行级锁定进行了一些研究,可以锁定删除或更新记录

  

FOR UPDATE

     

Official Documentation

开始交易之后,我必须选择我想锁定的记录,如下所示

SELECT * FROM Transaction WHERE id=1 FOR UPDATE

这样记录将锁定到transaction end

此方法不适用于MyISAM类型表

答案 2 :(得分:0)

看起来像race condition的典型示例。您可以并行执行两个并发脚本修改数据。可能您的第一个脚本成功插入记录并提交事务,第二个脚本成功删除后续记录。我不确定你的意思是“其他用户在其他脚本中同时执行的查询”。

答案 3 :(得分:0)

你必须这样做:

mysqli_autocommit($dbc,FALSE);

$dbc->begin_transaction();

$all_query_ok=true;

$q="INSERT INTO Transaction() VALUES()";
mysqli_query ($dbc,$q)?null:$all_query_ok=false;

$q="INSERT INTO Statement() VALUES()";
mysqli_query ($dbc,$q)?null:$all_query_ok=false;

if($all_query_ok==true){
    //all success
    mysqli_commit($dbc);
}else{
    //one of it failed , rollback everything.
    mysqli_rollback($dbc);
}

在调用begin_transaction时我可以使用面向对象或程序样式(我更喜欢面向对象)。