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 学习笔记(22) TableView

    [Cocos2d-x 学习笔记 ]目录 1. 简介 TableView直接继承了ScrollView和ScrollViewDelegate.说明TableView能实现ScrollView拖动cont ...

  2. Linux与Git学习笔记

    Linux基础概念篇: 终端.控制器 命令行界面 (CLI).终端 (Terminal).Shell.TTY的区别 Linux下的yum与apt-get Linux中su.su -和sudo的区别 L ...

  3. Sentinel Getting Started And Integration of Spring Cloud Alibaba Tutorials

    原文链接:Sentinel Getting Started And Integration of Spring Cloud Alibaba Tutorials Sentinel Getting Sta ...

  4. HTML CSS整理笔记

    ——修改placeholder提示的样式: 1.除IE外通用写法 类名或标签名::placeholder {color: red;}2.加兼容前缀写法 css超出一行显示省略号:给定宽度(width: ...

  5. 部署acfs笔记

    acfs问题分析 环境描述 某电力项目创建了两个磁盘组,分别是OGGEXT和OGGREP,利用这两个磁盘组划分了两个acfs文件系统,之后,cloud监控就一直在报磁盘空间不足,但是这两个文件系统的使 ...

  6. 使用Java8 Stream API对Map按键或值进行排序

    一.什么是Java 8 Stream 使用Java 8 Streams,我们可以按键和按值对映射进行排序.下面是它的工作原理: 将Map或List等集合类对象转换为Stream对象 使用Streams ...

  7. SpringCloud之Hystrix服务降级(七)

    Hystrix设计原则 1.防止单个服务的故障,耗尽整个系统服务的容器(比如tomcat)的线程资源,避免分布式环境里大量级联失败.通过第三方客户端访问(通常是通过网络)依赖服务出现失败.拒绝.超时或 ...

  8. C#/.NET/.NET Core定时任务调度的方法或者组件有哪些--Timer,FluentScheduler,TaskScheduler,Gofer.NET,Coravel,Quartz.NET还是Hangfire?

    原文由Rector首发于 码友网 之 <C#/.NET/.NET Core应用程序编程中实现定时任务调度的方法或者组件有哪些,Timer,FluentScheduler,TaskSchedule ...

  9. 《JavaScript设计模式与开发实践》-- 发布-订阅模式

    详情个人博客:https://shengchangwei.github.io/js-shejimoshi-fabudingyue/ 发布-订阅模式 1.定义 发布-订阅模式:发布-订阅模式又叫观察者模 ...

  10. Docker安装ElasticSearch 以及使用LogStash实现索引库和数据库同步

    1:下载 ElasticSearch 镜像 docker pull docker.io/elasticsearch:5.6.8 2:创建 ElasticSearch 容器: 注意:5.0默认分配jvm ...