【mysql】细说 数据库隔离级别 及实现

【mysql】细说 数据库隔离级别 及实现网上大多数关于隔离级别的文章都是讲了事务中的问题以及隔离级别可以解决的问题,我这次想看看数据库底层是如何实现隔离级别的。不过还是先来回顾一下隔离级别以及可能发生的问题。1.脏读:指的是一个事务的读操作读到了另一个未提交的事务修改的值。比如下面的场景:脏读的问题是,读到的值可能会被回滚,那么这个值就是失效的,不能继续使用,否则会有一致性问题。2.不可重复读:指的是一个事务读…

大家好,又见面了,我是你们的朋友全栈君。

网上大多数关于隔离级别的文章都是讲了事务中的问题以及隔离级别可以解决的问题,我这次想看看数据库底层是如何实现隔离级别的。

不过还是先来回顾一下隔离级别以及可能发生的问题。

1.脏读:指的是一个事务的读操作读到了另一个未提交的事务修改的值。比如下面的场景:

【mysql】细说 数据库隔离级别 及实现

脏读的问题是,读到的值可能会被回滚,那么这个值就是失效的,不能继续使用,否则会有一致性问题。

 

2.不可重复读:指的是一个事务读了同一个值两次,但是两次的值不同,因为中间另一个事务修改了这个值,比如下面的场景:

【mysql】细说 数据库隔离级别 及实现

t2事务是已提交的,所以t1的第二次读取是可以读到的。

 

3.幻读:仍然指的是一个事务中读了两次,结果不同,但是与不可重复读不同的是,这里不同是因为别的事物做了插入操作,而且读的条件是一个范围的条件,这样第二次会多读到一条数据,比如下面的例子:

【mysql】细说 数据库隔离级别 及实现

 

相应的有四种隔离级别,不同程度的解决了上面的问题:

【mysql】细说 数据库隔离级别 及实现

可以看到隔离界别越高,解决的问题就越多,但是并行化程度也越低,效率也越低。

 

那么数据库是如何实现隔离界别呢?下面以mysql innodb引擎来说下。事务隔离性,本质上解决事务的读写冲突的,在mysql中,读操作被实现为一种叫做“非锁定读取“的技术。什么意思,我们通常会说数据库里有共享锁和排它锁,读操作就是共享锁,只有共享锁和共享锁是非互斥的,那么如果一个读操作要在一个正在被修改的数据上进行,那么是无法加上获取该行对象的共享锁的,这便是数据库串行化隔离界别的实现方式,但是在其余的隔离界别下,我们不需要这么严格的隔离,我们允许了读操作可以在正在被修改的数据上即加上了排它锁的行数据上进行,这就是所谓的”非锁定读取“概念。

那么,读取的结果是什么?这个还需要明白另一点,就是我们数据库MVCC和undo日志,我们每一次的修改操作,并不是直接对行数据进行操作,比如我们设置id为3的行的A属性为10,并不是直接修改表中的数据,而是新加一行,同时数据表其实还有一些隐藏的属性,比如每一行的事务id,所以每一行数据可能会有多个版本,每一个修改过它的事务都会有一行,并且还会有关联的undo日志,表示这个操作原来的数据是什么,可以用它做回滚。那么为什么要这么做?因为如果我们直接把数据修改了,那么其他事务就用不了原先的值了,违反了事务的一致性。那么一个事务读取某一行的数据到底返回什么结果呢?取决于隔离级别,如果是Read Committed,那么返回的是最新的事务的提交值,所以未提交的事务修改的值是不会读到的,这就是Read Committed实现的原理。如果是Read Repeatable级别,那么只能返回发起时间比当前事务早的事务的提交值和比当前事务晚的删除事务删除的值。这其实就是MVCC方式。所以在第二个例子中,t2事务发生在t1后面,所以它更新的值是不会被t1读取到的,所以t1两次读取的值相同,也就是可以重复读。

关于可串行化的隔离界别,也很简单,严格的按照加锁协议来就可以,该级别可以避免上述所有的问题。

在oracle等数据库中,为了避免幻读,只能采用可串行化隔离级别,但是在innodb引擎中,在Repeatable Read级别也可以实现,主要是一种叫做”Next Locking“的技术,一种特殊的锁。

正常的锁一般是锁一行,称为是Record锁,而”Next Lock“则是锁一个范围内的行,比如说第三个例子中,t1事务第一次查询的是10到30之间的数据,那么最终这些数据都要被上锁,那么后面t2事务想要插入数据就不行了,会被拒绝,再往后,t1的第二次读取就会和第一次一样了。innodb采用这样的办法,就在repeatable read级别解决了幻读的问题。

最后总结一下innodb里面的锁的互斥,在可串行化级别,严格按照加锁协议,只有共享锁可以并行,其他全部阻塞。但是在其他的隔离级别,就放宽了很多。不过写-写是肯定不行的,读-读是肯定行的,读-写也是可以的,只不过读到什么内容就由MVCC来决定,由具体的隔离级别决定,写-读一般都可以,只有在启用了”Next Locking“的情况下会被拒绝。

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/141390.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Spring Boot 配置ContextPath「建议收藏」

    Spring Boot 配置ContextPath「建议收藏」Springboot默认是/ ,这样直接通过http://ip:port/就可以访问到index页面,如果要修改为http://ip:port/path/ 访问的话,那么需要在Application.properties文件中加入server.context-path=/你的path,比如:spring-boot,那么访问地址就是http://ip:port/spring-boot路径。

  • 虚拟机配置DNS服务器「建议收藏」

    虚拟机配置DNS服务器「建议收藏」虚拟机配置DNS服务DNS简介下面演示如何通过虚拟机安装DNS服务器windows2003(DNS服务端)安装DNS服务客户端做相应配置回到windows2003新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML图表FLowchart流程图导出与导入导出导入DNS简介

  • android开发之手机与单片机蓝牙模块通信

    之前两篇都是在说与手机的连接,连接方法,和主动配对连接,都是手机与手机的操作,做起来还是没问题的,但是最终的目的是与单片机的蓝牙模块的通信。 下面是到目前为止尝试的与单片机的通信方法,没有成功,但是从思路上来说没有问题,最大的问题是与单片机配对的时候,单片机的蓝牙模块的PIN配对码是写死的,固定为1234,而手机这边连接配对都是自动生成的PIN配对码,这种方式在手机与手机配对的时候是极

  • ant design vue上传文件_antd vue 表单

    ant design vue上传文件_antd vue 表单antdvue文件上传实例说明该实例是后端进行文件上传至minio服务器这里仅仅是展示前端antdvue得代码限制文件类型配置查看这里<template><a-upload:headers=”headers”:action=”url”:fileList=”fileList”@change=”handleChang…

  • idea删除项目「建议收藏」

    idea删除项目「建议收藏」1.使用IDEA打开需要删除的项目,在项目文件上右击选择RemoveModule或者按Delete键2.之后会弹出删除提示,“RemoveModule‘xxx’fromtheproject?Nofileswillbedeleted.” 意思是移除指定模块,但没有文件被删除,就是说,模块移除了,磁盘上的文件还在点击“OK”之后,可以看到列表中还是存在些文件,这些文件是模…

  • 系统环境变量与用户环境变量区别_windows7建立用户变量

    系统环境变量与用户环境变量区别_windows7建立用户变量区别:  环境变量分为系统环境变量和用户环境变量。环境变量是指系统环境变量,对所有用户起作用,而用户环境变量只对当前用户起作用。  例如你要用opencv,那么你把opencv的bin目录加入到path变量下面,那么它就是系统环境变量,所用用户登陆,在命令行输入opencv都会有opencv的帮助信息出来。而如果你在某个用户的变量下面新建一个变量,那么它就只对这个用户有用,当你以其他用户登陆时这

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号