事务的常见问题:脏读,幻读,不可重复读
更新丢失(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,它能够避免脏读取,而且具有较好的并发性能。
标签:事务,隔离,幻读,级别,脏读,数据,id
From: https://www.cnblogs.com/piggthird/p/17864837.html