数据库脏读、幻读
脏读
一个事务读取另一个事务未提交的数据:事务1读取一条数据并做了修改,此时事务2读取事务1已修改且未提交的数据;此时如果事务1回滚了修改操作,那么事务2读取的数据就是脏数据
幻读
一个事务按照相同的查询条件重新读取检索过的数据,但发现有新的数据插入:事务1按照条件a检索到b行数据,然后事务2再插入符合条件a的数据,当事务1再次按照条件a检索数据时发现多了事务2插入的数据
丢失的修改
两个事务同时修改了同一行数据并提交,其中一个事务覆盖了另一个事务的修改。
不可重复读
一个事务先后两次读取相同行的数据,发现数据不一致:事务1读取a行数据,事务2修改或删除部分或全部数据,事务1再次读取到的数据和第一次读取的的数据不一致。
解决办法
出现以上问题是数据库事务隔离级别的问题
SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离一般支持更高的并发处理,并拥有更低的系统开销。
Read Uncommitted(读取未提交内容)
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,以为他的性能也不比其他级别好多少。读取未提交的数据,也叫脏读(dirty read)
Read Committed(读取提交内容)
这个是大多数数据库系统的默认隔离级别(但不是MysQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别也支持所谓的不可重复读(Nonrepeatable Read),应为同一事物的其他实例在该实例处理期间可能会有新的提交,所以同一个select可能返回不同结果。
Repeatable Read(可重读)
这是MySQL的默认事务隔离级别,他确保统一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读(Phantom Read)。InnoDB和FaIcon存储引擎通过多版本并发控制机制解决了这个问题。
Seraliable(可串行化)
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超市现象和锁竞争。