1.三个问题
1.1 脏读问题
脏读的意思不是指数据有多脏,而是指数据有问题。
下面举例子说明。
假如 张三 正在写作业,这个时候 李四 过来了,他看到 张三 正在写代码 hello world 。
李四 看完后就走了,他走之后,张三就把 hello world 给删除了。
这里的李四 就相当于是 事务A,而张三就相当于是 事务B,这两个事务正在读写的是同一份数据。
在这个场景中,张三和李四这两个事务是完全并发的。
也就是说,如果是在没有任何限制的前提下,就会出现 脏读问题(数据有问题)。
总之就是说如果张三更改数据,李四是不会知道的,这也就回出现问题。
1.2 不可重复读
在一个事务中,连续两次读到的结果不一致,就是
不可重复读问题
下面举例说明。
现在已经约定好了,张三在写代码的时候,李四不可以看。要等到提交以后才可以看。
在 张三提交完代码后,李四这开始看代码,
当李四正在看的时候,张三想起代码有不对的地方,于是动手修改了并重新提交了一个版本。
此时就会导致李四在看代码的过程中,代码突然就改变了。
1.3 幻读问题
如果在同一个事务中,两次读到的结果集不同,这就是
幻读问题
。
比方说,虽然李四在读的时候张三不能修改,但是张三可以做别的事情,例如添加或删除一个文件。
此时,虽然李四读的代码没有改变,但是他发现文件的数量变了。
2.四个隔离级别
-
read uncommitted
这个级别不做任何限制,事务之间都是随意并发执行的。
并发程度最高,隔离性最低,会产生
脏读
、
不可重复读
、
幻读问题
。 -
read committed
此时这个级别对锁操作加锁了,并发程度降低,隔离性提高了。
解决脏读问题,但是还存在
不可重复读
和
幻读问题
。 -
repeatable read
此时对写和读操作都加锁了,并发程度进一步降低,隔离性进一步提高。
解决了脏读和不可重复读,但是可能会存在
幻读问题
。 -
serializable
此时会严格串行化,并发程度最低,隔离性最高。
解决了三个会出现的问题。
第三个级别是默认的级别,在以后的使用过程中要根据需求的场景来确定使用哪个隔离级别。
3.解决方案
3.1 脏读问题的解决:
可以采取
降低并发性,提高隔离性
的方法。
可以简单理解为 给 “写操作” 加锁。
意思就是说。张三在写代码的时候,不让李四看,等把代码提交了之后,李四才可以看。
举例来说明。
有人去上 WC 的时候,进去的时候把门锁上了,这个时候别人就进不来了。
当进行写加锁的时候,张三写的时候,李四就不能看了。
此时就相当于是降低了并发程度,提高了隔离性。
虽然降低了一定的效率,但是提高了准确性。
3.2 不可重复读问题的解决:
可以采用给
读操作加锁的方式
比如说,当李四在读代码的时候,我不可以修改。
此时这两个事务之间的并发程度进一步降低了,隔离性进一步提高了。
虽然运行速度又进一步变慢了,但是数据的准确度又进一步提高了。
3.3 幻读问题的解决:
想要解决幻读问题,可以采用串行化的方式,也就是
彻底的舍弃并发
。
也就是说,只要李四还在读代码,张三就什么都不能做,只能摸鱼。