MySQL(八)事务的隔离级别
一.事务的并发问题
1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据(修改)
2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。(修改)
3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。(明明已经全部修改完了,但是事务B又新增了一条,事务A就像是眼花了一样,咦咋还有数据没有修改,删除是一样的,同样的条件的select, 第1次和第2次读出来的记录数不一样)幻读对应的是新增或者删除
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
读未提交(read-uncommitted) | 是 | 是 | 是 |
不可重复读(read-committed)(读已提交) | 否 | 是 | 是 |
可重复读(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
(1)读未提交,Read Uncommitted:某个事务还没提交的时候,修改的数据,就让别的事务给读到了,很容易导致出错的。这个也叫做脏读。
(2)读已提交,Read Committed(不可重复读):这个比上面那个稍微好一点,但是一样比较尴尬,就是说事务A在跑的时候, 先查询了一个数据是值1,然后过了段时间,事务B把那个数据给修改了一下还提交了,此时事务A再次查询这个数据就成了值2了,这是读了人家事务提交的数据啊,所以是读已提交。这个也叫做不可重复读,就是所谓的一个事务内对一个数据两次读,可能会读到不一样的值。在读已提交模式下:如何解决不可重复读:只需要锁住满足条件的记录,就可以避免被其它事务修改,也就是 select for update, select in share mode;
(3)可重复读,Read Repeatable:这个就是比上面那个再好点儿,就是说事务A在执行过程中,对某个数据的值,无论读多少次都是值1;哪怕这个过程中事务B修改了数据的值还提交了,但是事务A读到的还是自己事务开始时这个数据的值。解决了脏读和不可重复读问题,在MySQL,InnerDB引擎下可以解决幻读,通过MVCC和间隙锁解决幻读
(4)串行化:幻读,不可重复读和可重复读都是针对两个事务同时对某条数据在修改,但是幻读针对的是插入,比如某个事务把所有行的某个字段都修改为了2,结果另外一个事务插入了一条数据,那个字段的值是1,第一个事务会突然发现多出来一条数据,那个数据的字段是1 (字段是1的有多条数据)。如果要解决幻读,就需要使用串行化级别的隔离级别,所有事务都串行起来,不允许多个事务并行操作。锁表,事务A操作结束,事务B才可以执行,不会出现幻读
MySQL默认为:可重复读