MySQL隔离级别

一、隔离级别导致的问题

  1. 脏读:A事物允许读取到B事物未提交的数据。
  2. 不可重复读:A事物在时间点T1读取了一些记录,在T2时再想重新读取一次同样的这些记录时,这些记录可能已经被改变、或者消失不见。
  3. 幻读:A事物在任意时刻查询的结果都是事务开始时的状态(一致性)。但是,如果另一个事务同时提交了新数据,本事务再更新时,就会“惊奇的”发现了这些新数据,貌似之前读到的数据是“鬼影”一样的幻觉。

二、事物隔离级别

  1. Read Uncommitted
  2. Read Committed
  3. Repeatable Read
  4. Serializable

每种隔离级别产生的问题:

隔离级别脏读不可重复读幻读
Read UncommittedYY
Read CommittedNYY
Repeatable Read(MySQL默认事物隔离级别) NY 
Serializable
NNN

三、测试

1.首先检查一下MySQL的版本号

select version();



2.查看一下系统的隔离级别和回话隔离级别

select @@global.tx_isolation, @@tx_isolation;


3.修改当前会话隔离级别,方便做测试

set session tx_isolation='read-uncommitted';

select @@global.tx_isolation, @@tx_isolation;


可以发现测试会话的隔离级别变成了不可重复读


4.修改系统级别的隔离级别

set global tx_isolation='read-uncommitted';

select @@global.tx_isolation, @@tx_isolation;


此时系统级和会话级别的事物隔离级别都变成了:READ-UNCOMMITTED


5.关闭SQL自动提交功能

set autocommit=off;

show variables like 'autocommit';


6.建立测试表

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8


7.测试脏读

Transaction ATransaction B
start transaction; 

start transaction;


insert into user(name, age) values ('张三',20);

此时Transaction B尚未提交,但是Transaction A已经读取到B更新的数据了

 
 rollback;


此时Transaction B回滚了,但是Transaction A已经读取不到刚刚那条记录了

 
  
按照上图的执行顺序,脏读就这样产生了。


8.测试不可重复读

set global tx_isolation='read-committed';
set session tx_isolation='read-committed';

Transaction ATransaction B
start transaction; 
 
 start transaction;


insert into user(name, age) values ('李四',30);

TransactionB未提交,所以TransactionA读取不到B的修改

 
 commit;

TransactionB提交,所以TransactionA读取到B的修改

 
按照上图的执行顺序,Transaction A在同一个事物中,不同时间点上,读取到的数据是不一样的,这就叫不可重复读。


9.测试可重复读

set global tx_isolation='repeatable-read';
set session tx_isolation='repeatable-read';

修改隔离级别为可重复读,这样同一个事物Transaction A中任一时刻读取的数据是可以保持一致了,但是紧接着就带来了幻读的问题了。

Transaction ATransaction B
 
 start transaction;


insert into user(id, name, age) values (6,'麻子',35);


commit;

TransactionB提交,但是此时TransactionA没有读取到B的修改,这就是所谓可重复读

 

------------------------------------------------------华丽的分割线------------------------------------------------------------

至此验证完了可重复读,下面紧接着就出现了幻读~

 


此时在TransactionA中执行insert into user(id, name, age) values (6,'麻子',35);出现错误

但是在华丽的分割线的上面,查询语句是没有查到有id为6的记录的

 
  


10.测试Serializable

set global tx_isolation='serializable';
set session tx_isolation='serializable';

设置隔离级别为Serializable后,就不会出现幻读的问题了。

在这种情况下,只允许一个事务在执行,其它事务必须等待这个事务执行完后才能执行。没有并发,只是单纯的串行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值