這是我參與新手入門的第1篇文章數據庫
事務的四個特性:原子性,一致性,隔離性,持久性。 其中原子性、一致性、持久性容易理解。今天重點來聊聊隔離性。markdown
隔離性簡單來講,就是每一個事務是相互隔離的,你作你的事,他作他的事,你們相互隔離開來。 可是,你們都是在同一個數據庫下操做,那這個「隔離」到底隔離到什麼程度呢?是「老死不相往來」,仍是」臨時隔離「,又或者是"你中有我,我中有你"?這就是涉及到了新的概念:隔離級別。併發
事務隔離級別有:工具
MySQL默認隔離級別爲:可重複讀spa
經過實際演示,咱們能夠很好理解各隔離級別。 相關準備:設計
MySQL 版本:5.7 (可經過
select version()
命令查詢)code表:orm
CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵', `number` varchar(20) NOT NULL COMMENT '學號', `name` varchar(20) DEFAULT NULL COMMENT '姓名', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='學生表'; 複製代碼
初始數據:索引
id number name 1 2021070501 張三 複製代碼
演示工具:Navicat (經過開啓多個查詢窗口,實現開啓多個事務)事務
演示一:
步驟 | 查詢窗口1(事務1) | 查詢窗口2(事務2) |
---|---|---|
step1 | 執行SQL: -- 開啓事務 BEGIN; > OK > 時間: 0s UPDATE student SET name = '李四' WHERE id = 1; > Affected rows: 1 > 時間: 0.002s |
|
step2 | BEGIN; SELECT * FROM student WHERE id = 1; =======結果======= id number name 1 2021070501 張三 |
|
step3 | COMMIT; > OK > 時間: 0.004s; |
|
step4 | SELECT * FROM student WHERE id = 1; =======結果======= id number name 1 2021070501 張三 |
|
step5 | COMMIT; > OK > 時間: 0s |
|
step6 | BEGIN; SELECT * FROM student WHERE id = 1; =======結果======= id number name 1 2021070501 李四 |
從上面演示能夠分析出:
事務之間雖然有隔離性,但若是兩個事務操做同一數據,那結果會怎麼樣呢,最終以哪一個事務執行結果爲準?沒有事務的狀況下,咱們很容易理解,哪條SQL語句最後執行,就以哪一個數據爲準。但加了事務,狀況就變得複雜起來了,SQL執行順序與事務提交順序可能不一致。好比:
事務1先執行
UPDATE student SET name = '張三1' WHERE id = 1;
複製代碼
事務2再執行
UPDATE student SET name = '張三2' WHERE id = 1;
複製代碼
而後先提交事務2,再提交事務1。那最終的結果是「張三1」仍是「張三2」呢?站在SQL執行順序角度來講,結果應該爲「張三2」;站在事務提交順序來講,結果應爲「張三1」。
那最終實際結果呢?答案是:這種狀況永遠不會發生!
咱們能夠實際操做試試: 演示二:
步驟 | 查詢窗口1(事務1) | 查詢窗口2(事務2) |
---|---|---|
step1 | BEGIN > OK > 時間: 0s UPDATE student SET name = '張三1' WHERE id = 1 > Affected rows: 1 > 時間: 0.001s |
|
step2 | BEGIN > OK > 時間: 0s UPDATE student SET name = '張三2' WHERE id = 1 ======觀察結果======= 沒反應,查詢時間一直走 |
|
step3 | COMMIT; > OK > 時間: 0.004s; |
|
step4 | 再次打開窗口,會發現有如下結果 > Affected rows: 1 > 時間: 4.843s |
從演示二咱們能夠看出,step2並不能正常執行,須要等待step3提交。這就是MYSQL的鎖機制。
當事務1先執行UPDATE student SET name = '張三1' WHERE id = 1
時便得到數據行(id=1)的鎖。事務2想執行UPDATE student SET name = '張三2' WHERE id = 1
時,由於該數據行是被鎖住的,因此不能執行,須要等待事務1釋放鎖。事務1提交事務便會把鎖釋放掉。因此,不一樣事務之間修改同一數據不會出現修改順序和提交順序不一致的狀況。
按照鎖粒度,能夠把MYSQL鎖簡單歸爲:行鎖和表鎖。行鎖就是鎖定行數據,表鎖是鎖定整張表數據。上面所說示例,就是行鎖。通常來講,匹配條件是主鍵或索引列時,數據的update和delete會加行鎖。若是增刪改查時匹配的條件字段不帶有索引,innodb使用的將是表級鎖。因而可知,咱們數據庫表設計中合理的索引是很是關鍵的。
有鎖的地方,必然就會出現死鎖的問題。之後有機會再聊更多的鎖及死鎖問題