Php PDO、mysql、事务和表锁定

Php PDO、mysql、事务和表锁定,php,mysql,transactions,locking,pdo,Php,Mysql,Transactions,Locking,Pdo,为了好玩,我正在用PDO替换我应用程序中的mysqli扩展 偶尔我需要使用事务+表锁定 在这些情况下,根据mysql手册,语法需要稍微不同。不要调用启动事务,而是这样做 SET autocommit=0; LOCK TABLES t1 WRITE, t2 READ, ...; ... do something with tables t1 and t2 here ... COMMIT; UNLOCK TABLES; () 我的问题是,它如何与PDO::beginTransaction交互?在这

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

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

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

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

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


感谢您的建议,

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

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

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

当不使用MySQL的古怪功能时,您可以自由混合使用事务和SQL命令的PDOAPI方法。

当您调用时,它会关闭自动提交

因此,您可以:

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

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

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

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

开始事务可能会锁定已使用的表。。。我急切地等待有人告诉我这是错误的,但以下是可能的原因:,这表明在事务启动时无法访问表,而不会被锁定,最后一句话:

。。。当事务处于活动状态时,您可以保证在您的工作

中没有其他人可以进行更改。 对我来说,这种行为非常聪明,而且还为PDO提供了足够的回旋空间来处理每个数据库,这毕竟是目的所在。如果这就是正在发生的事情,它只是大量的文档不足,应该被称为其他的东西,以避免与真正的数据库事务混淆,这并不意味着锁定

我认为,查尔斯的回答可能是最好的,如果你是在确定需要高并发性的工作负载;使用对数据库的显式查询手动执行,然后可以查看数据库的文档

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

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

因此,为了进一步说明我的结论,看起来这些函数的行为似乎根据数据库引擎(以及可能的其他因素)而改变。根据我的经验和文档,我无法通过编程了解正在发生的事情。。。哇…

“开始交易不同于关闭自动提交”,PDO则不然。当你打电话时,它会关闭自动提交功能。很好,我已经相应地更新了答案。我急切地等待MySQL在事务中获得正常的DDL和锁定行为的那一天。。。嗯,也许不是。不久前切换到Postgres。请检查此线程好吗?我仍然无法理解使用
PDO::beginTransaction()
和不使用
$this->PDO->setAttribute(PDO::ATTR_AUTOCOMMIT,0)之间的区别。你能帮忙吗?非常感谢你!这不是我的经验(在InnoDB表中使用mysql 5.6.27),“LOCK tables”命令基本上提交了之前启动的事务,所有后续命令都是单独提交的(即没有事务行为)“……无法通过编程知道发生了什么……呜呜……”-这是stack上我最喜欢的报价。