事务的隔离级别

发布时间 2023-11-29 14:55:15作者: PiggThird

事务的常见问题:脏读,幻读,不可重复读

更新丢失(Lost Update)
	原因:当多个事务选择同一行操作,并且都是基于最初选定的值,由于每个事务都不知道其他事务的存在,就会发生更新覆盖的问题。类比github提交冲突。

脏读(Dirty Reads)
	原因:事务A读取了事务B已经修改但尚未提交的数据。若事务B回滚数据,事务A的数据存在不一致性的问题。

不可重复读(Non-Repeatable Reads)
	原因:事务A第一次读取最初数据,第二次读取事务B已经提交的修改或删除数据。导致两次读取数据不一致。不符合事务的隔离性。

幻读(Phantom Reads)
	原因:事务A根据相同条件第二次查询,虽然查询不到事务B提交的新增数据,但是会影响事务A之后的一些操作,比如:事务A进行了一次select * from t1表查询,查询出id为1的数据,同时事务B进行了一次insert into t1 values(2,'xx'),也就是此时表中有了id为2的数据,但是在事务A中再次进行查询的时候,根本就查不到id为2的数据,但是当事务A进行insert into t1 values(2,'xx'),也想插入id为2的数据的时候,发现报错了,看图,但是事务A怎么查也查不到有id为2的数据,这就让事务A的使用者出现了幻觉,what happend!。如果不想出现幻读问题,那么自己在查询语句中手动加锁 for update,如果查询的是id为2的数据,即便是现在没有id为2的数据,其他事务也无法对id为2的索引位置进行数据的处理。
	

幻读和脏读有点类似
    脏读是事务B里面修改了数据,
    幻读是事务B里面新增了数据。

事务的隔离级别:未提交读\已提交读\可重复读\可序列化(串行化)

+------------------------------+---------------------+--------------+--------------+-----
| 隔离级别                      | 读数据一致性         | 脏读         | 不可重复 读   | 幻读   
+------------------------------+---------------------+--------------+--------------+-----
| 未提交读(Read uncommitted)    | 最低级别            | 是           | 是           | 是     
+------------------------------+---------------------+--------------+--------------+-----
| 已提交读(Read committed)      | 语句级              | 否           | 是           | 是     
+------------------------------+---------------------+--------------+--------------+-----
| 可重复读(Repeatable read)     | 事务级              | 否           | 否           | 是     
+------------------------------+---------------------+--------------+--------------+-----
| 可序列化(Serializable)        | 最高级别,事务级      | 否           | 否           | 否     
+------------------------------+---------------------+--------------+--------------+-----



查看当前数据库的事务隔离级别:show variables like 'tx_isolation';

事务的隔离级别设置

1.未提交读(READ UNCOMMITED) 解决的障碍:无; 引入的问题:脏读
    set SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

2.已提交读 (READ COMMITED) 解决的障碍:脏读; 引入的问题:不可重复读
    set SESSION TRANSACTION ISOLATION LEVEL read committed;

3.可重复读(REPEATABLE READ)解决的障碍:不可重复读; 引入的问题:幻读
    set SESSION TRANSACTION ISOLATION LEVEL repeatable read;

4.可串行化(SERIALIZABLE)解决的障碍:可重复读; 引入的问题:锁全表,性能低下
    set SESSION TRANSACTION ISOLATION LEVEL repeatable read;

总结:

事务隔离级别为可重复读时,如果有索引(包括主键索引)的时候,以索引列为条件更新数据,会存在间隙锁间、行锁、页锁的问题,从而锁住一些行;如果没有索引,更新数据时会锁住整张表

事务隔离级别为串行化时,读写数据都会锁住整张表

隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大,对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读取,而且具有较好的并发性能。