赞
踩
事务隔离级别是指多个事务之间,不同事务中涉及的读写操作互相影响的隔离。其中多个事务中同时对同一条数据或者表进行写操作(insert、update、delete),必定会导致事务间数据的相互影响,导致不可预知问题发生。主要的问题可以归为以下几种:
set session transaction isolation level read uncommitted;
set session autocommit=0;
建表语句:
create table tbl_transaction( column1 char, column2 char);
insert into tbl_transaction values ('a', 'b');
初始数据:
客户端1 | 客户端2 |
---|---|
begin; | begin; |
update tbl_transaction set column1=‘b’; | |
select * from tbl_transaction; 读取到了事务1未commit的修改 | |
rollback; | |
select * from tbl_transaction; 当客户端1回滚后读取到回滚后的数据 | |
commit; |
当我们把隔离级别设置为:
set session transaction isolation level read committed;
客户端1 | 客户端2 |
---|---|
begin; | begin; |
update tbl_transaction set column1=‘b’; | |
select * from tbl_transaction; 事务2没有读取到事务1的修改,脏读问题解决了 | |
commit; | |
select * from tbl_transaction; 当事务1commit之后,事务2可以读取到相关的修改 | |
commit; |
可以看到在事务1commit之前,事务2都无法看到事务1做出的修改。
这种级别为:提交读
但是这里又出现了另一个问题:事务2中同一条数据查询两次的查询结果都不一样,对于同一条数据不可重复读,这就是不可重复读问题。
提交读隔离级别解决了未提交读的问题,但是不能解决不可重复读问题。
怎么解决不可重复度问题呢?提供几个思路:
当我们把隔离级别设置为:
set session transaction isolation level read committed;
客户端1 | 客户端2 |
---|---|
begin; | |
begin; | |
select * from tbl_transaction; | |
insert into tbl_transaction values(‘c’, ‘d’); | |
commit; | |
select * from tbl_transaction; 事务2没有读取到事务1的插入,没出现幻读的现象 |
事务1的事务ID为ID1
事务2的事务ID 为ID2,其中ID2<ID1(事务ID分配并非在事务begin的时候分配,是执行Select的时候才分配的)
新插入的数据:
column1 | column2 | create_version | delete_version |
---|---|---|---|
‘c’ | ‘d’ | ID1 | null |
由于ID2<ID1,不满足create_version<=事务ID条件,因此新插入的数据没有被查出啦。
那啥时候会出现幻读的现象呢?可以从下面的例子:
客户端1 | 客户端2 |
---|---|
begin; | |
begin; | |
select * from tbl_transaction; | |
insert into tbl_transaction values(‘c’, ‘d’); | |
commit; | |
select * from tbl_transaction; 事务2没有读取到事务1的插入,没出现幻读的现象 | |
update tbl_transaction set column2=‘c’ where column1=‘c’; | |
再次select:会发现多了一条数据,出现了幻读。 |
那么遇到幻读现象怎么解决呢?
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。