MySQL原理及優化(三)MySQL事務與鎖詳解

2021-10-09 18:45:19 字數 3651 閱讀 4727

事務是資料庫管理系統執行過程中的乙個邏輯單位,由乙個有限的資料庫操作序列構成。

注意:第一,事務是資料庫的最小工作單元,是不可再分的。第二,它可能包含乙個或者一系列的dml語句。

原子性(atomicity)

不可再分,意味著對資料庫的操作要麼成功,要麼失敗。失敗的時候要進行回滾。

原子性,在innodb裡面是通過undo log來實現的,它記錄了資料修改之前的值(邏輯日誌),一旦發生議程,就可以用undo log來實現回滾操作。

一致性(consistent)

資料庫的完整性約束沒有被破壞,事務執行的前後都是合法的資料狀態。比如主鍵必須是唯一的,字段長度符合要求等。

隔離性(isolation)

很多事務對錶或者行的併發操作,應該是透明的,互相不干擾的。通過這種方式,保證業務資料的一致性。

永續性(durable)

對資料庫的任意操作,只要是事務提交成功,那麼結果就是永久性的。不肯那個因為系統宕機或者重啟又恢復了原來的狀態。這就是事務的永續性。

永續性的實現、資料庫崩潰恢復(crash-safe)的實現:

永續性是通過redo log和double write雙寫快取來實現的。我們運算元據的時候,會先寫到記憶體的buff pool裡面,同時記錄redo log,如果刷盤之前出現異常,在重啟後就可以讀取redo log的內容,寫入到磁碟,保證資料的永續性。恢復成功的前提是資料頁本身沒有破壞,是完整的,這個通過雙寫快取(double write)保證。

事務的原子性、隔離性、永續性最後都是為了實現一致性。

髒讀

不可重複讀

幻讀無論是髒讀,還是不可重複讀,還是幻讀,他們都是資料庫的讀一致性的問題,都是在乙個事務裡面前後兩次讀取出現了不一致的情況。

讀一致性的問題必須要有資料庫提供一定的事務隔離機制來解決。

事務隔離級別

sql92標準制定了四個隔離級別用來解決事務併發的問題。

innodb支援四個隔離級別和sql92定義的基本一致,隔離的級別越高,事務的併發度就越低。唯一的區別在於innodb在rr的級別解決了幻讀的問題。因此innodb預設使用rr作為事務隔離級別,既保證了資料的一致性,又支援較高的併發度。

基於鎖的併發操作(lock based concurrency control):要保證前後兩次讀取資料一致,在讀取資料的時候鎖定我要操作的資料,不允許其他的事務修改。

如果僅僅是基於鎖來實現事務隔離,乙個事務讀取的時候不允許其他事務修改,那麼意味著不支援讀寫操作,而我們的大多數應用都是讀多寫少的,這樣會極大地影響運算元據的效率。

如果要讓乙個事務前後兩次讀取的資料保持一致,那麼可以在修改資料的時候建立乙個備份或快照,後面再來讀取這個快照就行了。這種方案叫做多版本的併發控制multi version concurrency control。

mvcc的核心思想是,我可以查詢在我這個事務開始之前已經存在的資料,即使它在後面被修改或刪除了。在我之歌事務之後新增的資料,我是查不到的。

快照什麼時候建立?讀取的時候怎麼保證能讀取到這個快照而不是最新的資料?

innodb為每行記錄都實現了兩個隱藏字段:

mvcc的查詢規則:智慧型查詢建立時間小於等於當前事務id的資料,和刪除時間大於當前事務id的行。

在innodb中,mvcc是通過undo log實現的。

行級鎖:shared and exclusive locks,表級鎖:intention lockes 稱為鎖的基本模式。

record locks,gap locks、next-key locks叫做鎖的演算法。

表鎖:鎖住一張表;行鎖:鎖主表裡面的一行資料。鎖定粒度:表鎖大於行鎖。

加鎖效率:表鎖的加鎖效率大於行鎖的加鎖效率。

衝突概率:表鎖的衝突概率大於行鎖的衝突概率。

共享鎖(shared locks)

獲取一行資料的讀鎖以後,可以用來讀取資料後,可以用來讀取資料。

注意:不要在加了讀鎖以後寫資料,不然可能會造成死鎖的情況。多個書屋可以共享一把讀鎖。

加讀鎖:

select ...... lock in share mode;
釋放鎖有兩種方式:事務結束,鎖就會自動釋放,包括提交事務和結束事務。

排它鎖(exclusive locks)

排它鎖使用來來運算元據的,所以又叫做寫鎖。只要乙個事務獲取了一行資料的排它鎖,其他事務就不能再獲取這一行資料的共享鎖和排它鎖。

加寫鎖

update ...... for update
意向鎖

意向鎖是由資料庫自己維護的。當給一行資料加上共享鎖之前,資料庫會自動在這張表上加乙個意向共享鎖;當給一行資料加上排它鎖之前,資料庫會自動在這張表上加乙個意向排它鎖

如果一張表上至少有乙個意向共享鎖,說明其他的事務給其中的某些資料行加上了共享鎖;如果一張表上至少有乙個意向排它鎖,說明其他的事務給其中的某些資料行加上了排它鎖。

innodb的行鎖鎖住的是索引,如果沒有索引,會鎖住整張表。

因為查詢沒有使用索引,會進行全表掃面,把每乙個隱藏的聚集索引都鎖住了。

給唯一索引加鎖,主鍵索引也會被鎖住:通過輔助索引鎖定一行資料的時候,步驟跟檢索資料一樣,會通過主鍵值找到主鍵索引,然後鎖定。

測試表test1,表中有乙個主鍵索引。插入4行資料,主鍵值分別是1、4、7、10。因為使用的是主鍵索引加鎖,劃分標準就是主鍵索引的值。

使用唯一的索引(包括唯一索引和主鍵索引)使用等值查詢,精確匹配到一條記錄的時候,這個時候使用的是記錄鎖。

使用不同的key去加鎖,不會衝突,它只鎖住了這個record。

當查詢的記錄不存在,沒有命中任何乙個record,無論是等值查詢還是範圍查詢,使用的是間隙鎖。

間隙鎖只要是阻塞插入insert。相同的間隙鎖之間不衝突。

間隙鎖只在rr中存在,如果要關閉間隙鎖,就要把事務隔離級別設定成rc,並把innodb_locks_unsafe_for_binlog設定成on。

使用了查詢範圍,不僅命中了record記錄,還包含了gap,在這種情況下我們使用的就是臨鍵鎖,它是mysql裡面預設的行鎖演算法,相當記錄鎖加上間隙鎖。

唯一索引,等值查詢匹配到一條記錄的時候,退化成記錄鎖;沒有匹配到任何記錄的時候退化成間隙鎖。

innodb的rr級別能夠解決幻讀問題就是使用臨鍵鎖來實現的。

鎖在事務結束(commit、rollback)、客戶端斷開時進行釋放。

同一時刻智慧型友乙個事務持有這把鎖;

其他事務需要在這個事務釋放鎖之後才能獲取鎖,而不可以強行剝奪。

當多個事務形成等待環路的時候,即發生死鎖。

在程式中,操作多張表時,盡量以相同的順序訪問(避免形成等待環路);

批量操作單張表資料的時候,先對資料進行排序(避免形成等待環路);

申請足夠級別的鎖,如果運算元據,申請排它鎖。

盡量使用索引訪問資料,避免沒有where條件的操作,沒避免鎖表。

大事務化小事務

使用等值查詢而不是範圍查詢查詢資料,命中記錄,避免間隙鎖對併發的影響。

MySQL優化(三) 索引原理及索引優化

b tree索引,它是目前關係型資料庫中查詢資料最為常用和有效的索引,大多數儲存引擎都支援這種索引。使用b tree這個術語,是因為mysql在create table或其它語句中使用了這個關鍵字,但實際上不同的儲存引擎可能使用不同的資料結構,比如innodb就是使用的b tree。中的b是指bal...

MySQL架構原理及優化

客戶端向mysql伺服器傳送一條查詢請求 伺服器首先檢查查詢快取,如果命中快取,則立刻返回儲存在快取中的結果。否則進入下一階段 伺服器進行sql解析 預處理 再由優化器生成對應的執行計畫 mysql根據執行計畫,呼叫儲存引擎的api來執行查詢 將結果返回給客戶端,同時快取查詢結果 mysql 不會在...

MySQL索引原理及查詢優化

其實在工作中有去優化mysql語句,但之前優化僅僅是降到能夠接受花費時間之下,並有很多可以繼續提供的空間。很多時候在優化完成之後sql,也並不能向外展示。故這裡將自己平時優化的sql方法記錄下來,並找到乙個總結優化sql的地方。索引原理 mysql的建立索引其實就像是字典的目錄有一定的相似之處,通過...