当前位置: 移动技术网 > IT编程>数据库>Mysql > 事务的隔离级别- 极客时间()

事务的隔离级别- 极客时间()

2019年07月19日  | 移动技术网IT编程  | 我要评论
初识事务隔离 事务隔离级别的出现都是针对数据库的具体问题的, SQL 92标准对事务并发处理会存在的异常情况进行了分级, 分别为脏读(Dirty Read)、不可重复读(Unrepeatable Read)和幻读(Phantom Read). 三种异常 举个例子, 有个heros_temp表, 中有 ...

初识事务隔离

事务隔离级别的出现都是针对数据库的具体问题的, sql-92标准对事务并发处理会存在的异常情况进行了分级, 分别为脏读(dirty read)、不可重复读(unrepeatable read)和幻读(phantom read).

三种异常

举个例子, 有个heros_temp表, 中有三条数据:

先说脏读, 现在访问数据库, 对数据库进行了一次insert操作, 插入一条"吕布"的记录, 事务未提交, 现在重新开启一个事务, 查询数据库可以将吕布的记录查询出来. 这个就是脏读.

不可重复读呢? 现在先查询数据库记录, 之后重新开启一个事务, 修改一条记录, 现在在前一个事务中再次查询可以查询出修改后的数据, 前后查询出的数据不一致. 这个就是不可重复度.

幻读呢? 现在先查询数据库, 之后开启新事务insert一条记录, 在第一个事务中再次查询会多出插入的记录, 这个就是"幻读".

  1. 脏读: 读到事务中还没有提交的数据(可能事务回滚, 这个时候读到的数据无意义)
  2. 不可重复读: 对某数据进行读取, 发现两次读取的结果不同, 也就是没有读到相同的内容.(重点在于一条数据的修改, 也就是update 和 delete) 这个因为有其他事务对这个数据同时进行了修改和删除.
  3. 幻读: 事务a根据条件查询得到了n条数据, 但此时事务b更改或者增加了m条符合事务a查询条件的数据, 这样当事务a再次进行查询的时候大仙有n + m条数据, 产生了幻读.(重点在于新增多条记录insert)

事务的隔离级别有哪些?

解决异常数量从少到多的顺序决定了隔离级别的高低, 这四种隔离级别从低祷告分别是: 读未提交(read uncommitted)、读已提交(read committed)、可重复读(repeatable read)和可串行化(serializable). 这个隔离级别解决的异常情况如下:

读未提交,也就是允许读到未提交的数据,这种情况下查询是不会使用锁的,可能会产生脏读、不可重复读、幻读等情况。

读已提交就是只能读到已经提交的内容,可以避免脏读的产生,属于 rdbms 中常见的默认隔离级别(比如说 oracle 和 sql server),但如果想要避免不可重复读或者幻读,就需要我们在 sql 查询的时候编写带加锁的 sql 语句。

可重复读,保证一个事务在相同查询条件下两次查询得到的数据结果是一致的,可以避免不可重复读和脏读,但无法避免幻读。mysql 默认的隔离级别就是可重复读。

可串行化,将事务进行串行化,也就是在一个队列中按照顺序执行,可串行化是最高级别的隔离等级,可以解决事务读取中所有可能出现的异常情况,但是它牺牲了系统的并发性。

模拟异常

模拟的数据库表如下:

-- ----------------------------
-- table structure for heros_temp
-- ----------------------------
drop table if exists `heros_temp`;
create table `heros_temp`  (
  `id` int(11) not null,
  `name` varchar(255) character set utf8 collate utf8_general_ci not null,
  primary key (`id`) using btree
) engine = innodb character set = utf8 collate = utf8_general_ci row_format = dynamic;

-- ----------------------------
-- records of heros_temp
-- ----------------------------
insert into `heros_temp` values (1, '张飞');
insert into `heros_temp` values (2, '关羽');
insert into `heros_temp` values (3, '刘备');

开启两个客户端, 由于mysql的默认隔离级别是可重复度, 所以需要先将级别设为读未提交:

mysql> show variables like 'transaction_isolation'; // 查询当前隔离级别
mysql> set session transaction isolation level read uncommitted; // 设置隔离级别为读未提交
mysql> set autocommit = 0; // 设置事务不自动提交(由于mysql的事务是自动提交的, 这里需要改一下)
脏读

客户端2中开启事务, 写入新英雄, 不要提交

客户端1中查看

模拟不可重复读

客户端1查询

客户端2修改

客户端1再次查询

模拟幻读

客户端1查询

客户端2新增

客户端1再次查询

隔离级别都是针对对应的异常问题, 并且隔离级别针对每种rdbms都是相同的, 不同的是实现的原理不同.

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网