MySQL(十四)】事務 MVCC機制

事務的四大特性:Atomicity(原子性),Isolation(隔離性),Consistency(一致性)和Durability(持久性)。

重點說下隔離性,指的是多個事務並行執行時,效果上就像一個一個執行的。沒有因爲是並行而導致問題。因爲系統不可能完全讓事務順序執行,這樣性能太差,所以說需要在併發的同時滿足隔離性。

接下來,再看下事務併發執行時會遇到怎樣的問題?

髒寫,或者說寫覆蓋。就是是A更新一行數據,還未提交,事務B又更新了同一行數據。一句話概括即使,允許事務更新未提交的事務已經更新的行。這個會導致嚴重的問題,比如事務B之後又回滾了,那麼A的修改也會被覆蓋。

髒讀;

不可重複讀;

幻讀;

再重點看下幻讀,幻讀有兩個特點:一是必須是別的事務插入導致的;而是必須是第二次讀讀到的行變多了;

隔離級別

sql標準有四種隔離級別:

當然這個也僅是標準,不同的實現會略有不同,比如mysql就可以在rr級別下避免幻讀問題。另外再強調下事務與鎖的關係。爲了保證事務併發讀,在非序列化隔離級別下,事務的普通讀取都不需要加鎖,非鎖定讀。

下面看下mysql裏如何解決髒讀和不可重複讀問題的。

使用的是MVCC機制。

在非鎖定讀機制下,如何解決髒讀和不可重複讀問題?答案是使用快照思路,在事務讀取時,先得到一份當前數據庫數據的快照,只從這個快照裏讀數據,後面的修改都不會影響這個快照。那麼真的會備份全部數據生成這個快照嗎?

不會的。之前講過數據的行格式,知道每一條數據都有rollback_pointer屬性。這個是幹嘛的?其實每一個事務對同一行數據的修改均會被記錄到該行數據上,按照先後關係形成一個鏈表,而rollback_pointer指向的就是鏈表的頭結點。這個其實是undo log,記錄了修改的內容,方便後續回滾。

所以,所謂的快照,其實就是讀數據的事務需要在讀取前,得到讀取行的一個一致性視圖,這個視圖就是通過undo log來得到的。也就是隻讀自己可以看到的修改,屏蔽不能看到的修改。

對於rc級別,每一次普通的讀取語句都會計算出一個視圖;而對於rr級別,因爲保證需要在整個事務期間讀取到相同的值,所以會在第一次普通讀取語句計算出一個視圖,整個事務期間就用這個視圖;

那麼如何得到事務的可見性視圖?

在事務發起讀語句時,需要記錄這麼幾個值。

1.當前事務id爲A;

2.記錄當前所有活躍的事務id列表list;

3.下一個可分配的事務idC;

然後從後往前遍歷回滾段鏈表。拿到當前undo log裏的事務id,假設爲D:

如果D > C,說明事務D是本事務之後開啓的,不可見;

如果D < A,說明事務D在本事務開啓前就已提交,可見;

否則呢,看D是否在活躍事務列表list裏,如果在,事務D還未提交,不可見,否則說明已經提交,可見; 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章