RC模式下出现的脏读现象
有一张表如下:
mysql> select * from t1;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 25 |
| 4 | 李四 | 20 |
| 6 | 王五 | 17 |
| 9 | 大刀 | 27 |
| 15 | 赵虎 | 35 |
| 20 | 王强 | 32 |
+----+------+-----
我们开始一个事务
mysql> begin;
mysql> update t1 set name=‘大虎‘ where age=17;
此时,我们不执行提交,在另一会话查看
select * from t1;
mysql> select * from t1;
+------+--------+------+
| id | name | age |
+------+--------+------+
| 1 | 张三 | 25 |
| 4 | 李四 | 20 |
| 6 | 大虎 | 17 |
| 9 | 大刀 | 27 |
| 15 | 赵虎 | 35 |
| 20 | 王强 | 32 |
+------+--------+------+
数据已经发生改变了,这就是脏读了
事务还不确定提不提交,就可以读到所以这种模式不适合
例子解释:取款的时候,还没有点确认取款,但是查余额时,发现已经少了!所以这种模式一般不用
RU模式可防止脏读,但是会出现不可重复读和幻读
有一张表如下:
mysql> select * from t1;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 25 |
| 4 | 李四 | 20 |
| 6 | 王五 | 17 |
| 9 | 大刀 | 27 |
| 15 | 赵虎 | 35 |
| 20 | 王强 | 32 |
+----+------+-----
我们开始一个事务
mysql> begin;
mysql> update t1 set name=‘大虎‘ where age=17;
此时,我们不执行提交,在另一会话查看
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 25 |
| 4 | 李四 | 20 |
| 6 | 王五 | 17 |
| 9 | 大刀 | 27 |
| 15 | 赵虎 | 35 |
| 20 | 王强 | 32 |
+----+------+-----
数据并未发生变化,所以就防止了脏读现象
RC模式下的不可重复读现象
有一张表如下:
mysql> select * from t1;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 25 |
| 4 | 李四 | 20 |
| 6 | 王五 | 17 |
| 9 | 大刀 | 27 |
| 15 | 赵虎 | 35 |
| 20 | 王强 | 32 |
+----+------+-----
我们开始一个事务
mysql> begin;
mysql> update t1 set name=‘大虎‘ where age=17;
并且提交
mysql>commit;
此时,我们去查看数据,数据发生了变化
mysql> select * from t1;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 25 |
| 4 | 李四 | 20 |
| 6 | 大虎 | 17 |
| 9 | 大刀 | 27 |
| 15 | 赵虎 | 35 |
| 20 | 王强 | 32 |
+----+------+-----
这种情况看似很好,但是我们在执行命令
mysql> update t1 set name=‘大黄‘ where age=17;
并且提交
mysql>commit;
此时,我们去查看数据,数据发生了变化
mysql> select * from t1;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 25 |
| 4 | 李四 | 20 |
| 6 | 大黄 | 17 |
| 9 | 大刀 | 27 |
| 15 | 赵虎 | 35 |
| 20 | 王强 | 32 |
+----+------+-----
此时数据又发生了变化
这种情况下,我们不知道我们查询的结果是什么,这就是不可重复读的现象了
在这种模式下,一般的互联网公司是可以接受的,但是金融行业不能用这种模式
为什么金融行业不能用于这种模式?
银行12月31做年底盘点,要把数据卡在23:59:59,在RC模式下去统计的时候,这个时候不能因为要统计而把业务观点,但是由于是在RC模式下,统计的结果不停在变,有可能把这个时间点以后的数据统计进来了,所以金融行业不能用这种模式,因此,就要用RR模式
RC模式下的幻读现象
有一张表如下:
mysql> select * from t1;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 25 |
| 4 | 李四 | 20 |
| 6 | 王五 | 17 |
| 9 | 大刀 | 27 |
| 15 | 赵虎 | 35 |
| 20 | 王强 | 32 |
+----+------+-----
我们开始一个事务
mysql>begin;
mysql>update t1 set age=23 where age<25;
这个事务还没有提交,在另一个窗口又执行了一个事务
mysql>insert into t1 values(32,‘小强‘,‘17‘);
并且提交了
mysql>commit;
这个时候mysql>update t1 set age=23 where age<25;也提交了
我们再去查数据的时候可以看到,里面有一行数据age=17,这与我们预想的结果不一样
这种现象就是幻读现象了
在RC级别下,可以减轻GAP+NextLock锁的问题,但是会出现幻读现象,一般在为了读一致性会在正常select后添加for update语句.但是,请记住执行完一定要commit 否则容易出现锁等待比较严重.
RR模式下解决幻读现象和不可重复读现象
有一张表如下:
mysql> select * from t1;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 25 |
| 4 | 李四 | 20 |
| 6 | 王五 | 17 |
| 9 | 大刀 | 27 |
| 15 | 赵虎 | 35 |
| 20 | 王强 | 32 |
+----+------+-----
我们开始一个事务
mysql>begin;
mysql>update t1 set age=23 where age<25;
并且提交了
我们在另一窗口查看的时候,并不会出现新改的这一行,这样就解决了不可重复度现象
通俗点讲就是:我们打开一个窗口查询时,里面的表的数据会永远保持此时的状态,不管在别的窗口怎么改,在此窗口读到的还是我们打开窗口时的状态!
这种模式就是利用undo快照技术+GAP(间隙锁)+nextlock(下一键锁)(MVCC实际上就是在每一个会话开启时都会生成一个快照),将来在读取的时候,在别的会话不管怎么改,读取的都是起始时候的数据
解决幻读现象就是因为在这种模式下有间隙锁和下一键锁,
A事务在修改的时候,B事务插入数据根本就插入不了