mysql 查看锁_【MySQL入门】之MySQL数据库的锁机制(二)

793ea24711aa22e7800dfab8da23f258.gif

  上篇文章主要聊了全局锁和表锁,并详细分析MDL锁的作用以及可能带来的问题。今天我们主要来聊一聊Innodb存储引擎的行锁。MySQL的行锁是在引擎层由引擎自己实现的,并不是所有的引擎都支持行锁,MyISAM 引擎就不支持行锁。行锁,顾名思义就是针对数据表中的行记录的锁。比如事物A更新了一行,而事物B也要更新同一行,就必须等待事物A的操作完成后才能进行。下面我们就介绍下行锁的种类,针对不同的锁进行操作演示。

一. 行锁的种类

1.单个记录的锁(record lock),在RC隔离级别下只有record  lock记录锁模式。

2.间隙锁(Gap lock)

3.记录锁和间隙锁的组合(next-key lock), 加锁的基本单位就是next-key lock。

以下所有演示都是在RR隔离级别下进行的。

演示表t,主键是id,索引是age字段。

b00d55d891f79bd06f4d7f307610d134.png

表数据如下:

50e3eda811e38ce9528d3ec3ab3a55cf.png

二. 单个记录的锁

Session A

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> update t set name='lili' where age=24;Query OK, 0 rows affected (0.00 sec)Rows matched: 1  Changed: 1  Warnings: 0

Session B

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> update t set name='jim' where age=24;

试验结果:Session B

b26c4c27efed4edc9233ffda3eb9342d.png 

通过这个演示可以看出两个事务针对同一行数据修改时,后执行的事务会出现锁等待现象,超过innodb_lock_wait_timeout(默认50s)定义的时间后会超时。

我们再做个试验,把age上面的索引删除,看看会出现什么样的试验效果。

alter table t drop index idx_age;//删除索引

session  A

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> update t set name='lili' where age=24;Query OK, 1 row affected (0.00 sec)Rows matched: 1  Changed: 1  Warnings: 0

Session B

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> update t set name='jim' where age=16;

试验结果:Session B

404a2de3a9ac7309da99240b0cf33b2e.png

通过试验看出,虽然更新了不同的行,也出现了锁超时的情况。两个实现不同的地方就是试验2把索引删除了,试验结果就截然不同了。通过这个试验,我们可以看出,就是Innodb的行锁是加在索引上的。

三. 间隙锁(Gap lock)

在RR隔离级别下,为了避免幻读现象,引入了Gap lock。它锁定行记录的范围,不包含记录的本身,不允许在此范围内插入任何数据。

表数据如下:

Session A

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> select * from t where age<24 lock in share mode;+----+------+------+| id | name | age  |+----+------+------+|  4 | jack |   16 |+----+------+------+1 row in set (0.01 sec)

Session B

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> insert into t(name,age) value('angel',20);

实验结果:Session B

66b4edb61a6c369c3404397e95b24dda.png

可以看出innodb在age<24的范围内加了间隙锁,导致session B插入age=20的记录时阻塞。

注意:间隙锁只在RR隔离级别下生效,RC隔离级别下是允许出现幻读现象的。

四. Next-key Lock

Next-keys Lock是记录锁和间隙锁的组合,Innodb扫描索引记录时,会先对索引记录加上记录锁(Record Lock),再对索引记录之间的间隙加上间隙锁(Gap Lock)。

Innodb加锁的基本单位是next-key lock,是前开后闭区间。

Session A

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> select * from t where age >=16 and age<24 for update;+----+------+------+| id | name | age  |+----+------+------+|  4 | jack |   16 |+----+------+------+1 row in set (0.00 sec)

session B

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql>insert into t(name,age) value('lucy',17);

Session C

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql>update t set name='lucy' where age=24;

试验结果:

Session B

5283141ac69d2b452e8ae58915d7f136.png

Session C

b537d4079ab3ce9d439f8ec8c22f2de6.png

Innodb引擎加锁有个原则:查找过程中访问到的对象才会加锁。

在上面的例子中当用到age=16的时候,会在索引age上 (5,16]范围内加next-key锁,同时在(16,24]范围内加next-key锁,这样session A加锁的范围就是(5,24]。从结果上看也符合这个预期。

五. 锁监控

关于MySQL锁的监控,我们一般可以通过show processlist和show engine innodb status来查看和监控数据库的锁信息,其实还有一些更简单的方法,MySQL把事务和锁的信息记录在了information_schema库中,设计到的三张表分别是INNODB_TRX、INNODB_LOCKS和INNODB_LOCK_WAITS。

我们模拟了一个锁等待的场景,以下是从这三张表收集的信息

64acc83c19ed0463b250e144dd0e8de9.png0bc41edb88812e4fa89befd8e6d1d50e.png

b2a71c8c729e18ebecf0962cbec0edbb.png

通过以下命令可以查看锁源头:

SELECT r.trx_wait_started AS wait_started,TIMEDIFF(NOW(),r.trx_wait_started) AS wait_age,rl.lock_table AS locked_table,rl.lock_index AS locked_index,rl.lock_type AS locked_type,r.trx_id AS waiting_trx_id,r.trx_mysql_thread_id AS waiting_pid,sys.format_statement(r.trx_query) AS waiting_query,rl.lock_id AS waiting_lock_id,rl.lock_mode AS waiting_lock_mode,b.trx_id AS blocking_trx_id,b.trx_mysql_thread_id AS blocking_pid,sys.format_statement(b.trx_query) AS blocking_query,bl.lock_id AS blocking_lock_id,bl.lock_mode AS blocking_lock_mode FROM information_schema.INNODB_LOCK_WAITS w INNER JOIN information_schema.INNODB_TRX b ON b.trx_id = w.blocking_trx_id INNER JOIN information_schema.INNODB_TRX r ON r.trx_id = w.requesting_trx_id INNER JOIN information_schema.INNODB_LOCKS bl ON bl.lock_id = w.blocking_lock_id INNER JOIN information_schema.INNODB_LOCKS rl ON rl.lock_id = w.requested_lock_id ORDER BY r.trx_wait_started\G
b6102420e799be11ac44c5f64def6ee0.gif

     【MySQL入门】之MySQL数据库的锁机制(一)

18ebcee7dd44ce4c97a76dff6aa093e2.png 0f1e3c03f6eb8d84486ccf96d8eb70e5.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值