MySQL事务

数据库事务

定义

事务指的是一组数据库操作要么全部成功,要么全部失败。如果出现部分成功,那么将造成数据不一致等情况。

重点概念

事务特性(ACID):

  • 原子性(Atomicity)
  • 一致性(Consistency)
  • 隔离性(Isolation)
  • 持久性(Durability)
隔离性和隔离级别

多个事务同时执行,就可能出现脏读、不可重复读、幻读的问题,于是就有了隔离级别。隔离得越严实,效率就会越低。隔离级别从低到高分为:读未提交、读已提交、可重复读、串行化(读写加锁)四种,依次解决上面提到的三种问题。

  • 读未提交:事务未提交前,它做的变更在其它事务中可见。
  • 读已提交:事务提交后,它做的变更才能在其它事务中可见。
  • 可重复读:事务执行过程看到的所有数据,总是跟它启动时看到的一致。
  • 串行化:对同一行数据,读写都加锁,发生锁冲突时,后面的事务等前面执行完才能执行。

示例:

事务A事务B
1启动事务启动事务
2查询得到值为1查询得到值为1
3将1改为2
4查询得到值 v1
5提交事务
6查询得到值 v2
7提交事务
8查询得到值 v3

下面我们看看不同隔离级别下,v1、v2、v3 分别是多少

读未提交:v1是2,虽然B未提交但结果对A可见,v2v3也是2。
读已提交:v1是1,v2v3才是2。
可重复读:v1、v2是1,事务A未提交前看到的数据保持一致,v3才是2。
串行化:事务A查询会加锁,事务B执行更新被锁住,直到A提交后B才能继续执行。因此v1、v2是1,v3是2

小结:

  1. 隔离级别实现上离不开视图创建,读已提交在每个SQL语句开始执行时创建;可重复读在事务启动时创建。
  2. 读未提交直接返回记录上的最新值,没有视图概念;串行化使用加锁避免并行访问。

MySQL事务

MySQL是一个支持多引擎系统,但不是所有引擎都支持事务。
事务支持是在引擎层实现的,我们以常见的 InnoDB 引擎为例。

MySQL实现隔离级别

MySQL通过回滚日志实现”可重复读“隔离级别。
每一条记录在更新时会记录一条回滚操作,记录上最新值可通过回滚,得到前一个状态值。
不同的事务中的视图中,同一条记录可能存在多个版本,这就是数据库的多版本并发控制(MVCC)

MVCC

同一行记录存在多个版本,不同事务的快照(视图)是如何选取自己需要的版本呢?

  1. 每个事务在开始时向InnoDB申请一个的事务id,这个id是严格按照申请顺序递增的
  2. 每个数据版本都是由事务更新生成的,版本号就是对应的事务id,它说明了这个版本由谁生成
  3. 一行记录除了最新版本,其它旧版本都不是物理上真实存在的,都是通过当前版本和undo log计算得到
  4. 数据版本对事务视图是否可见总结如下:除了自己更新的总是可见
    • 版本未提交,不可见;
    • 版本已提交,但是是在视图创建后提交的,不可见;
    • 版本已提交,而且是在视图创建前提交的,可见。

InnoDB 利用了“所有数据都有多个版本”的这个特性,实现了“秒级创建快照”的能力。
MVCC也只适用于有视图概念的隔离级别

更新操作

RR(可重复读)隔离级别,如果只是查询操作,那么在事务执行期间会一直使用快照视图。
如果需要更新数据,能在视图基础上更新吗?答案是不能的,因为会丢失掉其它事务的更新(其它版本)

因此更新操作不能使用一致性读,而需要当前读(最新版本),当前读需要拿锁访问。所以不同事务更新相同行,由于行锁冲突进入锁等待。

注意:
如果更新数据失败,即该数据最新版本号非当前事务id,则继续查询该数据依然拿的是一致性视图

这就是一致性读、当前读、行锁之间的关系。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值