Bri*_*ian 50 php mysql transactions
在使用mysql数据库的PHP脚本中,我最近需要在恰好位于另一个事务中的位置使用事务.我的所有测试似乎表明这样做很好,但我找不到任何关于这种用法的文档.
我想确定 - 事务中的事务是否在mysql中有效?如果是这样,有没有办法找出嵌套交易中有多少层次?(即恢复正常需要多少次回滚)
布莱恩,提前谢谢
But*_*kus 59
与其他人的答案相反,您可以在交易中有效地创建交易,这很容易.您只需创建SAVEPOINT位置并使用ROLLBACK TO savepoint来回滚部分事务,其中savepoint是您为保存点提供的任何名称.链接到MySQL文档:http://dev.mysql.com/doc/refman/5.0/en/savepoint.html 当然,事务中任何地方的查询都不应该是隐式提交的类型,或者整个交易将被提交.
例子:
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.
# e.g.
ROLLBACK TO savepoint1;
COMMIT; # results in committing only the part of the transaction up to savepoint1
Run Code Online (Sandbox Code Playgroud)
在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
}
Run Code Online (Sandbox Code Playgroud)
Pas*_*TIN 51
您可能会对本手册的这一页感兴趣:12.3.3.导致隐含提交的陈述 ; 引用几句话:
本节中列出的语句(以及它们的任何同义词)隐式结束事务,就像您
COMMIT在执行语句之前完成了一样.
并且,页面中的位置更远:
事务控制和锁定语句.
BEGIN,LOCK TABLES,SET autocommit = 1(如果该值不是1), ,.START TRANSACTIONUNLOCK TABLES
另见本段:
事务不能嵌套.
这是commit当您发出START TRANSACTION语句或其同义词之一时对任何当前事务执行的隐式执行的结果.
MySql不支持嵌套事务.有几种方法可以模仿它.首先,您可以使用保存点作为一种交易形式,这样就可以为您提供两级交易; 我已将它用于测试,但如果您在生产代码中使用它,我不确定这些限制.一个更简单的解决方案是忽略第二个begin transaction而不是增加一个计数器.对于每一个commit,你减少它.一旦你达到零,你就做了一个实际的commit.这有明显的局限性; 例如.回滚将回滚所有事务,但对于只使用事务进行错误处理的情况,这可能是可以接受的.
在这个主题中有一些很好的答案,但是,如果你使用innoDB作为你的MySQL存储引擎并使用MySQL 5.0.3或更高版本,你可以直接获得嵌套交易,而无需你做任何额外的工作或者本线程中其他人描述的任何花哨技巧.
来自XA交易的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获取.第E.5节"XA事务限制"中描述了当前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!
Run Code Online (Sandbox Code Playgroud)
用于XA事务的MySQL文档:
我<3 XA Transactions 4 Eva!