|
隔離級(jí)別是在多個(gè)事務(wù)同時(shí)進(jìn)行更改和執(zhí)行查詢(xún)時(shí),對(duì)性能與結(jié)果的可靠性、一致性和再現(xiàn)性之間的平衡進(jìn)行微調(diào)的設(shè)置。 提供了SQL:1992標(biāo)準(zhǔn)中描述的四種事務(wù)隔離級(jí)別:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。InnoDB默認(rèn)的隔離級(jí)別是REPEATABLE READ。 InnoDB使用不同的鎖定策略支持這里描述的每個(gè)事務(wù)隔離級(jí)別。下面的列表描述了MySQL如何支持不同的事務(wù)級(jí)別。 1. REPEATABLE READ(可重復(fù)讀) 這是InnoDB的默認(rèn)隔離級(jí)別。同一個(gè)事務(wù)中的一致性讀取讀的是第一次讀取時(shí)建立的快照。這意味著,如果在同一個(gè)事務(wù)中發(fā)出幾個(gè)普通(非鎖定)SELECT語(yǔ)句,這些SELECT語(yǔ)句彼此之間也是一致的。(PS:可重復(fù)讀這個(gè)級(jí)別就是要保證同一個(gè)事務(wù)中,多次讀取相同的數(shù)據(jù),返回的結(jié)果是一樣的。) 對(duì)于鎖定讀(SELECT with FOR UPDATE or LOCK IN SHARE MODE)、UPDATE 和 DELETE 語(yǔ)句,鎖定取決于語(yǔ)句是使用具有唯一搜索條件的唯一索引,還是使用范圍類(lèi)型的搜索條件。
2. READ COMMITTED(讀已提交) 即使在同一事務(wù)中,每個(gè)一致的讀取都將設(shè)置并讀取自己的新快照。(PS:對(duì)比一下,對(duì)于一致性讀,可重復(fù)讀是讀取事務(wù)中第一次讀取時(shí)候建立的快照;而讀已提交,每次都是讀最新的快照) 對(duì)于鎖讀(SELECT with For UPDATE or LOCK IN SHARE MODE)、UPDATE語(yǔ)句和DELETE語(yǔ)句,InnoDB只鎖住索引記錄,而不鎖住它們之間的間隙,從而允許在鎖住的記錄旁邊自由插入新記錄。間隙鎖定僅用于外鍵約束檢查和重復(fù)鍵檢查。 由于禁用了間隙鎖,可能會(huì)出現(xiàn)幻像問(wèn)題,因?yàn)槠渌麜?huì)話(huà)可以在間隙中插入新行。 使用READ COMMITTED具有額外的效果:
舉個(gè)例子,考慮下面的語(yǔ)句: CREATE TABLE t (a INT NOT NULL, b INT) ENGINE = InnoDB; INSERT INTO t VALUES (1,2),(2,3),(3,2),(4,3),(5,2); COMMIT; 在這種情況下,表沒(méi)有索引,因此搜索和索引掃描使用隱藏的聚集索引鎖定記錄 假設(shè),第一個(gè)會(huì)話(huà)要執(zhí)行update語(yǔ)句: # Session A START TRANSACTION; UPDATE t SET b = 5 WHERE b = 3; 假設(shè),在第一個(gè)會(huì)話(huà)之后,第二個(gè)會(huì)話(huà)也要執(zhí)行如下update語(yǔ)句: # Session B UPDATE t SET b = 4 WHERE b = 2; 當(dāng)InnoDB執(zhí)行每個(gè)UPDATE時(shí),它首先為讀取的每一行獲取一個(gè)排他鎖,然后決定是否修改它。如果InnoDB沒(méi)有修改該行,則釋放鎖。否則,InnoDB會(huì)保留鎖直到事務(wù)結(jié)束。這對(duì)事務(wù)處理的影響如下。 如果用默認(rèn)的REPEATABLE READ隔離級(jí)別,第一個(gè)UPDATE在其讀取的每一行上獲取一個(gè)X鎖,并且不釋放其中的任何一個(gè): x-lock(1,2); retain x-lock x-lock(2,3); update(2,3) to (2,5); retain x-lock x-lock(3,2); retain x-lock x-lock(4,3); update(4,3) to (4,5); retain x-lock x-lock(5,2); retain x-lock (PS:之所以每一行都加排它鎖,是因?yàn)閎上沒(méi)有唯一索引) 第二個(gè)UPDATE在嘗試獲取任何鎖時(shí)立即阻塞(因?yàn)榈谝粋€(gè)UPDATE已在所有行上保留了鎖),并且直到第一個(gè)UPDATE提交或回滾后才繼續(xù)進(jìn)行: x-lock(1,2); block and wait for first UPDATE to commit or roll back 如果用READ COMMITTED隔離級(jí)別,第一個(gè)UPDATE在其讀取的每一行上獲取一個(gè)X鎖,并為未修改的行釋放X鎖: x-lock(1,2); unlock(1,2) x-lock(2,3); update(2,3) to (2,5); retain x-lock x-lock(3,2); unlock(3,2) x-lock(4,3); update(4,3) to (4,5); retain x-lock x-lock(5,2); unlock(5,2) 但是,如果WHERE條件包含一個(gè)索引列,并且InnoDB使用該索引,那么在獲取和保留記錄鎖時(shí),只考慮索引列。 再看下面一個(gè)例子,第一個(gè)UPDATE在b = 2的每一行上獲取并保留一個(gè)X鎖。第二個(gè)UPDATE在嘗試獲取同一記錄上的X鎖時(shí)會(huì)阻塞,因?yàn)樗彩褂迷赽列上定義的索引 。 CREATE TABLE t (a INT NOT NULL, b INT, c INT, INDEX (b)) ENGINE = InnoDB; INSERT INTO t VALUES (1,2,3),(2,2,4); COMMIT; # Session A START TRANSACTION; UPDATE t SET b = 3 WHERE b = 2 AND c = 3; # Session B UPDATE t SET b = 4 WHERE b = 2 AND c = 4; (PS:b列上有索引,這兩條語(yǔ)句在檢索時(shí)使用了b列上的索引,因此第一會(huì)話(huà)在b=2的列上加了X鎖,第一個(gè)會(huì)話(huà)更新b=2時(shí)會(huì)阻塞) 3. READ UNCOMMITTED(讀未提交) 會(huì)出現(xiàn)臟讀,一般不使用 4. SERIALIZABLE(串行化) 此級(jí)別類(lèi)似于REPEATABLE READ,但如果禁用了自動(dòng)提交,則InnoDB會(huì)將所有普通的SELECT語(yǔ)句隱式轉(zhuǎn)換為SELECT ... LOCK IN SHARE MODE。
|
|
|
來(lái)自: 新進(jìn)小設(shè)計(jì) > 《待分類(lèi)》