一文带你了解数据库隔离级别和锁之间的关系
前言:
很多人在学习数据库知识时,往往在学习到隔离级别和数据库锁这里有一些疑问:
隔离级别和数据库锁之间有什么关联呢?
本文就和大家聊聊这两者之间的联系,希望对大家有帮助!
聊聊两者之间的联系:
在具体聊之前,咱先记住一句话: 数据库事务有不同的隔离级别,不同的隔离级别对锁的使用是不同的,锁的应用最终导致不同事务的隔离级别。
首先来了解下有哪四种隔离级别:
- 读未提交:(Read Uncommitted)
- 读已提交(Read Committed) 大多数数据库默认的隔离级别
- 重复读(Repeatable-Read) mysql数据库所默认的级别
- 序列化(serializable)
四种隔离级别具体实现和不同:
首先程序是可以并发执行的,同样,在MySQL中,一个表可以由两个或多个进程同时来读写数据,这是没有问题的。
比如,此时有两个进程来读数据,这也没什么问题,允许。但是如果一个进程在读某一行的数据的过程中,另一个在进程又往这一行里面写数据(改、删),那结果会是如何?
同样,如果两个进程都同时对某一行数据进行更改,以谁的更改为准?那结果又会怎样,不敢想象,是不是数据就被破坏掉了。所以此时是冲突的。
既然会冲突就要想办法解决,靠谁来解决,这时候就是靠 锁机制 来维护了。怎么使用锁来使它们不冲突呢?
在事务开始的时候可以给要准备写操作的这一行数据加一个排它锁,如果是读操作,就给该行数据一个读锁。这样之后,在修改该行数据的时候,不让其他进程对该行数据有任何操作。
而读该行数据的时候,其他进程不能更改,但可以读。读或写完成时,释放锁,最后commit提交。 这时候读写就分离开了,写和写也就分离开了。
mysql开发者给这个解决冲突的方案起了一个名字叫做: 读未提交 :(Read Uncommitted)。这也就是事务的第一个隔离性。
注意:上面的加锁和释放锁的过程由mysql数据库自身来维护,不需要我们人为干涉。
但是这个程度的隔离性仅仅是不够的。看下面的测试结果:
1、A修改事务级别为:未提交读。并开始事务,对user表做一次查询:
2、B事务更新一条记录:
3、此时B事务还未提交,A在事务内做一次查询,发现查询结果已经改变:
4、B进行事务回滚:
5、A再做一次查询,查询结果又变回去了:
由试验得知:在一个进程的事务当中,我更改了其中的一行数据,但是我修改完之后就释放了锁,这时候另一个进程读取了该数据,此时先前的事务是还未提交的,直到我回滚了数据,另一个进程读的数据就变成了无用的或者是错误的数据。
我们通常把这种数据叫做脏数据,这种情况读出来的数据叫做 賍读 。
怎么办呢?当然还是靠锁机制。
无非是锁的位置不同而已,之前是只要操作完该数据就立马释放掉锁,现在是把释放锁的位置调整到事务提交之后,此时在事务提交前,其他进程是无法对该行数据进行读取的,包括任何操作。
那么数据库为此种状态的数据库操作规则又给了一个名字叫做: 读已提交 (Read Committed),或者也可以叫不可重复读。这也就是事务的第二个隔离性。
在某些情况下,不可重复读并不是问题,比如我们多次查询某个数据当然以最后查询得到的结果为主。但在另一些情况下就有可能发生问题,例如对于同一个数据A和B依次查询就可能不同,A和B就可能打起来了……
继续看下面的测试结果:
1、把隔离性调为READ-COMMITTED(读取提交内容)设置A的事务隔离级别,并进入事务做一次查询:
2、B开始事务,并对记录进行修改:
3、A再对user表进行查询,发现记录没有受到影响:
4、B提交事务:
5、A再对user表查询,发现记录被修改:
试验进行到这里,你会发现,在同一个事务中如果两次读取相同的数据时,最后的结果却不一致。
这里我们把这种现象称为: 不可重复读 。因为在第一个事务读取了数据之后,此时另一个事务把该数据给修改了,这时候事务提交,那么另一个事务在第二次读取的时候,结果就不一样,一个修改前的,一个是修改后的。
但是细心的你会发现,既然你说此种隔离性是在事务提交后才释放锁,那么在试验过程中,在该数据未提交前,另一个事务为什么也是仍然可以读取的呀。
是上面测试错了吗?不是的;
在这里mysql使用了一个并发版本控制机制,他们把它叫做MVCC,通俗的也就是说:mysql为了提高系统的并发量,在事务未提交前,虽然事务内操作的数据是锁定状态,但是另一个事务仍然可以读取数据的 快照版本 ;像 Oracle等大多数数据库默认的就是 读提交 这个级别的隔离性的。
但是mysql 的默认隔离级别却不是这个 。
而且不只是像上面在更新数据时出现这个问题,在插入数据时仍然会造成类似的这样一种现象: mysql虽然锁住了正在操作的数据行,但它仍然不会阻止另一个事务往表插入新行新的数据。
比如:一个事务读取或更新了表里的所有行,接者又有另一个事务往该表里插入一个新行,在事务提交后;
原来读取或更改过数据的事务又第二次读取了相同的数据,这时候这个事务中两次读取的结果集行数就不一样。原来更新了所有行,而现在读出来发现竟然还有一行没有更新。这就是所谓的 幻读 。
为了防止在同一事务中两次读取数据不一致,(包括不可重读和幻读),接下来该如何继续做呢?
mysql依然采取的是MVCC并发版本控制来解决这个问题,还是读取的快照数据。
具体是:如果事务中存在多次读取同样的数据,MySQL第一次读的时候仍然会保持选择读最新提交事务的数据,当第一次之后,之后再读时,mysql会取第一次读取的数据作为结果。
这样就保证了同一个事务多次读取数据时数据的一致性。这时候,mysql把这种解决方案叫做: 可重复读 (Repeatable-Read),也就是上述所写的第三个隔离性,也是mysql默认的隔离级别。
注意: 在可重复读的隔离级别下,除了会保证读操作的一致性外,在更新操作(当前读)时也会保证数据的一致性,避免出现不可重复读和幻读的错误;
具体是:在MySql的可重复读的隔离级别下,一个事务中更新数据,并且事务不提交,另启一个事务insert插入新数据,这时候是无法插入新数据的,插入操作被阻塞;为什么被阻塞呢?
因为在第一个事务中进行更新数据时(当前读),会使用 行锁 + 间隙锁 将表锁住了,所以在第二个事务中插入操作被阻塞;只有当第一个事务提交后,第二个事务中的插入操作才能被执行;
如果不阻塞的话,会存在什么问题? 会存在 幻读 的问题;例如:本来将全表数据的某个字段全部进行了更新,但是由于后面新增了数据,这些新增数据的那个字段并没有被更新,再次查看时就跟出现了幻觉一样;所以为了解决幻读的问题, 在可重复读隔离级别中提供了间隙锁 ,使用行锁+间隙锁将表锁住,让所有操作都不能修改数据 。
注意:innodb存储引擎中有对锁等待超时时间的配置,在规定时间内没有获取到锁的话,则此事务被中断,需要应用代码进行手动回滚或重试;
注意:幻读和不可重复读的区别:
- 幻读是针对的一批数据记录整体
- 不可重复读针对的是同一数据项的记录
最后这个时候,该我们的最后一种隔离级别也是最高的隔离级:别序列化(serializable)登场了。
该隔离级别会自动在锁住你要操作的整个表的数据,如果另一个进程事务想要操作表里的任何数据就需要等待获得锁的进程操作完成释放锁。
可避免脏读、不可重复读、幻读的发生。当然性能会下降很多,会导致很多的进程相互排队竞争锁。
后记:
上面所说的四种隔离性的锁机制应用是数据库自动完成的,不需要人为干预。
隔离级别的设置只对当前会话连接有效。对于使用MySQL命令窗口而言,一个窗口就相当于一个链接,当前窗口设置的隔离级别只对当前窗口中的事务有效 。
❤ 点赞 + 评论 + 转发 哟
如果本文对您有帮助的话,请挥动下您爱发财的小手点下赞呀,您的支持就是我不断创作的动力,谢谢啦!
您可以微信搜索 【木子雷】 公众号,大量Java学习干货文章,您可以来瞧一瞧哟!
一文带你了解数据库隔离级别和锁之间的关系相关推荐
- 仅此一文让你明白事务隔离级别、脏读、不可重复读、幻读
网络上关于这方面的博文有些偏理论,有些通篇代码,都不能深入浅出.本文用图文并茂的方式,配上行云流水般的代码,非要摆清楚这个问题.相关代码已提交至码云(点击这里下载). 事务是现代关系型数据库的核心之一 ...
- 【数据库】一篇文章搞懂数据库隔离级别那些事(LBCC,MVCC)
MySQL 事务 文章比较长,建议分段阅读 后续如果有改动会在 Junebao.top 之前对事务的了解仅限于知道要么全部执行,要么全部不执行,能背出 ACID 和隔离级别,知其然但不知其所以然,现在 ...
- 数据库隔离级别---MySQL的默认隔离级别就是Repeatable,Oracle默认Read committed,最高级别Serializable
目录 Read uncommitted 读未提交 Read committed 读提交 Repeatable read 重复读 Serializable 序列化 什么是脏读 重复读与幻读 隔离级别与锁 ...
- Spring的AOP和IOC是什么?使用场景有哪些?Spring事务与数据库事务,传播行为,数据库隔离级别
Spring的AOP和IOC是什么?使用场景有哪些?Spring事务与数据库事务,传播行为,数据库隔离级别 AOP:面向切面编程. 即在一个功能模块中新增其他功能,比方说你要下楼取个快递,你同事对你说 ...
- Spring事务管理amp;数据库隔离级别
一.spring事务管理 1. 什么是事务 事务(Transaction)是多个操作数据库的步骤(CRUD)的集合,是并发控制的单位,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可 ...
- mysql ansi sql标准_Mysql数据库隔离级别(ANSI SQL92规范,行锁,间隙锁)
一. 什么是数据库隔离级别? ANSI(美国国家标准学会:AMERICAN NATIONAL STANDARDS INSTITUTE)在多个事务并发的时候能够正确的处理数据所定义的规范.事务隔离级别越 ...
- 数据库隔离级别发展史
数据库隔离级别发展史 前言 ANSI SQL标准(1992):基于异象 A Critique of ANSI(1995):基于锁 问题本质 A Generalized Theory(1999):基于序 ...
- tidb数据库隔离级别剖析
本文章来源于:https://github.com/Zeb-D/my-review ,请star 强力支持,你的支持,就是我的动力. [TOC] 前言 在线应用业务中,数据库是一个非常重要的组成部分, ...
- Spring事务隔离级别与数据库隔离级别不一致时,该以谁为准?
原创博文,欢迎转载,转载时请务必附上博文链接,感谢您的尊重. 前言 通过本篇,你将了解到[Spring事务]与[数据库事务]的关系,以及优先级问题,我将为你一一论证. 阅读本篇,你可能会需要的博文: ...
最新文章
- 线性分类器与非线性分类器的区别是什么?有哪些优劣特性?
- jBPM3.12用户指南中文翻译----第一章 绪论
- 2008台北英特尔信息技术峰会主题演讲精选-王文汉
- 毫末智行 Fluid 实践:云原生 AI 让汽车变得“更聪明”
- Web自动化测试 Selenium+Eclipse+Junit+TestNG+Python
- openjdk(HOTSPOT)垃圾回收源码解读
- 使用扩展技术将SAP Fiori应用隐藏动态创建的UI字段
- matlab的可视化视频,MATLAB的可视化(一)
- 蔡高厅老师 - 高等数学-阅读笔记 - 01 - 前言、函数【视频第01、02、03、】
- oracle 表查询(1)
- 怎么分辨是不是外包工司_怎么分辨白酒是不是纯粮食酒?学会这几招,轻松辨别真假白酒...
- 三星a9s参数_三星A9s配置怎么样 三星A9s参数配置介绍
- 马士兵Java自学之路
- [技术交流]一些技术网站推荐。金融IT。
- 我99年想出来00年发表的一个概念,被百度百科引用了
- VMware vCenter vShield配置vxlan时候vib未安装
- 075-数组越界异常-ArrayIndexOutOfBoundsException-【视频讲解】
- [JavaScript]只需一行代码,轻松搞定快捷留言-V2升级版javascript
- 【LaTeX教程】九.Latex常见数学公式模板
- matlab建模DNA双链,PPT绘制科研图形—DNA双链、分子细胞模型