默认级别
– 默认隔离级别,mysql是Repeatable Reads(可重复读),其他数据库一般是 Read Committed(读已提交)
事务的隔离级别分为:
Read uncommitted(读未提交)
Read Committed(读已提交)
Repeatable Reads(可重复读)
Serializable(串行化)
SHOW VARIABLES LIKE '%isolation%';
-- transaction_isolation REPEATABLE-READ
Read uncommitted
读未提交:隔离级别最低的一种事务级别。在这种隔离级别下,会引发脏读、不可重复读和幻读。
Read Committed
读已提交读到的都是别人提交后的值。这种隔离级别下,会引发不可重复读和幻读,但避免了脏读。
Repeatable Reads
可重复读这种隔离级别下,会引发幻读,但避免了脏读、不可重复读。
Serializable
串行化是最严格的隔离级别。在Serializable隔离级别下,所有事务按照次序依次执行。脏读、不可重复读、幻读都不会出现。
一、Read uncommitted(读未提交)
start transaction;
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM ts_test;
-- 此时 在另外一个事务中更新一条记录,但是不提交事务,在本次事务内也能看到更新的最新值,如果另外一个事务最后回滚了改记录,这就是一条脏读的记录。
-- UPDATE ts_test SET version_test='update o' where id =2; //mysql 如果插入一条记录,可能导致间隙锁锁定改事务导致看不到未提交读的效果。
SELECT * FROM ts_test; -- 这个时候看到脏数据 update o
-- 此时另外一个事务 回滚了
-- ROLLBACK;
SELECT * FROM ts_test; -- 这个时候看到原始值 update xx
COMMIT;
二、 Read Committed(读已提交)
start transaction;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT * FROM ts_test;
-- 此时 在另外一个事务中更新一条记录,但是不提交事务,在本次事务不会看到这个修改。
-- UPDATE ts_test SET version_test='update o' where id =2;
SELECT * FROM ts_test; -- 这个时候不会看到脏数据 update o
-- 此时另外一个事务提交,将看到已提交的记录;
-- COMMIT;
SELECT * FROM ts_test; -- 不可重复读 这个时候看到提交的值 update o
-- 此时另外一个事务新增一条提交的记录,本次事务也能看到,幻读;
-- INSERT INTO ts_test (id,version_test) VALUES(21,'21');
SELECT * FROM ts_test; -- 幻读,看到了另外一个事务提交的新行,是本次事务开始的是没有的行
COMMIT;
三、 Repeatable Reads(可重复读)
start transaction;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT * FROM ts_test;
-- 此时 在另外一个事务中更新一条记录,并且提交事务,在本次事务不会看到这个修改。
-- UPDATE ts_test SET version_test='update o' where id =2;
SELECT * FROM ts_test; -- 可重复读 这个时候不会看到已提交的值 update o
-- 此时另外一个事务新增一条提交的记录,本次事务也能无法看到幻读,因为mysql的间隙锁解决了这个问题;
-- INSERT INTO ts_test (id,version_test) VALUES(22,'22');
SELECT * FROM ts_test; -- 不会幻读,不会看到了另外一个事务提交的新行,是本次事务开始的是没有的行
COMMIT;
四、 Serializable(串行化)
start transaction;
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT * FROM ts_test;
-- 此时 在另外一个事务中更新一条记录,则在另外一个事务中无法执行该表的操作
-- UPDATE ts_test SET version_test='update 24' where id =2;
-- 等该事务提交之后,另外一个事务才能更新成功,否则别阻塞,阻塞时间和数据库有关系。
COMMIT;