上一篇我们聊到了mariadb的锁,以及怎么手动加锁和解锁等等,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13196905.html;今天我们来聊一聊mariadb的事务隔离级别;在前边的随笔中,我们提到到了mysql的存储引擎,常用的有MyISAM和innodb,其中myisam不支持事务,innodb支持事务;所以我们常说的事务是针对innodb存储引擎来说的;所谓事务就是在我们在执行大批量语句时,为了保证数据库的完整性,要么语句全部执行,要么语句全部不执行;所以事务必须满足ACID这是个条件;A表示Atomicity,原子性,也是不可分性;C表示Consistency,一致性;I表示Isolation,隔离性,又称独立性;D表示Durability,持久性;所谓原子性,就是事务中执行的语句要么全部执行,要么全部不执行,如果事务在中途发生错误,那么前面执行过的语句将会回滚到事务前;一致性指的是在执行事务之前和事务执行完成后的数据库状态是完整的;也就是说我们执行的语句都按照我们预想的结果执行了;隔离性指数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。持久性指的是,事务执行完成后,对数据的修改是永久的;

  接下来我们来说说怎么在mariadb中开启事务吧

  用户手动开启事务用start transaction 或者使用begin语句开启事务;

  提示:以上红框中的语句就表示手动开启一个事务;这里需要注意一点,对于mysql来讲,默认在命令行执行的语句都是自动提交事务的;也就是说默认情况下我们在mysql shell中执行的语句它默认也会开启一个事务,但我们语句执行完成后,它会自动把该事务提交;所以我们手动开启一个事务可以使用start transaction 语句 或者begin 或者执行set autocommit=0来关闭自动提交事务;

  提示:提交事务用commit 语句,表示结束当前事务;当然结束当前事务也可以用rollback语句,表示回滚到事务之前的状态;回滚以后事务也就结束了;

  SAVEPOINT identifier:创建一个保存点,一个事务中可以存在多个保存点,回滚时我们可以指定回滚到某个点上;

MariaDB [first_db]> begin;
Query OK, 0 rows affected (0.000 sec) MariaDB [first_db]> select * from test_tb;
+------+----------+------+
| id | name | age |
+------+----------+------+
| 1 | xiaoming | 44 |
| 2 | zhangsan | 16 |
+------+----------+------+
2 rows in set (0.001 sec) MariaDB [first_db]> insert into test_tb values (3,"lisi",23);
Query OK, 1 row affected (0.002 sec) MariaDB [first_db]> savepoint one;
Query OK, 0 rows affected (0.001 sec) MariaDB [first_db]> insert into test_tb values (4,"wangwu",25);
Query OK, 1 row affected (0.001 sec) MariaDB [first_db]> savepoint two;
Query OK, 0 rows affected (0.000 sec) MariaDB [first_db]> select * from test_tb;
+------+----------+------+
| id | name | age |
+------+----------+------+
| 1 | xiaoming | 44 |
| 2 | zhangsan | 16 |
| 3 | lisi | 23 |
| 4 | wangwu | 25 |
+------+----------+------+
4 rows in set (0.001 sec) MariaDB [first_db]> rollback to one;
Query OK, 0 rows affected (0.001 sec) MariaDB [first_db]> select * from test_tb;
+------+----------+------+
| id | name | age |
+------+----------+------+
| 1 | xiaoming | 44 |
| 2 | zhangsan | 16 |
| 3 | lisi | 23 |
+------+----------+------+
3 rows in set (0.001 sec) MariaDB [first_db]>

  提示:存在多个保存点,如果回滚到前边的点以后,后面的保存点就没有了;

  接下来看看事务的隔离级别

  对于mysql数据库 innodb存储引擎支持的事务隔离级别有4中,READ-UNCOMMITED:读未提交;这表示事务还没有结束,其他用户或进程是可以实时的读到事务中对数据的改变,因为事务还没提交,所以我们认为其他用户或进程读到的数据就是一个不准确的数据,通常我们把这种叫脏读;READ-COMMITTED:读提交;这表示只有事务提交后,其他用户或进程才可以读到事务修改后的数据;这种事务隔离级别就要比前面的隔离级别要高一点,读到的数据也要精准一点;这种隔离级别就是只要事务A提交了,在其他事务里就可以读取到事务A修改后的数据;通常这种我们叫不可重复读,不可重复读表示在其他事务中,读到的数据是根据事务A是否提交有关系;REPEATABLE-READ:可重复读,这表示在A事务中修改后的数据,在B中事务上不可见的,即便A中事务已经提交,B中事务没有提交,那么在B中的事务中读到的还是A事务修改前的数据;只有当事务B结束后才能读到A事务修改后的数据;所以通常我们把这种方式也叫幻读,给人一种幻觉的感觉;SERIALIZABLE:串行化;这种隔离级别是最高的,但同时并发访问也是最差的,它表示事务A和事务B是顺序执行的,什么意思呢,就是说事务B必须要等到事务A完成后才可以执行;

  关闭自动提交功能

MariaDB [first_db]> select @@session.autocommit;
+----------------------+
| @@session.autocommit |
+----------------------+
| 1 |
+----------------------+
1 row in set (0.001 sec) MariaDB [first_db]> set @@session.autocommit=0;
Query OK, 0 rows affected (0.001 sec) MariaDB [first_db]> select @@session.autocommit;
+----------------------+
| @@session.autocommit |
+----------------------+
| 0 |
+----------------------+
1 row in set (0.001 sec) MariaDB [first_db]>

  提示:以上语句表示设定当前会话关闭自动提交功能,关闭此会话它将恢复原有设定;

  设置事务A的隔离级别为read-uncommitted

  提示:事务隔离级别字串要加引号,否则会提示语法错误

  设置会话B的隔离级别为read-uncommitted

  在事务A中修改表中数据,在会话B中查看表中数据,看看是否在会话B中看到修改后的数据?

MariaDB [first_db]> BEGIN;
Query OK, 0 rows affected (0.000 sec) MariaDB [first_db]> select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| REPEATABLE-READ |
+------------------------+
1 row in set (0.001 sec) MariaDB [first_db]> set @@session.tx_isolation='read-uncommitted';
Query OK, 0 rows affected (0.001 sec) MariaDB [first_db]> select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| READ-UNCOMMITTED |
+------------------------+
1 row in set (0.001 sec) MariaDB [first_db]> select * from test_tb;
+------+----------+------+
| id | name | age |
+------+----------+------+
| 1 | xiaoming | 44 |
| 2 | zhangsan | 16 |
+------+----------+------+
2 rows in set (0.001 sec) MariaDB [first_db]> insert into test_tb values(2,"xiaohong",33);
Query OK, 1 row affected (0.001 sec) MariaDB [first_db]> select * from test_tb;
+------+----------+------+
| id | name | age |
+------+----------+------+
| 1 | xiaoming | 44 |
| 2 | zhangsan | 16 |
| 2 | xiaohong | 33 |
+------+----------+------+
3 rows in set (0.001 sec) MariaDB [first_db]>

  提示:在事务A中插入数据在当前事务中是可以正常看到数据的变化;

  提示:可以看到在会话B上是可以正常看到事务A中数据的修改;

  提示:从上面的信息可以看到,当事务A中的修改操作回滚时,在会话B中是可以查看到回滚后的数据;这也意味这在会话B中读到的数据不是很准确;

  设置事务A的事务隔离级别为read-committed

  设置会话B的事务隔离级别为read-committed,然后在事务A上修改数据,不提交,看看会话B上是否可以看到?

MariaDB [first_db]> start transaction;
Query OK, 0 rows affected (0.001 sec) MariaDB [first_db]> select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| READ-UNCOMMITTED |
+------------------------+
1 row in set (0.001 sec) MariaDB [first_db]> set @@session.tx_isolation='read-committed';
Query OK, 0 rows affected (0.001 sec) MariaDB [first_db]> select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| READ-COMMITTED |
+------------------------+
1 row in set (0.001 sec) MariaDB [first_db]> select @@session.autocommit;
+----------------------+
| @@session.autocommit |
+----------------------+
| 0 |
+----------------------+
1 row in set (0.001 sec) MariaDB [first_db]> select * from test_tb;
+------+----------+------+
| id | name | age |
+------+----------+------+
| 1 | xiaoming | 44 |
| 2 | zhangsan | 16 |
+------+----------+------+
2 rows in set (0.001 sec) MariaDB [first_db]> insert into test_tb values(3,"wangwu",43);
Query OK, 1 row affected (0.001 sec) MariaDB [first_db]> select * from test_tb;
+------+----------+------+
| id | name | age |
+------+----------+------+
| 1 | xiaoming | 44 |
| 2 | zhangsan | 16 |
| 3 | wangwu | 43 |
+------+----------+------+
3 rows in set (0.001 sec) MariaDB [first_db]>

  在会话B中查看test_tb表,看看是否有能看到修改后的数据?

  提示:在会话B中可以看到的test_tb表中的数据还是事务A开始前的数据;

  提交事务A,看看会话B是否能够看到修改后的数据呢?

  提示:可以看到当事务A提交以后,在会话B中就可以看到事务A中修改后的数据;

  设置事务A的事务隔离级别为repeatable-read

MariaDB [first_db]> begin;
Query OK, 0 rows affected (0.000 sec) MariaDB [first_db]> set @@session.tx_isolation='repeatable-read';
Query OK, 0 rows affected (0.000 sec) MariaDB [first_db]> select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| REPEATABLE-READ |
+------------------------+
1 row in set (0.000 sec) MariaDB [first_db]>

  关闭事务B的自动提交功能并设置事务B的隔离级别为repeatable-read

  在事务A中修改数据,并提交,看看在事务B中是否能看到修改后的数据?

  在事务B中查看test_tb表中的数据,看看是否有变化呢?

  提示:可以看到在事务B中无论怎么查看数据都是没有发生变化;

  提交事务B在查看数据看看是否有变化?

  提示:可以看到当事务B提交以后,再次查看表中数据,就可以看到事务A更改以后的表数据了;

  设置会话A的事务隔离级别为serializable

  设置会话B的事务隔离级别为serializable

  在事务A,事务B中更新表中同一条数据,看看会发生什么?

  提示:在事务B中成功修改了第一条数据;

  提示:在事务A上就不能修改第一条数据了,那我们在事务A上是否可修改第二条数据呢?

  提示:可以看到第二条数据是能够修改的;

  提交事务B,看看A事务上是否可以修改第一条数据呢?

  提示:提交了事务B以后,在会话B上再次查看test_tb表中的数据,发现执行不了,原因是事务A修改了第二条数据,还未完成事务,所以一直阻塞;

  在事务A上修改第一条数据,看看是否可修改?

  提示:提交了事务B以后,在事务A上还是不能够修改第一条数据;原因是事务A修改了第二条数据,事务还没有结束,所以第三个事务就无法执行,所以我们在会话B上是不能够查看数据,因为默认情况查看数据也会启动一个事务;

  结束事务A,在会话B上看看是否可查询?

  提示:回滚了事务A,事务A也就结束了;在事务B中修改的数据,在事务A上做回滚,是回滚不回去的;这说明回滚操作只针对当前事务;

  提示:结束了事务A以后,在会话B上就可以正常查看test_tb上的数据了;

  以上就是在mariadb数据库上的事务的四种隔离级别的区别;从上面的演示可以看到,串行化的隔离级别最高,但是并发连接也是最差的,因为它必须要等到前一个事务结束后才可以执行后面的事务;其次就是可重读,可重读必须是两个事务都结束以后才可以看到真实修改后的数据;再其次就是不可重读,读提交,这种隔离级别必须是一方事务提交以后其他事务才可以读到真实修改数据;而隔离级别最低就是对未提交,这种隔离级别只要是事务中修改了,其他事务上就能够读到相应的数据;当然这种读到的数据也是最不靠谱的;

Mariadb之事务隔离级别的更多相关文章

  1. MySQL/MariaDB中的事务和事务隔离级别

    本文目录:1.事务特性2.事务分类 2.1 扁平事务 2.2 带保存点的扁平事务 2.3 链式事务 2.4 嵌套事务 2.5 分布式事务3.事务控制语句4.显式事务的次数统计5.一致性非锁定读(快照查 ...

  2. SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因

    原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫.所以花了点时间,把 SQL Server 数据库中 ...

  3. 30分钟全面解析-SQL事务+隔离级别+阻塞+死锁

    以前总是追求新东西,发现基础才是最重要的,今年主要的目标是精通SQL查询和SQL性能优化.  本系列主要是针对T-SQL的总结. [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础] ...

  4. SQL Server 事务隔离级别详解

    标签: SQL SEERVER/MSSQL SERVER/SQL/事务隔离级别选项/设置数据库事务级别 SQL 事务隔离级别 概述 隔离级别用于决定如果控制并发用户如何读写数据的操作,同时对性能也有一 ...

  5. InnoDB事务隔离级别

    转载于:http://blog.csdn.net/wudongxu/article/details/8623610 SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的 ...

  6. 1031MySQL事务隔离级别详解

    转自http://xm-king.iteye.com/blog/770721 SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的.低级别的隔离级一般支 ...

  7. 对于大于8046 bytes的行,RCSI/SI事务隔离级别无效

    自SQL Server 2005起,我们有了READ COMMITTED SNAPSHOT ISOLATION level (RCSI) 和SNAPSHOT ISOLATION level (SI)两 ...

  8. (转)SQL SERVER的锁机制(四)——概述(各种事务隔离级别发生的影响)

    六.各种事务隔离级别发生的影响 修改数据的用户会影响同时读取或修改相同数据的其他用户.即这些用户可以并发访问数据.如果数据存储系统没有并发控制,则用户可能会看到以下负面影响: · 未提交的依赖关系(脏 ...

  9. (转)SQL SERVER的锁机制(三)——概述(锁与事务隔离级别)

    五.锁与事务隔离级别 事务隔离级别简单的说,就是当激活事务时,控制事务内因SQL语句产生的锁定需要保留多入,影响范围多大,以防止多人访问时,在事务内发生数据查询的错误.设置事务隔离级别将影响整条连接. ...

随机推荐

  1. PowerPC-Link Command File解析

    https://mp.weixin.qq.com/s/CATWma2mv5IPYGtKZLuGDA   以Code Warrior 11生成的flash版本(FLASH.lcf)为例   一. 参考资 ...

  2. Chisel3 - model - 子模块,顶层模块

    https://mp.weixin.qq.com/s/3uUIHW8DmisYARYmNzUZeg   介绍如何构建由模块组成的硬件模型.   1. 子模块   一个模块可以有一个或多个子模块,创建子 ...

  3. Java实现 LeetCode 732 我的日程安排表 III(暴力 || 二叉树)

    732. 我的日程安排表 III 实现一个 MyCalendar 类来存放你的日程安排,你可以一直添加新的日程安排. MyCalendar 有一个 book(int start, int end)方法 ...

  4. Java实现 LeetCode 700 二叉搜索树中的搜索(遍历树)

    700. 二叉搜索树中的搜索 给定二叉搜索树(BST)的根节点和一个值. 你需要在BST中找到节点值等于给定值的节点. 返回以该节点为根的子树. 如果节点不存在,则返回 NULL. 例如, 给定二叉搜 ...

  5. Java实现 LeetCode 572 另一个树的子树(遍历树)

    572. 另一个树的子树 给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树.s 的一个子树包括 s 的一个节点和这个节点的所有子孙.s 也可以看做它自身的一棵子树 ...

  6. Java实现 LeetCode 438 找到字符串中所有字母异位词

    438. 找到字符串中所有字母异位词 给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引. 字符串只包含小写英文字母,并且字符串 s 和 p ...

  7. Java实现 LeetCode 134 加油站

    134. 加油站 在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升. 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升 ...

  8. Java实现 蓝桥杯 历届试题 大臣的旅费

    问题描述 很久以前,T王国空前繁荣.为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市. 为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首 ...

  9. Java培训Day02——制作疫情地图(一)

    一.前言 此次培训,是为期三天的网上培训.最终的目的是制作出疫情地图.首先我们来看看主要的讲课内容大纲. Day1 |-Java语法学习(个人感觉讲得还可以,主要围绕本次培训作出的讲解,没有像网上的基 ...

  10. idea 启动命令行的时候提示不能创建PTY

    问题描述: 昨天上午,凯哥还在好好的使用idea,中午的时候,360扫描,好像要升级还是要干嘛的,没细看,然后凯哥就点击确定.结果到下午使用idea的Terminal 命令行的时候提示,如下图错误: ...