十四、详解事务

本篇内容

  1. 什么是事务,它有什么用?
  2. 事务的几个特性
  3. 事务常见操作指令详解
  4. 事务的隔离级别详解
  5. 脏读、不可重复读、可重复读、幻读详解
  6. 演示各种隔离级别产生的现象
  7. 关于隔离级别的选择

一、什么是事务?

  数据库中的事务是指对数据库执行一批操作,这些操作最终要么全部执行成功,要么全部失败,不会存在部分成功的情况。

二、事务的几个特性(ACID)  

  原子性(Atomicity)

  事务的整个过程如原子操作一样,最终要么全部成功,或者全部失败,这个原子性是从最终结果来看的,从最终结果来看这个过程是不可分割的。

  一致性(Consistency)

  事务开始之前、执行中、执行完毕,这些时间点,多个人去观察事务操作的数据的时候,看到的数据都是一致的,比如在事务操作过程中,A连接看到的是100,那么B此时也去看的时候也是100,不会说AB看到的数据不一样,他们在某个时间点看到的数据是一致的。

  隔离性(Isolation)

  一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

  持久性(Durability)

  一个事务一旦提交,他对数据库中数据的改变就应该是永久性的。当事务提交之后,数据会持久化到硬盘,修改是永久性的。

三、Mysql中事务操作  

  mysql中事务默认是隐式事务,执行insert、update、delete操作的时候,数据库自动开启事务、提交或回滚事务。

  是否开启隐式事务是由变量autocommit控制的。

  所以事务分为隐式事务显式事务。  

  隐式事务

  事务自动开启、提交或回滚,比如insert、update、delete语句,事务的开启、提交或回滚由mysql内部自动控制的。

  查看变量autocommit是否开启了自动提交

  show variables like ‘autocommit‘;  --autocommit为ON表示开启了自动提交。  

  显式事务

  事务需要手动开启、提交或回滚,由开发者自己控制。

  方式1:

    //设置不自动提交事务
    set autocommit=0;
    //执行事务操作
    commit|rollback;

    set autocommit=0;

    insert into test1 values(1);

    commit;    ----rollback;

    set autocommit=1;  --把autocommit还原回去

  方式2:

    start transaction;//开启事务
    //执行事务操作
    commit|rollback;

    start transaction;

    insert into test1 values (2);

    insert into test1 values (3);    

    commit;    ----rollback;  

  savepoint关键字  

    在事务中我们执行了一大批操作,可能我们只想回滚部分数据,怎么做呢?

    我们可以将一大批操作分为几个部分,然后指定回滚某个部分。可以使用savepoin来实现,效果如下:

    start transaction;

    insert into test1 values (1);

    savepoint part1;//设置一个保存点

     insert into test1 values (2);

    rollback to part1;//将savepint = part1的语句到当前语句之间所有的操作回滚

    commit;//提交事务

    savepoint需要结合rollback to sp1一起使用,可以将保存点sp1rollback to之间的操作回滚掉。  

  只读事务

    表示在事务中执行的是一些只读操作,如查询,但是不会做insert、update、delete操作,数据库内部对只读事务可能会有一些性能上的优化。

    start transaction read only;

    示例:

    start transaction read only;

    select * from test1;

    delete from test1;

    ERROR 1792 (25006): Cannot execute statement in a READ ONLY transaction.
    commit;

    ----只读事务中执行delete会报错。

四、事务中的一些问题

  这些问题主要是基于数据在多个事务中的可见性来说的。  

  脏读

    一个事务在执行的过程中读取到了其他事务还没有提交的数据。
    这个还是比较好理解的。  

  读已提交    

    从字面上我们就可以理解,即一个事务操作过程中可以读取到其他事务已经提交的数据。

    事务中的每次读取操作,读取到的都是数据库中其他事务已提交的最新的数据(相当于当前读)  

  可重复读

    一个事务操作中对于一个读取操作不管多少次,读取到的结果都是一样的。  

  幻读

    脏读、不可重复读、可重复读、幻读,其中最难理解的是幻读

    幻读在可重复读的模式下才会出现,其他隔离级别中不会出现    

    幻读现象例子:

    可重复读模式下,比如有个用户表,手机号码为主键,有两个事物进行如下操作

    事务A操作如下:
      1、打开事务
      2、查询号码为X的记录,不存在
      3、插入号码为X的数据,插入报错(为什么会报错,先向下看)
      4、查询号码为X的记录,发现还是不存在(由于是可重复读,所以读取记录X还是不存在的)

    事物B操作:

        在事务A第2步操作时插入了一条X的记录,所以会导致A中第3步插入报错(违反了唯一约束)

        上面操作对A来说就像发生了幻觉一样,明明查询X(A中第二步、第四步)不存在,但却无法插入成功

      幻读可以这么理解:事务中后面的操作(插入号码X)需要上面的读取操作(查询号码X的记录)提供支持,但读取操作却不能支持下面的操作时产生的错误,就像发生了幻觉一样。

五、事务的隔离级别  

  当多个事务同时进行的时候,如何确保当前事务中数据的正确性,比如A、B两个事物同时进行的时候,A是否可以看到B已提交的数据或者B未提交的数据,这个需要依靠事务的隔离级别来保证,不同的隔离级别中所产生的效果是不一样的。

  事务隔离级别主要是解决了上面多个事务之间数据可见性及数据正确性的问题。

  隔离级别分为4种:

  1. 读未提交:READ-UNCOMMITTED
  2. 读已提交:READ-COMMITTED
  3. 可重复读:REPEATABLE-READ
  4. 串行:SERIALIZABLE

  上面4中隔离级别越来越强,会导致数据库的并发性也越来越低。   

  查看隔离级别:show variables like ‘transaction_isolation‘;  

  隔离级别的设置    

    分2步骤,修改文件、重启mysql,如下:

    修改mysql中的my.init文件,我们将隔离级别设置为:READ-UNCOMMITTED,如下:

    # 隔离级别设置,READ-UNCOMMITTED读未提交,READ-COMMITTED读已提交,REPEATABLE-READ可重复读,SERIALIZABLE串行
transaction-isolation=READ-UNCOMMITTED

    以管理员身份打开cmd窗口,重启mysql,如下:

    C:\Windows\system32>net stop mysql
    mysql 服务正在停止..
    mysql 服务已成功停止。

    C:\Windows\system32>net start mysql
    mysql 服务正在启动 .
    mysql 服务已经启动成功。    

  各种隔离级别中会出现的问题

  

隔离级别 脏读 不可重复读 幻读
READ-UNCOMMITTED
READ-COMMITTED
REPEATABLE-READ
SERIALIZABLE

  READ-UNCOMMITTED:读未提交

    读未提交情况下,可以读取到其他事务还未提交的数据,多次读取结果不一样,出现了脏读、不可重复读  

  READ-COMMITTED:读已提交

    读已提交情况下,无法读取到其他事务还未提交的数据,可以读取到其他事务已经提交的数据,多次读取结果不一样,未出现脏读,出现了读已提交、不可重复读。  

  REPEATABLE-READ:可重复读   

    可重复读情况下,未出现脏读,未读取到其他事务已提交的数据,多次读取结果一致,即可重复读。  

    幻读演示

    幻读只会在REPEATABLE-READ(可重复读)级别下出现,需要先把隔离级别改为可重复读。    

    A想插入数据***,插入之前先查询了一下(T5时刻)该用户是否存在,发现不存在,然后在T7时刻执行插入,报错了,报数据已经存在了,因为T6时刻B已经插入了***

    然后A有点郁闷,刚才查的时候不存在的,然后A不相信自己的眼睛,又去查一次(T8时刻),发现***还是不存在的。

    此时A心里想:数据明明不存在啊,为什么无法插入呢?这不是懵逼了么,A觉得如同发生了幻觉一样。  

  SERIALIZABLE:串行

    SERIALIZABLE会让并发的事务串行执行。

时间 窗口A 窗口B
T1 start transaction;  
T2 select * from test1;  
T3   start transaction;
T4   insert into test1 values (1);
T5 select * from test1;  
T6 commit;  
T7   commit;

  按时间顺序运行上面的命令,会发现T4-B这样会被阻塞,直到T6-A执行完毕。

  可以看出来,事务只能串行执行了。串行情况下不存在脏读、不可重复读、幻读的问题了。

六、关于隔离级别的选择  

  1. 需要对各种隔离级别产生的现象非常了解,然后选择的时候才能游刃有余
  2. 隔离级别越高,并发性也低,比如最高级别SERIALIZABLE会让事物串行执行,并发操作变成串行了,会导致系统性能直接降低。
  3. 具体选择哪种需要结合具体的业务来选择。
  4. 读已提交(READ-COMMITTED)通常用的比较多。

七、总结  

  1. 理解事务的4个特性:原子性、一致性、隔离性、持久性
  2. 掌握事务操作常见命令的介绍
  3. set autocommit可以设置是否开启自动提交事务
  4. start transaction:开启事务
  5. start transaction read only:开启只读事物
  6. commit:提交事务
  7. rollback:回滚事务
  8. savepoint:设置保存点
  9. rollback to 保存点:可以回滚到某个保存点
  10. 掌握4种隔离级别及了解其特点
  11. 了解脏读、不可重复读、幻读

原文地址:https://www.cnblogs.com/biao/p/11765469.html

时间: 2024-08-28 05:40:46

十四、详解事务的相关文章

Android笔记(七十四) 详解Intent

我们最常使用Intent来实现Activity之间的转跳,最近做一个app用到从系统搜索图片的功能,使用到了intent的 setType 方法和 setAction 方法,网上搜索一番,发现实现转跳只是Intent功能的九牛一毛,现在对Intent功能做一个总结,以作备忘. 我们经常使用如下方法实现一个转跳: Intent intent = new Inent(MainActivity.this,SecondActivity.class); startActivity(intent); 其实这

Mysql高手系列 - 第14篇:详解事务

这是Mysql系列第14篇. 环境:mysql5.7.25,cmd命令中进行演示. 开发过程中,会经常用到数据库事务,所以本章非常重要. 本篇内容 什么是事务,它有什么用? 事务的几个特性 事务常见操作指令详解 事务的隔离级别详解 脏读.不可重复读.可重复读.幻读详解 演示各种隔离级别产生的现象 关于隔离级别的选择 什么是事务? 数据库中的事务是指对数据库执行一批操作,这些操作最终要么全部执行成功,要么全部失败,不会存在部分成功的情况. 举个例子 比如A用户给B用户转账100操作,过程如下: 1

十图详解TensorFlow数据读取机制(附代码)

http://geek.csdn.net/news/detail/201552 在学习TensorFlow的过程中,有很多小伙伴反映读取数据这一块很难理解.确实这一块官方的教程比较简略,网上也找不到什么合适的学习材料.今天这篇文章就以图片的形式,用最简单的语言,为大家详细解释一下TensorFlow的数据读取机制,文章的最后还会给出实战代码以供参考. TensorFlow读取机制图解 首先需要思考的一个问题是,什么是数据读取?以图像数据为例,读取数据的过程可以用下图来表示: 假设我们的硬盘中有一

Android基础之十四数据存储 之 SQLite数据库详解

Android基础之十四数据存储 之 SQLite数据库详解 SQLite 是一款 轻量级的关系型数据库,它的运算速度非常快,占用资源很少,通常只需要几百 K 的内存就足够了,因而特别适合在移动设备上使用. SQLite 不仅支持标准的 SQL 语法,还遵循了数据库的 ACID( 原子性(Atomicity) .一致性(Consistency) . 隔离性(Isolation) . 持久性(Durability))事务,所以只要你以前使用过其他的关系型数据库,就可以很快地上手 SQLite.而

第十四章 nginx详解

14.1 nginx简介 Nginx(发音同engine x)是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like协议下发行. Nginx由俄罗斯的程序设计师Igor Sysoev所开发,最初供俄国大型的入口网站及搜寻引擎Rambler使用. 第一个公开版本0.1.0发布于2004年10月4日.其将源代码以类BSD许可证的形式发布,因它的稳定性.丰富的功能集.示例配置文件和低系统资源的消耗而闻名.2011年6月1日,nginx 1.0.4

【C语言天天练(十四)】const关键字详解

const是一个C语言的关键字,它限定一个变量不允许被改变.使用const在一定程度上可以提高程序的安全性和可靠性,另外,了解const的作用,在看别人的代码时,对理解对方的程序有一定帮助. 1.const可以理解成是"只读变量"的限定词,从这里可以看出,const修饰的是变量,跟常量是不同的,常量是被编译器放在内存中的只读区域,当然也就不能够去修改它.而"只读变量"则是在内存中开辟一个地方来存放它的值,只不过这个值由编译器限定不允许被修改.const就是用来限定一

“全栈2019”Java第五十四章:多态详解

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第五十四章:多态详解 下一章 "全栈2019"Java第五十五章:方法的静态绑定与动态绑定 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复"Java学习小组"

“全栈2019”Java第六十四章:接口与静态方法详解

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第六十四章:接口与静态方法详解 下一章 "全栈2019"Java第六十五章:接口与默认方法详解 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复"Java学习小组&qu

Android 基础总结:( 十四)Handler详解(上)

Handler的定义: 主要接受子线程发送的数据, 并用此数据配合主线程更新UI. 解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发,比如说,你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作. 如果此时需要一个耗时的操作,例如:联网读取数据,或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象,如果5秒钟还没有完成的话,会收