MySQL數據庫鎖介紹
1. 鎖的基本概念
2. 鎖的基本類型
2.1 共享鎖(Shared Lock,也叫S鎖)
2.2 排他鎖(Exclusive Lock,也叫X鎖)
產生排他鎖的sql: select * from ad_plan for update;
S X
時間\事務 |
Tx1: |
Tx2: |
T1 |
set autocommit=0; |
set autocommit=0; |
T2 |
select * from ad_plan lock in share mode; |
|
T3 |
|
update ad_plan set name='' ; blocking |
執行sql: select * from information_schema.innodb_locks; 可以查看鎖。
3. 鎖的粒度
就是通常我們所說的鎖級別。MySQL有三種鎖的級別:頁級、表級、行級。MySQL這3種鎖的特性可大致歸納如下:
表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖衝突的概率最高,併發度最低。
行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低,併發度也最高。
頁面鎖:開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度一般。
3.1 行鎖(Row Lock)
通常用在DML語句中,如INSERT, UPDATE, DELETE等。
InnoDB行鎖是通過給索引上的索引項加鎖來實現的,這一點MySQL與Oracle不同,後者是通過在數據塊中對相應數據行加鎖來實現的。InnoDB這種行鎖實現特點意味着:只有通過索引條件檢索數據,InnoDB才使用行級鎖,否則,InnoDB將使用表鎖!
INSERT INTO test_index values(1,'張一',15);
INSERT INTO test_index values(3,'張三',16);
INSERT INTO test_index values(4,'張四',17);
INSERT INTO test_index values(5,'張五',19);
INSERT INTO test_index values(7,'劉琦',19);
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | test_index | ALL | NULL | NULL | NULL | NULL | 5 | Using where |
+----+-------------+------------+------+---------------+------+---------+------+------+-------------+
ADD UNIQUE uk_id(id),
mysql> explain select * from test_index where id = 1;
+----+-------------+------------+-------+---------------+-------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+-------+---------+-------+------+-------+
| 1 | SIMPLE | test_index | const | uk_id | uk_id | 5 | const | 1 | NULL |
+----+-------------+------------+-------+---------------+-------+---------+-------+------+-------+
mysql> select * from test_index where age=17 lock in share mode;
+------+------+------+
| id | name | age |
+------+------+------+
| 4 | 張四 | 17 |
+------+------+------+
1 row in set (0.00 sec)
mysql> insert test_index values(8,'test',18);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
| lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data |
+--------------+-------------+-----------+-----------+---------------------+------------+------------+-----------+----------+--------------------+
| 45288:57:5:5 | 45288 | X,GAP | RECORD | `test`.`test_index` | idx_age | 57 | 5 | 5 | 19, 0x000000000208 |
| 45289:57:5:5 | 45289 | S,GAP | RECORD | `test`.`test_index` | idx_age | 57 | 5 | 5 | 19, 0x000000000208 |
+--------------+-------------+-----------+-----------+---------------------+------------+------------+-----------+----------+--------------------+
G | I | R | N | |||
G | + | + | + | + | ||
I | – | + | + | – | ||
R | + | + | – | – | ||
N | + | + | – | – |
間隙鎖只會出現在輔助索引(index)上,唯一索引(unique)和主鍵索引是沒有間隙鎖。
3.2 頁面鎖
3.3 表鎖(Table Lock)
在MySQL 數據庫中,使用表級鎖定的主要是MyISAM,Memory等一些非事務性存儲引擎。
A. trx1 BEGIN
B. trx1 給 T1 加X鎖,修改表結構。
C. trx2 BEGIN
D. trx2 給 T1 的一行記錄加S或X鎖(事務被阻塞,等待加鎖成功)
trx1要操作整個表,鎖住了整個表。那麼trx2就不能再對T1的單條記錄加X或S鎖,去讀取或修這條記錄。
3.3.1 表鎖—意向鎖
IS | IX | S | X | |
IS | + | + | + | – |
IX | + | + | – | – |
S | + | – | + | – |
X | – | – | – | – |