首页 > 数据库 >MySQL事务隔离级别

MySQL事务隔离级别

时间:2023-08-01 22:22:46浏览次数:38  
标签:事务 隔离 重复 幻读 提交 MySQL 级别

1 概念说明

1)脏读:指的是读到了其他事务未提交的数据,未提交意味着这些数据可能会回滚,也就是可能最终不会存到数据库中,也就是不存在的数据。读到了并不一定存在的数据,这就是脏读。

2)可重复读:在一个事务内,最开始读到的数据和事务结束前的任意时刻读到的同一批数据都是一致的。

3)不可重复读:对比可重复读,不可重复读指的是在同一事务内,不同时刻读到的同一批数据可能是不一样的,可能会受到其他事务的影响,比如其他事务改了这一批数据并提交了。

4)幻读:幻读是针对数据插入操作来说的,假设事务A对某些行的内容做了更改,但是还未提交,此时事务B插入了与事务A更新签的记录相同的记录行,并且在事务A提交之前先提交了,而这时,在事务A中查询,会发现好像刚刚的更改对于某些数据未起作用,但其实事务B刚插入进来的,让用户感觉到魔幻,这就是幻读。

2 事务隔离级别

2.1 事务隔离级别概述

2.1.1 读未提交(READ UNCOMMITTED)

MySQL事务隔离其实是依赖锁来实现的,加锁自然会带来性能的损失。而读未提交隔离级别是不加锁的,所以它的性能是最好的,没有加锁、解锁带来的性能开销。但是有利就有弊,这基本上就是裸奔了,所以连脏读的问题都没法解决。

2.1.2 读已提交(READ COMMITTED)

既然读未提交没办法解决脏数据的问题,那么就有了读提交。读提交就是一个事务只能读到其他事务已经提交过的数据,也就是其他事务调用commit命令之后的数据。

2.1.3 可重复读(REPEATABLE READ)

可重复读是对比不可重复而言的,上面说不可重复读是指同一个事务不同时刻读到的数据可能不一致。而重复读是指事务不会读到其他事务对已有数据的修改,即使其他事务已提交,就是说,事务开始时读到的已有数据是什么,在事务提交前的任意时刻,这些数据的值都是一样的。但是,对于其他事务新插入的数据是可以读到的,这就引发了幻读问题。

2.1.4 串行化(SERIALIZABLE)

串行化是4种事务隔离级别中隔离效果最好的,解决了脏读、不可重复读、幻读的问题,但是性能最差,它将事务的执行变为顺序执行,与其他三个隔离级别相比,它相当于单线程,后一个事务的执行必须等待前一个事务结束。

MySQL默认的事务隔离级别是可重复读(REPEATABLE READ)

事务隔离其实就是为了解决上面提到的脏读、不可重复读、幻读这几个问题

隔离级别

脏读

不可重复读

幻读

读未提交 可能 可能 可能
读已提交 不可能 可能 可能
可重复读 不可能 不可能 可能
串行化 不可能 不可能 不可能

2.2 事务隔离级别实现原理

2.2.1 读未提交

性能最好的事务隔离级别,也可以说是最野蛮的方式,因为它压根儿都不加锁,所以谈不上什么隔离效果,可以理解为没有隔离。

2.2.2 串行化

 串行化在读的时候加共享锁,也就是其他事务可以并发读,但是不能写,写的时候加排它锁,其他事务不能并发写也不能并发读。

2.2.3 读已提交 和 可重复读

 为了解决不可重复读,或者为了实现可重复读,MySQL采用了MVVC(多版本并发控制)的方式。在数据库表中看到的一行记录可能实际上有多个版本,每个版本的记录除了数据本身外,还要有一个表示版本的字段,即为row trx_id,而这个字段就是使其产生事务的ID,事务ID记为transaction id,它在事务开始的时候向事务系统申请,按时间先后顺序递增。

 按照上面这张图理解,一行记录现在就有3个版本,每一个版本都记录着使其产生的事务ID。在读的过程中,有一个快照的概念,这个学名叫做一致性视图,这就是可重复读和不可重复读的关键,可重复读是在事务开始的时候生成一个当前事务全局性的快照,而读提交则是每次执行执行语句的时候都重新生成一次快照。

对于一个快照来说,它能读到哪些版本数据,要遵循一下规则:

  • 当前事务内的更新,可以读到;
  • 版本未提交,不能读到;
  • 版本已提交,但是却在快照创建后提交的,不能读到;
  • 版本已提交,且是在快照创建前提交的,可以读到。

读提交和可重复读的主要区别就是在快照的创建上,可重复读仅在事务开始时创建一次,而读提交每次执行语句的时候都要创建一次。

2.3 并发写和幻读问题解决

2.3.1 并发写

当条件字段是索引时,直接在索引树中找到这条数据,直接加上行锁;当条件字段为非索引时,MySQL会为这张表中所有行加行锁,加上行锁后,MySQL会进行一遍过滤,发现不满足行就释放锁,最终只留下符合条件的行。

2.3.2 幻读

MySQL已经在可重复读隔离级别下解决了幻读的问题,而解决幻读用的也是锁,叫做间隙锁,MySQL把行锁和间隙锁合并在一起,解决了并发写和幻读的问题,这个锁叫做Next-Key锁。

假设现在表中有两条记录,并且age字段已经添加了索引,两条记录age的值分别为10和30。

 此时,在数据库中会为索引维护一套B+树,用来快速定位行记录。B+索引数是有序的,所以会把这张表的索引分割成几个区间

如图所示,分成了3个区间,(负无穷, 10]、(10, 30]、(30, 正无穷],在这三个区间是可以加间隙锁的。

 

 

如上图过程,在事务A提交之前,事务B的插入操作只能等待,这就是间隙锁的作用。当事务A执行update user set name='风筝2号’ where age = 10;的时候,由于条件 where age = 10 ,数据库不仅在 age =10 的行上添加了行锁,而且在这条记录的两边,也就是(负无穷,10]、(10,30]这两个区间加了间隙锁,从而导致事务B插入操作无法完成,只能等待事务A提交。不仅插入 age = 10 的记录需要等待事务A提交,age<10、10<age<30 的记录页无法完成,而大于等于30的记录则不受影响,这足以解决幻读问题了。

如果age不是索引列,那么数据库会为整个表加上间隙锁,所以在没有索引的情况下,无论age是否大于等于30,都要等待事务A提交可以成功插入。

原文连接:https://zhuanlan.zhihu.com/p/621709274

             https://zhuanlan.zhihu.com/p/641057722

 

标签:事务,隔离,重复,幻读,提交,MySQL,级别
From: https://www.cnblogs.com/daytoy105/p/17599226.html

相关文章

  • Java面试题 P30:数据库篇:MySql篇-MySql优化-索引-什么是聚集索引(聚簇索引)?什么是非聚集
     回表查询:先去二级索引找到主键,在用主键去聚集索引查到对应的值的过程交回表查询。   ......
  • [PHP]PDO的dsn对mysql的连接影响
    dsn的host字段中,'localhost'是一个影响其连接协议的值,当host取值'localhost',PDO会坚持使用unixsocket的方式去连接数据库:'mysql:host=localhost;dbname=mydb'以上配置,PDO会寻找php.ini中的pdo_mysql.default_socket值,尝试运用此路径通过unixsocket来连接mysql,如果此配置值不......
  • MySQL字符串截取之substring_index
    substring_index(str,delim,count)str:要处理的字符串delim:分隔符count:计数 例子:str=www.wikibt.comsubstring_index(str,'.',1)结果是:wwwsubstring_index(str,'.',2)结果是:www.wikibt也就是说,如果count是正数,那么就是从左往右数,第N个分隔符的左边的全部内容相......
  • MySQL 日期计算中的计算天数的方法(mysql日期计算天数)
    MySQL日期计算中的计算天数的方法MySQL作为一款高性能的数据库,可以支持日期计算功能,其中有两个函数可以计算出两个日期之间相差多少天数,那就是DATEDIFF和DATE_SUB函数。其中DATEDIFF函数是MySQL内置支持的函数,它可以计算两个日期之间的天数,DATE_SUB则是在DATEDIFF函数......
  • MySQL 日期计算中的计算天数的方法(mysql日期计算天数)
    MySQL日期计算中的计算天数的方法MySQL作为一款高性能的数据库,可以支持日期计算功能,其中有两个函数可以计算出两个日期之间相差多少天数,那就是DATEDIFF和DATE_SUB函数。其中DATEDIFF函数是MySQL内置支持的函数,它可以计算两个日期之间的天数,DATE_SUB则是在DATEDIFF函数......
  • mysql if 空字符串(如何使用mysql中的if函数处理空字符串)
    ysql中的if函数处理空字符串?ysql中,if函数可以用来实现条件判断。当我们需要处理空字符串时,可以使用if函数来判断字符串是否为空,然后根据判断结果进行相应的处理。if函数的语法如下:if(expr1,expr2,expr3)其中,expr1是条件表达式,如果该表达式的值为真,则返回expr2的值,否则返回expr3的值......
  • mysqlfrm工具使用及基于.frm和.ibd文件的数据恢复和.ibd迁移
    问题概述可以在数据库发生部分文件损坏,又没有相关备份时,利用mysqlfrm工具,读取数据库中表的.frm文件提取建表语句,结合.ibd文件做数据恢复。一、相关概念1、mysqlfrm工具mysqlfrm是一个恢复性质的工具,可以用来读取.frm文件并从该文件中找到表定义,生成ddl语句,生成的ddl语句多用于在另......
  • MySQL 连接语句优化技巧的示例和代码
    当涉及到实际案例时,以下是一些可以帮助实现快速查找的MySQL连接语句优化技巧的示例和代码:1.使用索引:CREATEINDEXidx_nameONyour_table(name);上述代码在名为your_table的表的name列上创建了一个索引。这将加快对该列的查询速度。2.编写有效的查询语句:SELECT*......
  • MySQL 排序一
    前言   排序是数据库中的一个基本功能,MySQL也不例外。用户通过Orderby语句即能达到将指定的结果集排序的目的,其实不仅仅是Orderby语句,Groupby语句,Distinct语句都会隐含使用排序。本文首先会简单介绍SQL如何利用索引避免排序代价,然后会介绍MySQL实现排序的内部原理,并介绍......
  • PHPMySQL防注入 如何使用安全的函数保护数据库
    PHPMySQL防注入如何使用安全的函数保护数据库在进行PHP编程开发时,安全性一直是开发人员必须注意的问题,其中最重要的是防止SQL注入攻击。SQL注入攻击是指通过输入恶意代码来攻击数据库的一种方式,攻击者通过输入SQL语句来绕过程序的安全机制,达到控制和操作数据库的目的。为了避免......