1、事务隔离级别有哪些
a、读未提交 - read-uncommitted
解释:事务A可以读取到其他事务没commit的数据,也就是会出现脏读的情况(其他事务rollback了这些就意味着读到了脏数据)
b、不可重复读 - read-committed
解释:事务A在开始后,其他事务改的数据,事务A再次读取,可以读取到过程之中其他数据更改的数据
c、可重复读 - repeatable-read
解释:事务A读取的数据,即使事务A过程中,B改了数据,A读到的都是一样的,也就是说在事务A整个过程之中,其他事务更改的数据,事务A都读取不到;
d、串行化 - serializable
事务A启动之后,无论是对某一个数据表读取还是更改操作都会给该表上锁,其他事务都无法再对这个表进行更改,必须等待事务提交或者回滚释放这个表锁;
2、事务隔离级别会导致的问题:
脏读:事务A读到事务B未commit的数据(rollback之后数据失效意味着事务A读到了无效的脏数据)
不可重复读:事务A过程之中,其他事务更改数据,读取到了其他事务commit的数据(正常情况希望整个事务反复读取的数据都不会变更)
幻读:事务A读取到的数据只有name为jack的行记录,但无法insert行name为rose的记录,提示rose已经存在(其他事务添加commit,不commit会等待(如果name是唯一值))
3、如何查看当前数据库的事务隔离级别
查看会话隔离级别(5.0以上版本):select @@tx_isolation;
查看会话隔离级别(8.0以上版本):select @@transaction_isolation;
4、更改当前数据库的事务隔离级别
set session transaction isolation level read uncommitted; 设置会话隔离级别为读未提交 set session transaction isolation level read committed; 设置会话隔离级别为读已提交 set session transaction isolation level repeatable read; 设置会话隔离级别为可重复读 set session transaction isolation level serializable; 串行化
5、模拟事务隔离级别带来的问题
# 准备数据 CREATE TABLE IF NOT EXISTS `user`( `id` INT UNSIGNED AUTO_INCREMENT, `name` VARCHAR(100) NOT NULL DEFAULT "", PRIMARY KEY (`id`) )ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO user (id, name) VALUES (1, "a"); INSERT INTO user (id, name) VALUES (2, "b");
验证脏读(让事务A读取到其他事务未commit的数据):
$A: begin; $B: begin; $B: insert into user value(3,"c"); # 此时读取到值为c的行记录 $A: select * from user; # 此时rollback那么意味着A客户端读取到的行记录c是脏数据 $B: rollback;
6、一张图看懂事务隔离级别会带来的问题有哪些:
脏读:
不可重复读( 读到其他事务commit后的数据逻辑上也不一定是错误,但是理想状态是希望事务内不断读取数据读到的都是一样的 ):
幻读:
可以验证到解决 幻读只能串行化(表锁):