MySQL高级知识(十四)——行锁
前言:前面学习了表锁的相关知识,本篇主要介绍行锁的相关知识。行锁偏向InnoDB存储引擎,开销大,加锁慢,会出现死锁,锁定粒度小,发生锁冲突的概率低,但并发度高。
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会话中更新后的值。(读己知所写:自己更改的数据自己知道,但是如果未提交,其他人是不知道的。)
#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_avg和Innodb_row_lock_waits。尤其是等待次数很高,而且每次等待时长不小时,就需要分析优化了。
6.优化建议
①尽可能让所有数据都通过索引来完成,避免无索引行升级为表锁。
②合理设计索引,尽量缩小锁的范围。
③尽可能使用较少的检索条件,避免间隙锁。
④尽量控制事务大小,减少锁定资源量和时间长度。
⑤尽可能降低事务隔离级别。
7.页锁
开销和加锁时间介于表锁和行锁之间,会出现死锁,锁定粒度介于表锁和行锁之间,并发度一般(了解即可)。
总结
①InnoDB存储引擎由于实现了行级锁定,虽然在锁定机制的实现方面所带来的性能损耗可能比表级锁定会更高一些(多个锁,一个锁),但是在整体并发处理能力方面要远远优于MyISAM的表级锁定。当系统处于高并发量的时候,InnoDB的整体性能和MyISAM相比就会有比较明显的优势了。
②InnoDB的行锁定同样尤其脆弱的一面(间隙锁危害),当使用不当时可能会让InnoDB的整体性能表现不仅不能比MyISAM高,甚至可能更差。
by Shawn Chen,2018.6.28日,下午。
相关内容
MySQL高级知识(十四)——行锁的更多相关文章
- MySQL高级知识(四)——Explain
前言:explain(执行计划),使用explain关键字可以模拟优化器执行sql查询语句,从而知道MySQL是如何处理sql语句.explain主要用于分析查询语句或表结构的性能瓶颈. 注:本系列随 ...
- MySQL高级知识系列目录
MySQL高级知识(一)——基础 MySQL高级知识(二)——Join查询 MySQL高级知识(三)——索引 MySQL高级知识(四)——Explain MySQL高级知识(五)——索引分析 MySQ ...
- MySQL高级知识(十三)——表锁
前言:锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算机资源(如CPU.RAM.I/O等)的争用外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是 ...
- MySQL高级知识(十六)——小表驱动大表
前言:本来小表驱动大表的知识应该在前面就讲解的,但是由于之前并没有学习数据批量插入,因此将其放在这里.在查询的优化中永远小表驱动大表. 1.为什么要小表驱动大表呢 类似循环嵌套 for(int i=5 ...
- MySQL高级知识(十五)——主从复制
前言:本章主要讲解MySQL主从复制的操作步骤.由于环境限制,主机使用Windows环境,从机使用用Linux环境.另外MySQL的版本最好一致,笔者采用的MySQL5.7.22版本,具体安装过程请查 ...
- MySQL高级知识(十二)——全局查询日志
前言:全局查询日志用于保存所有的sql执行记录,该功能主要用于测试环境,在生产环境中永远不要开启该功能. 1.如何开启 #1.通过my.cnf配置开启该功能. 注:对my.cnf文件配置后,需重启my ...
- MySQL高级知识(十)——批量插入数据脚本
前言:使用脚本进行大数据量的批量插入,对特定情况下测试数据集的建立非常有用. 0.准备 #1.创建tb_dept_bigdata(部门表). create table tb_dept_bigdata( ...
- MySQL高级知识(十一)——Show Profile
前言:Show Profile是mysql提供的可以用来分析当前会话中sql语句执行的资源消耗情况的工具,可用于sql调优的测量.默认情况下处于关闭状态,并保存最近15次的运行结果. 1.分析步骤 # ...
- MySQL高级知识(八)——ORDER BY优化
前言:在使用order by时,经常出现Using filesort,因此对于此类sql语句需尽力优化,使其尽量使用Using index. 0.准备 #1.创建test表. drop table i ...
随机推荐
- VS2015 项目中 添加windows服务
1. 在项目中添加winows服务 今天刚刚为自己的项目添加了windows服务,以服务的形式运行后台系统,为前端提供接口服务,下面说一下具体怎么为vs项目添加windows服务 2. 添加Windo ...
- netty-socketio 概述
netty-socketio 概述 netty-socketio是一个开源的Socket.io服务器端的一个java的实现,它基于Netty框架,可用于服务端推送消息给客户端. 说到服务端推送技术,一 ...
- Java java jdbc thin远程连接并操作Oracle数据库
JAVA jdbc thin远程连接并操作Oracle数据库 by:授客 QQ:1033553122 测试环境 数据库:linux 下Oracle_11g_R2 编码工具:Eclipse 编码平台:W ...
- JVM虚拟机深入理解+GC回收+类加载
旭日Follow_24 的CSDN 博客 ,全文地址请点击: https://blog.csdn.net/xuri24/article/details/81455449 一,前言 本文章是读了“深入理 ...
- 2018-10-04 [日常]用Python读取word文档中的表格并比较
最近想对某些word文档(docx)的表格内容作比较, 于是找了一下相关工具. 参考Automate the Boring Stuff with Python中的word部分, 试用了python-d ...
- openEntityForm如何给关于(regardingobjectid)类型查找字段赋值?
本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复264或者20170924可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong.me ...
- Eclipse For JavaSE安装、配置、测试
Eclipse For JavaSE安装.配置.测试(win7_64bit) 目录 1.概述 2.本文用到的工具 3.安装与配置 4.JavaSE开发测试 5.ADT安装与Android开发测试 6. ...
- Elasticsearch alias别名管理小结
Elasticsearch alias别名管理小结 By:授客 QQ:1033553122 建创测试数据 1 创建别名 2 移除别名 3 创建测试数据 4 批量操作 5 例1. 5 例2. 把多个索引 ...
- 腾讯云 Game-Tech 技术沙龙小游戏专场“空降”长沙
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯游戏云发表于云+社区专栏 小游戏作为今年快速成长的新生态,在开放进入市场之后持续成为行业热点,获得了游戏开发商的高度关注与参与.在 ...
- (后端)springboot 在idea中实现热部署(转)
自己用到了iIntelliJ IDEA 这个ide工具,但是和以前的工具写html,css,js直接刷新页面不同,这个需要去热部署,网上搜的解决方法: SpringBoot的web项目,在每一次修改了 ...