前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL 事务(4)

MySQL 事务(4)

作者头像
兜兜毛毛
发布2020-10-28 14:20:15
8600
发布2020-10-28 14:20:15
举报
文章被收录于专栏:兜兜毛毛兜兜毛毛兜兜毛毛

什么是事务?

数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。

这里有两个关键点,第一,它是数据库最小的工作单元,是不可以再分的。第二,它可能包含了一个或一系列DML语句,包括insert delete update。(单条DDL(create drop) 和DCL(grant revoke)也会有事务)

事务的四大特性(ACID)

特性

说明

原子性(Atomicity)

事务中的全部操作在数据库中是不可分割的,要么全部完成,要么全部不执行。

一致性(Consistent)

几个并行执行的事务,其执行结果必须与按某一顺序 串行执行的结果相一致。

隔离性(Isolation)

事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。

持久性(Durability)

对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。

原子性(Atomicity)

以转账为例,一个账户的余额减少,对应一个账户增加这两个一定是同时成功或同时失败。

全部成功好理解,问题是如果前一个操作已经成功,后一个操作失败了,如何让他全部失败呢?这时候我们必须要回滚。

原子性,在InnoDB里面是通过undo log来实现的,它记录了数据之前的值(逻辑日志),一旦发生异常,就可以用undo log来实现回滚操作。

一致性(Consistent)

还以转账为例,A账户余额有500元,这时有两个转账请求过来,都要转账500元,如果两个请求都执行成功,A账户的余额就成-500元,但这是错误的,储蓄卡的余额是不能小于0的,所以违反了一致性。完整性通常需要用户在代码中控制。

隔离性(Isolation)

有了事务的定义以后,在数据库里面会有很多的事务同时去操作我们的同一张表或者同一行数据,必然会产生一些并发或者干扰的操作,那么我们对隔离性的定义,就是这些很多个的事务,对表或者行的并发操作,应该是透明的,互相不干扰的。通过这种方式,我们最终也是保证业务数据的一致性。

像一致性的转账例子,应该是第一个事务转账成功,第二个事务提示余额不足。

持久性(Durability)

事务的持久性是什么意思呢?我们对数据库的任意的操作,增删改,只要事务提交成功,那么结果就是永久性的,不可能因为我们系统宕机或者重启了数据库的服务器,它又恢复到原来的状态了。这个就是事务的持久性。可以理解为数据已被写入到存储介质上。

持久性怎么实现呢?数据库崩溃恢复(crash-safe)是通过什么实现的?

持久性是通过redo log和double write双写缓冲来实现的,我们操作数据的时候,会先写到内存的buffer pool里面,同时记录redo log,如果在刷盘之前出现异常,在重启后就可以读取redo log的内容,写入到磁盘,保证数据的持久性。

当然,恢复成功的前提是数据页本身没有被破坏,是完整的,这个通过双写缓冲(double write)保证。

原子性,隔离性,持久性,最后都是为了实现一致性。

事务并发会遇到哪些问题?

当很多事务并发操作数据库的表或行时,如果没有我们刚才讲的事务隔离性时,会带来哪些问题?

如上图有两个事务,事务A先查询id=1的这行数据,之后事务B修改age=18,但未提交,此时事务A再次查询id=1的数据,这行数据age变成了18。这种在一个事务里,由于其他事务修改了数据并没有提交,而导致了前后两次读取数据不一致的情况,这种事务并发问题,我们将之定义为脏读

如果在转账案例里面,我们第一个事务读取到第二个事务未提交的余额进行了操作,但第二个事务进行了回滚,这个时候会导致数据不一致。

这种读取其他事务未提交的数据情况,我们叫做脏读

同样两个事务,A事务通过id=1查到一条数据。然后在第二个事务里执行一个update操作,并且修改了提交。然后A事务继续查询id=1的数据,此时A事务的前后两次查询数据不一致,像这种age到底等于16还是18,那么这种事务并发带来的问题,我们定义为不可重复读

这种一个事务读取到了其他事务已提交的数据导致前后两次读取数据不一致的情况,我们把它叫做不可重复读。

在上图中,我们在A事务中执行了一个范围查询,这个时候满足条件的数据只有一条。在B事务里面插入了一行新数据,并且提交了。此时在A事务再次查询时,会发现多了一条数据。这种情况我们定义为幻读

不可重复读和幻读的区别在哪里?

不可重复读是修改或者删除,幻读是插入。

小结:上边说的三大问题。无论是脏读、不可重复读、幻读,都是数据库的读一致性问题,都是在一个事务前后两次读取出现了不一致的情况。

读一致性的问题,必须要由数据库提供一定的事务隔离机制来解决。就像我们去饭店吃饭,基本的设施和卫生保证都是饭店提供的。那么我们使用数据库,隔离性的问题也必须由数据库帮助我们来解决。

MySql InnoDB 事务隔离级别

在MySQL InnoDB里面,不需要使用串行化的隔离级别去解决所有问题。我们来看一下MySQL InnoDB里面对数据库事务隔离级别的支持程度是什么样的。

事务隔离级别

脏读

不可重复读

幻读

未提交读(Read Uncommitted)

可能

可能

可能

已提交读(Read Committed)

不可能

可能

可能

可重复读(Repeatable Read)

不可能

不可能

对InnoDB不可能

串行化(Serializable)

不可能

不可能

不可能

InnoDB支持的四个隔离级别和SQL92定义的基本一致,隔离级别越高,事务的并发度就越低。唯一的区别就在于,InnoDB在RR的级别就解决了幻读的问题。这个也是InnoDB默认使用RR作为事务隔离级别的原因,既保证了数据的一致性,又支持较高的并发度。

实现方案

如果要解决读一致性的问题,保证一个事务中前后两次读取数据结果一致,实现事务隔离,你会怎么做?

一、基于锁的并发控制LBCC(Lock Based Concurrency Control)

既然要保证前后两次读取数据一致,那么我读取数据的时候,锁定我要操作的数据,不允许其他事务修改就行了。这种方案我们叫做基于锁的并发控制

如果仅仅是基于锁来实现事务隔离,一个事务读取的时候不允许其他时候修改,那就意味着不支持并发的读写操作,而大多数应用都是读多写少的,这样会极大地影响操作数据的效率。

二、多版本的并发控制 MVCC(Multi Version Concurrency Control)

如果要让一个事务前后两次读取的数据保持一致,那么我们可以在修改数据的时候给他建立一个备份或者叫快照,后面再来读取这个快照就行了。这种方案我们叫做多版本的并发控制

MVCC的核心思想是:我可以查到在我这个事务开始之前已经存在的数据,即使它在后面被修改或者删除了。在我这个事务之后新增的数据,我是查不到的。

那么这个快照什么时候创建?读取数据的时候,怎么保证能读取到这个快照而不是最新的数据?该如何实现?

InnoDB为每行记录都实现了三个隐藏字段:

字段名

长度

说明

DB_ROW_ID

6字节

行标识

DB_TRX_ID

6字节

插入或更新行的最后一个事务的事务ID,事务编号是自动递增的(可以理解为创建版本号,在数据新增或者修改为新数据的时候,记录当前事务ID)。

DB_ROLL_PTR

7字节

回滚指针(可以理解为删除版本号,数据被删除或记录为旧数据的时候,记录当前事务ID)。

DELETE_FLAG

删除标记

通过以上演示,通过事务ID的控制,无论其他事务是插入、修改、删除,第一个事务查询到的数据都没有变化。

可以将各事务中的查询逻辑按以下条件理解

select * from user_innoDB 
where DB_TRX_ID <= 2 or DB_ROLL_PTR <= 2;
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 事务的四大特性(ACID)
    • 事务并发会遇到哪些问题?
      • MySql InnoDB 事务隔离级别
        • 实现方案
        相关产品与服务
        云数据库 SQL Server
        腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档