lock mysql unlock_MySQL中的lock tables和unlock tables
MySQL允許客戶端會話顯式地獲取表鎖,以便與其他會話協作訪問表,或者防止其他會話在其需要獨占表時使用表。這個能力就是通過LOCK TABLES和UNLOCK TABLES實現的。
LOCK TABLES用于顯示的獲取表鎖,UNLOCK TABLES顯式釋放當前會話持有的任何表鎖。
MySQL 5.7版本中它們的完整語法是:
LOCK TABLES
tbl_name [[AS] alias] lock_type
[, tbl_name [[AS] alias] lock_type] …
lock_type: {
READ [LOCAL]
| [LOW_PRIORITY] WRITE
}
UNLOCK TABLES
LOCK TABLES可以為基表或視圖獲取表鎖。必須具有要鎖定的每個對象的“LOCK TABLES”權限和“SELECT”權限。
不同的鎖類型有不同的效果。
READ [LOCAL]鎖:
持有鎖的會話可以讀取表(但不能寫入表)。
多個會話可以同時獲取表的read鎖。
其它會話可以在不顯式獲取讀鎖的情況下讀取表。
加上LOCAL關鍵字,表示在持有鎖的同時允許其它會話執行非沖突插入語句(并發插入)。但是,如果要在持有鎖的同時使用外部進程操作數據庫,則不能使用READ LOCAL。對于InnoDB表,READ LOCAL與READ相同。
會話1登入,并修改提示符包含session1字樣,然后對emp表讀取,可以進行,然后用lock tables給emp表加read鎖定。
root@database-one 13:57: [(none)]> prompt \u@database-one \R:\m:\s [\d] session1>
PROMPT set to '\u@database-one \R:\m:\s [\d] session1>'
root@database-one 13:57:55 [(none)] session1>use gftest;
Database changed
root@database-one 13:58:31 [gftest] session1>select * from emp;
+--------+------+---------+------------+--------+
| ename | age | sal | hiredate | deptno |
+--------+------+---------+------------+--------+
| 郭軍 | 27 | 8400.00 | 2019-12-08 | 10 |
| 劉杰 | 30 | 9100.00 | 2018-04-09 | 10 |
| 王艷 | 24 | 6000.00 | 2020-01-05 | 20 |
| 馬麗 | 26 | 7200.00 | 2018-07-06 | 30 |
| 肖偉 | 29 | 8700.00 | 2017-05-28 | 30 |
+--------+------+---------+------------+--------+
5 rows in set (0.00 sec)
root@database-one 14:03:18 [gftest] session1>lock tables emp read;
Query OK, 0 rows affected (0.00 sec)
root@database-one 14:03:20 [gftest] session1>insert into emp values('陳實',31,9000,'2019-07-01',10);
ERROR 1099 (HY000): Table 'emp' was locked with a READ lock and can't be updated
可以看到,read鎖定時只能讀取,無法修改數據。
會話2登入,并修改提示符包含session2字樣,然后對emp表讀取。
root@database-one 14:04: [(none)]> prompt \u@database-one \R:\m:\s [\d] session2>
PROMPT set to '\u@database-one \R:\m:\s [\d] session2>'
root@database-one 14:05:04 [(none)] session2>use gftest;
Database changed
root@database-one 14:05:10 [gftest] session2>select * from emp;
+--------+------+---------+------------+--------+
| ename | age | sal | hiredate | deptno |
+--------+------+---------+------------+--------+
| 郭軍 | 27 | 8400.00 | 2019-12-08 | 10 |
| 劉杰 | 30 | 9100.00 | 2018-04-09 | 10 |
| 王艷 | 24 | 6000.00 | 2020-01-05 | 20 |
| 馬麗 | 26 | 7200.00 | 2018-07-06 | 30 |
| 肖偉 | 29 | 8700.00 | 2017-05-28 | 30 |
+--------+------+---------+------------+--------+
5 rows in set (0.00 sec)
root@database-one 14:05:20 [gftest] session2>lock tables emp read;
Query OK, 0 rows affected (0.00 sec)
可以看到,繼續能夠讀取,同時也能加read鎖。
[LOW_PRIORITY] WRITE鎖:
持有鎖的會話可以讀寫表。
只有持有鎖的會話才能訪問表。在釋放鎖之前,其他會話無法訪問它。
當保持WRITE鎖時,其他會話對表的鎖請求被阻塞。
LOW_PRIORITY關鍵字已經作廢。在以前的MySQL版本中,它影響鎖定行為,但現在已經不是這樣了。現在不推薦使用它,它的使用會產生一個警告。
會話1登入,并修改提示符包含session1字樣,然后對emp表寫入,可以進行,然后用lock tables給emp表加write鎖定。
root@database-one 21:32: [(none)]> prompt \u@database-one \R:\m:\s [\d] session1>
PROMPT set to '\u@database-one \R:\m:\s [\d] session1>'
root@database-one 21:32:57 [(none)] session1>use gftest;
Database changed
root@database-one 21:33:07 [gftest] session1>select * from emp;
+--------+------+---------+------------+--------+
| ename | age | sal | hiredate | deptno |
+--------+------+---------+------------+--------+
| 郭軍 | 27 | 8400.00 | 2019-12-08 | 10 |
| 劉杰 | 30 | 9100.00 | 2018-04-09 | 10 |
| 王艷 | 24 | 6000.00 | 2020-01-05 | 20 |
| 馬麗 | 26 | 7200.00 | 2018-07-06 | 30 |
| 肖偉 | 29 | 8700.00 | 2017-05-28 | 30 |
+--------+------+---------+------------+--------+
5 rows in set (0.00 sec)
root@database-one 21:33:20 [gftest] session1>insert into emp values('陳實',31,9000,'2019-07-01',10);
Query OK, 1 row affected (0.01 sec)
root@database-one 21:34:50 [gftest] session1>lock tables emp write;
Query OK, 0 rows affected (0.00 sec)
會話2登入,并修改提示符包含session2字樣,然后對emp表進行查詢。
root@database-one 21:38: [(none)]> prompt \u@database-one \R:\m:\s [\d] session2>
PROMPT set to '\u@database-one \R:\m:\s [\d] session2>'
root@database-one 21:38:13 [(none)] session2>use gftest;
Database changed
root@database-one 21:38:21 [gftest] session2>select * from emp;
可以看到,表被以write方式鎖定后,其它會話讀取都無法進行,更不用提寫入了。
UNLOCK TABLES顯式釋放當前會話持有的任何表鎖。我們去session1中釋放鎖。
root@database-one 21:36:20 [gftest] session1>
root@database-one 21:45:29 [gftest] session1>unlock tables;
Query OK, 0 rows affected (0.00 sec)
root@database-one 21:45:43 [gftest] session1>
root@database-one 21:38:21 [gftest] session2>select * from emp;
+--------+------+---------+------------+--------+
| ename | age | sal | hiredate | deptno |
+--------+------+---------+------------+--------+
| 郭軍 | 27 | 8400.00 | 2019-12-08 | 10 |
| 劉杰 | 30 | 9100.00 | 2018-04-09 | 10 |
| 王艷 | 24 | 6000.00 | 2020-01-05 | 20 |
| 馬麗 | 26 | 7200.00 | 2018-07-06 | 30 |
| 肖偉 | 29 | 8700.00 | 2017-05-28 | 30 |
| 陳實 | 31 | 9000.00 | 2019-07-01 | 10 |
+--------+------+---------+------------+--------+
6 rows in set (7 min 11.08 sec)
root@database-one 21:45:43 [gftest] session2>
可以看到,session1在21:45:29后釋放了鎖,session2在21:45:43前就立即讀取出了emp表的數據,整整排隊等待了7分多鐘,這些時間都被計入了這個SELECT的執行時間。
如果語句通過表名鎖定,則不能使用別名。
root@database-one 21:57:54 [gftest] session1>lock table emp read;
Query OK, 0 rows affected (0.01 sec)
root@database-one 21:58:02 [gftest] session1>select * from emp as e;
ERROR 1100 (HY000): Table 'e' was not locked with LOCK TABLES
root@database-one 21:58:06 [gftest] session1>select * from emp;
+--------+------+---------+------------+--------+
| ename | age | sal | hiredate | deptno |
+--------+------+---------+------------+--------+
| 郭軍 | 27 | 8400.00 | 2019-12-08 | 10 |
| 劉杰 | 30 | 9100.00 | 2018-04-09 | 10 |
| 王艷 | 24 | 6000.00 | 2020-01-05 | 20 |
| 馬麗 | 26 | 7200.00 | 2018-07-06 | 30 |
| 肖偉 | 29 | 8700.00 | 2017-05-28 | 30 |
| 陳實 | 31 | 9000.00 | 2019-07-01 | 10 |
+--------+------+---------+------------+--------+
6 rows in set (0.00 sec)
如果使用別名鎖定,則必須在語句中使用別名引用該表:
root@database-one 22:00:54 [gftest] session1>unlock tables;
Query OK, 0 rows affected (0.00 sec)
root@database-one 22:01:23 [gftest] session1>
root@database-one 22:01:25 [gftest] session1>lock table emp as e read;
Query OK, 0 rows affected (0.00 sec)
root@database-one 22:01:30 [gftest] session1>select * from emp;
ERROR 1100 (HY000): Table 'emp' was not locked with LOCK TABLES
root@database-one 22:01:34 [gftest] session1>select * from emp as e;
+--------+------+---------+------------+--------+
| ename | age | sal | hiredate | deptno |
+--------+------+---------+------------+--------+
| 郭軍 | 27 | 8400.00 | 2019-12-08 | 10 |
| 劉杰 | 30 | 9100.00 | 2018-04-09 | 10 |
| 王艷 | 24 | 6000.00 | 2020-01-05 | 20 |
| 馬麗 | 26 | 7200.00 | 2018-07-06 | 30 |
| 肖偉 | 29 | 8700.00 | 2017-05-28 | 30 |
| 陳實 | 31 | 9000.00 | 2019-07-01 | 10 |
+--------+------+---------+------------+--------+
6 rows in set (0.00 sec)
會話可以顯式釋放其鎖,或者在某些條件下隱式釋放鎖。
會話可以使用UNLOCK TABLES顯式釋放其鎖。
如果會話已經持有鎖,還發出LOCK TABLES語句來獲取新鎖,那么在授予新鎖之前,現有鎖將被隱式釋放。
如果會話開始事務(例如,使用START transaction),則隱式執行UNLOCK TABLES,從而釋放現有鎖。
無論客戶端會話的連接正常結束或異常終止,服務器均隱式釋放該會話持有的所有表鎖(事務性和非事務性)。
LOCK TABLES和UNLOCK TABLES與事務的交互如下:
LOCK TABLES不是事務安全的,在嘗試鎖定表之前隱式提交任何活動事務。
UNLOCK TABLES隱式提交任何活動事務,前提是LOCK TABLES已用于獲取表鎖。例如,在以下語句集中,UNLOCK TABLES釋放全局讀取鎖,但不提交事務,因為沒有有效的表鎖:
FLUSH TABLES WITH READ LOCK;
START TRANSACTION;
SELECT ... ;
UNLOCK TABLES;
開始事務(例如,使用START transaction)隱式提交任何當前事務并釋放現有表鎖。
對事務表(如InnoDB TABLES)使用LOCK TABLES和UNLOCK TABLES的正確方法是,以SET autocommit=0(不是START transaction)后跟LOCK TABLES開始事務,并且在顯式提交事務之前不調用UNLOCK TABLES。例如,如果需要寫入表t1并讀取表t2,可以執行以下操作:
SET autocommit=0;
LOCK TABLES t1 WRITE, t2 READ, ...;
... do something with tables t1 and t2 here ...
COMMIT;
UNLOCK TABLES;
ROLLBACK不會釋放表鎖。
綜上所述,當我們需要獨占式的對表做一些運維操作時,使用LOCK TABLES和UNLOCK TABLES是個很不錯的選擇。
總結
以上是生活随笔為你收集整理的lock mysql unlock_MySQL中的lock tables和unlock tables的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux vim复制粘贴命令(linu
- 下一篇: DDOS攻击软件手机版下载(ddos攻击