成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

MySQL中Lock Tables和Unlock Tables淺析

數據庫 MySQL
在MySQL中提供了鎖定表(lock tables)和解鎖表(unlock tables)的語法功能,ORACLE與SQL Server數據庫當中沒有這種語法。

[[384586]]

本文轉載自微信公眾號「DBA閑思雜想錄」,作者瀟湘隱者。轉載本文請聯系DBA閑思雜想錄公眾號。  

在MySQL中提供了鎖定表(lock tables)和解鎖表(unlock tables)的語法功能,ORACLE與SQL Server數據庫當中沒有這種語法。相信剛接觸MySQL的人,都想詳細、深入的了解一下這個功能.下面就盡量全面的解析、總結一下MySQL中lock tables與unlock tables的功能,如有不足或不正確的地方,歡迎指點一二。

鎖定表的語法:

  1. LOCK TABLES 
  2. tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} 
  3. [, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}] ... 

LOCAL修飾符表示可以允許在其他會話中對在當前會話中獲取了READ鎖的的表執行插入。但是當保持鎖時,若使用Server外的會話來操縱數據庫則不能使用READ LOCAL。另外,對于InnoDB表,READ LOCAL與READ相同。

  • The LOCAL modifier enables nonconflicting INSERT statements (concurrent inserts) by other sessions to execute while the lock is held. (See Section 8.11.3, “Concurrent Inserts”.) However, READ LOCAL cannot be used if you are going to manipulate the database using processes external to the server while you hold the lock. For InnoDB tables, READ LOCAL is the same as READ.

修飾符LOW_PRIORITY用于之前版本的MySQL,它會影響鎖定行為,但是從MySQL 5.6.5以后,這個修飾符已經被棄用。如果使用它則會產生警告。

  1. [LOW_PRIORITY] WRITE lock: 
  2.  
  3. The session that holds the lock can read and write the table
  4.  
  5. Only the session that holds the lock can access the tableNo other session can access it until the lock is released. 
  6.  
  7. Lock requests for the table by other sessions block while the WRITE lock is held. 
  8.  
  9. The LOW_PRIORITY modifier has no effect. In previous versions of MySQL, it affected locking behavior, but this is no longer trueAs of MySQL 5.6.5, it is deprecated and its use produces a warning. Use WRITE without LOW_PRIORITY instead

解鎖表的語法:

UNLOCK TABLES

LOCK TABLES為當前會話鎖定表。UNLOCK TABLES釋放被當前會話持有的任何鎖。官方文檔“13.3.5 LOCK TABLES and UNLOCK TABLES Syntax”已經對LOCK TALES與UNLOCK TABLES做了不少介紹,下面我們通過一些測試例子來深入的理解一下鎖表與解鎖表的相關知識點。我們先準備一下測試環境用的表和數據。

  1. mysql> create table test( id intname varchar(12)); 
  2. Query OK, 0 rows affected (0.07 sec) 
  3.  
  4. mysql> insert into test 
  5.     -> select 10001, 'kerry'   union all 
  6.     -> select 10002, 'richard' union all 
  7.     -> select 10003, 'jimmy' ; 
  8. Query OK, 3 rows affected (0.05 sec) 
  9. Records: 3  Duplicates: 0  Warnings: 0 
  10.  
  11. mysql>  

當前會話(會話ID為61)持有test表的READ鎖后,那么當前會話只可以讀該表,而不能往表中寫入數據,否則就會報“Table 'test' was locked with a READ lock and can't be updated”這樣的錯誤。

注意:如果使用LOCK TABLE WRITE鎖定表后,則可以更新數據。詳見后面介紹

  1. mysql> select connection_id(); 
  2. +-----------------+ 
  3. | connection_id() | 
  4. +-----------------+ 
  5. |              61 | 
  6. +-----------------+ 
  7. 1 row in set (0.00 sec) 
  8.  
  9. mysql> show open tables where in_use >=1; 
  10. Empty set (0.00 sec) 
  11.  
  12. mysql> lock tables test read
  13. Query OK, 0 rows affected (0.00 sec) 
  14.  
  15. mysql> show open tables where in_use >=1; 
  16. +----------+-------+--------+-------------+ 
  17. Database | Table | In_use | Name_locked | 
  18. +----------+-------+--------+-------------+ 
  19. | MyDB     | test  |      1 |           0 | 
  20. +----------+-------+--------+-------------+ 
  21. 1 row in set (0.01 sec) 
  22.  
  23. mysql> select * from test; 
  24. +-------+---------+ 
  25. | id    | name    | 
  26. +-------+---------+ 
  27. | 10001 | kerry   | 
  28. | 10002 | richard | 
  29. | 10003 | jimmy   | 
  30. +-------+---------+ 
  31. rows in set (0.00 sec) 
  32.  
  33. mysql> insert into test 
  34.     -> values(10004, 'ken'); 
  35. ERROR 1099 (HY000): Table 'test' was locked with a READ lock and can't be updated 
  36. mysql>  

 

其它會話也能查詢表test,但是不能修改表,如果執行DML操作的話,則會一直處于被阻塞狀態(Waiting for table metadata lock)。

另外,我們測試一下修飾符LOCAL的用途,如下所示:

  1. mysql> create table test2( id int , name varchar(12)) engine=MyISAM; 
  2. Query OK, 0 rows affected (0.05 sec) 
  3.  
  4. mysql> insert into test2 
  5.     -> select 1001, 'test'
  6. Query OK, 1 row affected (0.00 sec) 
  7. Records: 1  Duplicates: 0  Warnings: 0 
  8. mysql> select connection_id(); 
  9. +-----------------+ 
  10. | connection_id() | 
  11. +-----------------+ 
  12. |              66 | 
  13. +-----------------+ 
  14. 1 row in set (0.00 sec) 
  15.  
  16. mysql> lock tables test2 read local
  17. Query OK, 0 rows affected (0.00 sec) 
  18.  
  19. mysql> select * from test2; 
  20. +------+------+ 
  21. | id   | name | 
  22. +------+------+ 
  23. | 1001 | test | 
  24. +------+------+ 
  25. 1 row in set (0.00 sec) 
  26.  
  27. mysql> insert into test2 
  28.     -> select 1002, 'kkk'
  29. ERROR 1099 (HY000): Table 'test2' was locked with a READ lock and can't be updated 
  30. mysql>  

但是在其它會話當中,你可以看到表test2可以被插入。當然前提是表的存儲引擎不能是innodb引擎,否則使用修飾符LOCAL和不用LOCAL是一樣的,其它會話無法對表寫入。

  1. mysql> select connection_id(); 
  2. +-----------------+ 
  3. | connection_id() | 
  4. +-----------------+ 
  5. |              65 | 
  6. +-----------------+ 
  7. 1 row in set (0.00 sec) 
  8.  
  9. mysql> select * from test2; 
  10. +------+------+ 
  11. | id   | name | 
  12. +------+------+ 
  13. | 1001 | test | 
  14. +------+------+ 
  15. 1 row in set (0.00 sec) 
  16.  
  17. mysql> insert into test2 
  18.     -> select 1002, 'kkk'
  19. Query OK, 1 row affected (0.00 sec) 
  20. Records: 1  Duplicates: 0  Warnings: 0 

那么其他會話是否也能讀此表呢? 其它會話能否也能鎖定該表(LOCK TABLES READ LOCAL)?其它會話是否也能鎖定寫(LOCK TABLE WRITE)呢?。關于這些疑問,其它會話也能讀此表,其它表也能鎖定該表(LOCK TABLES READ LOCAL),但是不能LOCK TABLE WRITE。

對于MyISAM表,現在用的比較少,我們還是用InnoDB類型的表來實驗一下,在其中一個會話使用lock table鎖定表test,

  1. mysql> select connection_id(); 
  2. +-----------------+ 
  3. | connection_id() | 
  4. +-----------------+ 
  5. |              61 | 
  6. +-----------------+ 
  7. 1 row in set (0.00 sec) 
  8.  
  9. mysql> lock table test read
  10. Query OK, 0 rows affected (0.00 sec) 
  11.  
  12. mysql> show open tables where in_use >=1; 
  13. +----------+-------+--------+-------------+ 
  14. Database | Table | In_use | Name_locked | 
  15. +----------+-------+--------+-------------+ 
  16. | MyDB     | test  |      1 |           0 | 

然后在會話62中進行下面測試:

  1. mysql> select connection_id(); 
  2. +-----------------+ 
  3. | connection_id() | 
  4. +-----------------+ 
  5. |              62 | 
  6. +-----------------+ 
  7. 1 row in set (0.01 sec) 
  8.  
  9. mysql> select * from test; 
  10. +-------+---------+ 
  11. | id    | name    | 
  12. +-------+---------+ 
  13. | 10001 | kerry   | 
  14. | 10002 | richard | 
  15. | 10003 | jimmy   | 
  16. +-------+---------+ 
  17. rows in set (0.00 sec) 
  18.  
  19. mysql> lock tables test read
  20. Query OK, 0 rows affected (0.00 sec) 
  21.  
  22. mysql> show open tables where in_use >=1; 
  23. +----------+-------+--------+-------------+ 
  24. Database | Table | In_use | Name_locked | 
  25. +----------+-------+--------+-------------+ 
  26. | MyDB     | test  |      2 |           0 | 
  27. +----------+-------+--------+-------------+ 
  28. 1 row in set (0.00 sec) 
  29.  
  30. mysql> unlock tables; 
  31. Query OK, 0 rows affected (0.00 sec) 
  32.  
  33. mysql> show open tables where in_use >=1; 
  34. +----------+-------+--------+-------------+ 
  35. Database | Table | In_use | Name_locked | 
  36. +----------+-------+--------+-------------+ 
  37. | MyDB     | test  |      1 |           0 | 
  38. +----------+-------+--------+-------------+ 
  39. 1 row in set (0.00 sec) 
  40.  
  41. mysql> lock tables test write; 

 

如上測試所示,如果一個會話在一個表上獲得一個READ鎖后,所有其他會話只能從表中讀。不能往表中寫,其它會話也可在該表上獲取一個READ鎖,此時你會在show open tables里面看到in_use的值增加。其實LOCK TABLES READ是一個表鎖,而且是共享鎖。但是當一個會話獲取一個表上的READ鎖后,其它會話就不能獲取該表的WRITE鎖了,此時就會被阻塞,直到持有READ鎖的會話釋放READ鎖。

 

該會話(會話61)中則可以繼續獲取WRITE鎖。當該會話獲取WRITE鎖后,其它會話則無法獲取READ鎖了

  1. mysql> lock table test write; 
  2. Query OK, 0 rows affected (0.00 sec) 

另外需要注意的是,當前會話如果鎖定了其中一個表,那么是無法查詢其它表的。否則會報“ERROR 1100 (HY000): Table 'worklog' was not locked with LOCK TABLES”錯誤。

 

那么我們再來看看WRITE鎖吧。測試前,先在上面兩個會話中執行 unlock tables命令。然后獲得表TEST上的一個WRITE鎖,如下所示,當前會話可以讀寫表TEST

  1. mysql> unlock tables; 
  2. Query OK, 0 rows affected (0.00 sec) 
  3.  
  4. mysql> select connection_id(); 
  5. +-----------------+ 
  6. | connection_id() | 
  7. +-----------------+ 
  8. |              61 | 
  9. +-----------------+ 
  10. 1 row in set (0.00 sec) 
  11.  
  12. mysql> show open tables where in_use >=1; 
  13. Empty set (0.00 sec) 
  14.  
  15. mysql> lock tables test write; 
  16. Query OK, 0 rows affected (0.00 sec) 
  17.  
  18. mysql> select * from test; 
  19. +-------+---------+ 
  20. | id    | name    | 
  21. +-------+---------+ 
  22. | 10001 | kerry   | 
  23. | 10002 | richard | 
  24. | 10003 | jimmy   | 
  25. +-------+---------+ 
  26. rows in set (0.00 sec) 
  27.  
  28. mysql> update test set name='ken' where id=10003; 
  29. Query OK, 1 row affected (0.01 sec) 
  30. Rows matched: 1  Changed: 1  Warnings: 0 
  31.  
  32. mysql>  

其它會話無法讀寫表TEST,都會被阻塞,當然也無法獲取表TEST的READ鎖或WRITE鎖。也就是說當一個會話獲得一個表上的一個WRITE鎖后,那么只有持鎖的會話才能READ或WRITE表,其他會話都會被阻止。

  1. mysql> unlock tables; 
  2. Query OK, 0 rows affected (0.00 sec) 
  3.  
  4. mysql>  
  5. mysql>  
  6. mysql> show open tables where in_use >=1; 
  7. +----------+-------+--------+-------------+ 
  8. Database | Table | In_use | Name_locked | 
  9. +----------+-------+--------+-------------+ 
  10. | MyDB     | test  |      1 |           0 | 
  11. +----------+-------+--------+-------------+ 
  12. 1 row in set (0.00 sec) 
  13.  
  14. mysql> select * from test; 

  1. mysql> select connection_id(); 
  2. +-----------------+ 
  3. | connection_id() | 
  4. +-----------------+ 
  5. |              63 | 
  6. +-----------------+ 
  7. 1 row in set (0.00 sec) 
  8.  
  9. mysql> show processlist; 
  10. +----+------+-----------+------+---------+------+---------------------------------+--------------------+ 
  11. | Id | User | Host      | db   | Command | Time | State                           | Info               | 
  12. +----+------+-----------+------+---------+------+---------------------------------+--------------------+ 
  13. | 61 | root | localhost | MyDB | Sleep   |   86 |                                 | NULL               | 
  14. | 62 | root | localhost | MyDB | Query   |   40 | Waiting for table metadata lock | select * from test | 
  15. | 63 | root | localhost | MyDB | Query   |    0 | init                            | show processlist   | 
  16. | 64 | root | localhost | MyDB | Sleep   | 2551 |                                 | NULL               | 
  17. +----+------+-----------+------+---------+------+---------------------------------+--------------------+ 
  18. rows in set (0.00 sec) 

UNLOCK TABLES釋放被當前會話持有的任何鎖,但是當會話發出另外一個LOCK TABLES時,或當服務器的連接被關閉時,當前會話鎖定的所有表會隱式被解鎖。下面我們也可以測試看看

  1. mysql> lock tables test read
  2. Query OK, 0 rows affected (0.00 sec) 
  3.  
  4. mysql> show open tables where in_use >=1; 
  5. +----------+-------+--------+-------------+ 
  6. Database | Table | In_use | Name_locked | 
  7. +----------+-------+--------+-------------+ 
  8. | MyDB     | test  |      1 |           0 | 
  9. +----------+-------+--------+-------------+ 
  10. 1 row in set (0.00 sec) 
  11.  
  12. mysql> lock tables worklog read
  13. Query OK, 0 rows affected (0.00 sec) 
  14.  
  15. mysql> show open tables where in_use >=1; 
  16. +----------+---------+--------+-------------+ 
  17. Database | Table   | In_use | Name_locked | 
  18. +----------+---------+--------+-------------+ 
  19. | MyDB     | worklog |      1 |           0 | 
  20. +----------+---------+--------+-------------+ 
  21. 1 row in set (0.00 sec) 
  22.  
  23. mysql>  

 

那么我們如何在當前會話鎖定多個表呢?如下所示:

  1. mysql> show open tables where in_use >=1; 
  2. Empty set (0.00 sec) 
  3.  
  4. mysql> lock tables test read, worklog read
  5. Query OK, 0 rows affected (0.00 sec) 
  6.  
  7. mysql> show open tables where in_use >=1; 
  8. +----------+---------+--------+-------------+ 
  9. Database | Table   | In_use | Name_locked | 
  10. +----------+---------+--------+-------------+ 
  11. | MyDB     | worklog |      1 |           0 | 
  12. | MyDB     | test    |      1 |           0 | 
  13. +----------+---------+--------+-------------+ 
  14. rows in set (0.00 sec) 
  15.  
  16. mysql>  

另外,還有一些細節問題,LOCK TABLES是否可以為視圖、觸發器、臨時表加鎖呢?

  1. mysql> create table test2( id int, sex bit); 
  2. Query OK, 0 rows affected (0.06 sec) 
  3.  
  4. mysql> insert into test2 
  5.     -> select 10001, 1 union all 
  6.     -> select 10002, 0 union all 
  7.     -> select 10003, 1; 
  8. Query OK, 3 rows affected (0.02 sec) 
  9. Records: 3  Duplicates: 0  Warnings: 0 
  10. mysql> create view v_test 
  11.     -> as 
  12.     -> select t1.id, t1.name, t2.sex 
  13.     -> from test t1 left join test2 t2 on t1.id =t2.id; 
  14. Query OK, 0 rows affected (0.01 sec) 
  15. mysql> lock tables v_test read
  16. Query OK, 0 rows affected (0.00 sec) 
  17.  
  18. mysql> show open tables where in_use >=1; 
  19. +----------+-------+--------+-------------+ 
  20. Database | Table | In_use | Name_locked | 
  21. +----------+-------+--------+-------------+ 
  22. | MyDB     | test2 |      1 |           0 | 
  23. | MyDB     | test  |      1 |           0 | 
  24. +----------+-------+--------+-------------+ 
  25. rows in set (0.00 sec) 
  26.  
  27. mysql>  

如上測試所示,對于VIEW加鎖,LOCK TABLES語句會為VIEW中使用的所有基表加鎖。對觸發器使用LOCK TABLE,那么就會鎖定觸發器中所包含的全部表(any tables used in triggers are also locked implicitly)

  1. mysql> unlock tables; 
  2. Query OK, 0 rows affected (0.00 sec) 
  3.  
  4. mysql> create temporary table tmp like test; 
  5. Query OK, 0 rows affected (0.04 sec) 
  6.  
  7. mysql> show open tables where in_use >=1; 
  8. Empty set (0.00 sec) 
  9.  
  10. mysql> select database(); 
  11. +------------+ 
  12. database() | 
  13. +------------+ 
  14. | MyDB       | 
  15. +------------+ 
  16. 1 row in set (0.00 sec) 
  17.  
  18. mysql> select * from tmp; 
  19. Empty set (0.00 sec) 
  20.  
  21. mysql> insert into tmp 
  22.     -> select 1001, 'kerry' ; 
  23. Query OK, 1 row affected (0.01 sec) 
  24. Records: 1  Duplicates: 0  Warnings: 0 
  25.  
  26. mysql>  

LOCK TABLES 與 UNLOCK TABLES只能為自己獲取鎖和釋放鎖,不能為其他會話獲取鎖,也不能釋放由其他會話保持的鎖。一個對象獲取鎖,需具備該對象上的SELECT權限和LOCK TABLES權限。LOCK TABLES語句為當前會話顯式的獲取表鎖。最后,關于LOCK TABLES與事務當中鎖有那些異同,可以參考官方文檔:

LOCK TABLES and UNLOCK TABLES interact with the use of transactions as follows:

 

  • LOCK TABLES is not transaction-safe and implicitly commits any active transaction before attempting to lock the tables.
  • ·UNLOCK TABLES implicitly commits any active transaction, but only if LOCK TABLES has been used to acquire table locks. For example, in the following set of statements,UNLOCK TABLES releases the global read lock but does not commit the transaction because no table locks are in effect:

 

責任編輯:武曉燕 來源: DBA閑思雜想錄
相關推薦

2021-01-28 23:26:55

MySQL

2009-06-16 10:36:00

Google Fusi應用實例

2022-05-26 21:05:23

MySQL腳本數據庫

2011-03-15 16:47:08

Tables_privcolumns_pri

2009-06-16 21:59:25

云計算

2009-06-16 09:41:36

Fusion Tabl云計算數據庫

2009-06-16 09:44:10

Fusion Tabl云計算數據庫Google

2020-09-23 10:03:21

谷歌Android工具

2010-05-24 10:45:52

子命令Svn lock

2024-06-12 14:03:31

MySQLInnoDB

2025-04-24 10:56:01

MySQLInnoDB數據庫鎖

2009-06-04 09:47:48

MySQL隱藏控件TMPDIR

2019-09-03 11:23:13

MySQL技術磁盤

2023-06-27 08:28:40

MySQLInnoDB

2009-12-24 17:26:00

ADO創建表

2009-10-29 09:48:12

DAO.NET Dat

2009-05-13 11:13:07

MySQL定位性能故障

2022-05-24 07:39:09

MySQL數據庫日志

2009-09-14 19:58:47

DataSet和Dat

2011-06-09 18:05:00

QT MySql
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 色天天综合 | 国产精品久久久久久久久久久久久 | 少妇一级淫片免费播放 | 亚洲一区二区在线视频 | 精品国产乱码久久久久久1区2区 | 精品一区二区久久久久久久网站 | 精品在线一区二区 | 国产欧美一区二区三区久久手机版 | 午夜精品一区二区三区在线观看 | 日韩欧美综合在线视频 | 国产高清av免费观看 | 99精品视频在线 | 精品欧美乱码久久久久久 | 91短视频网址 | 日韩欧美一区二区三区免费看 | 成人在线一区二区三区 | 免费一级网站 | 荷兰欧美一级毛片 | 亚洲a级| 国产精品久久久久久久久久久久 | 99亚洲精品 | 久久国品片| 亚洲精品视频网站在线观看 | 亚州精品天堂中文字幕 | 日本成人在线观看网站 | 久久久久久99 | 色花av| 久久精品手机视频 | 国产羞羞视频在线观看 | 红桃视频一区二区三区免费 | 国产精品欧美一区二区三区不卡 | 成人毛片视频在线播放 | 亚洲 自拍 另类 欧美 丝袜 | 欧美精品一区在线 | 欧美电影在线观看网站 | 精品久久久久久久久亚洲 | 国产精品1区| 久久久久91 | 国产综合久久久久久鬼色 | 成人国产精品久久 | 91精品国产一区二区三区 |