详解MySQL(InnoDB)是如何处理死锁的
一、什么是死锁
官方定义如下:两个事务都持有对方需要的锁,并且在等待对方释放,并且双方都不会释放自己的锁。
这个就好比你有一个人质,对方有一个人质,你们俩去谈判说换人。你让对面放人,对面让你放人。
二、为什么会形成死锁
看到这里,也许你会有这样的疑问,事务和谈判不一样,为什么事务不能使用完锁之后立马释放呢?居然还要操作完了之后一直持有锁?这就涉及到 MySQL 的并发控制了。
MySQL的并发控制有两种方式,一个是 MVCC,一个是两阶段锁协议。那么为什么要并发控制呢?是因为多个用户同时操作 MySQL 的时候,为了提高并发性能并且要求如同多个用户的请求过来之后如同串行执行的一样(可串行化调度)。具体的并发控制这里不再展开。咱们继续深入讨论两阶段锁协议。
两阶段锁协议(2PL)
官方定义:
两阶段锁协议是指所有事务必须分两个阶段对数据加锁和解锁,在对任何数据进行读、写操作之前,事务首先要获得对该数据的封锁;在释放一个封锁之后,事务不再申请和获得任何其他封锁。
对应到 MySQL 上分为两个阶段:
- 扩展阶段(事务开始后,commit 之前):获取锁
- 收缩阶段(commit 之后):释放锁
就是说呢,只有遵循两段锁协议,才能实现 可串行化调度。
但是两阶段锁协议不要求事务必须一次将所有需要使用的数据加锁,并且在加锁阶段没有顺序要求,所以这种并发控制方式会形成死锁。
三、MySQL 如何处理死锁?
MySQL有两种死锁处理方式:
- 等待,直到超时(innodb_lock_wait_timeout=50s)。
- 发起死锁检测,主动回滚一条事务,让其他事务继续执行(innodb_deadlock_detect=on)。
由于性能原因,一般都是使用死锁检测来进行处理死锁。
死锁检测
死锁检测的原理是构建一个以事务为顶点、锁为边的有向图,判断有向图是否存在环,存在即有死锁。
回滚
检测到死锁之后,选择插入更新或者删除的行数最少的事务回滚,基于 INFORMATION_SCHEMA.INNODB_TRX 表中的 trx_weight 字段来判断。
四、如何避免发生死锁
收集死锁信息:
- 利用命令 SHOW ENGINE INNODB STATUS查看死锁原因。
- 调试阶段开启 innodb_print_all_deadlocks,收集所有死锁日志。
减少死锁:
- 使用事务,不使用 lock tables 。
- 保证没有长事务。
- 操作完之后立即提交事务,特别是在交互式命令行中。
- 如果在用 (SELECT ... FOR UPDATE or SELECT ... LOCK IN SHARE MODE),尝试降低隔离级别。
- 修改多个表或者多个行的时候,将修改的顺序保持一致。
- 创建索引,可以使创建的锁更少。
- 最好不要用 (SELECT ... FOR UPDATE or SELECT ... LOCK IN SHARE MODE)。
- 如果上述都无法解决问题,那么尝试使用 lock tables t1, t2, t3 锁多张表
以上所述是小编给大家介绍的MySQL(InnoDB)是如何处理死锁的详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!
相关推荐
-
mysql之innodb的锁分类介绍
一.innodb行锁分类 record lock:记录锁,也就是仅仅锁着单独的一行 gap lock:区间锁,仅仅锁住一个区间(注意这里的区间都是开区间,也就是不包括边界值. next-key lock:record lock+gap lock,所以next-key lock也就半开半闭区间,且是下界开,上界闭. www.jb51.net next-key 锁定范围:(负无穷大,最小第一记录],(记录之间],(最大记录,正无穷大) 二.语句锁定情况分析 SELECT ... FROM ... F
-
MySQL中InnoDB的间隙锁问题
在为一个客户排除死锁问题时我遇到了一个有趣的包括InnoDB间隙锁的情形.对于一个WHERE子句不匹配任何行的非插入的写操作中,我预期事务应该不会有锁,但我错了.让我们看一下这张表及示例UPDATE. mysql> SHOW CREATE TABLE preferences \G *************************** 1. row *************************** Table: preferences Create Table: CREATE TABLE
-
MySQL InnoDB之事务与锁详解
引题:为何引入事务? 1>.数据完整性 2>.数据安全性 3>.充分利用系统资源,提高系统并发处理的能力 1. 事务的特征 事务具有四个特性:原子性(Atomiocity).一致性(Consistency).隔离性(Isolation)和持久性(Durability),这四个特性简称ACID特性. 1.1原子性 事务是数据库的逻辑工作单位,事务中包括的所有操作要么都做,要么都不做. 1.2 一致性 事务执行的结果必须是使数据库从一个一致性的状态变到另外一个一致性状态. 1.3 隔离性 一
-
MySQL Innodb表导致死锁日志情况分析与归纳
案例描述在定时脚本运行过程中,发现当备份表格的sql语句与删除该表部分数据的sql语句同时运行时,mysql会检测出死锁,并打印出日志.两个sql语句如下:(1)insert into backup_table select * from source_table(2)DELETE FROM source_table WHERE Id>5 AND titleWeight<32768 AND joinTime<'$daysago_1week'teamUser表的表结构如下:PRIMARY
-
MySQL中Innodb的事务隔离级别和锁的关系的讲解教程
前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力.所以对于加锁的处理,可以说就是数据库对于事务处理的精髓所在.这里通过分析MySQL中InnoDB引擎的加锁机制,来抛砖引玉,让读者更好的理解,在事务处理中数据库到底做了什么. 一次封锁or两段锁? 因为有大量的并发访问,为了预防死锁,一般应用中推荐使用一次封锁法,就是在方法的开始阶段,已经预先知道会
-
MySQL InnoDB中的锁机制深入讲解
写在前面 数据库本质上是一种共享资源,因此在最大程度提供并发访问性能的同时,仍需要确保每个用户能以一致的方式读取和修改数据.锁机制(Locking)就是解决这类问题的最好武器. 首先新建表 test,其中 id 为主键,name 为辅助索引,address 为唯一索引. CREATE TABLE `test` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` int(11) NOT NULL, `address` int(11) NOT NULL, P
-
MySQL中InnoDB存储引擎的锁的基本使用教程
MyISAM和MEMORY采用表级锁(table-level locking) BDB采用页面锁(page-leve locking)或表级锁,默认为页面锁 InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁 各种锁特点 表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生冲突的概率最高,并发度最低 行级锁:开销大,加锁慢:会出现死锁:锁定粒度最小,发生锁冲突的概率最低,并发度也最高 页面锁:开销和加锁时间介于表锁和行锁之间:会出现死锁:锁定粒度介于表锁和行锁之
-
详解MySQL InnoDB的索引扩展
索引扩展,InnoDB通过将主键列附加到每个辅助索引中来自动扩展该索引.创建如下表结构: mysql> CREATE TABLE t1 ( -> i1 INT NOT NULL DEFAULT 0, -> i2 INT NOT NULL DEFAULT 0, -> d DATE DEFAULT NULL, -> PRIMARY KEY (i1, i2), -> INDEX k_d (d) -> ) ENGINE = InnoDB; Query OK, 0 rows
-
详解MySQL InnoDB存储引擎的内存管理
存储引擎之内存管理 在InnoDB存储引擎中,数据库中的缓冲池是通过LRU(Latest Recent Used,最近最少使用)算法来进行管理的,即最频繁使用的页在LRU列表的最前段,而最少使用的页在LRU列表的尾端,当缓冲池不能存放新读取到的页时,首先释放LRU列表尾端的页. 上面的图中,我使用8个数据页来表示队列,具体作用,先卖个关子.在InnoDB存储引擎中,缓冲池中页的默认大小是16KB,LRU列表中有一个midpoint的位置,新读取到的数据页并不是直接放入到LRU列表的首部,而是放入
-
详解MySql中InnoDB存储引擎中的各种锁
目录 什么是锁 InnoDB存储引擎中的锁 锁的算法 行锁的3种算法 幻像问题 锁的问题 脏读 不可重复读 丢失更新 死锁 什么是锁 现实生活中的锁是为了保护你的私有物品,在数据库中锁是为了解决资源争抢的问题,锁是数据库系统区别于文件系统的一个关键特性.锁机制用于管理对共享资源的并发访. 数据库系统使用锁是为了支持对共享资源进行并发访问,提供数据的完整性和一致性 InnoDB存储引擎区别于MyISAM的两个重要特征就是:InnoDB存储引擎支持事务和行级别的锁,MyISAM只支持表级别的锁 In
-
详解mysql 中的锁结构
Mysql 支持3中锁结构 表级锁,开销小,加锁快,不会出现死锁,锁定的粒度大,冲突概率高,并发度最低 行级锁,开销小,加锁慢,会出现死锁,锁定粒度小,冲突概率最低,并发度最高 页面锁,开销和加锁处于表锁和行锁之间,会出现死锁,锁粒度基于表和行之间,并发一般 InnoDB锁问题 InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION):二是采用了行级锁. 行级锁和表级锁本来就有许多不同之处,另外,事务的引入也带来了一些新问题. InnoDB的行锁模式及加锁方法 Inn
-
一条sql详解MYSQL的架构设计详情
目录 1 前言 2 应用层 2.1 连接线程处理 3 服务层 3.1 SQL 接口 3.2 SQL解析器 3.3 SQL优化器 3.4 执行器 3.5 查询缓存 4 存储引擎层 4.1 概述 4.2 缓冲池(buffer pool) 4.2.1 数据页.缓存页和脏页 4.2.2 元数据 4.2.3 free链表 4.2.4 flush链表 4.2.5 LRU链表 4.2.6 小结 4.3 undo log 4.4 redo log 5 总结 1 前言 对于一个服务端开发来说 MYSQL 可能是他
-
详解MySQL数据类型DECIMAL(N,M)中N和M分别表示的含义
同事问MySQL数据类型DECIMAL(N,M)中N和M分别表示什么含义,M不用说,显然是小数点后的小数位数,但这个N究竟是小数点之前的最大位数,还是加上小数部分后的最大位数?这个还真记不清了.于是乎,创建测试表验证了一番,结果如下: 测试表,seller_cost字段定义为decimal(14,2) CREATE TABLE `test_decimal` ( `id` int(11) NOT NULL, `seller_cost` decimal(14,2) DEFAULT NULL ) EN
-
详解mysql中的冗余和重复索引
mysql允许在相同列上创建多个索引,无论是有意还是无意,mysql需要单独维护重复的索引,并且优化器在优化查询的时候也需要逐个地进行考虑,这会影响性能. 重复索引是指的在相同的列上按照相同的顺序创建的相同类型的索引,应该避免这样创建重复索引,发现以后也应该立即删除.但,在相同的列上创建不同类型的索引来满足不同的查询需求是可以的. CREATE TABLE test( ID INT NOT NULL PRIMARY KEY, A INT NOT NULL, B INT NOT NULL, UNI
-
详解 Mysql 事务和Mysql 日志
事务特性 1.原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节. 2.一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 .比如A向B转账,不可能A扣了钱,B却没收到. 3.隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰.比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账. 4.持久性(Durability):事务完成后,事务对数据库的所有更新
-
详解MySQL 外键约束
官方文档: https://dev.mysql.com/doc/refman/5.7/en/create-table-foreign-keys.html 1.外键作用: MySQL通过外键约束来保证表与表之间的数据的完整性和准确性. 2.外键的使用条件 两个表必须是InnoDB表,MyISAM表暂时不支持外键(据说以后的版本有可能支持,但至少目前不支持) 外键列必须建立了索引,MySQL 4.1.2以后的版本在建立外键时会自动创建索引,但如果在较早的版本则需要显示建立: 外键关系的两个表的列必须
-
详解mysql DML语句的使用
前言: 在上篇文章中,主要为大家介绍的是DDL语句的用法,可能细心的同学已经发现了.本篇文章将主要聚焦于DML语句,为大家讲解表数据相关操作. 这里说明下DDL与DML语句的分类,可能有的同学还不太清楚. DDL(Data Definition Language):数据定义语言,用于创建.删除.修改.库或表结构,对数据库或表的结构操作.常见的有create,alter,drop等. DML(Data Manipulation Language):数据操纵语言,主要对表记录进行更新(增.删.改).
随机推荐
- 详解配置spring-boot-actuator时候遇到的一些小问题
- ruby实现的插入排序和冒泡排序算法
- jquery Form轻松实现文件上传
- SpringMVC 使用JSR-303进行校验 @Valid示例
- Oracle 11g下编译使用BBED的方法教程
- 解析利用wsdl.exe生成webservice代理类的详解
- JavaScript获取浏览器信息的方法
- 使用cropper.js裁剪头像的实例代码
- 全面解析Bootstrap手风琴效果
- JavaScript中的子窗口与父窗口的互相调用问题
- php使用百度ping服务代码实例
- Laravel 5.0 发布 新版本特性详解
- Android setButtonDrawable()的兼容问题解决办法
- 在Windows的Apache服务器上配置对PHP和CGI的支持
- ajax 数据库中随机读取5条数据动态在页面中刷新
- jsp中页面间传汉字参数转码的方法
- Jquery仿IGoogle实现可拖动窗口示例代码
- JavaScript 动态添加表格行 使用模板、标记
- Python的Django框架中的数据过滤功能
- JavaScript数组排序reverse()和sort()方法详解