创建bank数据库模拟银行转账。
create database bank;
use bank;
create table account
(ID INT PRIMARY KEY,
NAME CHAR(20),
BALANCE INT);
INSERT account values(1,‘Ma’,1000);
INSERT account values(2,‘Liu’,800);
INSERT account values(3,‘Zhang’,2000);
INSERT account values(4,‘Li’,1800);
INSERT account values(5,‘Wu’,3000);
select *from account;
–1. 读未提交
窗口一:
读脏数据(先)
set session transaction isolation level read uncommitted;
– 在另外一窗口中修改此记录–现在来查询所有的数据
select * from account where id = 1;
–可以发现可以查询,但会读脏数据–在另外一个窗口rollback,再来查询
select * from account where id = 1;
–发现两次读到的数据不一样
–为了不读脏数据只要将事务的隔离级别设置为 read commit,默认为此级别
窗口二:
–在另一窗口改变事务隔离级别
use bank;
start transaction;
update account set BALANCE =10000 where id = 1;
–在另一窗口观察
–现在rollback掉
rollback;
–2.读已提交
窗口一:
不读脏数据(先)
set session transaction isolation level read committed;
–在另外一窗口中修改此记录
–当在另一窗口中更改数据时,现在发现,读取到未修改之前的结果,直到另一窗
口中将此事务commit之后才可以看到新结果
select * from account where id = 1;
窗口二:
另一窗口中改变事务隔离级别为read committed
start transaction;
update account set BALANCE=9000 where id =1;
–在另一窗口中观察
–现在rollback掉,可以发现另外一窗口可以读取数据了
rollback;
–3.不可重复读
窗口一:
不可重复读(先)(read commit)
set session transaction isolation level read committed;
start transaction;
select balance from account where id = 1;–第一次读数据
–其它操作…
– 在另外一窗口中修改此记录,再来第二次读数据
–其它操作…
select balance from account where id = 1;
–可以发现数据已经发生了变化,两次读到的数据不一样
commit;
窗口二:
不可重复读
–下面的语句要在第一次读后全部执行完(commit)
start transaction;
update account set BALANCE=9000 where id = 1;
commit;
–执行另一窗口中第二次读操作
–4.可重复读
窗口一:
可重复读(先)(REPEATABLE READ)
set session transaction isolation level repeatable read;
start transaction;
select balance from account where id = 1;–第一次读数据
–其它操作…
– 在另外一窗口中修改此记录,发现可以正常提交,
–其它操作…
select balance from account where id = 1;
–可以发现两次读到的数据一样,只是我们在
–窗口一中查询到的结果不会改变,它还是之前查询的结果
commit;
窗口二:
可重复读
–下面的语句要在第一次读后执行,发现可以执行修改操作
–start transaction;
update account set BALANCE=8800 where id = 1;
在另一窗口继续读操作,再来提交
commit;
–执行另一窗口中再继续读操作
–5.幻读
窗口一:
幻读(幽灵)读(先)
set session transaction isolation level repeatable read;
start transaction;
select * from account; --记录下记录的条数
–其它操作…
– 在另一窗口中插入记录,并提交
从原理上看,可重复读是靠MVCC(多版本并发控制)保证的,该模式
下,保证事务只能读取到当前事务开启之前已经提交的事务进行的修改
以及当前事务本身对数据的修改。而我们上述只进行了插入,所以直接进行select
并不会影响到A的读取。
update account set balance=0 where id>5;
select * from account;
–可以发现已经读出了窗口二中的插入的数据, 两次读到的数据不一样.
commit;
窗口二:
幻读(幽灵)全部执行完(commit)
start transaction;
insert into account values(14,‘kkk’,5000);
insert into account values(15,‘lll’,6000);
commit;
–在窗口一中执行第二次读观察结果
–6.可串化
窗口一:
不幻读(幽灵)读(先)
set session transaction isolation level serializable;
start transaction;
select * from account;–第一次读
–其它操作
–同样在窗口二中试图插入记录,可以发现现在不能插入了
select * from account;–由于窗口二不能插入数据了,所以两次读出的结果一样
commit;
窗口二:
不幻读(幽灵)全部执行完(commit),可以发现执行不能完成
start transaction;
insert into account values(22,‘kkk’,3800);
insert into account values(23,‘lll’,6500);
commit;