共計 3302 個字符,預計需要花費 9 分鐘才能閱讀完成。
這篇文章主要講解了“怎么理解 Innodb 一致性非鎖定讀”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著丸趣 TV 小編的思路慢慢深入,一起來研究和學習“怎么理解 Innodb 一致性非鎖定讀”吧!
一致性非鎖定讀指 InnoDB 通過多版本控制 (MVCC) 的方式在某個時間點通過查詢數據庫快照數據來讀取數據。
在 RR 事務隔離級別下,在一個事務中第一次 (select 讀) 數據的時候創建快照,快照是在第一次 select 之前所有提交的數據的最新版本的數據,在此事務結束之前,select 到的數據是一致的(快照)。
注意:Begin 和 start transaction 開啟事務的時候快照并沒有創建,而是第一次 select 讀數據時候創建。
如下:
Session A
Session B
Session A drop table t;
Session A create table t(x int primary key);
Session A insert into t values (1),(5);
Session A begin;
Session A select @@tx_isolation;
+—————–+
| @@tx_isolation |
+—————–+
| REPEATABLE-READ |
+—————–+
Session A select * from t where x=5 for update;
上面的 for update 進行的鎖定讀,此時并沒有創建 read view 注意:for update 和 lock in share mode 都是鎖定讀,此時并不會創建快照
Session B begin;
Session B select @@tx_isolation;
+—————–+
| @@tx_isolation |
+—————–+
| REPEATABLE-READ |
+—————–+
1 row in set (0.00 sec)
Session B insert into t select 3;
Session B commit;
Session A select * from t; # 此時才創建 read view 生成快照
+—+
| x |
+—+
| 1 |
| 3 |
| 5 |
+—+
你可能會發現 RR 隔離級別,不是應該看不到其他事務修改的數據嗎?這正是因為 begin 開啟一個事務,不是 begin 的時候創建 read view,而是第一次進行快照讀的時候才創建
在 innodb 的 READ COMMITTED 和 REPEATABLE READ 隔離級別下執行 select 操作,默認模式就是一致性讀。
一致性讀不會對訪問的表加任何鎖,因此,其他會話可以任意的修改對象數據而不會影響當前會話的一致性讀。
在 RR 隔離級別下,某個時間點開啟一個事務 T1 查詢表的數據,接著開啟另外一個新的事務 T2 對其 delete、update、insert 數據并且 commit 成功后,在 T1 中無法看到 T2 修改并且提交的結果。
注意:快照讀主要適用于在一個事務中的 select 語句。所以事務中的 DML 語句是可以看到其他 session 中的事務的更新的,即時 SELECT 并不能看到這些
例如,同時開啟事務 T1、T2、T3, 在 T1 中刪除或者修改表 t 的數據,在 T2 中 select 查詢的結果(快照讀)是之前的 t 的數據(T2 事務開啟時間點的前 t 的數據), 但 T3 對表 t 修改或者刪除可能會影響剛才 T1 提交的行。
下面的例子中:Session A 只有在 Session B 的 insert 操作 commit 完成,并且 Session A 自身事務 commit 之后才能看到 Session B 插入的數據
可以使用 READ COMMITTED 或 locking read(SELECT * FROM t LOCK IN SHARE MODE;)來查看表最新的數據。
一致性讀不適用于特定的 DDL 語句如 DROP TABLE、ALTER TABLE。
另外,對于 INSERT INTO … SELECT, UPDATE … (SELECT)和 CREATE TABLE … SELECT 操作,雖然后面的 select 未指定 FOR UPDATE 或 LOCK IN SHARE MODE,但此時的 select 和 READ COMMIT 隔離級別下的 SELECT 一樣, 讀取最新版本數據(使用的當前讀)。
如下:
Session A
Session B
ession A create table a (x int primary key,y int);
Query OK, 0 rows affected (0.17 sec)
# 開啟一個新事務
Session A begin;
Query OK, 0 rows affected (0.00 sec)
Session A select * from a;
Empty set (0.00 sec)
# 插入數據
Session A insert into a select 1,2;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
# 當前事務能看到 insert 的數據
Session A select * from a;
+—+——+
| x | y |
+—+——+
| 1 | 2 |
+—+——+
1 row in set (0.00 sec)# 暫時不 commit
# 在 A 提交之前,B 開啟事務 Session B begin;
Query OK, 0 rows affected (0.00 sec)
# 此時查詢表 a 的數據,一致性非鎖定讀,讀到的是事務開啟前已經提交的數據,因為 B 的事務開始的時候 A 事務還沒有提交,故 A 中 insert 的數據不會顯示
Session B select * from a;
Empty set (0.00 sec)
#session A 提交上面的事務 Session A commit;
Query OK, 0 rows affected (0.00 sec)
# 在 B 中 select 查詢,依舊進行的是快照讀,故看不到數據 Seesion B select * from a;
Empty set (0.00 sec)
Seesion B select * from aa;
Empty set (0.00 sec)
#INSERT INTO … SELECT * FROM A; 操作
Seesion B insert into aa select * from a;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
Seesion B select * from a;
Empty set (0.00 sec)
# 發現直接 select 表 a 還是查不到數據,而 aa 表能看到數據
Seesion B select * from aa;
+—+——+
| x | y |
+—+——+
| 1 | 2 |
+—+——+
1 row in set (0.00 sec)
# 使用 lock in share mode 或 for update 進行當前讀能看到表 a 的數據
Seesion B select * from a lock in share mode;
+—+——+
| x | y |
+—+——+
| 1 | 2 |
+—+——+
1 row in set (0.00 sec)
Seesion B select * from a;
Empty set (0.00 sec)
Seesion B select * from a for update;
+—+——+
| x | y |
+—+——+
| 1 | 2 |
+—+——+
1 row in set (0.00 sec)
當 innodb_locks_unsafe_for_binlog 選項為 1 時(關閉 GAP 鎖),在 READ UNCOMMITTED, READ COMMITTED, REPEATABLEREAD 隔離級別下,select 查詢表的數據,不會對數據進行鎖定,而都是一致性讀。
感謝各位的閱讀,以上就是“怎么理解 Innodb 一致性非鎖定讀”的內容了,經過本文的學習后,相信大家對怎么理解 Innodb 一致性非鎖定讀這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是丸趣 TV,丸趣 TV 小編將為大家推送更多相關知識點的文章,歡迎關注!