1. 程式人生 > >MySQL資料庫事務處理

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繼續執行;