本文主要是帮助理解相关知识,没有具体的操作和代码。

事务

事务就是一组操作,这组操作要么全部成功,要么全部失败。

最经典的例子就是银行转账:

张三给李四转账100,对用户来说,就是一个操作。但对应到数据库中,至少需要三步:

//检查张三账户余额是否大于等于100
//张三账户-100
//李四账户+100

这三个操作可以没有顺序,但是必须全部成功或者全部失败。否则就可能导致张三损失100李四没收到,或者李四收到100但是张三没扣款成功(银行损失100)。

MySQL默认引擎InnoDB,支持事务;MyISAM引擎不支持事务。

事务的特性

前面说的其实都是事务的概念,具体怎么实现或者有什么要求呢?

一个运行良好的事务处理系统,必须基本满足四个特性(ACID),即原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)。

原子性(atomicity)

一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作。(这个特性基本上等同于事务的定义,所以必须满足)。

一致性(consistency)

数据库总是从一个一致性的状态转换到另外一个一致性的状态。在转账的例子中,若转账成功,张三和李四的账户总额和转账前也是一致。

隔离性(isolation)

一般来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。(这是本文的讨论的主要内容,因为在实际情况下,并不一定能保证隔离性。)

持久性(durability)

一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失。

事务的隔离级别

事务间的隔离

事务的四个特性中,原子性,一致性,持久性多数情况下都能保证。稍微复杂的是隔离性,因为我们在学习的过程中很多时候都是单用户,单连接,也就是一个事务执行完成再去执行另一个,很难体会到隔离性的内涵。

不妨想一下春运时候的12306系统,每个用户要完成的操作:

//假设某一线路总票数100张
//1.查询余票
//2.买票即总票数-1
//3.付款

这三个操作组成一个事务,在高并发的情况下,一个用户甲执行到第二步,票数减到99,此时第二个用户乙查询余票,票数应该是100还是99 ?

针对类似的疑问,SQL规范提出了四种情形,或者说用四种级别实现了不同的需求,不同级别决定了用户乙看到的是100还是99。

这四种级别分别是:

READ UNCOMMITTED(未提交读)

在READ UNCOMMITTED级别,事务中的修改,即使没有提交,对其他事务也都是可见的。

回到前面的例子,如果设置为这个级别,用户乙看到的将是99。这导致的问题是如果甲付款或者其他原因失败,乙读到其实是假数据,称为脏读。

脏读(Dirty Read)

事务读取到未提交的数据。

READ COMMITTED(提交读)

在READ COMMITTED级别,一个事务开始时,只能“看见”已经提交的事务所做的修改。换句话说,一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。

这是多数数据库系统的默认隔离级别(但MySQL不是)。

在前面的例子中,设置这个级别,乙看到的将是100。同样可能导致的问题是,乙在一次事务中,查询成功后,甲付款成功,票数变为99,乙再次查询,结果由100变成99。一次事务中两次查询结果不一致,也叫不可重复读。

不可重复读(nonrepeatable read)

两次执行同样的查询,得到了不一样的结果。

REPEATABLE READ(可重复读)

可重复读是MySQL的默认事务隔离级别。

REPEATABLE READ解决了脏读的问题。保证了在同一个事务中多次读取同样记录的结果是一致的(意思是对同样的数据修改不影响)。

但是可重复读隔离级别无法解决幻读的问题。

幻读(Phantom Read)

所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row)。

MySQL关于幻读的处理

InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读的问题。

InnoDB的MVCC是通过每一行加两个隐藏列来实现,一列记录行的创建时间,一列记录行的过期时间(或删除时间),实际记录的是版本号而非具体时间。 相当于行级锁,但是比加锁开销更低,也体现了一种用空间换时间的思想。详细内容参考文档或者相关书籍。

关于这个级别到底是否完全解决幻读问题,MySQL(8.0)文档是这样说的:

This is the default isolation level for InnoDB. Consistent reads within the same transaction read the snapshot established by the first read. This means that if you issue several plain (nonlocking) SELECT statements within the same transaction, these SELECT statements are consistent also with respect to each other.

For locking reads (SELECT with FOR UPDATE or FOR SHARE), UPDATE, and DELETE statements, locking depends on whether the statement uses a unique index with a unique search condition, or a range-type search condition.

For a unique index with a unique search condition, InnoDB locks only the index record found, not the gap before it.

For other search conditions, InnoDB locks the index range scanned, using gap locks or next-key locks to block insertions by other sessions into the gaps covered by the range.

如果在同一事务中发出多个普通(非锁定)SELECT语句,则这些SELECT语句彼此之间也是一致的。

对于锁定读取(使用FOR UPDATE或FOR SHARE进行SELECT),UPDATE和DELETE语句,锁定取决于该语句是使用具有唯一搜索条件的唯一索引还是范围类型搜索条件。

对于具有唯一搜索条件的唯一索引,InnoDB仅锁定找到的索引记录,而不锁定其前的间隙。

对于其他搜索条件,InnoDB使用间隔锁定或下一键锁定来锁定扫描的索引范围,以阻止其他会话插入该范围覆盖的间隔。

总结:如果是普通查询,能够避免幻读。对于锁定查询,只能在部分情况下(范围查询时)避免幻读。

SERIALIZABLE(可串行化)

SERIALIZABLE是最高的隔离级别。它通过强制事务串行执行,避免了前面说的幻读的问题。简单来说,SERIALIZABLE会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的问题。实际应用中也很少用到这个隔离级别,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别。

总结:

因为实际业务需要,产生了事务,又因为事务本身的特性,需要考虑不同事务之间的可见性,产生了隔离级别。

四种隔离级别:

READ UNCOMMITTED=》READ COMMITTED=》REPEATABLE READ=》SERIALIZABLE

越低的级别能够执行更高的并发,系统开销也更低。

本文主要参考了《高性能mysql(第3版)》,以及MySQL8.0官方文档。

MySQL中事务和事务的隔离级别的更多相关文章

  1. Mysql加锁过程详解(6)-数据库隔离级别(2)-通过例子理解事务的4种隔离级别

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

  2. sql 事务的四种隔离级别

    在 SQL 标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的.较低级别的隔离通常可以执行更高的并发,系统的开销也更低. read unco ...

  3. 数据库事务ACID特性及隔离级别

    数据库ACID特性介绍 1.原子性(Atomic)一个事务被视为一个不可分割的最小工作单元,这个事务里的所有操作要么全部成功执行,要么全都不执行,不能只执行其中的一部分操作.实现事务的原子性,要支持回 ...

  4. SQL Server事务的四种隔离级别

    在SQL标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改,哪些是在事务内和事务间可见的,哪些是不可见的.较低级别的隔离通常可以执行更高的并发,系统的开销也更低. 1.未提交读(Read ...

  5. 事务特性ACID及隔离级别

    注:例子引用来自:https://www.cnblogs.com/WJ-163/p/6023054.html 事务就是一组原子性的SQL查询,或者说一个独立的工作单元. 银行应用是解释事务必要性的一个 ...

  6. Spring事务传播机制与隔离级别(转)

    Spring事务传播机制与隔离级别 博客分类: Spring   转自:http://blog.csdn.net/edward0830ly/article/details/7569954 (写的不错) ...

  7. spring事务传播属性和隔离级别

    猫咪咪的Java世界 spring事务传播属性和隔离级别 博客分类: Spring java编程   1 事务的传播属性(Propagation) 1) REQUIRED ,这个是默认的属性 Supp ...

  8. 网络协议 finally{ return问题 注入问题 jdbc注册驱动问题 PreparedStatement 连接池目的 1.2.1DBCP连接池 C3P0连接池 MYSQL两种方式进行实物管理 JDBC事务 DBUtils事务 ThreadLocal 事务特性 并发访问 隔离级别

    1.1.1 API详解:注册驱动 DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用 原因有2个: >导致驱动被注册2 ...

  9. [Mysql]——通过例子理解事务的4种隔离级别(转)

    SQL标准定义了4种隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的. 低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销. 一.事务隔离级别分类 第1级别:R ...

  10. [Mysql]——通过例子理解事务的4种隔离级别

    SQL标准定义了4种隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的. 低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销. 首先,我们使用 test 数据库, ...

随机推荐

  1. 【python开发】迈出第一步,这可能是我唯一一次的Python开发了

    好久没写博了,今天就瞎唠唠吧 背景: 组内有个测试平台,是基于Python2+tornado 框架写的,之前自己维护了一套系统的UIweb自动化代码,现在需要集成进去.这很可能是自己唯一一次基于pyt ...

  2. 剑指 Offer 56 - II. 数组中数字出现的次数 II

    题目描述 在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次.请找出那个只出现一次的数字. 示例1: 输入:nums = [3,4,3,3] 输出:4 示例2: 输入:nums = ...

  3. Activiti7 启动流程实例

    package com.itheima.activiti; import org.activiti.engine.ProcessEngine; import org.activiti.engine.P ...

  4. 转载: Nginx 通览

    转载地址:https://developer.51cto.com/art/201912/608365.htm Nginx 简介 Nginx 是一个免费.开源.高性能.轻量级的 HTTP 和反向代理服务 ...

  5. vue父子组件状态同步的最佳方式

    哈喽!大家好!我是木瓜太香,一位老牌儿前端工程师,平时我们在使用 vue 开发的时候,可能会遇到需要父组件与子组件某个状态需要同步的情况,通常这个是因为我们封装组件的时候有一个相同的状态外面要用,里面 ...

  6. Linux搭建SonarQube

    环境:linux+jdk8+mysql5.7.31+sonarqube7.5+sonar-scanner-4.4+jenkins2.249+sonar-l10n-zh-plugin-1.25.jar ...

  7. linux 字符驱动框架(用户态的read,write,poll是怎么操作驱动的)

    前言 这篇文章是通过对一个简单字符设备驱动的操作来解释,用户态的读写操作是怎么映射到具体设备的. 因为针对不同版本的linux内核,驱动的接口函数一直有变化,这贴出我测试的系统信息: root@ubu ...

  8. 第0课 - 搭建开发环境之安装QT

    第0课 - 搭建开发环境之安装Qt 1. 课程学习的原材料 — Visual Studio 2010 — Qt SDK 4.7.4 — Qt Creator 2.4.1 2. Visual Studi ...

  9. Git切换分支开发

    入职第一家公司做开发的时候使用的项目版本管理工具是svn,公司内部搭建的服务器:在第二.第三家公司做开发的时候,使用的项目版本管理工具是Git,现在大多数公司使用的也是Git.刚进入公司的时候首先做的 ...

  10. 鸿蒙真的是套壳吗?HarmonyOS应用开发初体验,Java原生和JavaScript的mvvm开发

    初探寻鸿蒙os的应用开发 本期视频已发布到bilibili 注意是应用开发,没错码农(应用开发)一般关注这个就行了 IDE 点击应用开发以后,点击链接下载IDE,DevEco Studio是基于IDE ...