Transaction事务是指一个逻辑单元,执行一系列操作的SQL语句。

事务中一组的SQL语句,要么全部执行,要么全部回退。在Oracle数据库中有个名字,叫做transaction ID

在关系型数据库中,事务必须ACID的特性。

  • 原子性,事务中的操作,要不全部执行,要不都不执行
  • 一致性,事务完成前后,数据的必须保持一致。
  • 隔离性,多个用户并发访问数据库时,每一个用户开启的事务,相互隔离,不被其他事务的操作所干扰。
  • 持久性,事务一旦commit,它对数据库的改变是持久性的。

目前重点讨论隔离性。数据库一共有四个隔离级别

  • 未提交读(RU,Read Uncommitted)。它能读到一个事物的中间状态,不符合业务中安全性的保证,违背 了ACID特性,存在脏读的问题,基本不会用到,可以忽略

  • 提交读(RC,Read Committed)。顾名思义,事务提交之后,那么我们可以看到。这是一种最普遍的适用的事务级别。我们生产环境常用的使用级别。

  • 可重复读(RR,Repeatable Read)。是目前被使用得最多的一种级别。其特点是有GAP锁,目前还是默认级别,这个级别下会经常发生死锁,低并发等问题。

  • 可串行化,这种实现方式,其实已经是不是多版本了,而是单版本的状态,因为它所有的实现都是通过锁来实现的。

因此目前数据库主流常用的是RCRR隔离级别。

隔离性的实现方式,我们通常用Read View表示一个事务的可见性。

RC级别,事务可见性比较高,它可以看到已提交的事务的所有修改。因此在提交读(RC,Read Committed)隔离级别下,每一次select语句,都会获取一次Read View,得到数据库最新的事务提交状态。因此对于数据库,并发性能也最好。

RR级别,则不是。它为了避免幻读和不可重复读。保证在一个事务内前后数据读取的一致。其可见性视图Read View只有在自己当前事务提交之后,才会更新。

那如何保证数据的一致性?其核心是通过redo logundo log来保证的。

而在数据库中,为了实现这种高并发访问,就需要对数据库进行多版本控制,通过事务的可见性来保证事务看到自己想看到的那个数据版本(或者是最新的Read View亦或者是老的Read View)。这种技术叫做MVCC

多版本是如何实现的?通过undo日志来保证。每一次数据库的修改,undo日志会存储之前的修改记录值。如果事务未提交,会回滚至老版本的数据。其MVCC的核心原理,以后详谈

举例论证:

##  开启事务
MariaDB [scott]> begin;
Query OK, 0 rows affected (0.000 sec) ##查看当前的数据
MariaDB [scott]> select * from dept;
+--------+------------+----------+
| deptno | dname | loc |
+--------+------------+----------+
| 10 | ACCOUNTING | beijing |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | beijing |
| 50 | security | beijing |
| 60 | security | nanchang |
+--------+------------+----------+
6 rows in set (0.001 sec) ##更新数据
MariaDB [scott]> update dept set loc ='beijing' where deptno = 20;
Query OK, 1 row affected (0.001 sec) ## 其行记录| 20 | RESEARCH | DALLAS |已经被放置在undo日志中,目前最新的记录被改为'beijing':
MariaDB [scott]> select * from dept;
+--------+------------+----------+
| deptno | dname | loc |
+--------+------------+----------+
| 10 | ACCOUNTING | beijing |
| 20 | RESEARCH | beijing |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | beijing |
| 50 | security | beijing |
| 60 | security | nanchang |
+--------+------------+----------+ ##事务不提交,回滚。数据回滚至老版本的数据。
MariaDB [scott]> rollback;
Query OK, 0 rows affected (0.004 sec) MariaDB [scott]> select * from dept;
+--------+------------+----------+
| deptno | dname | loc |
+--------+------------+----------+
| 10 | ACCOUNTING | beijing |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | beijing |
| 50 | security | beijing |
| 60 | security | nanchang |
+--------+------------+----------+
6 rows in set (0.000 sec)

因为MVCC,让数据库有了很强的并发能力。随着数据库并发事务处理能力大大增强,从而提高了数据库系统的事务吞吐量,可以支持更多的用户并发访问。但并发访问,会出现带来一系列问题。如下:

数据库并发带来的问题 概述解释
脏读(Dirty Reads) 当一个事务A正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务B也访问这同一个数据,如不控制,事务B会读取这些"脏"数据,并可能做进一步的处理。这种现象被称为"脏读"(Dirty Reads)
不可重复读(Non-Repeatable Reads) 指在一个事务A内,多次读同一数据。在这个事务还没有结束时,另外一个事务B也访问该同一数据。那么,在事务A的两次读数据之间,由于第二个事务B的修改,那么第一个事务两次读到的的数据可能是不一样的 。出现了"不可重复读"(Non-Repeatable Reads)的现象
幻读(Phantom Reads) 指在一个事务A内,按相同的查询条件重新检索以前检索过的数据,同时发现有其他事务插入了数据,其插入的数据满足事务A的查询条件。因此查询出了新的数据,这种现象就称为"幻读"(Phantom Reads)

隔离级别和上述现象之间的联系。

隔离级别有:未提交读(RU,Read Uncommitted),提交读(RC,Read Committed),可重复读(RR,Repeatable Read),可串行化(Serializable)

隔离级别 脏读 不可重复读 幻读
未提交读(RU,Read Uncommitted) 可能 可能 可能
提交读(RC,Read Committed) 不可能 可能 可能
可重复读(RR,Repeatable Read) 不可能 不可能 可能
(间隙锁解决)
可串行化(Serializable) 不可能 不可能 不可能

实验环节

举例在隔离级别RRRC下,说明“不可重复读”问题。

MySQL的默认级别是Repeatable Read,如下:

MariaDB [(none)]> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ |
+-----------------------+
1 row in set (0.000 sec)

这里修改当前会话级别为Read Committed

MariaDB [scott]> set session transaction isolation level read committed;
Query OK, 0 rows affected (0.001 sec) MariaDB [scott]> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.000 sec)

在隔离级别已提交读(RC,Read Committed)下,出现了不可重复读的现象。在事务A中可以读取事务B中的数据。

在隔离级别可重复读(RR,Repeatable Read),不会出现不可重复读现象,举例如下:

举例说明“幻读”的现象。

行锁可以防止不同事务版本的数据在修改(update)提交时造成数据冲突的问题。但是插入数据如何避免呢?

在RC隔离级别下,其他事务的插入数据,会出现幻读(Phantom Reads)的现象。

而在RR隔离级别下,会通过Gap锁,锁住其他事务的insert操作,避免"幻读"的发生。

因此,在MySQL事务中,锁的实现方式与隔离级别有关,如上述实验所示。在RR隔离级别下,MySQL为了解决幻读的问题,已牺牲并行度为代价,通过Gap锁来防止数据的写入。这种锁,并行度差,冲突多。容易引发死锁。

目前流行的Row模式可以避免很多冲突和死锁问题,因此建议数据库使用ROW+RC(Read Committed)模式隔离级别,很大程度上提高数据库的读写并行度,提高数据库的性能。

理解MySQL数据库事务-隔离性的更多相关文章

  1. Mysql数据库事务隔离级别

    事务(transaction)是数据库管理系统的执行单位,可以是一个数据库操作(如Select操作)或者是一组操作序列.事务ACID属性,即原子性(Atomicity).一致性(Consistency ...

  2. mysql数据库——事务隔离级别

    四种隔离级别: 一:READ UNCOMMITTED(未提交读) 事务可以读取其他事务未提交的数据,称为脏读 二:READ COMMITTED(提交读) 一个事务开始时,只能"看见" ...

  3. 理解MySQL数据库事务

    1. 什么是事务处理? 事务处理是一种机制,它是用来管理必须成批执行的mysql操作.来保证数据库不完整的操作结果. 2. 为什么要使用事务处理? 在使用mysql操作数据的过程中,如果只是简单的中小 ...

  4. mysql事务之一:MySQL数据库事务隔离级别(Transaction Isolation Level)及锁的实现原理

    一.数据库隔离级别 数据库隔离级别有四种,应用<高性能mysql>一书中的说明: 然后说说修改事务隔离级别的方法: 1.全局修改,修改mysql.ini配置文件,在最后加上 1 #可选参数 ...

  5. MySQL数据库事务隔离级别(Transaction Isolation Level)

    转自: http://www.cnblogs.com/zemliu/archive/2012/06/17/2552301.html  数据库隔离级别有四种,应用<高性能mysql>一书中的 ...

  6. mysql数据库事务隔离原理

    今天在学习JDBC的时候看到了关于MySQL的事务的隔离级别的问题,感觉内容挺高级的,所以记录一篇文章,以备后面使用. 数据库隔离级别有四种,应用<高性能mysql>一书中的说明: 然后说 ...

  7. [转]MySQL 数据库事务隔离级别

    然后说说修改事务隔离级别的方法: 1. 全局修改,修改 mysql.ini 配置文件,在最后加上 1 #可选参数有:READ-UNCOMMITTED, READ-COMMITTED, REPEATAB ...

  8. mysql数据库事务详细剖析

    在写之前交代一下背景吧! 做开发也好久了,没怎么整理过知识,现在剖析一下自己对数据库事务的认识,以前用sqlserver,现在转java后又用mysql.oracle.我这块就主要解释一下mysql数 ...

  9. 跟面试官侃半小时MySQL事务隔离性,从基本概念深入到实现

    提到MySQL的事务,我相信对MySQL有了解的同学都能聊上几句,无论是面试求职,还是日常开发,MySQL的事务都跟我们息息相关. 而事务的ACID(即原子性Atomicity.一致性Consiste ...

随机推荐

  1. ‎Cocos2d-x 学习笔记(3.1) Scene 场景与场景切换

    1. Scene 简介 游戏中我们看到/看不到的所有元素都是展示在场景之Scene上. 我们可以把场景比作放在地上的没盖纸箱,层Layer是纸箱里堆放的玻璃,Sprite等元素画在玻璃Layer上,这 ...

  2. Head First设计模式——装饰者模式

    前言:对于设计模式我们有时候在想是否有必要,因为实际开发中我们没有那么多闲工夫去套用这么多设计模式,也没有必要为了模式而模式. 通常这些模式会引入新的抽象层,增加代码的复杂度,但是当我们掌握了这些设计 ...

  3. php后端开发要学什么

    PHP历史: 1994年创建,1995年对外发表第一个版本,名为:personal home page tools,之后发表PHP1.0.1995年中期,PHP2.0,从此建立了PHP在动态网站开发的 ...

  4. vue使用 封装websocket心跳包

    ---恢复内容开始--- 这套代码可以拿过去直接用 一些注意我会在下面代码中加上注释: 谢谢支持 核心代码 //这里需要引入vuex import store from './store'; let ...

  5. ajax 轮询(适合web端二维码请求)

    (前几天 一直弄二维码轮询登录 想了半天 总算弄出来了 分享给大家    ^-^) 轮询: 所谓轮询 肯定需要 setInterval   但是怎么加ajax请求  需要有点小问题而且轮询成功后需要停 ...

  6. python编程系列---Pycharm快捷键(更新中....)

    以下是我常用到的Pycharm快捷键(还有很多,只是我暂时用的最多的就这些): 在开发过程中,经常使用一些快捷键会大大提高开发效率,不要因为看这多而不用,常用的就那些,用得多就都记住了,脱离鼠标,逼格 ...

  7. 《如何学习基于ARM嵌入式系统》笔记整理

    author:Peong time:20190603 如何学习基于ARM嵌入式系统 一.嵌入式系统的概念 从硬件上讲,将外围器件,与CPU集成在一起. 从操作系统上讲,定制符合要求的系统内核 从应用上 ...

  8. Rancher 2.3.2 Stable!Istio UI已经GA!生产可用!

    2019年10月9日,Rancher 2.3正式发布,这是Rancher Labs迄今为止最重要的产品版本.Rancher 2.3是业界首个GA支持Windows容器的Kubernetes管理平台,并 ...

  9. day14作业

    文件内容如下,标题为:姓名,性别,年纪,薪资 egon male 18 3000 alex male 38 30000 wupeiqi female 28 20000 yuanhao female 2 ...

  10. Chrome插件开发(三)

    在日常工作中,我们可能经常需要在手机端测试我们所做的页面,如果每次在手机端测试都手输网址,网址短的还好,如果长的网址也需要一个字母一个字母去敲,那无疑是一场噩梦,试想我们有一个工具只需要点击一个按钮就 ...