通過start transaction 手動啟動事務(wù)之后,在執(zhí)行的每一條命令之后,通過savepoint 回滾點(diǎn)名字;設(shè)置一個回滾點(diǎn)標(biāo)記。這樣如果在執(zhí)行下一條命令的時候,如果發(fā)現(xiàn)數(shù)據(jù)被弄錯了??梢酝ㄟ^rollback to 回滾點(diǎn)名字;回到上一條執(zhí)行命令。這樣可以保證數(shù)據(jù)由于一時的操作失誤,前面的所有操作被清空。
老邊網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站設(shè)計等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營維護(hù)。創(chuàng)新互聯(lián)于2013年開始到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。
我們經(jīng)常會遇到操作一張大表,發(fā)現(xiàn)操作時間過長或影響在線業(yè)務(wù)了,想要回退大表操作的場景。在我們停止大表操作之后,等待回滾是一個很漫長的過程,盡管你可能對知道一些縮短時間的方法,處于對生產(chǎn)環(huán)境數(shù)據(jù)完整性的敬畏,也會選擇不做介入。最終選擇不作為的原因大多源于對操作影響的不確定性。實(shí)踐出真知,下面針對兩種主要提升事務(wù)回滾速度的方式進(jìn)行驗(yàn)證,一種是提升操作可用內(nèi)存空間,一種是通過停實(shí)例,禁用 redo 回滾方式進(jìn)行進(jìn)行驗(yàn)證。
仔細(xì)閱讀過官方手冊的同學(xué),一定留意到了對于提升大事務(wù)回滾效率,官方提供了兩種方法:一是增加 innodb_buffer_pool_size 參數(shù)大小,二是合理利用 innodb_force_recovery=3 參數(shù),跳過事務(wù)回滾過程。第一種方式比較溫和,innodb_buffer_pool_size 參數(shù)是可以動態(tài)調(diào)整的,可行性也較高。第二種方式相較之下較暴力,但效果較好。
兩種方式各有自己的優(yōu)點(diǎn),第一種方式對線上業(yè)務(wù)系統(tǒng)影響較小,不會中斷在線業(yè)務(wù)。第二種方式效果更顯著,會短暫影響業(yè)務(wù)連續(xù),回滾所有沒有提交的事務(wù)。
好像不支持事務(wù)回滾
mysql
Max版支持
mysql_query('BEGIN');//開始事務(wù)
mysql_query('..........');//中間執(zhí)行其他sql語句
mysql_query('COMMIT');//成功后提交事務(wù)
//mysql_query('ROLLBACK');//失敗后回滾
上面不是php代碼嗎
就是用mysql_query執(zhí)行而已
在當(dāng)前mysql中雖然出現(xiàn)了事務(wù)的支持,但它還很不成熟,所以,呵呵,先觀望事務(wù)吧,采取其他手段達(dá)到事務(wù)的效果
比如你想刪除或更新一些記錄,你可以創(chuàng)建一個臨時表或者使用預(yù)先建立的備份表,將要將要操作的數(shù)據(jù)備份下來,當(dāng)其他操作失敗時將這些數(shù)據(jù)恢復(fù)回去。當(dāng)然實(shí)際情況可能更復(fù)雜一些。這樣做看起來很麻煩,而且效率值得懷疑,不過需要事務(wù)處理的地方應(yīng)該不會很多,所以麻煩一次兩次還是可以忍受的。
事務(wù)處理本身就不是一個高效的、百分百安全的手段,我們完全可以通過優(yōu)化表的結(jié)構(gòu)、編寫有效的腳本而避免使用事務(wù)。關(guān)注我也關(guān)注
mysql_query("SET AUTOCOMMIT=0";
$sql=""
$sql2=""
$res = mysql_query($sql);
$res2 = mysql_query($sql2);
if($res $res2)
mysql_query("COMMIT");
else
mysql_query("ROLLBACK");
默認(rèn)情況下,MySQL采用autocommit模式運(yùn)行。這意味著,當(dāng)執(zhí)行更新表的語句之后,MySQL立刻把更新存儲到磁盤中。
事務(wù)安全型的存儲引擎(如InnoDB,?BDB或NDB簇),
使用以下語句禁用autocommit模式:
SET?AUTOCOMMIT=0;
使用START?TRANSACTION,autocommit仍然被禁用,直到COMMIT或ROLLBACK結(jié)束事務(wù)為止。然后autocommit模式恢復(fù)到原來的狀態(tài)。
mysql?select?*?from?test_main?//
+----+-------+
|?id?|?value?|
+----+-------+
|??1?|?ONE???|
|??2?|?TWO???|
|??3?|?THREE?|
+----+-------+
3?rows?in?set?(0.00?sec)
mysql?START?TRANSACTION;
-?//
Query?OK,?0?rows?affected?(0.00?sec)
mysql?INSERT?INTO?test_main?VALUES(4,?'FOUR')?//
Query?OK,?1?row?affected?(0.00?sec)
mysql?INSERT?INTO?test_main?VALUES(4,?'FOUR')?//
ERROR?1062?(23000):?Duplicate?entry?'4'?for?key?'PRIMARY'
mysql?ROLLBACK//
Query?OK,?0?rows?affected?(0.01?sec)
mysql?select?*?from?test_main?//
+----+-------+
|?id?|?value?|
+----+-------+
|??1?|?ONE???|
|??2?|?TWO???|
|??3?|?THREE?|
+----+-------+
3?rows?in?set?(0.00?sec)
當(dāng)啟動Binlog后,事務(wù)會產(chǎn)生Binlog Event,這些Event被看做事務(wù)數(shù)據(jù)的一部分。因此要保證事務(wù)的Binlog Event和InnoDB引擎中的數(shù)據(jù)的一致性。所以帶Binlog的CrashSafe要求MySQL宕機(jī)重啟后能夠保證:
- 所有已經(jīng)提交的事務(wù)的數(shù)據(jù)仍然存在。
- 所有沒有提交的事務(wù)的數(shù)據(jù)自動回滾。
- 所有已經(jīng)提交了的事務(wù)的Binlog Event也仍然存在。
- 所有沒有提交事務(wù)沒有記錄Binlog Event。
這些要求很好理解,如果重啟后數(shù)據(jù)還在,但是Binlog Event沒有了,就沒辦法復(fù)制到其他節(jié)點(diǎn)上了。如果重啟后,數(shù)據(jù)沒了,但是Binlog Event還在,那么不存在的數(shù)據(jù)就會被復(fù)制到其他節(jié)點(diǎn)上,從而導(dǎo)致主從的不一致。
為了保證帶Binlog的CrashSafe,MySQL內(nèi)部使用的兩階段提交(Two Phase Commit)。
2 - MySQL的Two Phase Commit(2PC)
在開啟Binlog后,MySQL內(nèi)部會自動將普通事務(wù)當(dāng)做一個XA事務(wù)來處理:
- 自動為每個事務(wù)分配一個唯一的ID
- COMMIT會被自動的分成Prepare和Commit兩個階段。
- Binlog會被當(dāng)做事務(wù)協(xié)調(diào)者(Transaction Coordinator),Binlog Event會被當(dāng)做協(xié)調(diào)者日志。
想了解2PC,可以參考文檔:【?!?/p>
- 分布式事務(wù)ID(XID)
使用2PC時,MySQL會自動的為每一個事務(wù)分配一個ID,叫XID。XID是唯一的,每個事務(wù)的XID都不相同。XID會分別被Binlog和InnoDB記入日志中,供恢復(fù)時使用。MySQ內(nèi)部的XID由三部分組成:
- 前綴部分
前綴部分是字符串"MySQLXid"
- Server ID部分
當(dāng)前MySQL的server_id
- query_id部分
為了保證XID的的唯一性,數(shù)字部分使用了query_id。MySQL內(nèi)部會自動的為每一個語句分配一個query_id,全局唯一。
參考代碼:sql/xa。h的struct xid_t結(jié)構(gòu)。
- 事務(wù)的協(xié)調(diào)者Binlog
Binlog在2PC中充當(dāng)了事務(wù)的協(xié)調(diào)者(Transaction Coordinator)。由Binlog來通知InnoDB引擎來執(zhí)行prepare,commit或者rollback的步驟。事務(wù)提交的整個過程如下:
1. 協(xié)調(diào)者準(zhǔn)備階段(Prepare Phase)
告訴引擎做Prepare,InnoDB更改事務(wù)狀態(tài),并將Redo Log刷入磁盤。
2. 協(xié)調(diào)者提交階段(Commit Phase)
2.1 記錄協(xié)調(diào)者日志,即Binlog日志。
2.2 告訴引擎做commit。
注意:記錄Binlog是在InnoDB引擎Prepare(即Redo Log寫入磁盤)之后,這點(diǎn)至關(guān)重要。
在MySQ的代碼中將協(xié)調(diào)者叫做tc_log。在MySQL啟動時,tc_log將被初始化為mysql_bin_log對象。參考sql/binlog.cc中的init_server_components():
if (opt_bin_log) tc_log= mysql_bin_log;
而在事務(wù)提交時,會依次執(zhí)行:
tc_log-prepare();
tc_log-commit();
參考代碼:sql/binlog.cc中的ha_commit_trans()。當(dāng)mysql_bin_log是tc_log時,prepare和commit的代碼在sql/binlog.cc中:
MYSQL_BIN_LOG::prepare();
MYSQL_BIN_LOG::commit();
-協(xié)調(diào)者日志Xid_log_event
作為協(xié)調(diào)者,Binlog需要將事務(wù)的XID記入日志,供恢復(fù)時使用。Xid_log_event有以下幾個特點(diǎn):
- 僅記錄query_id
因?yàn)榍熬Y部分不變,server_id已經(jīng)記錄在Event Header中,Xid_log_event中只記錄query_id部分。
- 標(biāo)志事務(wù)的結(jié)束
在Binlog中相當(dāng)于一個事務(wù)的COMMIT語句。
一個事務(wù)在Binlog中看起來時這樣的:
Query_log_event("BEGIN");DML產(chǎn)生的events; Xid_log_event;
- DDL沒有BEGIN,也沒有Xid_log_event 。
- 僅InnoDB的DML會產(chǎn)生Xid_log_event
因?yàn)镸yISAM不支持2PC所以不能用Xid_log_event ,但會有COMMIT Event。
Query_log_event("BEGIN");DML產(chǎn)生的events;Query_log_event("COMMIT");
問題:Query_log_event("COMMIT")和Xid_log_event 有不同的影響嗎?
- Xid_log_event 中的Xid可以幫助master實(shí)現(xiàn)CrashSafe。
- Slave的CrashSafe不依賴Xid_log_event
事務(wù)在Slave上重做時,會重新產(chǎn)生XID。所以Slave服務(wù)器的CrashSafe并不依賴于Xid_log_event 。Xid_log_event 和Query_log_event("COMMIT"),只是作為事務(wù)的結(jié)尾,告訴Slave Applier去提交這個事務(wù)。因此二者在Slave上的影響是一樣的。
3 - 恢復(fù)(Recovery)
這個機(jī)制是如何保證MySQL的CrashSafe的呢,我們來分析一下。這里我們假設(shè)用戶設(shè)置了以下參數(shù)來保證可靠性:
- 恢復(fù)前事務(wù)的狀態(tài)
在恢復(fù)開始前事務(wù)有以下幾種狀態(tài):
- InnoDB中已經(jīng)提交
根據(jù)前面2PC的過程,可知Binlog中也一定記錄了該事務(wù)的的Events。所以這種事務(wù)是一致的不需要處理。
- InnoDB中是prepared狀態(tài),Binlog中有該事務(wù)的Events。
需要通知InnoDB提交這些事務(wù)。
- InnoDB中是prepared狀態(tài),Binlog中沒有該事務(wù)的Events。
因?yàn)锽inlog還沒記錄,需要通知InnoDB回滾這些事務(wù)。
- Before InnoDB Prepare
事務(wù)可能還沒執(zhí)行完,因此InnoDB中的狀態(tài)還沒有prepare。根據(jù)2PC的過程,Binlog中也沒有該事務(wù)的events。 需要通知InnoDB回滾這些事務(wù)。
- 恢復(fù)過程
從上面的事務(wù)狀態(tài)可以看出:恢復(fù)時事務(wù)要提交還是回滾,是由Binlog來決定的。
- 事務(wù)的Xid_log_event 存在,就要提交。
- 事務(wù)的Xid_log_event 不存在,就要回滾。
恢復(fù)的過程非常簡單:
- 從Binlog中讀出所有的Xid_log_event
- 告訴InnoDB提交這些XID的事務(wù)
- InnoDB回滾其它的事務(wù)