mysql学习-事务隔离级别
1、事务概述
用户定义的一些列操作,将多个sql语句视为一个整体去执行,这些语句要么全部执行成功了,要么全部不执行。事务对于保证数据的一致性和完整性至关重要,尤其在多个用户对数据库进行并发操作。如果只有一个客户端连接操作mysql,就没必要讨论事务了。
2、如何告诉mysql是事务语句
begin/commit(begin和commit之间的语句,被视为事务)
begin/rollback(begin和rollback之间的语句,被视为回滚事务)
2、MySQL支持四种标准的事务隔离级别
2.1、read uncommit(读未提交)
最低隔离级别,允许一个事务读取其他事务未提交的数据。这会导致脏读、不可重复读、幻读问题。
设置隔离级别sql语句:
set transaction isolation level read uncommitted;
脏读
右侧客户端开启事务,插入数据,但未commit;
左侧客户端开启事务,却能读到右侧客户端未提交的事务数据;
相当于一个mysql客户端,读取到另一个客户端事务执行中间的结果。
【解决脏读】
可以升级隔离级别到read commit
2.2、read commit(读已提交)
一个事务只能读取其他事务已经提交的数据,可以防止脏读,但无法避免不可重复读和幻读
设置隔离级别sql语句:
set transaction isolation level read committed;
不可重复读
右侧客户端开启事务,2次查询name为test1的age,是不一样的结果。
相当于在一个事务内,查询某个值,俩次结果不同,不符合预期。
原因:第二次读取的时候,读到了其他事务提交的结果。
【解决不可重复读】
可以升级隔离级别到 repeatable read
2.3、repeatable read(可重复读,mysql的默认级别)
这是MySQL的InnoDB存储引擎默认的隔离级别。它确保在同一事务内的多次读取同样的数据行时,即使其他事务修改了这些数据行,也不会影响当前事务的读取结果。这可以防止脏读和不可重复读,但幻读仍可能发生。
幻读
右侧客户端开启事务,先查询了下id>4的数据,然后插入一条新数据,但是报错了。
原因:左侧客户端开启事务,并且已经插入了这条新数据commit;
所以会出现,右侧客户端以为可以插入新数据,但是插入数据又报错了。
[解决办法]
给读操作加锁(for update),右侧客户端会阻塞等待左侧客户端事务完成。
select * from student_info where id > 4 for update;
2.4、serializable(可串行化)
最高的隔离级别,完全串行化处理,事务一个接一个地执行,可以防止所有并发引起的问题,包括脏读、不可重复读和幻读,这个效率也是最低的。
学习链接:https://github.com/0voice