MySQL資料庫事務處理
事務處理用於有效記錄某機構感興趣的業務活動(稱為事務)的資料處理(例如銷售、供貨的定購或貨幣傳輸)。通常,聯機事務處理 (OLTP) 系統執行大量的相對較小的事務。——百度百科
事務處理是將多個操作或者命令一起執行,所有命令全部成功執行才意味著該事務的成功,任何一個命令失敗都意味著該事務的失敗。
以銀行轉賬為例(100塊都不給), A要給B 轉賬100元, A轉賬的指令已經成功發出,而B 由於未知的原因接收失敗, 如果兩個命令單獨執行,那麼A賬戶少了100塊,但是B又沒收到100塊,顯而易見是不合理的; 如果將A向B 轉賬100元當成一個事務處理,那麼由於B 接收的失敗,整個轉賬事務都將失敗,A不會少100,B更不會增加100,這個時候“100塊都不給”才是合理的情況。
因此,事務處理是不是一榮俱榮,而是一毀全毀。
接下來介紹MySQL資料庫中如何進行事務處理以及鎖定。
0 資料庫事務處理相關命令 進行的操作 命令 檢視儲存引擎 SHOW CREATE TABLE 表名; 更改引擎 ALTER TABLE 表名 ENGINE=新引擎名; 回滾 ROLLBACK; 宣告事務開始 BEIGIN; 事務提交 COMMIT; 查詢自動提交功能狀態 SELECT @@AUTOCOMMIT; 設定自動提交功能 SET AUTOCOMMIT=0或1; 設定分離水平 SET SESSION TRANSACTION ISOLATION LEVEL 分離水平; 1 儲存引擎 MySQL資料庫的儲存引擎是可以選擇改變和替換的(可替換儲存引擎構架,Pluggable Storage Engine Architecture)。MySQL主要有8種儲存引擎:
儲存引擎 特徵 MyISAM 高速引擎,不支援事務處理 InnoDB 支援行鎖定以及事務處理,速度比MyISAM稍慢 ISAM MyISAM的前身 MERGE 將多個MyISAM型別的表作為一個表來處理的引擎 MEMORY,HEAP 只在記憶體上儲存資料 Falcon 一種新的儲存引擎,支援事務處理 ARCHIVE 將資料壓縮後儲存(只能支援INSERT/SELECT操作 CSV 以CSV形式儲存資料(應用於跨平臺資料交換) MySQL的儲存引擎種類和特徵
(1)檢視儲存引擎 SHOW CREATE TABLE 表名; 檢視某表使用的儲存引擎,語法程式碼如下:
`SHOW CREATE TABLE 表名;` 1 如,要查看錶customer的儲存引擎,可以輸入程式碼:
`SHOW CREATE TABLE customer;` 1
如圖表所示ENGINE=後面顯示的就是儲存引擎。
(2)更改儲存引擎ALTER TABLE 表名 ENGINE=新引擎名;
若要更改儲存引擎,可以使用程式碼:
>ALTER TABLE 表名 ENGINE=新引擎名; 1 eg:將表customer的儲存引擎修改為MyISAM,輸入指令:
ALTER TABLE customer ENGINE=MyISAM; 1
2 事務處理 之前講到,事務處理是一毀全毀,因此事務中任意一個任務或指令失敗,整個事務都將失敗。那是怎麼實現的呢?方法是時間中多個任務全部成功,則任務成功結束,並且會進行提交(COMMIT),如果任何一件任務失敗,則強制回滾(ROLLBACK)到初始狀態。
事務處理涉及到三個最重要的命令:BEGIN,ROLLBACK,COMMIT,分別表示宣告事務開始,回滾和確認提交。
(1)回滾演示(ROLLBACK) 首先將表格customer 的儲存引擎設定為InnoDB, 確認表格資料;SELECT * FROM customer; 事務開始;BEGIN; 刪除表格資料;DELETE FROM customer; 再次查看錶格資料;SELECT * FROM customer; 回滾到初始狀態;ROLLBACK; 再次查看錶格資料;SELECT * FROM customer;
可以看到,當執行ROLLBACK;之後,刪除的記錄又恢復到了BEGIN之前的狀態,如果將ROLLBACK 換成COMMIT,那麼事務將會提交,刪除的記錄就不能恢復了。
(2)自動提交
當搜尋引擎為MyISAM時,因為不支援事務處理,因此命令一旦執行,就一定會提交,這種預設的提交方式被稱為自動提交。
而當搜尋引擎設定為InnoDB時,可以設定自動提交功能是否開啟,當自動提交功能為ON時,命令執行就會提交(COMMIT),而自動提交設定為OFF 時,必須執行COMMIT才提交,可以使用ROLLBACK進行回滾。
查詢當前自動提交功能狀態:
>SELECT @@AUTOCOMMIT; 1 設定自動提交功能:
>SET AUTOCOMMIT=0或1; 1 如圖,將自動提交設定為OFF,插入一條記錄,然後使用回滾ROLLBACK,再次檢視記錄,會發現不見了。
(3)部分回滾 SAVEPOINT
直接ROLLBACK會回滾到BEGIN開始之前的地方,而通過SAVEPOINT可以儲存一個點,通過ROLLBACK TO SAVEPOINT就可以回滾到儲存點了,也就實現了“想去哪就去了哪”。
部分回滾主要有兩個步驟: ①儲存點
>SAVEPOINT 儲存點名; 1 ②回滾到儲存點
>ROLLBACK TO SAVEPOINT 儲存點名; 1 eg:
(4)不能事務處理的命令(直接提交) 大部分命令都可以通過事務處理(BEGIN -ROLLBACK- COMMIT)進行操作,但是:
DROP DATABASE; DROP TABLE; DROP; ALTER TABLE 不能通過事務處理,會直接COMMIT;
3 鎖定與事務處理 前面講到的ROLLBACK 等操作指令都是基於一個使用者進行的。但是事務型別往往不只一個使用者,多個使用者同時操作,如被人廣泛詬病的“12306”火車票購票系統,全國各地的售票視窗以及網際網路購票註冊賬戶,成千上萬的使用者同時使用,因此事務處理必須能夠處理多個使用者同時操作的情況,這就需要鎖定。
舉個例子,如果某班火車只剩最後一張票,A和B 同時登陸網站購票,得到的反饋是還剩一張,於是A,B 都趕緊下單,處理這種衝突事件,就需要對該事務進行鎖定(LOCK),接觸鎖定被稱為解鎖(Unlock)。
3.1 鎖定
(1)鎖定的分類
鎖定分為共享鎖定(Shared Lock)和排他鎖定(Exclusive Lock):
共享鎖定是將物件資料變為只讀形式,不能進行更新,所以也成為讀取鎖定; 排他鎖定是當執行INSERT/UPDATE/DELETE的時候,其它事務不能讀取該資料,因此也成為寫入鎖定。 (2)鎖定的粒度
鎖定物件的大小是鎖定的粒度,有三種粒度:
記錄 表 資料庫 3.2 事務處理的分離水平
需要使用鎖定來有效解決事務衝突的情況,但是鎖定也會使效能下降(因為別人無法訪問),因此頻繁鎖定不一定合理,資料庫中,使用分離水平來表示事務處理之間的影響程度。
事務處理的分離水平對應的資料整合情況:
分離水平 非提交讀取 不可重複讀取 幻象讀取 READ UNCOMMITED √ √ √ READ COMMITED × √ √ REPEATABLE READ × × √ SERIALIZABLE × × × 設定分離水平可以使用命令:
>SET SESSION TRANSACTION ISOLATION LEVEL 分離水平; 1
為了模擬多個使用者對資料庫進行訪問和操作,我們開啟兩個命令視窗接入MySQL。 (1)非提交讀取
非提交讀取指的是別的事務能夠讀取到還沒有提交的更新資料,只發生在分離水平為READ UNCOMMITED的情況下。
因為對事務處理的讀取沒有任何限制,所以一般不推薦使用。
eg:
兩個視窗的執行順序如圖紅色序號所示: ①首先再A視窗對Id為g001的記錄的nam進行修改; ②然後B進行訪問,發現已經能夠讀取新的nam; ③A執行ROLLBACK,回滾到初始狀態(nam恢復原來的記錄); ④B再次查詢,又得到OLD記錄(舊記錄); ⑤A再次UPDATE,並COMMIT; ⑥B再次SELECT,得到新紀錄(new)。 可以看到,當A還沒提交,B就可以看到更新的資料,這個時候很可能出現問題,比如A後來執行ROLLBACK,B看到的資料實際上是錯誤的資料。
(2)不可重複讀取
不可重複讀取是指在某事務處理過程中對資料進行讀取,由於該事務更新操作導致多次讀取資料時發生了改變。
不可重複讀取發生在READ COMMITED 一下的分離水平。
eg:
命令順序依然如圖紅色數字所示: ①A更新id為g001的nam; ②B查詢,結果是OLD資料; ③A提交更新; ④B再次查詢,得到更新後的NEW資料。 B先後兩次查詢,結果不一致。
(3)幻象讀取
幻象讀取指的是,在某事物處理資料過程中對資料多次讀取,由於該事務的插入/刪除操作而導致在多次讀取過程中讀取到不存在或者消失的資料。
下圖是幻象讀取發生的例子:
①A事務開始; ②B查詢; ③A插入一條記錄並提交; ④B再次查詢; 可以看到B連續執行兩次的查詢,前後結果不一致。
當設定分離水平為SERIALIZABLE時,可以消除幻象讀取。
①A事務開始; ②B查詢; ③A插入一條資料;(此時A會一直等待,直到B提交) ④B提交; ⑤A提交; ⑥B再次查詢;
特別需要注意的是,由於B正在讀取資料,當A 執行插入命令時,無法立馬得到結果,而是一直等待,直到B提交。當B提交時,A的插入命令自動完成。
3.3 死鎖 Dead Lock(狹路相逢勇者勝)
死鎖指的是兩個事務互相對待對方釋放鎖定,則永遠也不可能接觸鎖定的狀態。
如A,B兩個使用者都對錶customer中記錄’g001’和’g002’實施了排他鎖定,由於兩個事務互相等待對方釋放鎖定,所以形成了死鎖。
A和B執行命令順序紅色字型所示: ①A事務開始,並對’g001’進行了更新; ②B事務開始,並對’g002’進行了更新; ③A對’g002’進行更新;(A等待B提交釋放鎖定) ④B對’g001’進行更新;(B等待A提交釋放鎖定,A、B互相等待陷入死鎖)
此時,MySQL資料庫讓B強制解除鎖定,A繼續執行;