mysql:如何解决数据修改冲突(事务+行级锁的实际运用)
摘要:最近做一个接诊需求遇到一个问题,假设一个订单咨询超过3次就不能再接诊,但如果两个医生同时对该订单进行咨询,查数据库的时候查到的接诊次数都是2次,那两个医生都能接诊,所谓接诊可以理解为更新了接诊次数,此时就出现了问题(接诊了4次)。
其实这个问题看似很明朗,但想要完全解决需要理解事务和锁的概念,以前总对事务的隔离级别有点云里雾里,现在可以通过这个案例可以理清楚。
事务
操作数据库最小的工作单位,简单讲就是将多条dml(增删改)语句联合完成。要么同时成功,要么同时失败。看到这里你可能会发现光加事务解决不了上述问题,而且加了事务之后,多条事务之间的相互关系就涉及到事务的隔离级别,所以接着往下看。
事务隔离级别
READ UNCOMMITTED(读未提交,脏读)
事务中的修改,即使没有提交,对其他会话也是可见的。可以读取未提交的数据——脏读。脏读会导致很多问题,一般不适用这个隔离级别.。
-- ------------------------- read-uncommitted实例 ------------------------------
-- 设置全局系统隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
-- Session A
START TRANSACTION;
SELECT * FROM USER;
UPDATE USER SET NAME="READ UNCOMMITTED";
-- commit; -- Session B
SELECT * FROM USER; //SessionB Console 可以看到Session A未提交的事物处理,在另一个Session 中也看到了,这就是所谓的脏读
id name
2 READ UNCOMMITTED
34 READ UNCOMMITTED
READ COMMITTED(读已提交,不可重复读)
一般数据库都默认使用这个隔离级别(MySQL 不是), 这个隔离级别保证了一个事务如果没有完全成功(commit 执行完),事务中的操作对其他会话是不可见的。
-- ------------------------- read-cmmitted实例 ------------------------------
-- 设置全局系统隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- Session A
START TRANSACTION;
SELECT * FROM USER;
UPDATE USER SET NAME="READ COMMITTED";
-- COMMIT; -- Session B
SELECT * FROM USER; //Console OUTPUT:
id name
2 READ UNCOMMITTED
34 READ UNCOMMITTED ---------------------------------------------------
-- 当 Session A执行了commit,Session B得到如下结果:
id name
2 READ COMMITTED
34 READ COMMITTED
REPEATABLE READ (可重复读)
一个事务中多次执行统一读 SQL,返回结果一样。这个隔离级别解决了脏读的问题,幻读问题。这里指的是 innodb 的 rr 级别,innodb 中使用 next-key 锁对"当前读"进行加锁,锁住行以及可能产生幻读的插入位置,阻止新的数据插入产生幻行。

会话T1事务中执行一次查询,然后会话T2新插入一行记录,这行记录恰好可以满足T1所使用的查询的条件。然后T1又使用相同 的查询再次对表进行检索,但是此时却看到了事务T2刚才插入的新行。这个新行就称为“幻像”,因为对T1来说这一行就像突然 出现的一样。innoDB 的 RR 级别无法做到完全避免幻读。
SERIALIZABLE (可串行化)
最强的隔离级别,通过给事务中每次读取的行加锁,写加写锁,保证不产生幻读问题,但是会导致大量超时以及锁争用问题。
mysql默认的隔离级别是可重复读,看到这里大家应该明白,即使隔离级别是可重复读,但因为select操作时并未加锁,导致都会查到符合条件的数据,所以这里要引入一个锁的概念:行级锁。
行级锁
共享锁(S) 共享锁也称为读锁,读锁允许多个连接可以同一时刻并发的读取同一资源,互不干扰;
排他锁(X) 排他锁也称为写锁,一个写锁会阻塞其他的写锁或读锁,保证同一时刻只有一个连接可以写入数据,同时防止其他用户对这个数据的读写。
总结(解决方案)
其实上文分析了那么多,最后的解决方案很简单。就是在原来的read和update合起来加事务,原来的select语句加排他锁,即在select语句后面加for update。假如有事务A,B,加入排他锁之后,假设事务A先获得锁,事务B必须等到事务A commit之后才能开始select,所以读到的是最新修改的数据。至于为什么不加共享锁,除了可能造成脏写之后,在这种情况下还可能造成死锁。假如两个事务 A 、 B 都读取同一行记录,那么在这一行就加上了共享锁,但是 A 和B 事务中都需要修改这一行,那么都要等待对方释放共享锁才能进行,结果造成了死锁。
mysql:如何解决数据修改冲突(事务+行级锁的实际运用)的更多相关文章
- Mysql在InnoDB引擎下索引失效行级锁变表锁案例
先做好准备,创建InnoDB引擎数据表,并添加了相应的索引 DROP TABLE IF EXISTS `innodb_lock`; CREATE TABLE `innodb_lock` ( `a` ) ...
- Mysql的行级锁
我们首先需要知道的一个大前提是:mysql的锁是由具体的存储引擎实现的.所以像Mysql的默认引擎MyISAM和第三方插件引擎 InnoDB的锁实现机制是有区别的. Mysql有三种级别的锁定:表级锁 ...
- SQL Server 中 ROWLOCK 行级锁
一.ROWLOCK的使用 1.ROWLOCK行级锁确保,在用户取得被更新的行,到该行进行更新,这段时间内不被其它用户所修改.因而行级锁即可保证数据的一致性,又能提高数据操作的并发性. 2.ROWLOC ...
- Mysql事务及行级锁的理解
在最近的开发中,碰到一个需求签到,每个用户每天只能签到一次,那么怎么去判断某个用户当天是否签到呢?因为当属表设计的时候,每个用户签到一次,即向表中插入一条记录,根据记录的数量和时间来判断用户当天是否签 ...
- Mysql事务及行级锁
事务隔离级别 数据库事务隔离级别,只是针对一个事务能不能读取其它事务的中间结果. Read Uncommitted (读取未提交内容) 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果.本隔离 ...
- Mysql的事务及行级锁
转自:http://www.cnblogs.com/edwinchen/p/4171866.html 以签到为例,每个用户每天只能签到一次,那么怎么去判断某个用户当天是否签到呢?因为当初表设计的时候, ...
- [数据库事务与锁]详解五: MySQL中的行级锁,表级锁,页级锁
注明: 本文转载自http://www.hollischuang.com/archives/914 在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的 ...
- MySQL行级锁,表级锁,页级锁详解
页级:引擎 BDB. 表级:引擎 MyISAM , 理解为锁住整个表,可以同时读,写不行 行级:引擎 INNODB , 单独的一行记录加锁 表级,直接锁定整张表,在你锁定期间,其它进程无法对该表进行写 ...
- MySQL行级锁、表级锁、页级锁详细介绍
原文链接:http://www.jb51.net/article/50047.htm 页级:引擎 BDB.表级:引擎 MyISAM , 理解为锁住整个表,可以同时读,写不行行级:引擎 INNODB , ...
随机推荐
- Golang之应用测试
Go 应用测试 测试的覆盖率 命令: go test ./ -v -cover 在<Go Web 编程>一书中,有以下结论: 这并不是绝对的,测试文件可以在不同的包,进行测试也是不会出现问 ...
- html 04-HTML标签图文详解(一)
04-HTML标签图文详解(一) #一.排版标签 #注释标签 <!-- 注释 --> #段落标签<p> <p>This is a paragraph</p ...
- angular8 大地老师学习笔记---第八课
/*ViewChild获取dom节点 1.模板中给dom起一个名字 <div #myBox> 我是一个dom节点 </div> 2.在业务逻辑里面引入ViewChild imp ...
- 使用GitHub发布自己的静态网站
可参考GitHub官方文档 https://pages.github.com/ https://help.github.com/ 1.在本地新建一个文件夹.然后在文件夹中用git初始化文件夹 git ...
- win10开启运行下显示历史操作记录
步骤 设置,隐私,常规,允许windows跟踪应用启动,以改进开始和搜索结果
- 给因特尔S2600CO服务器主板安装【SAS控制器】驱动
给因特尔S2600CO服务器主板安装[SAS控制器]驱动 1:首先打开[设备管理器]找到未识别驱动的[SAS控制器]双击进入 2:在[详细信息]选项卡,选择[兼容Id]属性可以看到PCI\VEN_80 ...
- MethodHandleVS反射
Method Handle与反射 如无特殊说明,本文所有代码均基于JDK1.8.0_221 Method Handle入门 反射我们都知道,为我们提供了运行时对类的成员方法访问的手段,极大地提高了Ja ...
- EF Core 三 、 骚操作 (导航属性,内存查询...)
EF Core 高阶操作 本文之前,大家已经阅读了前面的系列文档,对其有了大概的了解 我们来看下EF Core中的一些常见高阶操作,来丰富我们业务实现,从而拥有更多的实现选择 1.EF 内存查找 wh ...
- java中将从数据库查询的信息输出到excel文件中
package com.cn.peitest.excel; import java.io.File; import java.lang.reflect.Field; import java.util. ...
- IDEA和eclips工具对比
描述 eclipse idea 在当前类查找方法 ctrl+o ctrl+F12 查找文件 ctrl+shift+N 大小写转换 ctrl+shift+X ctrl+shift+Y ctrl ...