PDO,mysql,事务和表锁定

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PDO,mysql,事务和表锁定相关的知识,希望对你有一定的参考价值。

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

有一段时间我需要使用事务+表锁定。

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

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

(Qazxswpoi)

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

感谢您的建议,

答案

在MySQL中,由于LOCK / UNLOCK TABLES的工作方式,开始事务与关闭自动提交不同。在MySQL中,LOCK TABLES提交任何打开的事务,但关闭自动提交实际上并不启动事务。 MySQL很有趣。

在PDO中,使用http://dev.mysql.com/doc/refman/5.0/en/lock-tables-and-transactions.html启动事务实际上并不启动新事务,它只是关闭自动提交。在大多数数据库中,这是理智的,但它可能具有MySQL提到的行为的副作用。

你可能不应该依赖这种行为以及它如何与MySQL的怪癖相互作用。如果你要处理MySQL的表锁定和DDL行为,你应该避免它。如果要关闭自动提交,请手动将其关闭。如果要打开交易,请手动打开交易。

您可以自由地混合使用PDO API处理事务和SQL命令的方法,否则不会使用MySQL的奇怪之处。

另一答案

当你调用beginTransaction时,它会关闭自动提交。

所以你可以这样做:

PDO::beginTransaction()

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

另一答案

我花了很多时间来解决这个问题,而且这方面的php文档充其量是模糊的。我发现的一些事情,使用MySQL InnoDB表运行PHP 7:

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

开始一个事务可能会锁定已使用的表...我急切地等待有人告诉我我错了,但这里有原因:$db->beginTransaction(); $db->exec('LOCK TABLES t1, t2, ...'); # do something with tables $db->commit(); $db->exec('UNLOCK TABLES'); ,它显示一个表在交易开始时无法访问,没有被锁定。 This comment,最后滑入:

...当交易处于活动状态时,您可以保证在您工作的过程中没有其他人可以进行更改

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

我认为查尔斯的答案可能是最好的,如果你确定需要高并发性的工作量;使用对数据库的显式查询手动完成,然后您可以通过数据库的文档。

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

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

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

以上是关于PDO,mysql,事务和表锁定的主要内容,如果未能解决你的问题,请参考以下文章

MySQL行级锁和表级锁

mysql中锁

MYSQL事务与锁表的问题?

PDO如何完成事务操作

Mysql原理篇之锁--14

PDO 事务函数与 MySQL 事务语句?