脏读(dirty read)不可重复读(unrepeatable read)幻读(phantom problem)解析,phantom
1. 脏读
首先区分脏页和脏数据
脏页是内存的缓冲池中已经修改的page,未及时flush到硬盘,但已经写到redo log中。读取和修改缓冲池的page很正常,可以提高效率,flush即可同步。
脏数据是指事务对缓冲池中的行记录record进行了修改,但是还没提交!!!,如果这时读取缓冲池中未提交的行数据就叫脏读,违反了事务的隔离性。
脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
2. 不可重复读
是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,第二个事务已经提交。那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。如果只有在作者全部完成编写后编辑人员才可以读取文档,则可以避免该问题
3. 幻读 :
是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。例如,一个编辑人员更改作者提交的文档,但当生产部门将其更改内容合并到该文档的主复本时,发现作者已将未编辑的新材料添加到该文档中。如果在编辑人员和生产部门完成对原始文档的处理之前,任何人都不能将新材料添加到文档中,则可以避免该问题。
数据库隔离机制介绍
Isolation 属性一共支持五种事务设置,具体介绍如下:
l DEFAULT 使用数据库设置的隔离级别 ( 默认 ) ,由 DBA 默认的设置来决定隔离级别 .MySQL默认为repeatable_read
l READ_UNCOMMITTED 会出现脏读、不可重复读、幻读 ( 隔离级别最低,并发性能高 )
l READ_COMMITTED 会出现不可重复读、幻读问题(锁定正在读取的行)
l REPEATABLE_READ 会出幻读(锁定所读取的所有行)
l SERIALIZABLE 保证所有的情况不会发生(锁表)
不可重复读的重点是修改 :
同样的条件 , 你读取过的数据 , 再次读取出来发现值不一样了
幻读的重点在于新增或者删除
同样的条件 , 第 1 次和第 2 次读出来的记录数不一样
| 脏读 | 不可重复读 | 幻读 | |
| Serializable | 不会 | 不会 | 不会 |
| REPEATABLE READ | 不会 | 不会 | 会 |
| READ COMMITTED | 不会 | 会 | 会 |
| Read Uncommitted | 会 | 会 | 会 |
一般事务简单的讲就是对数据库表的添加、删除、修改和查询操作。。。
事务具有原子性
事务中包含的添加、删除、更新等操作要么全部做完
要么全部都不做,以保证数据库的一致性和正确性
举个例子说:银行账户,你首先查看还有1000元,然后你要取500元钱,在你取钱时取款机出问题,你没能取成500元钱,这时就会回滚,不会说因为这样你下次再查看的时候就只有500了
spring的事务处理主要是依靠AOP实现的,这个没什么好说的随便搜索一下,网上很多示例。
隔离级别是针对并发事务而言的,单个事务的处理很简单不多说。并发事务的处理则比较复杂,因为往往一条数据是跨事务的,这会造成许多不可预知的后果。
一般来说,系统执行并发事务时,会把当前在执行的事务独立起来,也就是和其他事务进行隔离。好像系统中只有这一个事务,其他事务不存在一样。这也就是完全隔离,即系统中只运行单位时间内,最多只有一个事务在执行,其他事务要等到该事务执行完毕之后才能执行,这在现实中基本是不可行的,比如,你要更新你的QQ用户信息,那么就是说,在你更新的这段时间内,其他的用户是无法更新他的用户信息的。
举个深动的例子,把事务比作一条在公路上奔跑的汽车,完全隔离,就像是,在汽车从公路一头到另一头这段时间内,公路上不允许有其他的汽车,这样做当然可以完全避免车祸,也就是数据跨事务带来的隐患风险,但是带来了巨大的效率问题,那么如果同时在公路上让多辆汽车行驶会造成什么情况呢。
具体来说有一下几种:
更新丢失(Lost Update):两个事务都企图去更新一行数据,导致事务抛出异常退出,两个事务的更新都白费了。
脏数据(Dirty Read):如果第二个应用程序使用了第一个应用程序修改过的数据,而这个数据处于未提交状态,这时就会发生脏读。第一个应用程序随后可能会请求回滚被修改的数据,从而导致第二个事务使用的数据被损坏,即所谓的“变脏”。
不可重读(Unrepeatable Read):一个事务两次读同一行数据,可是这两次读到的数据不一样,就叫不可重读。如果一个事务在提交数据之前,另一个事务可以修改和删除这些数据,就会发生不可重读。
幻读(Phantom Read):一个事务执行了两次查询,发现第二次查询结果比第一次查询多出了一行,这可能是因为另一个事务在这两次查询之间插入了新行。
以上就是并行事务处理时常遇到的大致问题。针对这些问题,提出了几个不同的事务隔离级别,适应特定的环境需要。
具体是:
读操作未提交(Read Uncommitted):说明一个事务在提交前,其变化对于其他事务来说是可见的。这样脏读、不可重读和幻读都是允许的。当一个事务已经写入一行数据但未提交,其他事务都不能再写入此行数据;但是,任何事务都可以读任何数据。这个隔离级别使用排写锁实现。
读操作已提交(Read Committed):读取未提交的数据是不允许的,它使用临时的共读锁和排写锁实现。这种隔离级别不允许脏读,但不可重读和幻读是允许的。
可重读(Repeatable Read):说明事务保证能够再次读取相同的数据而不会失败。此隔离级别不允许脏读和不可重读,但幻读会出现。
可串行化(Serializable):提供最严格的事务隔离。这个隔离级别不允许事务并行执行,只允许串行执行。这样,脏读、不可重读或幻读都可发生。