首页 > 数据库 >Java学习之mysql为什么可以实现可重复读

Java学习之mysql为什么可以实现可重复读

时间:2023-06-25 10:55:27浏览次数:59  
标签:事务 Java log 重复 ID trx 版本 mysql id

  • 什么是mvcc

Mysql的隔离级别是‘可重复读’,即:事务A在读到一条数据之后,此时事务B对该数据进行了修改操作并提交,那么事务A再读该数据,依然还是原来的内容。它的实现原理是MVCC(Multi-Version Concurrency Control)多版本并发控制,MVCC保证当前查询为快照读,所以不受其他事务影响。

什么是当前读和快照读

  • 当前读:读取当前版本的数据即最新的数据,并且会对读取的数据加锁,防止被其他事务修改。
  • 快照读:事务A查询数据时把查询到的数据拍成一张照片,事务A再次查询数据时好像一直查询的那张照片上的数据,但是数据会被事务B、事务C修改,所以查询的不一定是正确数据。

‘可重复读’可以预防那些事务问题

  • 未提交时读 Read Uncommitted(最低级别,任何情况都无法保证。)
  • 已提交后读 Read Committed(可避免脏读的发生。)
  • 可重复读 Repeatable Read(可避免脏读、不可重复读的发生。)
  • 序列化(串行化) Serializable(可避免脏读、不可重复读、幻读的发生。)

补充:脏读、幻读、不可重复读的区别

mvcc如何实现RC和RR的隔离级别

  • RC(Read Committed)的隔离级别下,每个快照读都会生成并获取最新的readview。
  • RR(Repeatable Read)的隔离级别下,只有在同一个事务的第一个快照读才会创建readview,之后的每次快照读都使用的同一个readview,所以每次的查询结果都是一样的。

mvcc的原理

mvcc实现原理主要有三个部分:隐藏字段、undoLog、ReadView。

1、隐藏字段

  • DB_ROW_ID : 隐藏ID,当创建表没有合适的索引作为聚集索引时,会用该隐藏ID创建聚集索引;
  • DB_TRX_ID : 记录操作该数据事务的事务ID;
  • DB_ROLL_PTR : 指向上一个版本数据在undo log 里的位置指针;

2、undoLog(Mysql三大日志之一)

 

  • Undo Log:事务回滚

 

数据库事务四大特性中有一个是原子性,具体来说就是原子性是指对数据库的一系列操作,要么全部成功,要么全部失败,不可能出现部分成功的情况。实际上,原子性底层就是通过undo log实现的。undo log主要记录了数据的逻辑变化,比如一条 INSERT 语句,对应一条 DELETE 的undo log,对于每个 UPDATE 语句,对应一条相反的 UPDATE 的undo log,这样在发生错误时,就能回滚到事务之前的数据状态。这些多条数据的更新成为版本链(在每次更新该记录后,都会将旧值放到一条undo日志中。随着更新次数的增多,所有的版本都会被roll_pointer属性连接成一条链表,这个链表就称之为版本链)。

 

  • Bin Log:数据同步

 

binlog用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在磁盘中。binlog是mysql的逻辑日志,并且由Server层进行记录,使用任何存储引擎的mysql数据库都会记录binlog日志。binlog是通过追加的方式进行写入的,可以通过max_binlog_size参数设置每个binlog文件的大小,当文件大小达到给定值之后,会生成新的文件来保存日志。

 

  • Redo Log:数据备份

 

redo log包括两部分:一个是内存中的日志缓冲(redo log buffer),另一个是磁盘上的日志文件(redo log file)。mysql每执行一条DML语句,先将记录写入redo log buffer,后续某个时间点再一次性将多个操作记录写到redo log file。这种先写日志,再写磁盘的技术就是MySQL里经常说到的WAL(Write-Ahead Logging) 技术。

3、ReadView

Read View就是一个保存事务ID的list列表,这个列表用来记录当前数据库系统中活跃的读写事务,也就是已经开启了,正在进行数据操作但是还未提交保存的事务。可以通过这个列表来判断某一个版本是否对当前事务可见。其中,有四个重要的字段:

  • creator_trx_id:创建当前Read View所对应的事务ID
  • m_ids:所有当前未提交事务的事务ID,也就是活跃事务的事务id列表
  • min_trx_id:m_ids里最小的事务id值
  • max_trx_id:InnoDB 需要分配给下一个事务的事务ID值(事务 ID 是累计递增分配的,所以后面分配的事务ID一定会比前面的大!)

如何通过ReadView来判断记录的某个版本是可见的?(小于、等于、不在、坚持回溯)

(trx_id表示要读取的事务id)

  • 如果trx_id == creator_trx_id,则表明当前事务在访问它自己修改过的记录,所以该版本可以被当前事务访问。
  • 如果trx_id < min_trx_id,则表明生成该版本的事务在当前事务生成ReadView之前已经提交了,所以该版本可以被当前事务访问。
  • 如果trx_id >= max_trx_id,则表明生成该版本的事务在当前事务生成ReadView之后才开启,所以该版本不可以被当前事务访问。
  • 如果trx_id in m_ids,说明创建ReadView时生成该版本的事务还是活跃的,该版本不可以被访问。
  • 如果trx_id not in m_ids,说明创建ReadView时生成该版本的事务已经被提交,该版本可以被访问。
  • 如果某个版本的数据对当前事务不可见,那就顺着版本链找到下一个版本的数据,并继续执行上面的步骤来判断记录的可见性,以此类推,直到版本链中的最后一个版本。

标签:事务,Java,log,重复,ID,trx,版本,mysql,id
From: https://www.cnblogs.com/Bernard94/p/17415101.html

相关文章

  • Linux 安装/卸载 MySQL 8.0
    Linux安装/卸载MySQL8.0原创 默存 全栈客 2023-06-1511:14 发表于甘肃收录于合集#linux1个#mysql1个安装Centos安装MySQL8.0操作系统环境[root@t2 local]# hostnamectlStatic hostname: hadoop-masterIcon name: computer-desktopChassis: de......
  • MySQL - 死锁的产生及解决方案
    MySQL-死锁的产生及解决方案原创 一安 一安未来 2023-06-1508:02 发表于北京收录于合集#干货分享集115个大家好,我是一安~简介死锁指两个或多个事务相互等待对方释放锁,从而导致进程无法继续执行的一种情况。当一个事务需要锁定一些资源时,如果这些资源已经被其他......
  • Java 插入排序
    publicstaticint[]insertSort(int[]nums){for(inti=1,len=nums.length;i<len;i++){intcurrent=nums[i];intj=i-1;for(;j>=0&&current<nums[j];j--)num......
  • JavaScript中最好的明暗模式主题切换
    了解如何使用JavaScript、CSS自定义属性、本地存储和系统设置为您的网站构建终极主题Toggle™️。无需框架!我曾经不同意浅色和深色模式切换。“切换开关是用户系统偏好设置!”我会天真地感叹,选择让prefers-color-schemeCSS媒体查询控制我个人网站上的主题。没有切换。没有选择......
  • 面试官:MySQL 自增主键一定是连续的吗?大部分人都会答错!
    测试环境:MySQL版本:8.0数据库表:T(主键id,唯一索引c,普通字段d)如果你的业务设计依赖于自增主键的连续性,这个设计假设自增主键是连续的。但实际上,这样的假设是错的,因为自增主键不能保证连续递增。推荐一个开源免费的SpringBoot实战项目:https://github.com/javastacks/sprin......
  • Java 设计模式实战系列—策略模式
    从优惠打折活动说起电商平台为了增加销量经常搞一些活动,比如618、双十一,还有一些节假日活动,根据销量的变化又经常更新不同的活动。最开始为了增加销量,全场都六折://打六折publicBigDecimalsixDiscount(BigDecimalamount){BigDecimaldiscount=BigDecimal.valueOf(0......
  • 学习笔记-Java动态代理的简单使用
    代理模式一种设计模式简单地说,在代理模式中存在三个角色用户代理被代理的对象用户调用代理,代理去调用被代理的对象以此来实现功能的增强动态代理在java中有两种实现方法JDK中的Proxy类CGLIBJDK中的Proxy类步骤实现InvocationHandler接口......
  • Mongo与MySql区别
    1.MongoDBmongoDB是一种分布式文档型数据库,具有分布式架构设计。mongoDB分布式架构包含:分片、副本和分布式查询路由1.1分片MongoDB分片技术将数据分割成多个分片(shard),每个分片存储部分数据。分片可以按照数据的范围、has值、分片键等方式进行分配。在分片集群中有一个特定的m......
  • 记一次字符串末尾空白丢失的排查 → MySQL 是会玩的!
    开心一刻今天答应准时回家和老婆一起吃晚饭,但临时有事加了会班,回家晚了点回到家,本以为老婆会很生气,但老婆却立即从厨房端出了热着的饭菜老婆:还没吃饭吧,去洗下,来吃饭吧我洗好,坐下吃饭,内心感动十分;老婆坐旁边深情的看着我老婆:你知道谁最爱你吗我毫不......
  • MySQL 进阶语法
    selectinto语法在MySQL中,SELECTINTO语法用于将查询结果插入到一个新表或已存在的表中。下面是SELECTINTO的语法示例:创建一个新表并将查询结果插入其中:CREATETABLEnew_table_nameSELECTcolumn1,column2,...FROMoriginal_tableWHEREcondition;这将从ori......