鎖定義
鎖是計算機協調多個進程或線程並發訪問某一資源的機制。
數據庫中,除了傳統的計算資源(cpu、ram、i/o等)的爭用以外,數據也是一種需要用戶共享的資源。保證數據並發訪問的一致性、有效性是所有數據庫必須解決的一個問題。
鎖分類
從性能上分為:樂觀鎖和悲觀鎖
(樂觀鎖:用版本對比來實現,數據庫可設置一個版本控制的字段,每次查詢時記錄當時版本號,更新時與原來的版本記錄對比,如果相同則進行更新操作)
悲觀鎖:
從數據庫的操作類型區分:讀鎖和寫鎖
讀鎖(共享鎖):多個線程的讀操作可以同時對同一數據進行
寫鎖(排它鎖):當前寫操作過程中,其他線程的讀、寫操作均不可進行
從數據的操作粒度區分:表鎖和行鎖
表鎖
表鎖的操作
增加表鎖:lock table 表名 read(write), 表名2 read(write)
查看表上面加的鎖:show open tables
刪除表鎖:unlock tables
行鎖
支持事務
事務屬性(ACID)
原子性:一個事務方法塊作為一個最小單位不可切分,對數據庫的操作要不全部執行,要不全部不執行
一致性:事務方法塊對數據庫的執行結果要保持一致,要不一起成功要不一起失敗(傾向於執行結果)
隔離性:每個事務對數據庫的操作獨立運行,不能受到其他事務的干擾
持久性:操作后的數據庫數據是永久性的
並發事務帶來的問題
更新丟失:多個事務同時操作同一條數據,最后commit的事務的結果數據會覆蓋之前事務的操作結果,造成其他事務更新數據丟失的現象
臟讀:一個事務讀取某一條數據時,另外一個事務同時對此數據進行了修改卻並未提交事務,而被當前事務讀取到
不可重復度:一個事務多次讀取某一條數據的過程中,另外一個事務對此數據進行了修改且提交了事務,從而造成當前事務前后不同時間段從此數據中讀取到了不同的值
幻讀:一個事務的多次查詢過程中,另外一個數據新插入了一條數據並提交了事務,從而被當前事務所讀取到
事務隔離級別
讀未提交(read uncommitted):讀取同一條數據時,可以讀取到其他事務的修改操作且未commit的結果
讀已提交(read committed):讀取同一條數據時,可以讀取到其他事務的修改操作且已經commit的結果
可重復讀(repeatable read):某一session事務的業務過程中如果需要多次查詢某一條數據,如果其他事務對此數據進行了修改且comiit,當前事務讀取到的數據仍然與最初的查詢結果保持不變(mysql默認的事務隔離級別)
可串行化(serializable):多個事務同時操作同一條數據時,將多個事務串成一串,一個一個的執行(單線程,效率低)
MVCC機制 (個人理解)
mysql對表中的每條數據新增了兩個隱藏標記:新建事務id和刪除事務id,
每個事務對某一條數據進行修改操作時,mysql類似的根據原數據clone一條數據,並設置新數據的新建事務id為當前事務的id
每個事務對某一條數據進行刪除操作時,mysql會設置目標數據的刪除事務id為當前事務id,
也就是說:某一事務對數據的修改、刪除操作,mysql其實並未真實立刻進行修改或刪除,而是根據當前事務id做了一個綁定,然后再根據當前事務id查詢出“修改、刪除”操作后的數據結果,從而模擬出當前事務的 修改、刪除操作
每個session事務對數據庫進行查詢時(首次查詢),mysql會生成一個針對此session事務的快照,當此事務對數據進行修改、刪除操作時會依據以上規則(類似以上操作)進行操作,然后再次生成新的快照,供此session事務之后 的查詢使用
mysql的begin/start transaction命令並不是一個事務的起點,執行到命令之后的第一個操作innoDB表的語句時,事務才會真正啟動
間隙鎖
某個事務對表種 4-20的數據進行修改、刪除操作過程中,會在此區間產生間隙鎖,當前事務結束之前其他事務不可對此間隙的數據進行修改、刪除操作。(間隙鎖可有效避免臟讀、幻讀)
mysql鎖的優化方法:
盡量減小"間隙鎖"的范圍,從而達到更高的並發效果
盡量控制事務大小,減少鎖的占用時間
無索引數據的話,行鎖會自動升級為表鎖,so:合理設計索引