这是我总结的事务的四种隔离机制,比较好理解,主要是有些地方文字游戏说不清楚很容易混淆:

Read Uncommitted(读未提交)A未完,B已更新,未提交,A读到B已更新的数据,由于未提交,那么可能会回滚,所以这样的数据就是错误的数据也就是脏读。

Read Committed(读已提交)A未完,B已更新,已提交,A读到B已更新且提交的数据,由于已提交,所以是正确的数据,但是可能这个事务比较长,读几次都不一样,从业务上说也许对也许不对,所以这个是不可重复读的。

Repeatable Read(可重复读)A未完,B不一定可以更新,不管B有无更新/提交,A读不到B的数据(MYSQL默认),自己每次读都是一样的,但是存在幻读,幻读是期间发送新增删除这样的操作导致。

Serializable(串行化),绝对无错。

-------------

MySQL事务学习总结

关于幻读,网上很多描述都是错误的。

幻读是指读到了其它事务提交的新增数据,

不可重复读是指读到了其他事务提交的更改数据(更改或删除)。

为了解决不可重复读,只需要通过行级锁来实现就可以了,但是为了解决幻读,则不能仅仅锁住一条数据,因为这样的锁不能阻止别的事务新增记录,MySQL用了间隙锁来解决这个问题,而不是表级锁。

InnoDB实现的是MVCCMVCC中,读分为快照读和当前读

MySQL加锁处理分析@何登成的技术博客

快照读(简单的select操作,属于快照读,不加锁)

select * from test where money = 500;

当前读(特殊的读操作,插入/更新/删除操作,属于当前读,需要加锁)

select * from table where ? for update;
insert into table values (…);
update table set ? where ?;
delete from table where ?;

可能会觉奇怪,为什么insert update delete也属于当前读,因为针对这些操作,都是InnoDB先把数据筛选出来,加锁,把数据交给MySQL Server处理,Server处理好后交给InnoDB更新,然后InnoDB释放锁,这里面就有读的操作。
这里说的幻读指的是当前读。这是登博关于幻读的解释,所谓幻读,就是同一个事务,连续做两次当前读 (例如:select from t1 where id = 10 for update;),那么这两次当前读返回的是完全相同的记录 (记录数量一致,记录本身也一致),第二次的当前读,不会比第一次返回更多的记录 (幻象)。

-----

MySQL数据库间隙锁

当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(Next-Key锁)。

举例来说,假如user表中只有101条记录,其empid的值分别是 1,2,...,100,101,下面的SQL:

select * from  user where user_id > 100 for update;
是一个范围条件的检索,InnoDB不仅会对符合条件的user_id值为101的记录加锁,也会对user_id大于101(这些记录并不存在)的“间隙”加锁。

InnoDB使用间隙锁的目的,一方面是为了防止幻读,以满足相关隔离级别的要求,对于上面的例子,要是不使用间隙锁,如果其他事务插入了user_id大于100的任何记录,那么本事务如果再次执行上述语句,就会发生幻读;另外一方面,是为了满足其恢复和复制的需要
---------------------

下面MySQL书《高性能MySQL(第3版)》:

隔离机制的比较

其实也有人喜欢用锁来控制并发,书中还提到了“隐式”和“显示锁定”,是这么建议的:

虽然这样,但是其实如果不经过实际的演练还是很难理解上面说的事务隔离机制到底怎么样可以防止并发。

1.查看MySQL版本

我们的版本是5.1.7

2.查看存储引擎

>show engines;

存储引擎是:InnoDB

3.实验表

假设有个商品表g,关键字段num表示库存,name表示商品名称

主要就是看不同事务隔离机制下并发修改库存是否会出现超卖。

假设我们的程序需要先查询库存,如果库存>0都可以卖,update扣库存,否则rollback。

为了制造并发肯定需要2个事务,假设是A和B。

4.确认事务隔离机制

修改会话的事务隔离级别

set session transaction isolation level read uncommitted;
set session transaction isolation level read committed;
set session transaction isolation level repeatable read;
set session transaction isolation level serializable;

>select @@global.tx_isolation,@@tx_isolation;

隔离级别1:Serializable 串行化

场景一:

显然一开始AB查询的数据是一样的num=1

A开始update

这时候在等待,无法update。

过一会就超时了。

如果这个时候B也update那么一样会等待超时

所以这样,AB就会都超时。

这时即使commit也是返回0,数据库不会变化。

场景二:

A在update等待的时候,B马上commit,但是B没有update

查看结果

这次A成功的扣库存。

所以从上面可以得出一个结论:serializable是可以很好的控制并发。

然后需要把库存改为1,便于测试。

隔离级别2:read committed 读已提交

>set session transaction isolation level read committed;

>select @@global.tx_isolation,@@tx_isolation;

场景一:

初始化AB查出来的库存都是1,然后A可以update一条数据,无等待。

这时候AB再比较下库存,A已经是0,B是1,因为A没有commit。

然后A执行commit操作,这时候B再查已经是库存0;

这时候B执行update返回是0行,因为update不能满足where条件,所以B只有Commit,然后重新提交。

场景二:

一开始AB都是一样的库存1,然后A开始update,然后A的库存是0,B是1,因为A还没有提交。

这时候B再update

按照前面的经验,B等待其实是再等A提交,A如果一直不提交,B就会超时。

这时A提交commit,B查询就得到A更新后的结果,这时B查到库存是0自然不会去更新,也就只能结束事务。

场景三:

AB先后update,然后A在B超时之前commit,这时由于B已经读到A更新后的结果0,所以B就不能成功update。

隔离级别3.repeatable read 可重复读

>set session transaction isolation level repeatable read;

>select @@global.tx_isolation,@@tx_isolation;

场景一:

然后A开始update,然后A和B分别读到库存是1和0

然后A提交commit,这时候再查看A和B的库存还是保持不变。

这时候B再次尝试update

依然是返回0条,说明更新不成功。

场景二:

AB同时update

如果A不及时commit那么B肯定会超时

如果A及时commit

所以可以看出无论是read committed还是repeatable read只要update的条件where  num>0足够充分都是可以控制并发防止超卖的。

如果没有带where  num>0这个控制条件,那么肯定会可以update成功的。

隔离级别4.read uncommitted

这个是需要杜绝的,就不讨论了。

如果没有带where  num>0,那么会怎么样呢。其实只要理解了上述流程就可以想明白会怎么样。

对于read committed

A已经update,B读到库存是0自然不会去更新;

A没有update,B读到库存是1,这要看A会不会及时提交;

如果A及时提交,B自然会去更新因为满足where条件,且成功,这样就超卖-1;

这时候由于B没有提交,所以AB分别查出0和-1

然后B提交commit,AB查出的都是-1,就不演示了。

修改会话为repeatable read

AB先后update,B在等待

然后A立即提交commit,B马上update得到返回。

结果就是-1产生了超卖:

总结:

1.使用serializable是可以防止超卖,但是性能怎么样需要数据说明;

2.read committed和repeatable read带上where条件库存num>0都是可以防止超卖的,不过需要处理超时。

3.其他各种组合情况还会更复杂,具体具体问题具体分析。

forupdate实验

A开始 :

B开始:

扩展阅读:

《数据库事务的四大特性以及事务的隔离级别》

事务的四个特征ACID

⑴ 原子性(Atomicity)
  原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。

⑵ 一致性(Consistency)
  一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。

  拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。

⑶ 隔离性(Isolation)
  隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离

  即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。

  关于事务的隔离性数据库提供了多种隔离级别

⑷ 持久性(Durability)
  持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

------------

事务隔离级别

三种读现象:

⑴ 脏读
  脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。
  当一个事务正在多次修改某个数据,而在这个事务中这多次的修改都还未提交,这时一个并发的事务来访问该数据,就会造成两个事务得到的数据不一致。

⑵不可重复读
  不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。
  例如事务T1在读取某一数据,而事务T2立马修改了这个数据并且提交事务给数据库,事务T1再次读取该数据就得到了不同的结果,发送了不可重复读。
  不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据
  在某些情况下,不可重复读并不是问题,比如我们多次查询某个数据当然以最后查询得到的结果为主。但在另一些情况下就有可能发生问题,

⑶ 幻读
  幻读是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。

  幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)

MySQL数据库的四种隔离级别:
Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
⑵ Repeatable read (可重复读):可避免脏读、不可重复读的发生。
Read committed (读已提交):可避免脏读的发生。
Read uncommitted (读未提交):最低级别,任何情况都无法保证。

  以上四种隔离级别最高的是Serializable级别,最低的是Read uncommitted级别,当然级别越高,执行效率就越低。像Serializable这样的级别,就是以锁表的方式(类似于Java多线程中的锁)使得其他的线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况。在MySQL数据库中默认的隔离级别为Repeatable read (可重复读)。

  在MySQL数据库中,支持上面四种隔离级别,默认的为Repeatable read (可重复读);而在Oracle数据库中,只支持Serializable (串行化)级别和Read committed (读已提交)这两种级别,其中默认的为Read committed级别。

事务隔离机制原理深入分析以及MySQL不同隔离级别分场景下实验对比相关推荐

  1. 事务隔离机制原理分析以及是否可以防止订单超卖

    事务的隔离机制是指: Read Uncommitted(读取未提交内容) Read Committed(读取提交内容) Repeatable Read(可重读) Serializable(可串行化) ...

  2. MySQL数据库(分库分表)中间件对比

    分区:对业务透明,分区只不过把存放数据的文件分成了许多小块,例如mysql中的一张表对应三个文件.MYD,MYI,frm. 根据一定的规则把数据文件(MYD)和索引文件(MYI)进行了分割,分区后的表 ...

  3. mysql 迁移方案_不同场景下 MySQL 的迁移方案

    本文内容 为什么要迁移 MySQL 迁移方案概览 MySQL 迁移实战 注意事项 技巧 总结 一.为什么要迁移 MySQL 迁移是 DBA 日常维护中的一个工作.迁移,是把实际存在的物体挪走,保证该物 ...

  4. mysql 存储时间 时间戳_具体场景下MySQL中用“时间戳”存储时间的问题

    今天看二哥写的关于数据库中时间戳存储的问题,觉得有必要思考下这个问题,之前自己也是认为用int型将时间存储在数据库是个不错的选择,但是我们往往理想化或者没有考虑特殊情景. 假如有这么一个场景:一个商城 ...

  5. java 类隔离_微服务架构中zuul的两种隔离机制实验

    ZuulException REJECTED_SEMAPHORE_EXECUTION 是一个最近在性能测试中经常遇到的异常.查询资料发现是因为zuul默认每个路由直接用信号量做隔离,并且默认值是100 ...

  6. MySQL事务篇:ACID原则、事务隔离级别及事务机制原理剖析

    引言 众所周知,MySQL数据库的核心功能就是存储数据,通常是整个业务系统中最重要的一层,可谓是整个系统的"大本营",因此只要MySQL存在些许隐患问题,对于整个系统而言都是致命的 ...

  7. 玩转MySQL:你懂什么是事务机制原理吗

    引言 众所周知,MySQL数据库的核心功能就是存储数据,通常是整个业务系统中最重要的一层,可谓是整个系统的"大本营",因此只要MySQL存在些许隐患问题,对于整个系统而言都是致命的 ...

  8. mysql当前时间减一分钟_MySQL数据库事务的机制【总结】

    php中文网最新课程 每日17点准时技术干货分享 这几天面试多次被问到了数据库事务机制.隔离级别.乐观锁悲观锁类的问题,之前对这些只能说有所了解,有些概念还停留在记忆层面,没有理解,所以回答的不好.后 ...

  9. 《深入理解分布式事务》第三章 Spring 事务的实现原理

    <深入理解分布式事务>第三章 Spring 事务的实现原理 文章目录 <深入理解分布式事务>第三章 Spring 事务的实现原理 一.Spring 事务原理 1.JDBC 直接 ...

最新文章

  1. macos apache php,如何在mac上配置apache和php
  2. mongodb语法与spring实现
  3. 论文阅读课2-Inter-sentence Relation Extraction with Document-level (GCNN,句间关系抽取,ACL2019
  4. php取整数余数,js取整数、取余数的方法
  5. 潮流色彩碰撞C4D几何空间!这样的艺术背景素材,设计师都喜欢
  6. 使用git将本地仓库上传到远程仓库
  7. JavaEE系统架构师学习路线
  8. SQL中JOIN和UNION区别及用法
  9. C++ 17 string_view(转载)
  10. 测试开发工程师的学习之路---1--规划
  11. Graphene图数据建模工具
  12. 已解决(Python运行报错)SyntaxError: expression cannot contain assignment, perhaps you meant “==“?
  13. 【论文阅读笔记 + 代码解读】(2018 AAAI)ST-GCN
  14. c语言mn间有多少素数,素数表达式p=2a+1 (a ≠ 2mn+m+n)由此出发看哥猜、挛猜比较清晰...
  15. Perl的opendir
  16. BigDecimal 保留两位小数
  17. Vue+MySQL实现登录注册案例
  18. 剑指offer面试题(31-40)——java实现
  19. 如何快速对接快递模块之电商平台
  20. linux moxa 多串口卡_MOXA多串口卡在Linux下的安装

热门文章

  1. mysql 数字区间_币投君0904丨数字货币暴跌原因何在
  2. word文档怎么给数字加千分符_Word中如何将文档中的金额数值设置为财务数字中的千分位格式...
  3. ajax返回一段html代码,【提问】ajax请求返回整个html页面
  4. 深蓝学院的深度学习理论与实践课程:第三章
  5. Modus串行链路系统电气特性:2线-Modus、4线-Modus、RS232-Modus和RS485-Modus的特性
  6. 业务逻辑组件化android,AppJoint 极简 Android 组件化方案
  7. 一、multiprocessing.pool.RemoteTraceback
  8. 鲲鹏服务器拦截系统调用,鲲鹏服务器unicfg工具适配OpenEuler 20.03问题
  9. python删除csv某一行_Python如何修改CSV的某一行/列的值
  10. 【敏捷开发】Node.js(nodejs)实现一个接口完成增删改查聚合接口4个功能,最大限度节省接口数量,正所谓“一口多用”(基础版、免登陆、无鉴权)