数据库的隔离级别以及脏读,不可重复读和幻读
数据库的隔离性:
- 多个事务并发执行时,事务之间不能相互干扰。(其本质就是线程安全的问题).
隔离性和并发性其实是相悖的,隔离是为了保证数据的准确,并发是为了保证事务的执行效率。如果多个事务之间隔离性越强,并发程度就越低,效率就越低;多个事务之间隔离性越弱,并发程度就越高,效率就越高。但是在不同的场景下,对于数据的准确性要求不一样,就可以在满足数据准确要求的前提下尽可能的提高并发程度。
并发执行事务时可能产生的恶果(脏读,不可重复读,幻读)
-
脏读
-
事务中的修改,即使没有提交,对其他事务也都是可见的。其他事务可以读取没有提交的数据并使用,这就是脏读。
例如:在线文档编辑,一个人正在编写文档,其他人仍可以查看这个文档,然后获取到第一个人编写的信息,在此之后第一个人修改了他写入的信息并提交,那么读取的人就读到了脏数据,这也就是脏读。 -
解决办法就是给写操作加锁,第一个人修改的时候第二人尝试读取数据就会阻塞,直到第一个人提交完数据,第二个人才可以读取。
引入写加锁,事务的并发程度降低,效率变低,隔离性提高 -
不可重复读
-
是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。
因为一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的,所以两次查询会得到不同的结果。
例如:还是文档编辑但不是在线的,A两次去读这个文档,在这之间,B重新写了这个文档,就会导致A两次读取文档获取到的信息不相同。 -
解决办法就是给读加锁,在A读取这个文档的时候,B不能重新编辑。 引入读加锁,事务的并发程度更低,效率也更低,隔离性又提高一个阶层。
-
幻读
当某个事务在读取某个范围内的记录时,另外一个事务又在范围内插入了新的记录,当之前的事务再次读取该范围的数据,发现新增了记录,就跟产生了幻觉一样。
例如:事务1查询id<10的记录时,返回了4条记录,接着事务2插入了一条id为3的记录,并提交。接着事务1查询id<10的记录时,返回了5条记录,新增了一条。 -
解决办法就是严格的串行化执行,强制事务串行执行,避免了前面说的幻读的问题。
数据库的隔离级别:
1.Read uncommitted
(未提交读)
- 允许事务读取未提交的数据,隔离程度低,并发程度高,但会有脏读问题
2.Read committed
(提交读)
- 不可读取未提交的写数据,允许写并发。隔离程度提高,并发性降低,解决了脏读但是会出现不可重复读的问题。
3.Repeatable read
(可重复读)
- MYSQL的默认事务隔离级别。该级别解决了不可重复读的问题,但是无法解决幻读的问题。隔离性提高,并发程度又降低。
4.Serializable
(串行化)
- 这是最高的隔离级别。强制事务串行执行,避免了幻读的问题。它会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的问题,实际中很少使用。
隔离级别 | 脏读可能性 | 不可重复读可能性 | 幻读可能性 |
---|---|---|---|
Read uncommitted | ✔ | ✔ | ✔ |
Read committed | ✖ | ✔ | ✔ |
Repeatable read | ✖ | ✖ | ✔ |
Serializable | ✖ | ✖ | ✖ |
本文地址:https://blog.csdn.net/zyrzl/article/details/107656914