• 软件:1160
  • 资讯:41590|
  • 收录网站:97880|

IT精英团

如果有人问你MySql的隔离级别是什么 把这篇文章发给他!

如果有人问你MySql的隔离级别是什么 把这篇文章发给他!

浏览次数:
评论次数:
编辑: 乐咏
信息来源: ITPUB
更新日期: 2021-06-04 16:31:07
摘要

首先要明白什么是事务?事务是程序中一系列严密的操作,所有的操作必须完成,否则在所有的操作中所做的所有的更改都会被撤销。也就是事务的原子性,一个事务中的一系列的操作要么全部成功,要么就是失败。事务的结束有两种,当事务中所有的步骤全" />

-->
  • 资讯详情

作者lzyz 1992来自lhollis(id:Hollis Chuang)首先要明白什么是事务?事务是一个由一系列严格操作组成的程序,所有操作必须完成,否则所有操作中所做的所有更改都将被撤销。也就是事务的原子性。事务中的一系列操作要么成功,要么失败。

交易结束有两种。当事务中的所有步骤成功执行时,事务被提交。如果其中一个步骤失败,将会发生回滚操作,在事务开始之前反转所有操作。

事务的ACID事务有四个特点

原子事务是数据库的逻辑工作单元,它包含多个操作,要么全部完成,要么没有完成。

隔离(隔离也是本文的重点)事务不能相互干扰,即一个事务的操作与数据库的其他事务操作隔离,并发执行的每个事务相互干扰

一旦持久事务被提交,它的改变是永久性的

一致事务执行的结果必须从一种状态变为另一种状态,所以当数据库只包含事务提交成功的结果时,就说数据库处于一致状态。如果数据库系统在操作过程中失败,一些未完成的事务被迫中止,一些修改被写入数据库,则数据库处于不正确的状态。

实际上,以上三个条件(原子性、隔离性和持久性)最终都是为了保持数据库数据的一致性。MySQL的四种隔离级别SQL标准定义了四种隔离级别,用来限定事务内外的哪些改变是可见的,哪些是不可见的。读取未提交的数据。在这个隔离级别,所有事务都可以看到其他事务未提交的执行结果。(实际生产中不可能使用这种隔离级别)

[Read Committed]这个隔离级别是大多数数据库的默认隔离级别(不是MySQL默认)。它满足隔离:的简单定义。一个事务只能看到其他提交的事务所做的更改。该隔离级别还支持不可重复读取,即相同的选择可能得到不同的结果

重新读取【可重复读取】这是MySQL的默认隔离级别,保证同一事务并发读取数据时会看到同一条数据线。但是,会导致理论上的另一个问题,“魔法阅读”。幻读:在相同条件下查询部分数据,然后其他交易在此条件下【增加】或【删除】数据,导致不同的读取结果。InnoDB存储引擎通过多版本控制(MVCC)机制解决了这个问题

Serializable [Serializable]这是事务的最高隔离级别。它通过强制事务排序,使它们不能相互冲突,从而解决了魔法阅读的问题。它为每个读取的数据线添加一个共享锁。但是,它可能会导致超时和锁争用(这种隔离级别过于极端,实际生产中基本不使用)

这四种隔离级别采用不同的锁类型来实现脏读读取前一事务的未提交或回滚的数据

选择查询具有相同的不可重复性,但结果不同,并且一些事务在此过程中会更新原始数据

魔读两个查询的结果数量不一样,过程中增加或删除了一些事务

以下是由不同隔离级别引起的不同问题的摘要

各个隔离级别的详细测试图检查数据库的隔离级别,显示类似“%isolation%%”的变量

设置数据库setsessiontransactionis的隔离级别

olation level Read Uncommitted;

设置数据库的隔离级别为:Read Uncommitted

实验一:Read Uncommitted

Read Uncommitted 即:读取未提交前置条件:将数据库的隔离级别设置为read uncomitted;

set session transaction isolation level Read Uncommitted;


img
img
第一步:A开启事务:start tracsaction;
img
第二步:A查询数据:select * from test;
img
第三步:B开启事务:start transaction;
img
第四步:B查询数据:select * from test;
img
第五步:B更新数据:update test set num =10 where id = 1;B没有提交事务
img
第六步:A读取数据----A读取到了B未提交的数据(当前数据库的隔离级别是:Read Uncommitted
img
第七步:B回滚数据:rollback;
img
第八步:B查询数据:select * from test;
img
第九步:A查询数:select * from test;
img
结论:事务B更新了数据,但是没有提交,事务A读取到的是B未提交的记录。因为造成脏读。Read Uncommitted是最低的隔离级别

实验二:读取已提交-Read Committed

前置条件:将数据库的隔离级别设置为:Read Committed;

set session transaction isolaction level Read Committed;


img
img
第一步:A开始事务:start transaction;
img
第二步:A查询数据:select *from test;
img
第三步:B开启事务:start transaction;
img
第四步:B查询数据:select * from test;
img
第五步:B更新数据:update test set num =10 where id=1查看结果:
img
第六步:A查询数据:select * from test;
img
第七步:B提交数据:commit;
img
第八步:A查询数据:select * from test;
img
结论:Read Committed 读已提交的隔离级别解决了脏读的问题,但是出现了不可重复读的问题,即事务A在两次查询的结果不一致,因为在两次查询之间事务B更新了一条数据。读已提交的只允许读取已经提交的记录 ,但是不要求可重复读

实验三:可重读度-Repeatable Read

前置条件:将数据库的级别设置为可重复度set session transaction isolation level repeatable read;
img
第一步:A开始事务:start transaction;
img
第二步:A查询数据:select * from test;
img
第三步:B开启事务:start transaction;
img
第四步:B查询数据:select * from test;
img
第五步:B更新数据:update test set num=10 where id=1;
img
此时B并没有提交事务第六步:B查询数据:select * from test;
img
第七步:A查询数据
img
结果仍然是之前的结果(因为B事务还没有提交)第八步:B提交事务:commit;
img
第九步:A查询数据:select * from test;此时A查询的记录仍然和之前一样
img
第十步:B插入一条数据并提交事务:inset into test(num) value(4);
img
第十一步:A查询数据,发现结果还是和之前的一样:select * from test;
img
第十二步:A提交事务并查询数据
img
此时发现A查询的数据已经和B查询的结果一致了;结论:Repeatable Read隔离级别只允许读取已经提交的事务的记录,

实验四:串行化-Serializable

前置条件:将数据库的隔离级别设置为可串行化
img
第一步:A开始事务并查询数据
img
第二步:B开启事务并insert数据,发现只能等待,并不能执行下去
img
第三步:A提交事务
img
第四步:B插入数据
img
结论:serializable完全锁定字段,若一个事务来操作同一份数据,那么就必须等待,直到前一个事务完成并解除锁为止。是完整的隔离级别,会锁住对应的数据表,因为会导致效率问题。


本文小结本片文章并没有深入的去讲解原理,而是让大家能够从更直观的从隔离级别的表面去了解隔离级别,因为我发现我的很多同事对此是模模糊糊,模棱两可的,但是这个是不可以的,因为技术本身是不允许存在这种歧义的,懂就是懂,才能合理运用,如果模棱两可,那么在实际运用中一定也是漏洞百出,所以这也是这篇文章诞生的原因。我们可以先抛开原理与底层的具体实现,先能够清晰且明了的搞清楚各个专业术语的含义,这未尝不是一种进步。最后以一句不积跬步无以至千里,不积小流无以成江河与诸君共勉!
Nginx通过启用ssl会话重用可以提高多少性能?
« 上一篇
返回列表
下一篇 »
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
你会是第一个来这里评论的人吗?
最近发布资讯
更多