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

文章目录

    • 事务隔离级别
      • 解析
    • 常用命令
      • 查看事务隔离级别设置
      • 修改隔离级别
      • 隔离级别演示
      • Mysql事务操作
    • MVCC实现原理
      • undo log版本链
      • ReadView
    • 练习一下
      • 案例1
      • 案例2
    • 问答环节
      • 1、Mysql 可重复读到底有没有解决幻读?

事务隔离级别

Mysql的事务隔离级别是由Mysql的各种锁以及MVCC机制来实现的。
不同隔离级别存在的问题:
Mysql事务隔离级别是怎么实现的?_第1张图片

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

解析

Undo Log版本链
Mysql事务隔离级别是怎么实现的?_第3张图片

RC隔离级别时的ReadView:
Mysql事务隔离级别是怎么实现的?_第4张图片

常用命令

查看事务隔离级别设置

# 查看事务隔离级别 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(回滚指针):指向上一个版本的数据。
    Mysql事务隔离级别是怎么实现的?_第5张图片

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会被重新创建,可以读取到其他事务提交后被新增的数据。

你可能感兴趣的:(#,数据库,mysql,数据库,java)