想象一下你馬上出發要去一家餐廳吃飯,但是你去之前不確定會不會滿桌,你又不想排號。這時的你會有兩個選擇,如果你是個樂觀的人,內心戲可能會是「管他的,去了再說,大不了沒座就回來」。反之,如果你是一個悲觀的人,可能會先打個電話預約一下,先確認下肯定有座,同時交點定金讓餐廳預留好這個座位,這樣就可以直接去了 ...
想象一下你馬上出發要去一家餐廳吃飯,但是你去之前不確定會不會滿桌,你又不想排號。這時的你會有兩個選擇,如果你是個樂觀的人,內心戲可能會是「管他的,去了再說,大不了沒座就回來」。反之,如果你是一個悲觀的人,可能會先打個電話預約一下,先確認下肯定有座,同時交點定金讓餐廳預留好這個座位,這樣就可以直接去了。
上面這個例子很直觀的對應了兩種事務模型的行為,樂觀事務模型就是直接提交,遇到衝突就回滾,悲觀事務模型就是在真正提交事務前,先嘗試對需要修改的資源上鎖,只有在確保事務一定能夠執行成功後,才開始提交。
理解了上面的例子後,樂觀事務和悲觀事務的優劣就很好理解了。對於樂觀事務模型來說,比較適合衝突率不高的場景,因為直接提交(“直接去餐廳”)大概率會成功(“餐廳有座”),衝突(“餐廳無座”)的是小概率事件,但是一旦遇到事務衝突,回滾(回來)的代價會比較大。悲觀事務的好處是對於衝突率高的場景,提前上鎖(“打電話交定金預約”)的代價小於事後回滾的代價,而且還能以比較低的代價解決多個併發事務互相衝突、導致誰也成功不了的場景。
再次解釋背後思想:
常規的鎖是先互斥,再修改數據。不管是不是發生了衝突,我們都會先做互斥。但樂觀鎖不同,它是先計算出所有修改的數據,然後最後一步統一提交修改。提交時會進行衝突檢查,如果沒有衝突,也就是說,在我之前沒有人提交過新版本,或者雖然有人提交過新版本,但是修改的數據和我所依賴的數據並不相關,那麼提交會成功。否則就是發生了衝突,會放棄本次修改。
為什麼要用樂觀鎖?至少它讓鎖資料庫的粒度降到最低,判斷衝突的邏輯也都是可預期的行為,這就避免了出現死鎖的可能。我們很容易可以推理得知,在所有並行執行的事務中,必然有一個事務的提交會成功。這樣就避免了饑餓(永遠都沒人可以成功)。
reference:
1. https://pingcap.com/blog-cn/pessimistic-transaction-the-new-features-of-tidb/
2. 許式偉架構課