事务内的Mysql事务
在一个使用mysql数据库的PHP脚本中,我最近需要在碰巧在另一个事务中的一个点上使用一个事务。 我所有的testing似乎表明这工作正常,但我无法find任何有关此用法的文档。
我想确定 – 交易内的交易有效的MySQL? 如果是这样,是否有办法找出你在嵌套事务中有多less层次? (即多less回滚才能恢复正常)
在此先感谢,布赖恩
本手册的这一页可能会让你感兴趣: 12.3.3。 导致隐式提交的声明 ; 引用几句话:
本节列出的语句(以及它们的任何同义词)隐式地结束一个事务,就像在执行语句之前执行了一个
COMMIT
一样。
而且,在页面的更远处:
事务控制和locking语句。
BEGIN
,LOCK TABLES
,SET autocommit = 1
(如果值不是1),START TRANSACTION
,UNLOCK TABLES
。
另见这个paragrah:
事务不能嵌套。
当您发出START TRANSACTION
语句或其同义词之一时,这是对任何当前事务执行的隐式commit
的结果。
希望这可以帮助 !
与其他人的回答相反,您可以在交易中有效地创build交易,这非常简单。 您只需创buildSAVEPOINT位置并使用ROLLBACK TO savepoint来回滚事务的一部分,其中savepoint是指定保存点的任何名称。 链接到MySQL文档: http : //dev.mysql.com/doc/refman/5.0/en/savepoint.html当然,事务中任何地方的查询都不应该是隐式提交的types,或者整个交易将被承诺。
例子:
START TRANSACTION; # queries that don't implicitly commit SAVEPOINT savepoint1; # queries that don't implicitly commit # now you can either ROLLBACK TO savepoint1, or just ROLLBACK to reverse the entire transaction. SAVEPOINT savepoint2; # queries that don't implicitly commit # now you can ROLLBACK TO savepoint1 OR savepoint2, or ROLLBACK all the way. # eg ROLLBACK TO savepoint1; COMMIT; # results in committing only the part of the transaction up to savepoint1
在PHP中,我写了这样的代码,它完美的工作:
foreach($some_data as $key => $sub_array) { $result = mysql_query('START TRANSACTION'); // note mysql_query is deprecated in favor of PDO $rollback_all = false; // set to true to undo whole transaction for($i=0;$i<sizeof($sub_array);$i++) { if($sub_array['set_save'] === true) { $savepoint = 'savepoint' . $i; $result = mysql_query("SAVEPOINT $savepoint"); } $sql = 'UPDATE `my_table` SET `x` = `y` WHERE `z` < `n`'; // some query/queries $result = mysql_query($sql); // run the update query/queries $more_sql = 'SELECT `x` FROM `my_table`'; // get data for checking $result = mysql_query($more_sql); $rollback_to_save = false; // set to true to undo to last savepoint while($row = mysql_fetch_array($result)) { // run some checks on the data // if some check says to go back to savepoint: $rollback_to_save = true; // or just do the rollback here. // if some check says to rollback entire transaction: $rollback_all = true; } if($rollback_all === true) { mysql_query('ROLLBACK'); // rollback entire transaction break; // break out of for loop, into next foreach } if($rollback_to_save = true) { mysql_query("ROLLBACK TO $savepoint"); // undo just this part of for loop } } // end of for loop mysql_query('COMMIT'); // if you don't do this, the whole transaction will rollback }
我想确定 – 交易内的交易有效的MySQL?
没有。
MySql不支持嵌套事务。 有几种方法可以模拟它。 首先,您可以使用保存点作为交易的一种forms,以便为您提供两个级别的交易; 我用这个来testing,但是我不确定这个限制,如果你在生产代码中使用它的话。 一个简单的解决scheme是忽略第二个begin transaction
,而是增加一个计数器。 对于每个commit
,你减less它。 一旦你达到零,你做一个实际的commit
。 这有明显的局限性; 例如。 回滚将回滚所有事务,但是对于只使用事务进行error handling的情况,这可能是可以接受的。
在这个线程中有一些很好的答案,但是,如果你使用innoDB作为你的MySQL存储引擎并且使用MySQL 5.0.3或者更高版本,你可以立即获得嵌套事务,而不需要任何额外的工作。在这个线程中其他人描述的任何花哨的技术。
从XA Transactions上的MySQL文档:
MySQL 5.0.3及更高版本为XA事务提供服务器端支持。 目前,这种支持可用于InnoDB存储引擎。 MySQL XA实现基于X / Open CAE文档“分布式事务处理:XA规范”。 本文档由The Open Group发布,可在http://www.opengroup.org/public/pubs/catalog/c193.htm获取; 。 当前XA实现的限制在第E.5节“对XA事务的限制”中进行了描述。
我的XA交易示例只为你:
# Start a new XA transaction XA START; # update my bank account balance, they will never know! UPDATE `bank_accounts` SET `balance` = 100000 WHERE `id` = 'mine'; # $100,000.00 is a bit low, I'm going to consider adding more, but I'm not sure so # I will start a NESTED transaction and debate it... XA START; # max int money! woo hoo! UPDATE `bank_accounts` SET `balance` = 2147483647 WHERE `id` = 'mine'; # maybe thats too conspicuous, better roll back XA ROLLBACK; # The $100,000 UPDATE still applies here, but the max int money does not, going for it! XA COMMIT; # Oh No! Sirens! It's the popo's!!! run!! # What the hell are they using ints for money columns anyway! Ahhhh!
MySQL文档对于XA事务:
- 13.3.7。 XA交易
- 13.3.7.1。 XA事务SQL语法
- 13.3.7.2。 XA交易状态
- E.6。 XA交易的限制
我<3 XA交易4伊娃!
你可能想检查你的testing方法。 在MaxDB之外,MySQL不像嵌套事务那样支持任何东西。
它的确如此: http : //dev.mysql.com/doc/refman/5.0/en/xa.html