1

我有一个每秒处理许多查询的系统。mysql我用和对我的系统进行编码PHP

我的问题是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

4 回答 4

2

我不知道您在谈论哪种交易,但是通过mysqli扩展,我使用以下方法来处理交易:

那么过程是这样的:

  1. 开始新的交易mysqli::begin_transaction
  2. 执行您的 SQL 查询
  3. 成功时用于mysqli::commit确认您的查询在步骤 2 中所做的更改,在步骤 2中执行查询期间出错时mysqli::rollback用于恢复它们所做的更改。

您可以将事务视为查询的临时缓存。它在某种程度上类似于 PHP 中带有ob_*函数的输出缓存。只要您没有刷新缓存数据,屏幕上就不会发生任何事情。与事务相同:只要您没有提交任何内容(并且自动提交已关闭),数据库中就不会发生任何事情。

于 2014-09-25T08:50:11.883 回答
1

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

更新

官方文档

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

SELECT * FROM Transaction WHERE id=1 FOR UPDATE

这样记录将被锁定,直到transaction end

此方法不适用于 MyISAM 类型表

于 2014-10-24T06:15:32.350 回答
0

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

于 2014-10-26T22:58:35.993 回答
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 时可以使用面向对象或过程风格(我更喜欢面向对象)。

于 2014-10-29T16:47:03.933 回答