原文鏈接: https://15721.courses.cs.cmu.edu/spring2018/
Compare-and-Swap(CAS) 樂觀鎖實現機制
- 原子操作,認爲某一內存位置M的值應爲V,如果是,則將位置M的值更新爲V’,否則,操作失敗
圖1.1
內存位置M的值爲20,compare value爲20,兩者相等,如圖1,將位置M更新爲30,如圖2
圖 1.2
內存位置M的值爲30,compare value爲25,兩者不相等,如圖3,該操作失敗
圖 1.3
- 可以通過intrinsic function call(內部函數調用)完成,無需寫machine code,編譯器知道如何轉化爲instruction
Isolation levels(隔離級別)
Serializability(序列化隔離級別):可以忽略併發場景,但並行度過低,性能受限
事務隔離級別控制該事務暴露給其他併發事務的行爲
可能會引起如下現象:髒讀、不可重複讀、幻讀等。
髒讀:事務1 insert一條數據,但未提交,事務2可以select到這條未提交的數據,一旦事務1發生回滾,該條數據則爲髒數據(mysql undo),稱爲髒讀,即讀到爲提交的數據。
不可重複讀:事務1 select某一條數據,得到一個結果,事務2 update該條數據並已提交,事務1此時再去select該條數據,得到的結果和上次select的結果不一致。不可重複讀主要針對update。
幻讀:事務1 select 某一組數據,如select age小於15的數據,得到一組結果,事務2 insert 一條數據,該數據age 小於15,事務1 再次select age小於15的數據,發現多一條記錄。幻讀主要針對insert
基本的事務隔離級別如下:
Serializable(序列化):無幻讀、所有讀可重複、無髒讀
Repeatale reads(可重複讀):可能存在幻讀(phantoms)
Read commited(提交讀):可能存在幻讀、不可重複讀
Read uncommited(未提交讀):所有都有可能發生
如圖2.1 是主流數據的事務隔離級別:
圖 2.1
事務隔離級別基於SQL-92標準,只關注與基於2PL(2階段鎖)的數據庫系統(DBMS),如下兩個級別與2PL無關
CURSOR STABILITY:
--DB2 的默認隔離級別,
--cursor(遊標)是一個pointer inside database system of points out whatever data itms a tuple that the query is operating on that moment,I need to access,the cursor will acquire locks with the things that wants to access,即如果需要掃描2個tuples時,遊標會找到第一個tuple,並對其加鎖,然後做操作,做完操作後釋放該鎖,然後再去獲取第二個tuple的遊標鎖,然後做操作,然後釋放該鎖)
--對於2PL在growing phase獲取所有鎖,如果釋放一個鎖,進入shrinking phase,you can never go back and acquire another lock,but in cursor locking you can do that,由於only one query can hold one cursor at a time,所以不用擔心死鎖
--介於讀提交和可重複讀之間,強於讀提交是因爲可以防止update丟失現象
--可以防止update丟失現象(but not laways)
--update 丟失:如圖2.2
假設在一個單core系統中,txn1 read(A)獲取遊標鎖並釋放,txn2 write(A) 獲取遊標鎖並釋放,txn1 write(A) 獲取遊標鎖並釋放,txn1 commit,稍後txn2 commit。雖然txn2 commit比txn1晚,但是隻能看到txn1 write(A),而txn2 write(A) 被txn1 重寫了,所以txn2 的update似乎丟失了
如果txn1知道將會write(A),就會一直hold the cursor lock,txn2會阻塞,txn1 先提交,然後txn2 執行,就不會出現update丟失的現象。
所以CURSOR STABILITY可以防止update丟失現象,but not always。
|
圖 2.2 update丟失
SNAPSHOT ISOLATION(快照隔離級別):
--參考tidb/cockroachDB,tidb默認級別爲SI,cockroachDB支持SI/SSI兩種級別
--保證事務中所有的read,可以查看到事務開始時,數據庫存在的一致性快照,可以理解爲對每個事務start_timestamp做一致性快照,該快照應用於該事務的所有read
--since that snapshot,事務只有在write與其他的併發update無衝突時才能提交
--易受寫偏序(write skew)現象影響
--寫偏序:如圖2.3
假如txn1想把白塊變成黑塊,txn2想把黑塊變成白塊,當txn1和txn2併發時,他們事務開始時拿到的一致性快照都是上半黑下半白,當txn1和txn2 commit後,變成了上半白下半黑。
但是如果兩個事務序列化執行,得到的操作,應該是txn1先把白的變成黑的,txn2再把黑的變成白的。最後的結果是全白。即由於兩者各自拿到了一致性快照,因爲無法知曉其他事務的修改,提交時又不衝突,而造成的最終結果不一致。
圖2.3 寫偏序
幾種事務隔離級別的關係
圖2.4 幾種事務隔離級別的關係