MySQL中的事務和鎖簡單測試
一直以來,對於MySQL中的事務和鎖的內容是淺嘗輒止,沒有花時間瞭解過,在一次看同事排查的故障中有個問題引起了我的興趣,雖然過去了很久,但是現在簡單總結一下還是有一些收穫。
首先我們初始化資料,事務的隔離級別還是MySQL預設的RR,儲存引擎為InnoDB
>create table test(id int,name varchar(30));
>insert into test values(1,'aa');
開啟一個會話,開啟事務。
會話1:
[test]>start transaction;
這個時候我們檢視show processlist的資訊是不會看到更為具體的SQL等的資訊。
我們在另外一個會話中檢視事務相關的一個表,Innodb_trx,其實它對應的儲存引擎是MEMORY
[information_schema]>select *from innodb_trx\G
然後在會話1執行一條語句。
select * from test where id=1 for update;
再次檢視事務表的資訊,我們對比前後兩次的結果變化,發現唯一的不同是trx_lock_structs的地方,由0變為了2
對於這個欄位的含義,可以參考官方文件的介紹。
https://dev.mysql.com/doc/refman/5.6/en/innodb-trx-table.html
對於欄位TRX_LOCK_STRUCTS的官方解釋如下:
The number of locks reserved by the transaction.
會話2:
這個時候在會話2中執行語句會發生阻塞,因為存在相應的鎖等待。
select * from test where id=1 for update;
等待一段時間,會話2就會提示超時。
[test]>select * from test where id=1 for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
這個地方和一個引數是有關聯的,innodb_lock_wait_timeout它會控制阻塞等待的時長。
[test]>show variables like '%innodb_lock_wait_timeout%';
| Variable_name | Value |
| innodb_lock_wait_timeout | 120 |
對於事務相關的資訊檢視,在MySQL中有三個比較經典的資料字典,innodb_lock_waits,innodb_trx,innodb_trx,三者可以結合起來,就能夠查到相對比較完整的阻塞資訊和事務的情況,官方提供的一個SQL如下:
我們簡稱為check_trx.sql,在這個場景中我們執行check_trx.sql會發現執行緒3573在等待,阻塞它的正是執行緒3574
這個時候有一個地方需要注意,那就是透過show engine innodb status得到的結果中,標紅的部分可以看出鎖是表級鎖。這個還是和表的結構有一定的關係。
我們可以換一個方式來測試完善,比如測試一下死鎖。
測試死鎖
首先給表test新增一條記錄
insert into test values(2,'bb');
為了杜絕表級鎖,對錶test 新增主鍵,如果採用下面的方式新增主鍵,竟然不可以,看來Oracle用慣了,很多思維方式要複製過來,SQL語法還是有不少地方需要注意。
[test]>alter table test modify id primary key;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server vline 1。。。
可以使用下面的方式來新增主鍵。
[test]>ALTER TABLE test ADD UNIQUE INDEX (id), ADD PRIMARY KEY (id);
Query OK, 2 rows affected (0.25 sec)
Records: 2 Duplicates: 0 Warnings: 0
接下來來複現一下死鎖的情況。
會話1:
開啟事務,更新id=1的那行資料。
start transaction;
[test]>select * from test where id=1 for update;
+----+------+
| id | name |
+----+------+
| 1 | aa |
+----+------+
1 row in set (0.00 sec)
這個時候檢視innodb_trx的資訊,只有1條記錄。
會話2:
開啟事務,更新id=2的那行資料。
start transaction;
select * from test where id=2 for update;
(root:localhost:Sat Oct 8 18:15:10 2016)[test]>select * from test where id=2 for update;
+----+------+
| id | name |
+----+------+
| 2 | bb |
+----+------+
1 row in set (0.00 sec)
這個時候兩者是不存在阻塞的情況,因為彼此都是影響獨立的行。
>source check_trx.sql
Empty set (0.00 sec)
檢視事務表,裡面就是2條記錄了。
會話1:
在會話1中修改id=2的資料行。
select * from test where id=2 for update;
檢視事務表,會有一條阻塞的資訊。
會話2:
在會話2中修改id=1的資料行,這個時候會發現存在死鎖,而MySQL會毫不猶豫的清理掉阻塞的那個會話。這個過程是自動完成的。
[test]>select * from test where id=1 for update;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
檢視阻塞的資訊,就會發現已經被清理掉了。
[(none)]>source check_trx.sql
Empty set (0.00 sec)
檢視事務表,會發現只有1條記錄了。
總體感覺MySQL的資料字典還是比較少,不過使用起來還是比較清晰。
首先我們初始化資料,事務的隔離級別還是MySQL預設的RR,儲存引擎為InnoDB
>create table test(id int,name varchar(30));
>insert into test values(1,'aa');
開啟一個會話,開啟事務。
會話1:
[test]>start transaction;
這個時候我們檢視show processlist的資訊是不會看到更為具體的SQL等的資訊。
我們在另外一個會話中檢視事務相關的一個表,Innodb_trx,其實它對應的儲存引擎是MEMORY
[information_schema]>select *from innodb_trx\G
然後在會話1執行一條語句。
select * from test where id=1 for update;
再次檢視事務表的資訊,我們對比前後兩次的結果變化,發現唯一的不同是trx_lock_structs的地方,由0變為了2
對於這個欄位的含義,可以參考官方文件的介紹。
https://dev.mysql.com/doc/refman/5.6/en/innodb-trx-table.html
對於欄位TRX_LOCK_STRUCTS的官方解釋如下:
The number of locks reserved by the transaction.
會話2:
這個時候在會話2中執行語句會發生阻塞,因為存在相應的鎖等待。
select * from test where id=1 for update;
等待一段時間,會話2就會提示超時。
[test]>select * from test where id=1 for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
這個地方和一個引數是有關聯的,innodb_lock_wait_timeout它會控制阻塞等待的時長。
[test]>show variables like '%innodb_lock_wait_timeout%';
| Variable_name | Value |
| innodb_lock_wait_timeout | 120 |
對於事務相關的資訊檢視,在MySQL中有三個比較經典的資料字典,innodb_lock_waits,innodb_trx,innodb_trx,三者可以結合起來,就能夠查到相對比較完整的阻塞資訊和事務的情況,官方提供的一個SQL如下:
我們簡稱為check_trx.sql,在這個場景中我們執行check_trx.sql會發現執行緒3573在等待,阻塞它的正是執行緒3574
這個時候有一個地方需要注意,那就是透過show engine innodb status得到的結果中,標紅的部分可以看出鎖是表級鎖。這個還是和表的結構有一定的關係。
我們可以換一個方式來測試完善,比如測試一下死鎖。
測試死鎖
首先給表test新增一條記錄
insert into test values(2,'bb');
為了杜絕表級鎖,對錶test 新增主鍵,如果採用下面的方式新增主鍵,竟然不可以,看來Oracle用慣了,很多思維方式要複製過來,SQL語法還是有不少地方需要注意。
[test]>alter table test modify id primary key;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server vline 1。。。
可以使用下面的方式來新增主鍵。
[test]>ALTER TABLE test ADD UNIQUE INDEX (id), ADD PRIMARY KEY (id);
Query OK, 2 rows affected (0.25 sec)
Records: 2 Duplicates: 0 Warnings: 0
接下來來複現一下死鎖的情況。
會話1:
開啟事務,更新id=1的那行資料。
start transaction;
[test]>select * from test where id=1 for update;
+----+------+
| id | name |
+----+------+
| 1 | aa |
+----+------+
1 row in set (0.00 sec)
這個時候檢視innodb_trx的資訊,只有1條記錄。
會話2:
開啟事務,更新id=2的那行資料。
start transaction;
select * from test where id=2 for update;
(root:localhost:Sat Oct 8 18:15:10 2016)[test]>select * from test where id=2 for update;
+----+------+
| id | name |
+----+------+
| 2 | bb |
+----+------+
1 row in set (0.00 sec)
這個時候兩者是不存在阻塞的情況,因為彼此都是影響獨立的行。
>source check_trx.sql
Empty set (0.00 sec)
檢視事務表,裡面就是2條記錄了。
會話1:
在會話1中修改id=2的資料行。
select * from test where id=2 for update;
檢視事務表,會有一條阻塞的資訊。
會話2:
在會話2中修改id=1的資料行,這個時候會發現存在死鎖,而MySQL會毫不猶豫的清理掉阻塞的那個會話。這個過程是自動完成的。
[test]>select * from test where id=1 for update;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
檢視阻塞的資訊,就會發現已經被清理掉了。
[(none)]>source check_trx.sql
Empty set (0.00 sec)
檢視事務表,會發現只有1條記錄了。
總體感覺MySQL的資料字典還是比較少,不過使用起來還是比較清晰。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-2125959/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL 事務和鎖MySql
- MySQL事務和鎖MySql
- MySQL中的事務原理和鎖機制MySql
- mysql事務和鎖InnoDBMySql
- mysql簡單效能測試MySql
- MySQL中的事務和MVCCMySqlMVC
- MySQL InnoDB中的事務隔離級別和鎖的關係MySql
- MySQL事務與鎖MySql
- mysql事務隔離級別和鎖MySql
- (16)mysql 中的表鎖定及事務控制MySql
- DBUNITS的單元測試事務回滾
- MySQL Profile在5.7的簡單測試MySql
- sqlite的事務和鎖SQLite
- Oracle的事務和鎖Oracle
- 簡單瞭解 MySQL 中相關的鎖MySql
- MySQL 筆記 - 事務&鎖MySql筆記
- mysql之鎖與事務MySql
- MySQL詳解--鎖,事務MySql
- 對線面試官:MySQL 事務、鎖和MVCC面試MySqlMVC
- 庫存-Mysql中的事務、鎖與儲存引擎MySql儲存引擎
- mysql 事務處理及表鎖定深入簡析MySql
- MySQL索引條件下推的簡單測試MySql索引
- MySql中的事務MySql
- MySQL實戰 | 06/07 簡單說說MySQL中的鎖MySql
- 測試MySQL鎖的問題MySql
- 面試中的老大難-mysql事務和鎖,一次性講清楚!面試MySql
- pl/sql中的forall簡單測試SQL
- MySQL入門--事務與鎖MySql
- mysql鎖與事務總結MySql
- 最簡單的微服務部署測試實踐微服務
- SQL Server中的事務與鎖SQLServer
- MySQL行級鎖測試MySql
- MySQL 中的事務理解MySql
- 簡單介紹MySQL開啟事務的兩種方式MySql
- MySQL 的索引和事務MySql索引
- mysql 事務,鎖,隔離機制MySql
- Mysql事務以及加鎖機制MySql
- Redis的事務、樂觀鎖和悲觀鎖Redis