[英]Mysql transactions within transactions
在使用mysql數據庫的PHP腳本中,我最近需要在恰好位於另一個事務中的位置使用事務。 我的所有測試似乎表明這樣做很好,但我找不到任何關於這種用法的文檔。
我想確定 - 事務中的事務是否在mysql中有效? 如果是這樣,有沒有辦法找出嵌套交易中有多少層次? (即恢復正常需要多少次回滾)
布萊恩,提前謝謝
與其他人的答案相反,您可以在交易中有效地創建交易,這很容易。 您只需創建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
在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不支持嵌套事務。 有幾種方法可以模仿它。 首先,您可以使用保存點作為一種交易形式,這樣就可以為您提供兩級交易; 我已將它用於測試,但如果您在生產代碼中使用它,我不確定這些限制。 一個更簡單的解決方案是忽略第二個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!
用於XA事務的MySQL文檔:
我<3 XA Transactions 4 Eva!
您可能想檢查您的測試美食。 在MaxDB之外,MySQL不像嵌套事務那樣遠程支持任何東西。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.