我有一个每秒处理许多查询的系统。我使用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
确实在事务期间锁定了记录
答案 0 :(得分:2)
我不知道您正在谈论哪种交易,但使用mysqli
扩展程序我使用以下方法处理交易:
然后过程如下:
mysqli::begin_transaction
mysqli::commit
确认您在步骤2中执行查询时执行的查询所做的更改或,在执行第2步中的查询时,使用mysqli::rollback
还原所做的更改它们。您可以将事务视为查询的临时缓存。它有点类似于PHP中带有ob_*
函数的输出缓存。只要您没有刷新缓存的数据,屏幕上就不会发生任何事情。与事务相同:只要您没有提交任何内容(并且自动提交已关闭),数据库中就不会发生任何事情。
答案 1 :(得分:1)
我对行级锁定进行了一些研究,可以锁定删除或更新记录
FOR UPDATE
在开始交易之后,我必须选择我想锁定的记录,如下所示
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时我可以使用面向对象或程序样式(我更喜欢面向对象)。