1. 程式人生 > 實用技巧 >mysql檢視隔離級別 與 ACID

mysql檢視隔離級別 與 ACID

1、檢視當前會話的隔離級別:

select @@tx_isolation;

2、檢視系統的隔離級別:

select @@global.tx_isolation;

3、設定會話的隔離級別,隔離級別由低到高設定依次為:

set session transacton isolation level read uncommitted;
set session transacton isolation levelread committed;
set sessiontransacton isolation levelrepeatable read;
set sessiontransacton isolation levelserializable;

4、設定當前系統的隔離級別,隔離級別由低到高設定依次為:

set globaltransacton isolation level read uncommitted;
set global transacton isolation levelread committed;
set global transacton isolation levelrepeatable read;
setglobal transacton isolation levelserializable;

注意:mysql預設的事務處理級別是'REPEATABLE-READ',而Oracle和SQL Server是READ_COMMITED

ACID特性

資料庫管理系統中事務(transaction)的四個特性(分析時根據首字母縮寫依次解釋):原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、永續性(Durability)

所謂事務,它是一個操作序列,這些操作要麼都執行,要麼都不執行,它是一個不可分割的工作單位。(執行單個邏輯功能的一組指令或操作稱為事務)

詳解

1. 原子性

原子性是指事務是一個不可再分割的工作單元,事務中的操作要麼都發生,要麼都不發生。

可採用“A向B轉賬”這個例子來說明解釋

在DBMS中,預設情況下一條SQL就是一個單獨事務,事務是自動提交的。只有顯式的使用start transaction

開啟一個事務,才能將一個程式碼塊放在事務中執行。

2. 一致性

一致性是指在事務開始之前和事務結束以後資料庫的完整性約束沒有被破壞。這是說資料庫事務不能破壞關係資料的完整性以及業務邏輯上的一致性

如A給B轉賬,不論轉賬的事務操作是否成功,其兩者的存款總額不變(這是業務邏輯的一致性,至於資料庫關係約束的完整性就更好理解了)。

保障機制(也從兩方面著手):資料庫層面會在一個事務執行之前和之後,資料會符合你設定的約束唯一約束,外來鍵約束,check約束等)和觸發器設定;此外,資料庫的內部資料結構(如 B 樹索引或雙向連結串列)都必須是正確的。業務的一致性一般由開發人員進行保證,亦可轉移至資料庫層面。

3. 隔離性

多個事務併發訪問時,事務之間是隔離的,一個事務不應該影響其它事務執行效果。

在併發環境中,當不同的事務同時操縱相同的資料時,每個事務都有各自的完整資料空間。由併發事務所做的修改必須與任何其他併發事務所做的修改隔離。事務檢視資料更新時,資料所處的狀態要麼是另一事務修改它之前的狀態,要麼是另一事務修改它之後的狀態,事務不會檢視到中間狀態的資料

事務最複雜問題都是由事務隔離性引起的。完全的隔離性是不現實的,完全的隔離性要求資料庫同一時間只執行一條事務,這樣會嚴重影響效能。

關於隔離性中的事務隔離等級(事務之間影響),參見相應博文

4. 永續性

這是最好理解的一個特性:永續性,意味著在事務完成以後,該事務所對資料庫所作的更改便持久的儲存在資料庫之中,並不會被回滾。(完成的事務是系統永久的部分,對系統的影響是永久性的,該修改即使出現致命的系統故障也將一直保持)

MySQL的事務隔離級別

MySQL提供了4種事務隔離級別,其中最常用的InnoDB儲存引擎的預設隔離級別為可重複讀。

事務隔離級別髒讀不可重複讀幻讀
讀未提交(read-uncommitted)
已提交讀(read-committed)
可重複讀(repeatable-read)
序列化(serializable)

1、未提交讀。

最低的隔離級別(是一種危險的隔離級別,會出現髒讀),其含義是允許一個事務讀取另外一個事務沒有提交的資料。

T2時刻中事務1中扣減了庫存,T3時刻中事務2也扣減了庫存,但是它也讀取到了T2時刻中事務1的操作,因此T3時刻扣減後庫存為0,這個時候T5在提交事務後事務1進行回滾,因為第一類丟失更新已經被克服,所以庫存最終會出現髒讀(庫存應該為1才是正確的)。

2、讀寫提交。

指一個事務只能讀取到另外一個事務已經提交的資料。

在T3時刻,因為採用了讀寫提交的隔離級別,所以事務2不會讀取到事務1中未提交的庫存1,所以在T3時刻事務2扣除庫存後還剩下庫存為1,然後提交事務。則庫存在T4中就變成了1。在T5時刻,事務1回滾,因為第一類丟失更新已經克服,所以最後的庫存結果也變為了1。

3、可重複讀。

克服讀寫提交中出現的不可復讀的現象,因為在讀寫提交的時候,可能出現一些值的變化,影響當前事務的執行。

4、序列化

最高的隔離級別,會要求所有的SQL按照順序執行,這樣就可以克服上述隔離級別出現的問題,所以能夠保證資料的一致性。

InnoDB 與 MyISAM


1. InnoDB 支援事務,MyISAM 不支援事務。這是 MySQL 將預設儲存引擎從 MyISAM 變成 InnoDB 的重要原因之一;

2. InnoDB 支援外來鍵,而 MyISAM 不支援。對一個包含外來鍵的 InnoDB 錶轉為 MYISAM 會失敗;

3. InnoDB 是聚集索引,MyISAM 是非聚集索引。聚簇索引的檔案存放在主鍵索引的葉子節點上,因此 InnoDB 必須要有主鍵,通過主鍵索引效率很高。但是輔助索引需要兩次查詢,先查詢到主鍵,然後再通過主鍵查詢到資料。因此,主鍵不應該過大,因為主鍵太大,其他索引也都會很大。而 MyISAM 是非聚集索引,資料檔案是分離的,索引儲存的是資料檔案的指標。主鍵索引和輔助索引是獨立的。

4. InnoDB 不儲存表的具體行數,執行 select count(*) from table 時需要全表掃描。而MyISAM 用一個變數儲存了整個表的行數,執行上述語句時只需要讀出該變數即可,速度很快;

5. InnoDB 最小的鎖粒度是行鎖,MyISAM 最小的鎖粒度是表鎖。一個更新語句會鎖住整張表,導致其他查詢和更新都會被阻塞,因此併發訪問受限。這也是 MySQL 將預設儲存引擎從 MyISAM 變成 InnoDB 的重要原因之一;

如何選擇:

1. 是否要支援事務,如果要請選擇 InnoDB,如果不需要可以考慮 MyISAM;

2. 如果表中絕大多數都只是讀查詢,可以考慮 MyISAM,如果既有讀寫也挺頻繁,請使用InnoDB。

3. 系統奔潰後,MyISAM恢復起來更困難,能否接受,不能接受就選 InnoDB;

4. MySQL5.5版本開始Innodb已經成為Mysql的預設引擎(之前是MyISAM),說明其優勢是有目共睹的。如果你不知道用什麼儲存引擎,那就用InnoDB,至少不會差。