繁体   English   中英

PDO,mysql,事务和表锁定

[英]PDO, mysql, transactions and table locking

为了好玩,我正在用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;

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

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

谢谢你的建议,

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

所以你可以这样做:

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

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

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

在PDO中,使用beginTransaction启动事务实际上并不启动新事务,它只是关闭自动提交。 在大多数数据库中,这是理智的,但它可能具有MySQL提到的行为的副作用。

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

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

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

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

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM