本文主要分析在不牽扯分布式的情況下事務與一致性的實現辦法。先說一下事務的acid四個特性,即原子性(atomicity)、一致性(consistency)、隔離性(isolation)、永續性(durability)。
其他的幾個特性應該很好理解,但是一致性這個概念不太好理解,在這一致性指的是資料比較合理,在經過一系列的操作之後資料依然是我們想要看到的,並不是指的語法上的規則,常見的說明例子就是轉賬問題。
redu和undo機制是資料庫實現事務的基礎。redu日誌用來在斷電/資料庫崩潰等狀況發生時重演一次刷資料的過程,把redo日誌裡的資料刷到資料庫裡,保證了事務的永續性(durability);undo日誌是在事務執行失敗的時候撤銷對資料庫的操作,保證了事務的原子性(atomicity)。
但是只有只有原子性和永續性是無法保證資料一致性的,例如:事務1對a使用者加了100元,首先獲取a的資料,但是這時事務2也對a加了100元,結果應該是加了200元,但是事務1覆蓋了事務2,最後只加了100元,所以需要把兩個事務隔離起來,即隔離性(isolation),使的兩個事務併發和序列執行的結果都是一致的。
資料庫使用鎖的方式保證隔離性(也就是最終資料保證了一致性),innodb實現的方式有以下兩種:
悲觀鎖控制
樂觀鎖(資料多版本)控制
悲觀鎖:拿來資料就先上鎖,這樣別的執行緒拿資料就會阻塞。像行鎖,頁鎖,表鎖以及共享鎖,排它鎖都是悲觀鎖。我們說的那些鎖一般都是悲觀鎖。
樂觀鎖:悲觀鎖只是一種概念,其實沒有鎖,mysql預設其他執行緒不會改變資料,所以不加鎖,只是在提交的時候判斷是不是被更改過了,一般用版本戳(mvcc )來實現樂觀鎖。
一,使用(悲觀)鎖控制
按照鎖的使用方式分為共享鎖和排它鎖。
共享鎖(share locks,s鎖):乙個執行緒給資料加上共享鎖後,其他執行緒只能讀取資料,不能修改。
排它鎖(exclusive locks,x鎖):乙個執行緒給資料加上排它鎖後,其他執行緒不能讀取也不能修改。
沒有鎖:innodb所有的普通select都是快照讀,都不加鎖。
相容性規則為:共享鎖和共享鎖相容,排它鎖和其他的鎖都排斥。
如果乙個請求的鎖模式與當前的鎖相容,innodb就將請求授予該事務,反之,如果兩者不相容,該事物就會等到鎖釋放。
對於update,delete和insert語句,innodb會自動給涉及的資料加排它鎖,所以如果插入操作卡住了也無法查詢;
對於普通的select語句,innodb不會加任何鎖;
事務也可以通過以下語句手動的給事務加共享鎖和排它鎖:
select * from table_name where ... lock in share mode 會給事務加上共享鎖;
select * from table_name where ... for update 會給事務加上排它鎖。
按照鎖的粒度分為行鎖和表鎖以及間隙鎖
行鎖是通過給索引上的索引項加鎖來實現的,只有通過索引條件來檢索資料才會用到行鎖,否則innodb將會使用表鎖。
表鎖:select * from table_nane where name = 『小巷』 for update 。name欄位不是唯一索引字段,所以是表鎖。
行鎖:select * from table_name where id = 1 for update 。id 欄位為唯一索引字段,所以使用的就是行鎖,且是排它鎖。
頁鎖(又叫gap鎖):又稱為間隙鎖。所謂表鎖鎖表,行鎖鎖行,那麼頁鎖折中,鎖相鄰的一組資料,可以用來防止幻讀。
通過加鎖控制,可以保證資料的一致性,但是同樣一條資料,不論用什麼樣的鎖,只可以併發讀,並不可以讀寫併發(因為寫的時候加的是排他鎖所以不可以讀),這時就要引入資料多版本控制了,也就是樂觀鎖這個概念。
看完以上可能覺得有點,又是按照粒度又是按照使用方式分的。單獨理解就行,沒必要關聯一下,另外上面說到的這些鎖都算作是悲觀鎖的概念。
二,使用資料多版本(mvcc)控制
使用鎖控制併發時,只要是寫資料的任務沒有完成,資料就不可以被其他的任務獲取,就連讀資料的select操作也會阻塞,這對併發度要求較大的環境有很大的影響,為了解決這個問題引出了資料多版本。
資料多版本實現的原理是:
1,寫任務發生時,首先複製乙份舊資料,以版本號區分
2,寫任務操作新轉殖的資料,直至提交
3,併發讀的任務可以繼續從舊資料(快照)讀取資料,不至於堵塞
排它鎖 是 序列執行
共享鎖 是 讀讀併發
資料多版本 是 讀寫併發
三,redo,undo,回滾段
在innodb的具體實現上,依賴redo日誌,undo日誌,回滾段(rollback segment)
redo日誌的作用?
資料庫事務提交後,按照隨機方式寫入磁碟上效能太低,為了提高效率先寫到redo日誌裡,再刷到磁碟上(此時變成了順序寫)。
假如我在提交事務時資料庫崩潰了,重啟時,會從redo日誌裡把沒有刷到磁碟的資料刷到磁碟上(redo意為把刷磁碟的操作進行一次重演)。簡言之,redo的作用是為了保障已提交事務的acid特性,也就是保證了資料的d(durability)永續性。
undo日誌的作用?
資料庫修改資料但未提交時,會將事務修改資料的映象(即舊資料)存到undo日誌裡,當事務回滾或資料庫崩潰時,會從undo日誌裡獲取舊資料,避免未提交資料對資料庫的影響。簡言之,undo的作用是為了保障未提交的事務不會對資料庫的acid產生影響。也就是保證了操作的a(atomicity)原子性。
回滾段的作用?
儲存undu日誌的地方,就是回滾段。
innodb所有的普通select都是快照讀,快照讀不加鎖。這也是innodb支援高併發的乙個原因之一
資料庫筆記
資料庫mariadb 基本操作 mysql secure installation 配置嚮導 mysql uroot p 登陸資料庫 enter password 輸入密碼 welcome to the mariadb monitor.commands end with or g.your mari...
資料庫筆記
1.資料庫分頁查詢 select from table limit startline,pagesize 從startline開始查詢pagesize大小行資料 2.級聯操作 當存在外來鍵約束時,主表若想刪除或修改資料,必須先修改副表中相關聯的資料.如果想直接修改或刪除主表資料,同時改變副表 資料就...
資料庫筆記
筆記記錄 左外連線left join 涉及表 student,fee,fee info三張表,截圖依次如下 兩張表應用 查詢1 查詢2 對比就可以看出區別,查詢2比查詢1多1條鳳姐的記錄 此條記錄的s.number沒有對應的f.feeid 查詢1 s.number找不到對應的f.feeid時,會自動...