2010-06-24 171 views
14

为了好玩,我用PDO替换了我应用程序中的mysqli扩展。PDO,mysql,交易和表锁定

有一段时间我需要使用交易+表锁定。

在这些情况下,根据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”。

谢谢你的建议,

回答

4

在MySQL中,开始交易比关闭自动提交,因为如何LOCK/UNLOCK TABLES作品不同。在MySQL中,LOCK TABLES提交所有打开的事务,但关闭自动提交实际上并不是开始一个事务。 MySQL很有趣。

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

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

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

+0

“开始一个事务是不同于关闭自动提交”不与PDO它不是“T。当你调用[PDO :: beginTransaction()](http://php.net/manual/en/pdo.begintransaction.php)时,它会关闭自动提交。 – Olhovsky 2012-11-19 13:34:17

+0

好点,我相应地更新了我的答案。我急切地等待MySQL获得理智的DDL并锁定交易中的行为......呃,也许不是。前一阵子转向Postgres。 – Charles 2012-11-19 16:29:52

+0

你能检查这个线程吗? https://stackoverflow.com/questions/47810114/php-pdo-mysql-and-how-does-it-really-deal-with-mysql-transactions我仍然不明白使用'PDO :: beginTransaction ()'带和不带'$ this-> pdo-> setAttribute(PDO :: ATTR_AUTOCOMMIT,0);'。能否请你帮忙?非常感谢你! – tonix 2017-12-14 10:06:57

9

当您拨打PDO::beginTransaction()时,会关闭自动提交。

所以,你可以这样做:

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

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

+2

这不是我的经验(在InnoDB表中使用mysql 5.6.27),'LOCK TABLES'命令基本上提交了以前启动的事务,并且所有后续的命令都是单独提交的(即没有事务行为) – mils 2016-01-20 03:18:48

3

我花了大量的时间来解决这个问题,而且这个领域的PHP文档充其量是模糊的。有几件事情我已经找到了,运行PHP 7 MySQL的InnoDB表:

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

开始交易可锁定使用的表 ...我热切地等待着有人来告诉我,我错了这一点,但这里的原因可能是:This comment,其中显示了一个表不可访问当交易开始时,不被锁定。 This PHP documentation page,这在最后滑倒:

...而交易活跃,你保证,当你在你的工作

的中间,我这种行为是相当聪明的,并且还提供了PDO应付足够的回旋余地没有其他人可以做出改变每一个数据库,这毕竟是目标。如果这是正在发生的事情,它只是大量地被记录下来,应该被称为别的东西,以避免与真正的数据库事务混淆,这并不意味着锁定。

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

更新 我有一个生产服务器和使用PDO交易功能,而现在,最近运行使用AWS的极光数据库(MySQL的完全兼容,但内置自动缩放等)。我已经证明了这两点:

  • 事务(纯粹提交所有数据库更改的能力)使用PDO :: beginTransaction()工作。总之,我知道许多脚本在数据库选择/更新过程中失败了,数据完整性一直保持不变。
  • 表锁定没有发生,我有一个索引重复错误来证明这一点。

因此,为了进一步得出结论,看起来这些功能的行为似乎会根据数据库引擎(以及其他因素)而改变。据我可以从经验和文档告诉,没有办法知道程序上发生了什么事......呐喊......