MySQL数据库锁介绍(二)

2014-11-24 16:41:22 · 作者: · 浏览: 1
--+------------+-------+---------------+-------+---------+-------+------+-------+ type: const ,key:uk_id,rows:

1 很明显是会使用行锁,锁定一条记录。
下面做个有趣的实验:两个事务,TX1加共享行锁, 查询age=17的记录, TX2往数据库里插入一条age=18的记录。
TX1:
mysql> set autocommit=0;

mysql> select * from test_index where age=17 lock in share mode;

+------+------+------+

| id   | name | age  |

+------+------+------+

|    4 | 张四 |   17 |

+------+------+------+

1 row in set (0.00 sec)



TX2:
mysql> set autocommit=0;

mysql> insert test_index values(8,'test',18);

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

结果是TX2获取锁超时,看来TX1锁定的并不止age=17的记录,不存在的间隙age=18,也被加锁了。
执行select * from information_schema.innodb_locks;可以看到加锁的具体信息
+--------------+-------------+-----------+-----------+---------------------+------------+------------+-----------+----------+--------------------+

| 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 |

+--------------+-------------+-----------+-----------+---------------------+------------+------------+-----------+----------+--------------------+

行锁S、X锁上做了一些精确的细分,在代码中称作Precise Mode。这些精确的模式, 使的锁的粒度更细小。可以减少冲突。
A.间隙锁(Gap Lock),只锁间隙。
B.记录锁(Record Lock) 只锁记录。
C.Next-Key Lock(代码中称为Ordinary Lock),同时锁住记录和间隙。
D.插入意图锁(Insert Intention Lock),插入时使用的锁。在代码中,插入意图锁,实际上是GAP锁上加了一个LOCK_INSERT_INTENTION的标记。
行锁兼容矩阵
G I R N
G + + + +
I + +
R + +
N + + –+ 代表兼容, -代表不兼容.
G代表Gap锁,I代表插入意图锁,R代表记录锁,N代表Next-Key锁.
S锁和S锁是完全兼容的,因此在判别兼容性时不需要对比精确模式。
精确模式的检测,用在S、X和X、X之间。
从这个矩阵可以看到几个特点:
A. INSERT操作之间不会有冲突。
B. GAP,Next-Key会阻止Insert。
C. GAP和Record,Next-Key不会冲突
D. Record和Record、Next-Key之间相互冲突。
E. 已有的Insert锁不阻止任何准备加的锁。
Gap lock:
间隙锁只会出现在辅助索引(index)上,唯一索引(unique)和主键索引是没有间隙锁。
间隙锁(无论是S还是X)只会阻塞insert操作。
间隙锁的目的是为了防止幻读(但是需要应用自己加锁,innodb默认不会加锁防止幻读)。
3.2 页面锁
3.3 表锁(Table Lock)
对整个表加锁,影响标准的所有记录。通常用在DDL语句中,如DELETE TABLE,ALTER TABLE等。
很明显,表锁影响整个表的数据,因此并发性不如行锁好。
在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 表锁—意向锁
为了方便检测表级锁和行级锁之间的冲突,就引入了意向锁。
A. 意向锁分为意向读锁(IS)和意向写锁(IX)。
B. 意向锁是表级锁,但是却表示事务正在读或写某一行记录,而不是整个表。 所以意向锁之间不会产生冲突,真正的冲突在加行锁时检查。
C. 在给一行记录加锁前,首先要给该表加意向锁。也就是要同时加表意向锁和行锁。
采用了意向锁后,上面的例子就变成了:
A. trx1 BEGIN
B. trx1 给 T1 加X锁,修改表结构。
C. trx2 BEGIN
D. trx2 给 T1 加IX锁(事务被阻塞,等待加锁成功)
E. trx2 给 T1 的一行记录加S或X锁.
表锁的兼容性矩阵
IS IX S X
IS + + +
IX + +
S + +
X –+ 代表兼容, -代表不兼容
意向锁之间不会冲突, 因为意向锁仅仅代表要对某行记录进行操作。在加行锁时,会