嘗試進行歸納總結事務和鎖的一些思考.
數據庫是什么? 保存數據的地方.
為什么保存數據要用數據庫呢? 我直接把數據放文件里, 不也一樣嗎? 比如我自己序列化json文件保存成txt文件成不? 也行, 但是就不方便檢索, 之類的.
數據庫就方便檢索了呀, 數據庫相比文件系統有4個特點:
- A - 原子性
- C - 一致性
- I - 隔離性
- D - 持久性
這里只說鎖, 鎖是用來保證隔離性的.
隔離性是啥?
比如, 我現在自己實現了一個不怎么完善的數據庫, 只是按SQL標准實現了增刪改查等命令, 但是操作的數據是直接落實到系統的文件上的. 同時, 要知道SQL標准也規定了4種數據庫事務隔離級別, 別急, 我們這個不完善的數據庫沒有實現事務隔離級別, 也沒有實現任何鎖, 僅僅是我們知道有這么個東西而已, 暫時不打算去實現它^_^
雖然我們沒有實現它, 但還是可以從事務的角度來進行一下思考, 也就是說我們假想事務這么個東西, 可以啟動事務, 提交事務和回滾事務.
假設兩個事務--A, B, 說明以下幾種存在的問題:
- 臟讀 - A事務啟動, 先讀取一行, 值為1, 還沒提交, B事務啟動, 修改了A剛剛讀取的那一行, 修改為2, 注意, 沒有鎖, 雖然在我們的想像中, B還沒有提交, 但是anyway, B就是直接就把修改寫到文件里了, 然后A再讀取這一行, 值是2. 這叫做A事務讀取到了B事務還沒提交的數據, 是為臟讀.
- 不可重復讀 - A事務啟動, 先讀取一行, 值為1, 還沒提交, B事務啟動, 還是把A讀取的一行修改為2, 注意, 接下來B提交了, 嘿嘿, 剛剛B沒提交, 這下B提交了, 是不是沒問題了? No way!! 不管怎樣, B還是把2寫到文件里了, 然后A再讀取這一行, 值是2. 這叫做A事務的兩次對同一記錄讀取到了不同值, 是為不可重復讀.
- 幻讀 - A事務啟動, 讀取值小於2的, 假設現在就一條, B事務啟動, 插入了一條值為1的, 不管提交不提交, A事務再去讀取值小於2的記錄, 就會發現有兩條了. 是為幻讀, 怎么我出現幻覺了嗎? 剛剛還是一個呢, 現在怎么變成倆了??
- 丟失更新 - 不說了
鎖和MVCC主要就是用來解決以上幾個問題的, 如何解決? 且聽下回分解.
MVCC - 多版本並發控制, 僅僅是為是在RC和RR級別中普通的Select操作時不加鎖, 提高並發性能用.
幻讀的解決, 首先要使用RR級別, 並且開啟gap lock, 也就是innodb_locks_unsafe_for_binlog設置為0, 若為1表示使用不安全的binlog, 也就是表示不使用gap lock, 換言之, gap lock在一定程度上是保護了安全的binlog的, 即保證主從上數據的一致性. 其次, 還要在所有Select語句后加上 lock in share mode或者for update, 用來顯式的加鎖.