mysql———事务和事务的隔离性(代码片段)

wtxuebc wtxuebc     2022-12-08     455

关键词:

文章目录

    事务在现阶段数据库中很常见,因为现版本 InnoDB 代替了 MySQL 的原生存储引擎 MyISAM,这与它不支持事务有很大关系;而 InnoDB 是支持事务的,所以说事务的操作是在引擎层的;事务的实现和 InnoDB 的 redo log 密不可分,本篇博客主要讲事务的隔离性及底层实现;学术有限,欢迎大佬补充!

事务:简单来说,事务就是要保证一组数据库操作,要么全部成功,要么全部失败;原子的执行一组数据库操作

​    在 MySQL 中,事务是在引擎层实现的。MySQL 是一个支持多引擎的系统,因为Server层和引擎层是分离开来的,引擎层是插件式的,支持多个存储引擎,其中Server层执行引擎层提供的接口; 但是并不是所有的存储引擎都支持事务。MySQL 原生引擎 MyISAM就不支持事务,这也是MyISAM 被 InnoDB 取代的中啊哟原因之一;

    本篇文章以 InnoDB 为例,刨析 MySQL 在事务支持方面的隔离性实现实现;

事务的ACID

​     事务的 ACID 就是 A(Atomicity原子性)C(Consistency一致性)I(Isolation隔离性)D(Durability持久性);

​     Atomicity(原子性):一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简。
​     Consistency(一致性):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。
​     Isolation(隔离性):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。
​     Durability(持久性):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。( 感兴趣的同学可以了解一下 redo log )

隔离与隔离级别

​     当数据库上有多个事务同时执行的时候,就有可能出现脏读 ( 读到其他事务为提交的数据 ) 、不可重复读 ( 前后读取的内容不一样,主要是读到更新带来的内容 ) 、幻读 ( 读到了上次没有的内容,单指插入带来的内容 )

​     需要解决上面带来的问题,就需要对事物进行隔离;在谈隔离之前你要知道,隔离的越严实,效率越低;因此很多时候,我们都要在二者之间找一个平衡点。

​     在进行隔离的时候,不同的隔离程度会解决不同程度带来的问题,因此涉及到一个隔离级别;

​ SQL标准的事务隔离级别包括:

​     未提交读(Read uncommitted)(一个事务还没提交时,它做的变更就就被别的事务看到)

​     提交读(read committed)(一个事务提交之后,它做的变更才能被其他事务看到)

​     可重复读(repeatable read) ( 一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。 )

​     串行化(Serializable)(顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。)

再注意一个窍门:可重复读和串行化的区别是:

    可重复读隔离级别下的事务 A 没提交时,“别的事务 B 已经对他的数据做了修改“,而必须等 A 提交后,B修改的数据才能读到;但是A还没提交时,此时B已经修改了!

而串行化加锁了!B 再修改时就阻塞了!必须等 A 提交后,B才能修改,“此时A还没提交时,B不可能提交成功!,B必须在A后面提交!”

举一个简单的例子更形象的了解隔离级别:

mysql> create table T(c int) engine = InnoDB;
inset into T(c) values(1);


​     我们来看看在不同的隔离级别下,事务 A 会有哪些不同的返回结果,也就是图里面 V1、V2、V3 的返回值分别是什么。

  • 若隔离级别是“读未提交”, 则 V1 的值就是 2。这时候事务 B 虽然还没有提交,但是结果已经被 A 看到了。因此,V2、V3 也都是 2。
  • 若隔离级别是“读提交”,则 V1 是 1,V2 的值是 2。事务 B 的更新在提交后才能被 A 看到。所以, V3 的值也是 2。
  • 若隔离级别是“可重复读”,则 V1、V2 是 1,V3 是 2。之所以 V2 还是 1,遵循的就是这个要求:事务在执行期间看到的数据前后必须是一致的。
  • 若隔离级别是“串行化”,则在事务 B 执行“将 1 改成 2”的时候,会被锁住。直到事务 A 提交后,事务 B 才可以继续执行。所以从 A 的角度看, V1、V2 值是 1,V3 的值是 2。

数据库的视图:

    在实现上,数据库里面会创建一个视图,访问程度时候以视图的逻辑结果为准;

    在 “可重复度” 隔离级别下, 这个视图是在事务启动时创建的,整个事务存在期间都用这个视图,事务结束后新的语句执行时会给予最近的数据创建一个新的视图
    在 “读提交” 隔离级别下,这个视图是在每个 SQL 语句来时执行时的时候创建的。因此每个语句在执行时会给予最新的数据创建一个新的视图
    “读未提交” 隔离级别下直接返回记录的最新值,没有视图概念
    而 “串行化” 隔离级别下直接用加锁的方式避免并行访问;

事务隔离的实现

​     在 MySQL 中,实际上每条记录在更新的时候都会同时记录一条回滚操作。记录上的最新值,通过回滚操作,都可以得到前一个状态的值;就是说,除了记录变更记录,还会记录一条变更相反的回滚操作记录,前者记录在redo log,后者记录在undo log ( **回滚日志,也就是rollback,记录的是更新的逆过程,如果你执行了insert语句,那么undo log记录的就是delete,以此类推 **)。

    假设一个值从 1 被按顺序改成了 2、3、4,在回滚日志里面就会有类似下面的记录。


     当前值是 4,但是在查询这条记录的时候,不同时刻启动的事务会有不同的视图 (read-view)。如图中看到的,在视图 A、B、C 里面,这一个记录的值分别是 1、2、4,同一条记录在系统中可以存在多个版本,就是数据库的多版本并发控制(MVCC)。对于视图 A,要得到 1,就必须将当前值依次执行图中所有的回滚操作得到

​     同时你会发现,即使现在有另外一个事务正在将 4 改成 5,这个事务跟 read-view A、B、C 对应的事务是不会冲突的。

​     在可重复读隔离级别中,表中的数据其实已经改变,在前面的视图里,需要查找某条记录时,是通过取当前数据,再取视图对应的回滚段回滚到该视图的值。

那么回滚日志什么时候删除?

​     在不需要的时候!在系统判断当没有事务再需要用到这些回滚日志时,回滚日志会被删除。(评判标准是,当前系统里没有比这个回滚日志更早的视图的时候,就是说这个数据不会再有谁驱使他回滚了! 请看上面图下面的那句话,[对于视图 A,要得到 1,就必须将当前值依次执行图中所有的回滚操作得到],若没有像视图A这样比回滚日志更早的视图时,回滚日志会被删除!)

为什么建议尽量不要用长事务?

​     长事务意味着系统里面会存在很老的事务视图。由于这些事务随时可能访问数据库里面的任何数据,所以这个事务提交之前,数据库里面它可能用到的回滚记录都必须保留,这就会导致大量占用存储空间(就是说!长事务导致对应的事务视图长时间存在,那么对应的回滚日志也是会一直存在的,占内存!)。

​ 长事务除了对回滚段的影响,还占用锁资源!

事务的启动方式

​     如前面所述,长事务有这些潜在风险,我当然是建议你尽量避免。其实很多时候业务开发同学并不是有意使用长事务,通常是由于误用所致。MySQL 的事务启动方式有以下几种:

  • 显式启动事务语句, begin 或 start transaction。配套的提交语句是 commit,回滚语句是 rollback

  • set autocommit=0,这个命令会将这个线程的自动提交关掉。意味着如果你只执行一个 select 语句,这个事务就启动了,而且并不会自动提交。这个事务持续存在直到你主动执行 commit 或 rollback 语句,或者断开连接

    ​     有些客户端连接框架会默认连接成功后先执行一个 set autocommit=0 的命令。这就导致接下来的查询都在事务中,如果是长连接,就导致了意外的长事务。
    ​     因此,我会建议你总是使用 set autocommit=1, 通过显式语句
    的方式来启动事务。

    ​     在 autocommit 为 1 的情况下,用 begin 显式启动的事务,如果执行 commit 则提交事务。如果执行 commit work and chain,则是提交事务并自动启动下一个事务,这样也省去了再次执行 begin 语句的开销。同时带来的好处是从程序开发的角度明确地知道每个语句是否处于事务中。你可以在 information_schema 库的 innodb_trx 这个表中查询长事务,比如下面这个语句,用于查找持续时间超过 60s 的事务。

事务的启动时机:

  • 第一种启动方式:是在执行第一个快照语句时创建的;
  • 第二种启动方式:是在执行 start transaction with consistent snapshot时创建的。

一致性视图没有物理结构,作用是事务执行期间用来定义 ” 我能看到什么数据“

两种操作的 “ 读 ”!

查询逻辑:

一个数据版本,对于一个事务视图来说,除了自己的更新总是可见以外,有三种情况:

    版本未提交,不可见;

    版本已提交,但是是在视图创建后提交的,不可见;

    版本已提交,而且是在视图创建前提交的,可见。

    一致性读 :虽然这一行数据被修改过,但是事务 A 不论在什么时候查询,看到这行数据的结果都是一样的。

更新逻辑:

    更新数据都是先读后写的,而这个读,只能读当前的值,称为“当前读”(current read)

mysql事务四大特性和事务隔离级别(代码片段)

文章目录1.MySQL事务的四大特性2.MySQL事务的并发问题3.MySQL事务的隔离级别1.MySQL事务的四大特性MySQL事务具有四个特性:原子性、一致性、隔离性、持久性,这四个特性简称ACID特性一、原子性(Atomicity):一个... 查看详情

mysql事务readcommitted隔离级别的数据可见性(代码片段)

模拟MySQL事务ReadCommited已提交读隔离级别数据的可见性。预先创建一张表test,表中只有一个字段state。createtabletest(stateintnotnull)engine=InnoDBcharset=utf8mb4;在两个终端中分别开启两个事务:事务的隔离级别是ReadCommitted结论:在ReadCommitt... 查看详情

mysql———事务和事务的隔离性(代码片段)

文章目录事务的ACID隔离与隔离级别事务隔离的实现事务的启动方式事务的启动时机:两种操作的“读”!  事务在现阶段数据库中很常见,因为现版本InnoDB代替了MySQL的原生存储引擎MyISAM,这与它不支持事务有很大... 查看详情

mysql事务(代码片段)

文章目录二、MySQL事务2.1、事务的概念2.2、事务的ACID特点①原子性(Atomicity)②一致性(Consistency)③隔离性(Isolation)ⅰ查询全局事务隔离级别:ⅱ查询会话事务隔离级别ⅲ设置全局事务隔离级别ⅳ... 查看详情

mysql事务(代码片段)

文章目录二、MySQL事务2.1、事务的概念2.2、事务的ACID特点①原子性(Atomicity)②一致性(Consistency)③隔离性(Isolation)ⅰ查询全局事务隔离级别:ⅱ查询会话事务隔离级别ⅲ设置全局事务隔离级别ⅳ... 查看详情

mysql事务隔离级别(代码片段)

MySQL的事务必须满足A(原子性)C(一致性)I(隔离性)D(持久性)原则。其中,隔离性是为了尽量减少并发事务彼此之间的影响,最高的隔离级别可以保证并发事务之间互不影响。  在... 查看详情

mysql的事务四个特性以及事务的四个隔离级别(代码片段)

一、事务四大属性分别是原子性、一致性、隔离性、持久性。1、原子性(Atomicity)原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能... 查看详情

mysql的事务四个特性以及事务的四个隔离级别(代码片段)

一、事务四大属性分别是原子性、一致性、隔离性、持久性。1、原子性(Atomicity)原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能... 查看详情

[javaweb-mysql]事务的四大特征和隔离级别(代码片段)

事务的四大特征: 1.原子性:是不可分割的最小操作单位,要么同时成功,要么同时失败。 2.持久性:当事务提交或回滚后,数据库会持久化的保存数据。 3.隔离性:多个事务之间。相互独立。 4.一致... 查看详情

mysql事务实现原理(代码片段)

事务是什么?首先思考一个问题,事务是什么?以下是事务的相关解释MySQL中的事务是一种用于确保数据库操作的完整性和一致性的机制。事务处理具有以下四个基本特性,通常被称为ACID特性:原子性(Atomicity):原子性是指事... 查看详情

mysql事务隔离(代码片段)

阅读目录事务的介绍隔离级别1READUNCOMMITTED(未提交读)2READCOMMITTED(提交读)3REPEATABLEREAD(可重复读)SERIALIZABLE(可串行化)事务隔离的实现事务启动的方式事务的介绍事务就是一组原子性的sql查询,或者说是一个独立的工作单元。简... 查看详情

mysql事务隔离级别(2022.05.15)(代码片段)

事务是什么?一般是指要做的或所做的事情为什么要引入事务?为了保证工作流程中操作的数据的可靠性原子性(Atomicity):指的是事务是一个不可分割的单位,要么事务中的所有的操作全部成功,要么全... 查看详情

mysql高级篇——事务的隔离级别与简单应用(代码片段)

...发所存在的问题1.1脏写1.2脏读1.3不可重复读1.4幻读2.SQL中事务的隔离级别3.案例实操3.1查看与修改MySQL的隔离级别3.2读未提交-举例3.3 读已提交-举例3.4 可重复读-举例3.5 幻读-举例1.数据并发所存在的问题针对事务的隔离性和并发... 查看详情

从头开始搞懂mysql(03)事务隔离性(代码片段)

1、什么是事务?提到事务,我们肯定不陌生,和数据库打交道的时候,我们肯定会用到事物经典案例就是转账,小孙要给小白转100块钱,现在小孙的卡里只有100块钱。转账过程具体到程序里会有一系列操... 查看详情

mysql-mvcc多版本控制及事务的隔离性(代码片段)

MySQL事务的启动方式隐式:执行SQL语句自动提交(前提MySQL使用SETAUTOCOMMIT=1开启自动提交)显式:begin/starttransaction;updateusersetusername='timi'whereid=1;commit;begin/starttransaction命 查看详情

mysql的事务详解(代码片段)

...ySQL✨一句短话:难在坚持,贵在坚持,成在坚持!文章目录一.事务的业务场景二.事务的使用三.事务的特性(ACID)1.原子性(Atomicity)2.一致性(Consistency)3.持久性(Durability)4.隔离性(Isolation)四.事务并发异常1.脏读2.不可重复读3.幻读四.MySQL的... 查看详情

mysql事务(代码片段)

@[TOC]Mysql事务简介事务四大特征(ACID)推荐:https://blog.csdn.net/lianghecai52171314/article/details/102782804原子性:事务是最小单位,不可再分,例如:update…insert…delete…一致性:所有的DML语句操作,必须同时成功... 查看详情

mysql的事务和引擎,注意细品(代码片段)

mysql事务和引擎一、MySQL事务(一)、MySQL事务的概念(二)、事务的ACID特点1、ACID特点2、数据不一致产生的结果:(三)、事务的隔离1、MySQL事物隔离级别1.1查询全局事务隔离级别1.2查询会话事务隔离级别1.3设... 查看详情