PDO,mysql,事务和表锁定

Tra*_*vis 15 php mysql pdo locking transactions

为了好玩,我正在用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;
Run Code Online (Sandbox Code Playgroud)

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

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

感谢您的建议,

Olh*_*sky 10

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

所以你可以这样做:

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

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

  • 这不是我的经验(使用带有InnoDB表的mysql 5.6.27),'LOCK TABLES'命令基本上提交先前启动的事务,并且所有后续命令都是单独提交的(即没有事务行为) (2认同)

Jam*_*son 7

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

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

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

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

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

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

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

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

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


Cha*_*les 6

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

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

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

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