Mysql事务隔离级别是怎么实现的?

事务隔离级别

Mysql的事务隔离级别是由Mysql的各种锁以及MVCC机制来实现的。
不同隔离级别存在的问题:
在这里插入图片描述

在Mysql Innodb存储引擎下,RC、RR是基于MVCC(多版本并发控制)进行并发事务控制的。
先来看一个问题,先想一下在不同隔离级别下,事务D读取到的内容是什么?

解析

Undo Log版本链
在这里插入图片描述

RC隔离级别时的ReadView:
在这里插入图片描述

常用命令

查看事务隔离级别设置

# 查看事务隔离级别 5.7.20 之后
show variables like 'transaction_isolation';
SELECT @@transaction_isolation

# 5.7.20 之后
SELECT @@tx_isolation
show variables like 'tx_isolation'

+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |
+---------------+-----------------+

修改隔离级别

完整设置语句

SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}

案例:设置全局隔离级别为读提交级别。

mysql> set global transaction isolation level read committed;

隔离级别演示

set tx_isolation='read-committed';
BEGAIN;
UPDATE t_user set name = '子涵先生';COMMIT;

Mysql事务操作

Mysql事务开启有两种方式:

  • begin/start transaction:begin/start transaction 命令并不是一个事务的起点,在执行到它们之后的第一个操作InnoDB表的语句,事务才真正启动。
  • start transaction with consistent snapshot:这个命令可以立即启动一个事务。

InnoDB里面每个事务有一个唯一的事务ID,叫作transaction id。它是在事务开始的时候向InnoDB的事务系统申请的,是按申请顺序严格递增的。

MVCC实现原理

MVCC的实现原理是基于:undolog版本链+Readview。

undo log版本链

  • trx_id:事务版本号,自增;
  • DB_ROLL_PTR(回滚指针):指向上一个版本的数据。
    在这里插入图片描述

UBDO_LOG版本链不是立即删除的,Mysql在确保版本链数据不再被“引用”后才会进行删除。

ReadView

ReadView的作用:从版本链中读取数据,数据读取的时候为“快照读”。

补充一下:

  1. 快照读:普通的select查询语句;
  2. 当前读:Insert、Update、Delete、Select … for update、Select …lock in share mode。

ReadView的结构:

  • m_ids:表示在生成readview时,当前系统中活跃的读写事务id列表;
  • min_trx_id:表示在生成readview时,当前系统中活跃的读写事务中最小的事务id,也就是m_ids中最小的值;
  • max_trx_id:表示生成readview时,系统中应该分配给下一个事务的id值;
  • creator_trx_id:表示生成该readview的事务的事务id。

MVCC中的数据读取规则

  1. 优先读取当前事务版本中的数据;
  2. 否则根据版本链找到非活跃事务中的数据。

READ COMMITTEDREPEATABLE READ均是基于MVCC实现的,其区别就在于ReadView中的的生成时机:

  • READ COMMITTED生成时机是在每次查询时;
  • REPEATABLE READ是在当前事务开启时创建的。

练习一下

案例1

事务A:

select * from user where user_name ='张三';  -- 张三user_age为50
-- 此时事务B执行一下
select * from user where user_name ='张三';  -- question1:在两种不同的事务隔离级别下,张三user_age为结果为多少?

事务B:

insert into user (user_name,user_age) values ('张三',25);

案例2

事务A:

select * from user where user_name ='张三';  -- 张三user_age为50
-- 此时事务B执行一下
select * from user where user_name ='张三';  -- question1:张三user_age为结果为多少?
update set user_age = 100 where user_name ='张三'; 
select * from user where user_name ='张三';  -- question2:张三user_age为结果为多少?

事务B:

insert into user (user_name,user_age) values ('张三',25);

问答环节

1、Mysql 可重复读到底有没有解决幻读?

幻读的官网解释:The so-calledphantomproblem occurs within a transaction when the same query produces different sets of rows at different times. For example, if aSELECTis executed twice, but returns a row the second time that was not returned the first time, the row is a“phantom”row.

能,但不完全能,遇到当前读的时候,ReadView会被重新创建,可以读取到其他事务提交后被新增的数据。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子涵先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值