PDO、mysql、事务和表锁定

2022-08-30 23:26:33

为了好玩,我正在用PDO替换我的应用程序中的mysqli扩展。

偶尔我需要使用事务+表锁定。

在这些情况下,根据mysql手册,语法需要有点不同。而不是调用启动事务,你这样做...

SET autocommit=0;
LOCK TABLES t1 WRITE, t2 READ, ...;
... do something with tables t1 and t2 here ...
COMMIT;
UNLOCK TABLES;

(http://dev.mysql.com/doc/refman/5.0/en/lock-tables-and-transactions.html)

我的问题是,这如何与PDO::beginTransaction交互?在这种情况下,我可以使用PDO::beginTransaction吗?或者我应该手动发送sql“SET自动提交= 0;...等等”。

感谢您的建议,


答案 1

当您调用 PDO::beginTransaction() 时,它将关闭自动提交。

所以你可以做:

$db->beginTransaction();
$db->exec('LOCK TABLES t1, t2, ...');
# do something with tables
$db->commit();
$db->exec('UNLOCK TABLES');

在 commit() 或 rollBack() 之后,数据库将返回到自动提交模式。


答案 2

我花了大量的时间在这个问题上,而这个领域的PHP文档充其量是模糊的。我发现了一些东西,使用MySQL InnoDB表运行PHP 7:

PDO::beginTransaction不只是关闭自动提交,在用失败的代码测试了Olhovsky提供的答案之后,回滚不起作用;没有交易行为。这意味着它不能这么简单。

开始事务可能会锁定使用的表...我急切地等待有人告诉我我错了,但这可能是原因:这个评论,它显示一个表在交易开始时无法访问,没有被锁定。这个PHP文档页面,在最后滑入:

...在交易处于活动状态时,可以保证在您工作期间,其他人无法进行更改

对我来说,这种行为非常聪明,也为PDO提供了足够的回旋余地来应对每个数据库,这毕竟是目标。如果这就是正在发生的事情,它只是大量记录不足,应该被称为其他东西,以避免与真正的数据库事务混淆,这并不意味着锁定。

查尔斯的答案我认为可能是最好的,如果你追求确定需要高并发性的工作负载;使用对数据库的显式查询手动执行此操作,然后您可以按照数据库的文档进行操作。

更新我已经使用PDO事务函数启动并运行了一段时间的生产服务器,最近使用AWS的Aurora数据库(与MySQL完全兼容,但构建为自动扩展等)。我已经向自己证明了这两点:

  • 事务(纯粹是将所有数据库更改一起提交的能力)使用PDO::beginTransaction()工作。简而言之,我知道许多脚本在数据库选择/更新的中途失败了,并且数据完整性得到了维护。
  • 表锁定没有发生,我有一个索引复制错误来证明这一点。

因此,为了进一步得出我的结论,看起来这些函数的行为似乎会根据数据库引擎(可能还有其他因素)而变化。就我从经验和文档中可以看出的,没有办法以编程方式知道发生了什么......呐喊。。。


推荐