MySQL中InnoDB存储引擎的锁的基本使用教程


Posted in MySQL onMay 26, 2021

MyISAM和MEMORY采用表级锁(table-level locking)

BDB采用页面锁(page-leve locking)或表级锁,默认为页面锁

InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁

各种锁特点

表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生冲突的概率最高,并发度最低

行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高

页面锁:开销和加锁时间介于表锁和行锁之间;会出现死锁;锁定粒度介于表锁和行锁之间,并发度一般

InnoDB存储引擎的锁

InnoDB存储引擎实现了如下两种锁

1、共享锁(S Lock),允许事务读一行数据

2、排他锁(X Lock),允许事务更新或者删除一行数据

共享锁和排他锁的兼容如下图所示
MySQL中InnoDB存储引擎的锁的基本使用教程

 

一致性的非锁定读

一致性的非锁定行读(consistent nonlocking read)是指InnoDB存储引擎通过行多版本控制(multi versioning)的方式来读取当前执行时间数据库中行的数据。如果读取的行正在执行DELETE、UPDATE操作,这是读取操作不会因此而会等待行上锁的释放,相反,InnoDB会去读取行的一个快照数据。

之所以称其为非锁定读,因为不需要等待访问的行上X锁的释放。快照数据是指改行之前版本的数据,该实现是通过undo段来实现的。但是在不同事务隔离级别下,读取的方式不同,并不是每个事务隔离级别下读取的都是一致性读。

例如:

对于read committed的事务隔离级别,他总是读取行的最新版本,如果行被锁定了,则读取该行版本的最新一个快照。

对于repeatable read(innoDB存储引擎的默认隔离级别),总是读取事务开始时的行数据。

 非锁定读的机制大大提高了数据读取的并发性,在Innodb存储引擎默认设置下,这是默认的读取方式,但是在某些情况下,可以对读进行加锁,比如:

1、显式对读进行加锁,如使用 select --- for update ;select --- lock in share mode

2、在外键的插入和更新上,因为在外键的插入和更新上,对于数据的隔离性要求较高,在插入前需要扫描父表中的记录是否存在,所以,在外键的插入删除上,InnoDB会使用加S锁的方式来实现。

InnoDB锁的算法

1、Record Lock:单个行记录上的锁

2、Gap Lock:间隙锁,锁定一个范围,但不包含记录本身

3、Next-key Lock:Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身

Record Lock总是会去锁住索引记录,如果InnoDB存储引擎表建立的时候没有设置任何一个索引,这时InnodB存储引擎会使用隐式的主键来进行锁定,在Repeatable Read隔离级别下,Next-key Lock 算法是默认的行记录锁定算法。

锁带来的问题

1、丢失更新

如何避免丢失更新:让事务变成串行操作,而不是并发的操作,即对每个事务开始---对读取记录加排他锁。

2、脏读

脏读即一个事务可以读到另一个事务中未提交的数据,这违反了数据库的隔离性。

脏读发生的条件是需要事务的隔离级别为Read uncommitted。

3、不可重复读

不可重复读与脏读的区别是:脏读是读到未提交的数据,而不可重复读读到的是已经提交的数据。

一般来说,不可重复读是可以接受的,在InnoDB存储引擎中,通过使用Next-Key Lock算法来避免不可重复读的问题。

值得注意的是,默认情况下InnoDB存储引擎不会回滚超时引发的错误异常。

死锁的相关问题

1、死锁发生的条件

互斥条件:一个资源每次只能被一个进程使用;请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放;不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺;循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

2、死锁检测(根据网上的经验)

Innodb检测死锁有两种情况,一种是满足循环等待条件,还有另一种策略:锁结构超过mysql配置中设置的最大数量或锁的遍历深度超过设置的最大深度时,innodb也会判断为死锁(这是提高性能方面的考虑,避免事务一次占用太多的资源)。

因循环等待条件而产生的死锁只有可能是四种形式:两张表两行记录交叉申请互斥锁、同一张表则存在主键索引锁冲突、主键索引锁与非聚簇索引锁冲突、锁升级导致的锁等待队列阻塞。

3、死锁避免(根据网上的经验)

1.如果使用insert…select语句备份表格且数据量较大,在单独的时间点操作,避免与其他sql语句争夺资源,或使用select into outfile加上load data infile代替 insert…select,这样不仅快,而且不会要求锁定
2. 一个锁定记录集的事务,其操作结果集应尽量简短,以免一次占用太多资源,与其他事务处理的记录冲突。
3.更新或者删除表格数据,sql语句的where条件都是主键或都是索引,避免两种情况交叉,造成死锁。对于where子句较复杂的情况,将其单独通过sql得到后,再在更新语句中使用。
4. sql语句的嵌套表格不要太多,能拆分就拆分,避免占有资源同时等待资源,导致与其他事务冲突。
5. 对定点运行脚本的情况,避免在同一时间点运行多个对同一表进行读写的脚本,特别注意加锁且操作数据量比较大的语句。
6.应用程序中增加对死锁的判断,如果事务意外结束,重新运行该事务,减少对功能的影响。

4、死锁解决

1)先执行show processlist找到死锁线程号.然后Kill pid

2)Show innodb status检查引擎状态 ,可以看到哪些语句产生死锁

3)查看information_schema架构下的innodb_locks、innodb_trx、innodb_lock_waits等表

 
PS:Mysql死锁

既然谈到死锁,那附带地就专门说一下。
何为死锁?
 
死锁是对资源的分配和使用不当而造成的。是两个进程争夺某一资源而出现相互等待的现象。具体的来讲,出现死锁需要满足四个必要条件:
(1)互斥条件:每一个资源都只能被一个进程使用
(2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
(3)不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
很显然,出现死锁需要两个或者两个以上的进程,换句话说,死锁发生在并发的程序中。在Mysql中,由于目前只有InnoDB引擎使用事务(InnoDB支持锁),便有了InnoDB和死锁的旷世基情。
死锁的检测
 
1、通过使用Show innodb status检查引擎状态 ,可以看到哪些语句产生deadlock
2、MySQL提供了一个information_schema,通过查看innodb_locks、innodb_trx、innodb_lock_waits这几个表检测死锁。
因循环等待条件而产生的死锁只有可能是四种形式:两张表两行记录交叉申请互斥锁、同一张表则存在主键索引锁冲突、主键索引锁与非聚簇索引锁冲突、锁升级导致的锁等待队列阻塞。

死锁避免

1.如果使用insert…select语句备份表格且数据量较大,在单独的时间点操作,避免与其他sql语句争夺资源,或使用select into outfile加上load data infile代替 insert…select,这样不仅快,而且不会要求锁定
2. 一个锁定记录集的事务,其操作结果集应尽量简短,以免一次占用太多资源,与其他事务处理的记录冲突。
3.更新或者删除表格数据,sql语句的where条件都是主键或都是索引,避免两种情况交叉,造成死锁。对于where子句较复杂的情况,将其单独通过sql得到后,再在更新语句中使用。
4. sql语句的嵌套表格不要太多,能拆分就拆分,避免占有资源同时等待资源,导致与其他事务冲突。
5. 对定点运行脚本的情况,避免在同一时间点运行多个对同一表进行读写的脚本,特别注意加锁且操作数据量比较大的语句。
6.应用程序中增加对死锁的判断,如果事务意外结束,重新运行该事务,减少对功能的影响。

MySQL 相关文章推荐
将图片保存到mysql数据库并展示在前端页面的实现代码
May 02 MySQL
MySql存储过程之逻辑判断和条件控制
May 26 MySQL
mysql5.7使用binlog 恢复数据的方法
Jun 03 MySQL
解决mysql的int型主键自增问题
Jul 15 MySQL
MySQL定时备份数据库(全库备份)的实现
Sep 25 MySQL
MySQL分库分表详情
Sep 25 MySQL
mysql5.6主从搭建以及不同步问题详解
Dec 04 MySQL
JMeter对MySQL数据库进行压力测试的实现步骤
Jan 22 MySQL
MySQL数据库如何给表设置约束详解
Mar 13 MySQL
MySQL如何快速创建800w条测试数据表
Mar 17 MySQL
MySQL数据库如何使用Shell进行连接
Apr 12 MySQL
详解MySQL的内连接和外连接
May 08 MySQL
MySql存储过程之逻辑判断和条件控制
MYSQL主从数据库同步备份配置的方法
May 26 #MySQL
MYSQL数据库使用UTF-8中文编码乱码的解决办法
May 26 #MySQL
Mysql效率优化定位较低sql的两种方式
May 26 #MySQL
Mysql中 unique列插入重复值该怎么解决呢
May 26 #MySQL
MySQL查看表和清空表的常用命令总结
May 26 #MySQL
MySQL中distinct与group by之间的性能进行比较
You might like
Optimizer与Debugger兼容性问题的解决方法
2008/12/01 PHP
php中使用接口实现工厂设计模式的代码
2012/06/17 PHP
PHP zip扩展Linux下安装过程分享
2014/05/05 PHP
2017年最新PHP经典面试题目汇总(上篇)
2017/03/17 PHP
详解php curl带有csrf-token验证模拟提交方法
2018/04/18 PHP
PHP使用gearman进行异步的邮件或短信发送操作详解
2020/02/27 PHP
jquery实现的省市区三级联动
2015/04/02 Javascript
localResizeIMG先压缩后使用ajax无刷新上传(移动端)
2015/08/11 Javascript
Node.js连接postgreSQL并进行数据操作
2016/12/18 Javascript
基于Vue实现可以拖拽的树形表格实例详解
2018/10/18 Javascript
Vue中使用JsonView来展示Json树的实例代码
2020/11/16 Javascript
python使用cookie库操保存cookie详解
2014/03/03 Python
Python编程语言的35个与众不同之处(语言特征和使用技巧)
2014/07/07 Python
python中黄金分割法实现方法
2015/05/06 Python
python 限制函数调用次数的实例讲解
2018/04/21 Python
Python3.5装饰器原理及应用实例详解
2019/04/30 Python
Pycharm+django2.2+python3.6+MySQL实现简单的考试报名系统
2019/09/05 Python
Python爬虫图片懒加载技术 selenium和PhantomJS解析
2019/09/18 Python
Python rabbitMQ如何实现生产消费者模式
2020/08/24 Python
Pytest测试框架基本使用方法详解
2020/11/25 Python
next在python中返回迭代器的实例方法
2020/12/15 Python
pycharm进入时每次都是insert模式的解决方式
2021/02/05 Python
使用css3绘制出各种几何图形
2016/08/17 HTML / CSS
表达自我的市场:Society6
2018/08/01 全球购物
函数指针的定义是什么
2016/08/14 面试题
大学生应聘自荐信
2013/10/11 职场文书
优秀中学生事迹材料
2014/01/31 职场文书
入党思想汇报怎么写
2014/04/03 职场文书
建筑公司员工自我鉴定
2014/04/08 职场文书
市场营销战略计划书
2014/05/06 职场文书
体育节口号
2014/06/19 职场文书
教师职业道德事迹材料
2014/08/18 职场文书
离婚协议书怎么写的
2014/12/14 职场文书
打架检讨书
2015/01/27 职场文书
2015年机械设备管理工作总结
2015/05/04 职场文书
2016读书月活动心得体会
2016/01/14 职场文书