MySQL高级知识(十四)——行锁

前言:前面学习了表锁的相关知识,本篇主要介绍行锁的相关知识。行锁偏向InnoDB存储引擎,开销大,加锁慢,会出现死锁,锁定粒度小,发生锁冲突的几率低,但并发度高。html


0.准备

#1.建立相关测试表tb_innodb_lock,注意数据库引擎为InnoDB数据库

drop table if exists test_innodb_lock; CREATE TABLE test_innodb_lock ( a INT (11), b VARCHAR (20) ) ENGINE INNODB DEFAULT charset = utf8; insert into test_innodb_lock values (1,'a'); insert into test_innodb_lock values (2,'b'); insert into test_innodb_lock values (3,'c'); insert into test_innodb_lock values (4,'d'); insert into test_innodb_lock values (5,'e');

#2.建立索引。并发

create index idx_lock_a on test_innodb_lock(a); create index idx_lock_b on test_innodb_lock(b);

1.行锁定基本演示

#1.打开A、B另个会话,并关闭数据库的自动提交。高并发

set autocommit=0;

#2.在A会话中作更新操做。性能

从查询结果可知:在A会话中更新数据成功。学习

#3.在B会话中作查询操做。测试

分析:优化

B会话中并无读取到A会话中更新后的值。(读己知所写:本身更改的数据本身知道,可是若是未提交,其余人是不知道的。spa

#4.在A会话中执行commit命令,而后在B会话中再次查询。设计

#5.在A会话中作更新操做,而后在B会话中也作更新操做。

这时在A会话中commit操做,可看到B会话中发生了更新操做。

分析:

由于咱们操做的同一行数据,而因为InnoDB为行锁,在A会话未提交时,B会话只有阻塞等待。若是操做不一样行,则不会出现阻塞状况。

2.索引失效致使行锁升级为表锁

#1.在A会话中执行以下更新语句。

#2.在B会话中执行以下更新语句。

分析:

首先将表中的数据更新为b=1000,2000,3000,4000,5000。

在A会话中操做的第一行数据,可是where中使用了b=1000,发生了自动转换致使索引失效,从而使锁的级别从行锁升级为表锁,所以B会话中操做第五行数据出现阻塞的状况。

3.间隙锁的危害

#1.间隙锁定义:

当咱们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁,对于键值在条件范围内但不存在的记录,叫做“间隙(GAP)”。

InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁。(Next-Key锁)

#2.间隙锁危害:

由于在Query执行过程当中经过范围查找的话,会锁定整个范围内的全部索引键值即便这个索引不存在。间隙锁有一个比较致命的弱点,就是当锁定一个范围键值后,即便某些不存在的键值也会被无辜的锁定,而形成在锁定的时候没法插入锁定值范围内的任何数据。在某些场景下这个可能会对性能形成很大的危害。

#3.间隙锁演示。

要演示间隙锁,咱们须要对test_innodb_lock中的数据进行修改,修改后的数据以下:

注:a列的值并不连续。

①在A会话中执行以下语句。

②在B会话中执行以下语句。

只有在A会话commit后,B会话才能进行插入操做。

4.如何锁定某一行

利用for update

①在A会话中执行以下语句。

此时就锁定了a=7这一行。

②在B会话中对该行进行更新操做。

只有在A会话中进行了commit后,B会话的更新操做才能执行。

5.行锁分析

#1.使用以下命令。

show status like 'innodb_row_lock%';

各个状态量说明:

①Innodb_row_lock_current_waits:当前正在等待锁定的数量。

Innodb_row_lock_time:从系统启动到如今锁定的时长。

Innodb_row_lock_time_avg:每次等待锁所花平均时间。

④Innodb_row_lock_time_max:从系统启动到如今锁等待最长的一次所花的时间。

Innodb_row_lock_waits:系统启动后到如今总共等待锁的次数。

这个五个状态量中,比较重要的是:

Innodb_row_lock_time、Innodb_row_lock_time_avgInnodb_row_lock_waits。尤为是等待次数很高,并且每次等待时长不小时,就须要分析优化了。

6.优化建议

①尽量让全部数据都经过索引来完成,避免无索引行升级为表锁

②合理设计索引,尽可能缩小锁的范围。

③尽量使用较少的检索条件,避免间隙锁。

④尽可能控制事务大小,减小锁定资源量和时间长度。

⑤尽量下降事务隔离级别。

7.页锁

开销和加锁时间介于表锁和行锁之间,会出现死锁,锁定粒度介于表锁和行锁之间,并发度通常(了解便可)。

总结

①InnoDB存储引擎因为实现了行级锁定,虽然在锁定机制的实现方面所带来的性能损耗可能比表级锁定会更高一些(多个锁,一个锁),可是在总体并发处理能力方面要远远优于MyISAM的表级锁定。当系统处于高并发量的时候,InnoDB的总体性能和MyISAM相比就会有比较明显的优点了。

②InnoDB的行锁定一样尤为脆弱的一面(间隙锁危害),当使用不当时可能会让InnoDB的总体性能表现不只不能比MyISAM高,甚至可能更差。


by Shawn Chen,2018.6.28日,下午。


相关内容 

MySQL高级知识系列目录

相关文章
相关标签/搜索