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的核心原理,以后详谈

举例论证:

  1. ## 开启事务
  2. MariaDB [scott]> begin;
  3. Query OK, 0 rows affected (0.000 sec)
  4. ##查看当前的数据
  5. MariaDB [scott]> select * from dept;
  6. +--------+------------+----------+
  7. | deptno | dname | loc |
  8. +--------+------------+----------+
  9. | 10 | ACCOUNTING | beijing |
  10. | 20 | RESEARCH | DALLAS |
  11. | 30 | SALES | CHICAGO |
  12. | 40 | OPERATIONS | beijing |
  13. | 50 | security | beijing |
  14. | 60 | security | nanchang |
  15. +--------+------------+----------+
  16. 6 rows in set (0.001 sec)
  17. ##更新数据
  18. MariaDB [scott]> update dept set loc ='beijing' where deptno = 20;
  19. Query OK, 1 row affected (0.001 sec)
  20. ## 其行记录| 20 | RESEARCH | DALLAS |已经被放置在undo日志中,目前最新的记录被改为'beijing':
  21. MariaDB [scott]> select * from dept;
  22. +--------+------------+----------+
  23. | deptno | dname | loc |
  24. +--------+------------+----------+
  25. | 10 | ACCOUNTING | beijing |
  26. | 20 | RESEARCH | beijing |
  27. | 30 | SALES | CHICAGO |
  28. | 40 | OPERATIONS | beijing |
  29. | 50 | security | beijing |
  30. | 60 | security | nanchang |
  31. +--------+------------+----------+
  32. ##事务不提交,回滚。数据回滚至老版本的数据。
  33. MariaDB [scott]> rollback;
  34. Query OK, 0 rows affected (0.004 sec)
  35. MariaDB [scott]> select * from dept;
  36. +--------+------------+----------+
  37. | deptno | dname | loc |
  38. +--------+------------+----------+
  39. | 10 | ACCOUNTING | beijing |
  40. | 20 | RESEARCH | DALLAS |
  41. | 30 | SALES | CHICAGO |
  42. | 40 | OPERATIONS | beijing |
  43. | 50 | security | beijing |
  44. | 60 | security | nanchang |
  45. +--------+------------+----------+
  46. 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,如下:

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

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

  1. MariaDB [scott]> set session transaction isolation level read committed;
  2. Query OK, 0 rows affected (0.001 sec)
  3. MariaDB [scott]> select @@tx_isolation;
  4. +----------------+
  5. | @@tx_isolation |
  6. +----------------+
  7. | READ-COMMITTED |
  8. +----------------+
  9. 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. [BZOJ1965][AHOI2005] 洗牌 - 扩展欧几里得

    题目描述 为了表彰小联为Samuel星球的探险所做出的贡献,小联被邀请参加Samuel星球近距离载人探险活动. 由于Samuel星球相当遥远,科学家们要在飞船中度过相当长的一段时间,小联提议用扑克牌打 ...

  2. 分布式FastDFS集群部署

    FastDFS FastDFS的作者余庆在其 GitHub 上是这样描述的:"FastDFS is an open source high performance distributed f ...

  3. 常用函数-Win-IP

    //************************************************************************* // 函数名: GetAppPath // 返回 ...

  4. postman-windows下newman的使用

    一.newman的安装 1.安装node.js下载https://nodejs.org/en/ C:\Users\iphauser>node -vv10.16.1C:\Users\iphause ...

  5. Open vSwitch系列之一 Open vSwitch诞生

    Open vSwitch系列之一 Open vSwitch诞生 Open vSwitch系列之二 安装指定版本ovs 2006年,SDN诞生于美国GENI项目资助的斯坦福大学Clean Slate课题 ...

  6. MySQL操作(一)用户及权限

    一.mysql 里的所有用户都是存储在数据库mysql的user表里 二.创建普通用户.赋权.撤销权限 的操作 1.创建用户(需要先用root进去mysql)格式:create  user  '用户名 ...

  7. fenby C语言 P10

    if判断语句; if(a<0)→if(条件) if(){C语言语句} #include <stdio.h> int main() { int a=10; if(a>0) { p ...

  8. 第五篇 Flask 中内置的 Session

    Flask中的Session非常的奇怪,他会将你的SessionID存放在客户端的Cookie中,使用起来也非常的奇怪 1. Flask 中 session 是需要 secret_key 的 from ...

  9. (Java) JWT-TokenUtils

    package com.vcgeek.hephaestus.utils; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; imp ...

  10. Linux中vi命令的详细总结

    vi命令的使用 首先可以新建一个文件夹 touch 1.txt  之后通过vi命令进入其中  vi 1.txt 进入其中开始编辑,按下a键可以进行输入. 随便输入一些东西(暂时不支持中文) 非输入模式 ...