一、事务并发问题
1. 脏读
含义:在事务过程中,A事务还未提交,B事务就读到了A事务未提交的数据。
一个事务正在对一条记录做修、改,在这个事务完成并提交前,这条记录的数据就处于不一致状态;这时,另一个事务也来读取同一条记录,如果不加控制,第二个事务读取了这些“脏”数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象的叫作"脏读"(DirtyReads)。
简答来说,读取了其他事务未提交的数据
解决方法:将数据库事务提升到提交读或以上的隔离级别。
2. 不可重复读
含义:一次事务中,两次读操作中,读出来的数据内容不一致。
A事务在本次事务中,对自己未操作过数据,进行多次读取,结果出现不一致或记录不存在的情况。(update和delete)
一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了改变、或某些记录已经被删除了!这种现象就叫作 “不可重复读”(Non-Repeatable Reads)。
解决方法:将数据库事务提升到可重复读或以上的隔离级别。
3. 幻读
含义:一次事务中,两次读操作中,读到的数据行数不一致。读到了新增或者读不到删除的语句。
A事务在本次事务中,对自己未操作过数据,进行多次读取,结果出现不一致或记录不存在的情况。(insert)
一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读”(Phantom Reads)。
解决方法:将数据库事务提升到序列化(串行化)或以上的隔离级别。
注:幻读和不可重复读很像但有区别。幻读是事务1操作过程中,有新数据添加提交了。再读时会出现新数据。不可重复读是,事务1操作过程中,之前读过的数据被修改或删除了。
4. 丢失修改(脏写)
含义:多个事务同时对数据进行修改,其中一个事务的数据被另一个事务的操作覆盖,导致丢失修改。如果一个事务修改了另一个未提交事务修改过的数据,那就意味着发生了 脏写
解决:脏写这个问题太严重了,不论是哪种隔离级别,都不允许脏 写的情况发生。
二、隔离级别
读未提交(read-uncommitted):最低级别,基本只保证持久性;会出现脏读,不可重复读,幻读的问题。
读已提交(read-committed):语句级别;会出现不可重复读,幻读的问题。
可重复读(repeatable-read):事务级别;只会出现幻读问题。–mysql默认的
串行化(serializable):最高级别,也就是事务与事务完全串行化执行,无并发可言,性能低;但不会出现任何问题。相当于锁表
三、 隔离性相关的锁机制
RU:事务读取时不加锁
RC:事务读取时加行级共享锁(读到才加锁),一旦读完,立刻释放(并不是事务结束)。
RR:事务读取时加行级共享锁,直到事务结束时,才会释放。
SE:事务读取时加表级共享锁,直到事务结束时,才会释放。
MVCC机制:生成一个数据快照,并用这个快照来提供一定级别的一致性读取,也称为多版本数据控制。
不可重复读或幻读的解决方法:读取数据时加共享锁,写数据时加排他锁,都是事务提交才释放锁
脏读的的解决方法:修改时加排他锁,直到事务提交后释放,读取时加共享锁