前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >探讨MySQL事务的特性与原理(理解MySQL的隔离级别及MVCC)

探讨MySQL事务的特性与原理(理解MySQL的隔离级别及MVCC)

原创
作者头像
潋湄
发布2024-09-19 16:03:51
1220
发布2024-09-19 16:03:51

概述:

MySQL是日常开发中使用最广泛的数据库,深入理解它的特性、隔离级别等有助于我们更好地解决实际问题

事务特性介绍:

ACID,分别是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)

原子性是指事务中的所有操作要么全部成功,要么全部失败

一致性是指事务执行前后,数据始终处于一致性状态,不会出现数据丢失

隔离性是指事务提交前的中间状态对其他事务不可见,即相互隔离

持久性是指事务提交后,数据的修改永久保存在数据库中

事务特性原理:

原子性(Atomicity)

原子性主要由undo log实现:

undo log

undo log是回滚日志,用于记录数据被修改前的信息,它每次都会在一条语句执行时存储一条反方向执行的语句,比如delete一条数据是,undo log中会记录一条insert的语句,主要作用包括提供回滚MVCC(多版本并发控制),因此通过undo log,当sql语句执行出错时,就可以通过undo log回滚到语句执行之前的状态,保证事务的原子性

持久性(Duration)

持久性主要由redo log实现:

redo log

redo log是重做日志,记录的是事务提交是数据页的物理修改,该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log file),前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息存储到该日志文件中,用于在刷新脏页到磁盘发生错误时,进行数据恢复使用。因此即使系统发生崩溃,系统也可以从日志中获取记录来恢复数据。

不使用redo log

为了更好理解,我们可以看一下如果没有redo log时,要实现持久性要如何实现:

1、从磁盘加载数据到内存

2、在内存中修改数据

3、把新数据持久化到磁盘

不适用redo log的持久化策略
不适用redo log的持久化策略

但是这样做会有严重的性能问题:

1、InnoDB在磁盘中存储的基本单元是页,如果本次修改只改动一页中的几个字节,但是最终还是要刷新整页的数据,十分浪费资源

2、一个事务可能修改多页中的数据,页之间不是连续的,就会产生随机IO,性能更差

使用redo log

因此我们可以引入redo log来对流程进行修改:

1、从磁盘加载数据到内存

2、在内存中修改数据

3、把新数据写到redo log buffer中

4、把redo log buffer中数据持久化到redo log文件中

5、把redo log文件中数据持久化到数据库磁盘中

而由于redo log采用的是追加的方式记录日志,是顺序读顺序写,因此会比随机读随机写效率高出不少,大大提高了原始策略持久化的效率

具体流程图就是下面这样:

引入redo log后的持久化策略
引入redo log后的持久化策略

因此,在每次sql语句执行时,会将undo log日志与redo log日志结合起来使用来保证事务的原子性与持久性,大致流程如下:

sql语句读写流程
sql语句读写流程

一致性(Consistency)

主要由代码逻辑层面保证,通过完整性约束(主键约束,外键约束)等完成

隔离性(Isolation)

隔离性主要由MVCC来实现的,在深入学习MVCC之前,一定要说一下事务的隔离级别,而事务的隔离级别是根据不同并发事务产生的问题导致的,因此必须要先说一下并发事务产生的问题:

并发事务产生的问题

脏读:一个事务读到其他事务未提交的数据

不可重复读:多次读取相同的数据,得到的结果集不一致,即读到其他事务提交后的数据,针对于数据的内容,主要是读到了其他事务执行update、delete后的数据

幻读:相同的查询条件,多次读取的结果不一致,即读到其他事务提交后的结果,针对于数据的数量,主要是读到了其他事务执行insert后的数据

隔离级别

Read UnCommitted(读未提交):读到其他事务未提交的数据,会出现脏读,不可重复度,幻读

Read Committed(读已提交):读到其他事务已提交的数据,解决了脏读,会出现不可重复读,幻读

Repeatable Read(可重复读):相同的数据,多次读取到的结果集一致,解决了不可重复读,但是还是有可能出现幻读,这里举一个出现了幻读的例子方便理解:

可重复读出现幻读例子
可重复读出现幻读例子

第一次读取的内容与第二次并没有变化,满足可重复读,但是读取内容的数量发生了变化,因此并不能解决幻读

Serializable(串行化):所有事务串行执行,解决了幻读

读取的两种模式

当前读:读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。我们日常的操作:select ... lock in share mode(共享锁),select ... for update、update、insert、delete(排他锁)都是一种当前读。

快照读:简单的select(不加锁)就是快照读,读取的是记录数据的可见版本

之后我们开始详细介绍一下MVCC(多版本并发控制 Multi-Version Concurrency Control)

MVCC介绍

MVCC多版本并发控制,会维护一个数据的多个版本,使得读写操作没有冲突,MVCC的具体实现,还需要依赖于数据库中记录的三个隐式字段、undo log日志、readView

三个隐式字段:
三个隐式字段
三个隐式字段
undo log

回滚日志,在insert、update、delete的时候产生的便于数据回滚的日志。

当insert的时候,产生的undo log只在回滚时需要,事务提交后可以被立即删除;而update、delete的时候,产生的undo log日志不仅在回滚时需要,在快照读时也需要,不会被立即删除。

在数据库执行sql语句时,会根据每条语句生成一条undo log日志,结合数据库的隐藏字段,便可以生成一条版本链:

undo log版本链
undo log版本链
readView

ReadView(读视图)是快照读SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的(未提交的)id,它其中包含了四个字段:

readView包含的四个字段
readView包含的四个字段

版本链数据访问规则

在判断读取哪条数据时,会依照如下的四条判断条件,根据当前undo log的版本号与当前版本的字段进行比较,自上而下,如果遇到合适的条件说明匹配成功:

(1)trx_id == creator_trx_id,说明修改这条数据的事务就是当前事务,所以可见

(2)trx_id < min_trx_id,说明修改这条数据的事务在当前事务生成readView的时候已经提交,所以可见

(3)trx_id 的大小在min_trx_id和max_trx_id之间,此时trx_id如果在m_ids中,说明修改这条数据的事务此时还未提交,所以不可见,相反如果不在m_ids中,说明事务已经提交,可见。

(4)trx_id >= max_trx_id,说明修改这条数据的事务在当前事务生成readView的时候还未启动,所以不可见

生成readView的时机

RC(Read Commited):在事务中每一次执行快照读时生成ReadView

RR(Repeatable Read):仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView

综上所述,隔离性就是MVCC通过它的隐藏字段等一系列规则解决的,数据库默认的隔离级别是RR(Repeatable Read)

自此,有关于事务的四大特性与他们的底层原理就讲解完毕了,创作不易,如果对你有帮助的话,劳烦点个赞啦,祝好!!!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述:
  • 事务特性介绍:
  • 事务特性原理:
    • 原子性(Atomicity)
      • undo log
    • 持久性(Duration)
      • redo log
    • 一致性(Consistency)
      • 隔离性(Isolation)
        • 并发事务产生的问题
        • 隔离级别
        • 读取的两种模式
        • MVCC介绍
    相关产品与服务
    云数据库 MySQL
    腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档