🍖事务隔离机制

一.事务隔离机制介绍

事务具备原子性、一致性、隔离性、持久性四大特性python

隔离性顾名思义指的就是事务彼此之间隔离开, 多个事务在同时处理一个数据时彼此之间互相不影响, 如若是隔离的不够好就有可能会产生脏读、不可重复度、幻读等读现象mysql

二.隔离性的四个级别

1.等级(隔离程度)由低到高

  • Read uncommitted (未提交读)
  • Read committed (提交读)
  • Repeatable read (可重复读) (mysql默认)
  • Serializable (可序列化)

2.依次解决的读现象

  • ✔ : 可能出现sql

  • ❌ : 不会出现数据库

  脏读 不可重复读 幻读
Read uncommitted
Read committed ×
Repeatable read(mysql默认) × ×
Serializable × × ×

须要强调的是 : 咱们确实能够采用提升事务的隔离级别的方式来解决脏读、不可重复读、幻读等问题, 但与此同时, 事务的隔离级别越高, 并发能力也就越低; 因此, 还须要读者根据业务须要进行权衡session

三.四种级别介绍

1.未提交读 (Read uncommitted)

  • 定义

是最低的隔离级别, 在这种事务隔离级别下, 一个事务能够读到另一个事务未提交的数据并发

  • 数据库加锁状况(实现原理)

事务在读数据的时候并未对数据加锁spa

事务在修改数据的时候只对数据增长行级共享锁code

  • 现象解释

事务1读取某行记录时, 事务2也能对这行记录进行读取、更新, 而且由于事务一并未对数据增长任何锁索引

当事务2也对该记录进行更新时, 事务1再次读取该记录, 能读到事务2对该记录的修改版本 (由于事务2只增长了共享读锁, 事务1能够再增长共享读锁读取数据), 即便该修改还没有被提交, 若此时事务2回滚, 那事务1读到的就脏数据了, 这就引起了脏读现象事务

事务1更新某行记录时, 事务2不能对这行记录作更新, 直到事务1结束 (由于事务1对数据增长了共享读锁, 事务2不能增长排他写锁进行数据的修改)

2.提交读 (Read committed)

  • 定义

能够理解成都已提交, 在一个事务修改数据过程当中, 若是事务还没提交, 其余事务不能读该数据

  • 数据库加锁状况

事务对当前被读取的数据增长行级共享锁(读到时才加锁), 一旦读完该行, 当即释放该行行级共享锁

事务在更新某数据的瞬间(在更新的瞬间), 必须先对其加行级排它锁, 直到事务结束才释放

  • 现象解释

事务1在读取某行记录的整个过程当中, 事务2均可以对该行记录进行读取 (由于事务一对该行记录增长行级共享锁的状况下, 事务二一样能够对该数据增长共享锁来读数据)

事务1读取某行的一瞬间, 事务2不能修改该行数据, 可是, 只要事务1读取完改行数据, 事务2就能够对该行数据进行修改 (事务一在读取的一瞬间会对数据增长共享锁, 任何其余事务都不能对该行数据增长排他锁; 可是事务一只要读完该行数据, 就会释放行级共享锁, 一旦锁释放, 事务二就能够对数据增长排他锁并修改数据)

事务1更新某行记录时, 事务2不能对这行记录作更新, 直到事务1结束 (事务一在更新数据的时候, 会对该行数据增长排他锁, 知道事务结束才会释放锁, 因此, 在事务二没有提交以前, 事务一都能不对数据增长共享锁进行数据的读取; 因此, 提交读能够解决脏读的现象)

3.可重复读 (Repeatable reads)

  • 定义

因为提交读隔离级别会产生不可重复读的读现象, 因此比提交读更高一个级别的隔离级别就能够解决不可重复读的问题, 这种隔离级别就叫可重复读

  • 数据库锁状况

事务在读取某数据的瞬间 (就是开始读取的瞬间), 必须先对其加行级共享锁, 直到事务结束才释放

事务在更新某数据的瞬间 (就是发生更新的瞬间), 必须先对其加行级排他锁, 直到事务结束才释放

  • 现象解释

事务1在读取某行记录的整个过程当中, 事务2均可以对该行记录进行读取 (由于事务一对该行记录增长行级共享锁的状况下, 事务二一样能够对该数据增长共享锁来读数据)

事务1在读取某行记录的整个过程当中, 事务2都不能修改该行数据 (事务一在读取的整个过程会对数据增长共享锁, 直到事务提交才会释放锁, 因此整个过程当中, 任何其余事务都不能对该行数据增长排他锁; 因此, 可重复读可以解决不可重复读的读现象)

事务1更新某行记录时, 事务2不能对这行记录作更新, 直到事务1结束 (事务一在更新数据的时候, 会对该行数据增长排他锁, 知道事务结束才会释放锁, 因此, 在事务二没有提交以前, 事务一都能不对数据增长共享锁进行数据的读取; 因此, 提交读能够解决脏读的现象)

4.可序列化 (Serializable)

  • 定义

是最高的隔离级别, 前面三种隔离级别都没法解决的幻读, 在可序列化的隔离级别中能够解决

  • 数据库锁状况

事务在读取数据时, 必须先对其加表级共享锁, 直到事务结束才释放

事务在更新数据时, 必须先对其加表级排他锁, 直到事务结束才释放

  • 现象解释

事务1正在读取A表中的记录时, 则事务2也能读取A表, 但不能对A表作更新、新增、删除, 直到事务1结束 (由于事务一对表增长了表级共享锁, 其余事务只能增长共享锁读取数据, 不能进行其余任何操做)

事务1正在更新A表中的记录时, 则事务2不能读取A表的任意记录, 更不可能对A表作更新、新增、删除, 直到事务1结束 (事务一对表增长了表级排他锁, 其余事务不能对表增长共享锁或排他锁, 也就没法进行任何操做)

  • 序列化事务产生的效果
  • 没法读取其余事务已经修改单位提交的记录
  • 在当前事务完成以前, 其余事务不能修改当前事务已经读取的记录
  • 在当前事务完成以前, 其余事务插入的新记录, 其索引键值不能在当前事务的任何语句所读取的索引键范围中

5.隔离级别的选择

四种事务隔离级别从隔离程度上愈来愈高, 但同时在并发性上也就愈来愈低; 之因此有这么几种隔离级别, 就是为了方便开发人员在开发过程当中根据业务须要选择最合适的隔离级别

四.修改事务隔离级别

1.查看当前事务隔离级别

  • 能够经过模糊匹配变量名
show variables like "%tx_isolation";

image-20210302190403075

  • 直接查看变量 tx_isolation
select @@tx_isolation;

image-20210302190600192

  • 也能够经过如下语句查看
select @@global.tx_isolation;   # 查看全局事务隔离级别
select @@session.tx_isolation;  # 查看当前会话事务隔离级别

image-20210302190857307

ps : 在MySQL 8.0.3 中, tx_isolation 变量被 transaction_isolation 变量替换了; 在 MySQL 8.0.3 版本中查询事务隔离级别, 只要把上述查询语句中的 tx_isolation 变量替换成 transaction_isolation 变量便可

2.修改事务隔离级别

Mysql提供了 set transaction 语句来改变单个会话或者全局会话的事务隔离级别

set [session|global] transaction isolation level
    [read ununcommitted|read committed|repeatable read|serializable]
  • session : 表示修改的事务隔离级别将应用于当前 session(当前 cmd 窗口) 内的全部事务
  • global : 表示修改的事务隔离级别将应用于全部 session (全局) 中的全部事务, 且当前已经存在的 session 不受影响
  • 若是省略 session 和 global, 则表示修改的事务隔离级别将应用于当前 session 内的下一个还未开始的事务

3.用户权限问题

任何用户都能改变会话的事务隔离级别, 可是只有拥有 super 权限的用户才能改变全局的事务隔离级别

  • 验证修改全局事务隔离级别, 当前会话不受影响
select @@global.tx_isolation;   # 查看全局事务隔离级别
select @@session.tx_isolation;  # 查看当前会话事务隔离级别
set global transaction isolation level read committde; 
# 修改全局事务隔离级别

image-20210302195744397

  • 能够经过直接修改 tx_isolation 变量来修改当前 session 的事务隔离级别
set tx_isolation="read-committed";
select @@session.tx_isolation;

image-20210302204911467

---end---

相关文章
相关标签/搜索