事務 原子性 事務(transaction)中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。 一致性: 執行的結果必須是使資料庫從一個一致性狀態變到另一個一致性狀態。因此當資料庫只包含成功事務提交的結果時,就說資料庫處於一致性狀態。 隔離性 一個事務的執行不能被其他事務干擾。即一 ...
目錄
事務
-
原子性
事務(transaction)中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。
-
一致性:
執行的結果必須是使資料庫從一個一致性狀態變到另一個一致性狀態。因此當資料庫只包含成功事務提交的結果時,就說資料庫處於一致性狀態。
-
隔離性
一個事務的執行不能被其他事務干擾。即一個事物內部的操作及使用的數據對併發的其他事務是隔離的,併發執行的各個事物之間不能互相干擾
-
持久性
一個事務的執行不能被其他事務干擾。即一個事物內部的操作及使用的數據對併發的其他事務是隔離的,併發執行的各個事物之間不能互相干擾
begin; #開始事務
...
rollback; #回滾事務
savepoint 回滾點; #添加回滾點
rollback to 回滾點; #回滾到指定回滾點
...
commit; #提交事務
併發三大問題
-
丟失修改:兩個都改
事務T1和事務T2同時讀入同一數據進行修改,T1或者T2修改數據丟失的問題
-
不可重覆讀:一讀一改
事務T1讀取數據後,事務T2修改數據,使得T1兩次讀取的值不一致的問題
-
讀臟數據的問題:一讀一改 + 事務撤銷
事務T2修改數據,事務T1讀數據,T2事務撤銷,T1讀取數據不正確
排他鎖和共用鎖
-
排他鎖:寫鎖
當前事務給數據添加寫鎖後,其他事務既不能讀,也不能寫,也不能添加鎖。
-
共用鎖:讀鎖
當前事務給數據添加讀鎖後,其他事務僅可以讀,當前數據所有讀鎖釋放後,才可以添加寫鎖。
-
一級封鎖協議
事務T在修改數據R之前必須獲得排他鎖(解決丟失修改問題)
-
二級封鎖協議
一級封鎖協議+事務T在讀數據R之前必須先對數據添加共用鎖,讀完立即釋放(解決丟失修改和讀臟數據的問題)
因為事務結束前釋放了共用鎖,因此其他事務可以進行修改數據,因此無法解決不可重覆讀問題。
-
三級封鎖協議
一級封鎖協議+事務T在讀數據R之前必須先對數據添加共用鎖,且事務結束後才釋放共用鎖。
事務隔離
-
讀-未提交(read uncommitted):未上鎖
事務T1可以查看事務T2未提交的數據。(讀臟數據的問題)
-
讀-已提交(read committed): 上了寫鎖,提交後解鎖
事務T1只能讀取到T2已經提交後的數據。(不可重覆讀)
-
可重覆讀(repeatable read): 三級封鎖協議
事務T1讀取一張表時,事務T2不能修改那張表的數據。(幻讀: 數據不真實)
-
序列化/串列化(serializable)
併發都沒了,事務T1和事務T2不能對同一張表操作。
# 查看事務隔離級別
select @@transaction_isolation;
# 設置事務隔離級別
set global transaction ioslation level 隔離級別
全局鎖
全局鎖就是對整個資料庫實例加鎖,即資料庫中的所有表都將被加上鎖,加鎖後整個實例就處於只讀狀態,後續的DML的寫語句,DDL語句,已經更新操作的事務提交語句都將被阻塞。
# 開啟全局鎖,全局鎖只有讀
flush tables with read lock;
# 解除全局鎖
unlock tables;
表鎖
表鎖作用於某一張表,是MyISAM和InnoDB存儲引擎支持的方式,是
MyISAM
的預設鎖機制。
# 添加寫鎖/讀鎖
lock table 表名稱 read/write;
# 解鎖
unlock tables;
為表添加寫鎖後,不能讀取表中任何數據。
為表添加讀鎖後,不能修改表中任何數據。
行鎖
僅
InnoDB
引擎支持行鎖
-- 添加讀鎖(共用鎖), 只能在事務中使用
select * from ... lock in share mode;
-- 查詢時添加寫鎖(排他鎖)
select * from ... for update;
-- 更新時自動添加寫鎖
update 表名 set xxx = xxx where xxx
行鎖的細分,瞭解一下就好。
記錄鎖
(Record Locks)記錄鎖, 僅僅鎖住索引記錄的一行,在單條索引記錄上加鎖。Record lock鎖住的永遠是索引,而非記錄本身,即使該表上沒有任何索引,那麼InnoDB會在後臺創建一個隱藏的聚集主鍵索引,那麼鎖住的就是這個隱藏的聚集主鍵索引。所以說當一條sql沒有走任何索引時,那麼將會在每一條聚合索引後面加寫鎖,類似於表鎖,但原理上和表鎖是完全不同的。
間隙鎖
(Gap Locks)僅僅鎖住一個索引區間(開區間,不包括雙端端點)。在索引記錄之間的間隙中加鎖,或者是在某一條索引記錄之前或者之後加鎖,並不包括該索引記錄本身。比如在 1、2中,間隙鎖的可能值有 (-∞, 1),(1, 2),(2, +∞),間隙鎖可用於防止幻讀,保證索引間的不會被插入數據。
臨鍵鎖
(Next-Key Locks)Record lock + Gap lock,左開右閉區間。預設情況下,
InnoDB
正是使用Next-key Locks來鎖定記錄(如select … for update語句)它可以根據場景進行靈活變換:
場景 | 轉換 |
---|---|
使用唯一索引進行精確匹配,但表中不存在記錄 | 自動轉換為 Gap Locks |
使用唯一索引進行精確匹配,且表中存在記錄 | 自動轉換為 Record Locks |
使用非唯一索引進行精確匹配 | 不轉換 |
使用唯一索引進行範圍匹配 | 不轉換,但是只鎖上界,不鎖下界 |
引擎間的鎖機制
使用InnoDB的情況下,在執行更新、刪除、插入操作時,資料庫也會自動為所涉及的行添加寫鎖(排他鎖),直到事務提交時,才會釋放鎖,執行普通的查詢操作時,不會添加任何鎖。而當不使用where
語句時,行鎖會升級為讀鎖。
使用MyISAM的情況下,在執行更新、刪除、插入操作時,資料庫會對涉及的表添加寫鎖,在執行查詢操作時,資料庫會對涉及的表添加讀鎖。