161223、mysql锁的两个例子
版本:mysql5.5.52
存储引擎:InnoDB
隔离级别:READ-COMMITTED
示例一:
事务1:左图 事务2:右图
1、
事务2中属于快照读,基于多版本的并发控制协议——MVCC,读取的是记录可见版本,不用加锁,事务1属于当前读,加排它锁,因此事务1虽然未提交,事务2依然可以执行。快照读是mysql InnoDB存储引擎下,隔离级别为READ COMMITTED和REPEATABLE READ时,select语句默认的读取模式。
2、
事务1属于当前读,加排它锁,事务2的读取操作也是需要排他锁的,因此读取被阻塞,导致超时,直到事务1提交后,事务2才能读取:
3、
事务1属于当前读,加排它锁,但由于隔离级别为READ-COMMITTED,不加gap锁,依然可以插入,如果将隔离级别换成REPEATABLE READ,第一次插入操作被阻塞,直到事务1提交时,插入操作才执行:
gap就是索引树中插入新记录的空隙,相应的gap lock就是加在gap上的锁,主要是为了防止幻读,只在REPEATABLE READ或以上的隔离级别下的特定操作才会取得gap lock。
4、
对于事务1开启后在事务2中插入的记录,由于没有加排它锁,可以直接删除:
开启前已存在的记录,在事务1中加了排它锁,需等待事务1提交才能在事务2中删除:
示例二:
有一个后台的定时任务,定时向第三方发出状态改变请求,同时改变本地数据表的状态,但这个状态是否改变成功是需要第三方确认的,确认的方式是第三方以http请求的形式返回一个处理结果标志(成功或者失败),如果请求没有响应,则重复请求多次,直到我方响应。伪代码如下:
步骤一
我方发送状态改变请求:
@Transaction
public void sendChange(int id){
HttpUtils.send(id,"change");
statusDao.update(id,"pendSuccess");
relatedPeopleDao.update(id,"pendFinishRequest");
}
步骤二
我方响应第三方返回的处理结果(方法被web层调用):
@Transaction
public void doResponse(int id, String resultStatus){
relatedPeopleDao.update(id,resultStatus);
statusDao.update(id,resultStatus);
}
这个程序大部分情况是可以正常运行的,因为第三方返回处理结果有一段更长的网络延时,但是否存在这种可能,在方法sendChange开始执行 relatedPeopleDao.update(id,"pendFinishRequest")
这段代码的时候, 第三方很快返回了处理结果,relatedPeopleDao.update(id,resultStatus)已经执行且持有related_people表相关记录的锁,同时等待status表的锁被释放,但是此时sendChange的一系列操作尚未提交数据库,status的相关记录表仍被事务1持有,两个事务同时持有对方的资源同时在等待对方释放相关的锁,这就产生了死锁现象。
解决方法之一是在执行doResponse操作之前先检查下related_people表相关记录的状态是否处于合适状态,状态检查是一个普通的select操作,数据库隔离级别为读已提交,因此,如果步骤一中事务未提交,则不会读取到其改变的状态,提交后才能读取到。
@Transaction
public void doResponse(int id, String resultStatus){
if(relatedPeopleDao.isPendFinishRequest(id)){
relatedPeopleDao.update(id,resultStatus);
statusDao.update(id,resultStatus);
}
}
161223、mysql锁的两个例子的更多相关文章
- MYSQL 锁机制 分析
MySQL的表级锁有两种模式:表共享读锁(Table Read Lock)和表独占写锁(Table WriteLock).MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执 ...
- mysql锁
锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所有数 ...
- 【MySQL】MySQL锁和隔离级别浅析一
<MySQL技术内幕InnoDB存储引擎>第一版中对于MySQL的InnoDB引擎锁进行了部分说明,第二版有部分内容更新. 与MySQL自身MyISAM.MSSQL及其他平台BD锁的对比: ...
- MySQL锁详解
一.概述 数据库锁定机制简单来说就是数据库为了保证数据的一致性而使各种共享资源在被并发访问访问变得有序所设计的一种规则.对于任何一种数据库来说都需要有相应的锁定机制,所以MySQL自然也不能例外.My ...
- MySQL锁与MVCC
--MySQL锁与MVCC --------------------2014/06/29 myisam表锁比较简单,这里主要讨论一下innodb的锁相关问题. innodb相比oracle锁机制简单许 ...
- MySQL锁总结
本文同时发表在https://github.com/zhangyachen/zhangyachen.github.io/issues/78 MySQL 锁基础 参考了何登成老师文章的结构MySQL 加 ...
- Mysql锁机制--索引失效导致行锁变表锁
Mysql 系列文章主页 =============== Tips:在阅读本文前,最好先阅读 这篇(Mysql锁机制--行锁)文章~ 在上篇文章中,我们看到InnoDB默认的行锁可以使得操作不同行时不 ...
- mysql锁机制详解
前言 大概几个月之前项目中用到事务,需要保证数据的强一致性,期间也用到了mysql的锁,但当时对mysql的锁机制只是管中窥豹,所以本文打算总结一下mysql的锁机制. 本文主要论述关于mysql锁机 ...
- Mysql锁(翻译)
内容主要是对mysql文档的翻译. 1. shared(s) 共享锁2. exclusive(x) 排它锁 innodb的s锁和x锁是行级锁.事务T1获得s锁,事务T2仍然可以获得s锁.事务T1获得x ...
随机推荐
- 规范和封装jdbc程序代码
JDBC 部分方法引用工具类 package it.cast.jdbc; import java.sql.Connection; import java.sql.DriverManager; impo ...
- PHP配置参数
PHP使用到两个比较重要的配置文件: php.ini:决定php语言运行的环境,支持扩展的模块 , 开发环境的配置.(路径一般位于/etc/php.ini 或 /usr/local/php/etc/p ...
- solr5.2 mysql 增量索引
前提:数据库里数据进行增删改操作时,相应的solr需要修改或者新建索引,之前从数据库中导入数据并创建索引的操作是全量创建,如果本身数据库数据量非常大,就需要增量创建索引 1./usr/local/sr ...
- Mysql 获取年级每个班前十学生的信息
select * from Table1 a where 10>(select count(*) from Table1 where ClsNo=a.ClsNo and Score>a.S ...
- sprint3总结
经过了半个学期以来的sprint冲刺,并且充分学习了android开发后对项目有了更加充分的认识理解,开发速度自然而然就上来了,没有了上一个学期的懵懂,虽然开发起来还是比较困难,但是胜在有同组组员帮忙 ...
- subString(), subStr(),splice(),split()的区别
1.slice(): Array和String对象都有 在Array中 slice(i,[j]) i为开始截取的索引值,负数代表从末尾算起的索引值,-1为倒数第一个元素 j为结束的索引值,缺省时则获 ...
- php识别中文编码并自动转换为UTF-8
原文地址:http://www.codefans.net/articles/1272.shtml php自动识别编码,若里面有中文的话,将其转换为UTF-8就最好了,因为中文在Gbk编辑情况情况下,有 ...
- bootstrap插件引用
若按照步骤报这种错误,从这几方面进行排错 1.引用css/js的顺序 2.是否以及引入相应的包 3.是否正确调用(此处需要注意有require.js的情况,要不把switch方法写入require里面 ...
- phpstudy的apache端口没有被占用,也有vc9,防火墙也没开,也开杀毒软件,就是无法启动apache
我电脑装了一个独立的apche和一个phpstudy的apache,我学习是教学视频是php5.2而phpstudy刚好支持. 但是我在选取phpstudy的php版本5.3n以上就无法启动apach ...
- jira任务批量操作示例
1. 获取jira任务编号 使用字段提取工具获取编号,如WQBNEWSDLDL-347,WQBNEWSDLDL-348: 字段提取正则表达式:(?<2>[\[[](?<1>[A ...