===========================================
原文链接: 通俗理解数据库隔离机制 转载请注明出处!
===========================================
在理解数据库隔离机制的时候发现网上很多文章都是千篇一律,解释语言太过于标准书面化,描述的晦涩难懂,因果关系模糊。在这里将自己对隔离机制的理解描述一下,力争做到能够通过浅显的语言描述出来。
数据库隔离机制是对于多线程同时操作数据库而言的。对于单线程操作数据库不存在所谓的隔离,也不需要进行隔离。这里需要注意一点【操作数据库】这里要注意区分这个操作是读取或者修改已存在的数据,还是插入删除新的数据。
数据库隔离机制四种:
1、未提交读(Read Uncommitted)
自定义名称:修改级别隔离(只要修改了数据,则其他事务就可以看到)
可以理解为:A事务只要修改了数据,无论有没有提交,其他事务都能够读取到A事务修改后的结果。
潜在问题【对于同一记录进行修改操作】:A事务修改之后未提交,B事务读取到修改之后的数据,然后在这个基础上进行操作修改并提交。然后A提交失败,数据回滚,则数据就出现异常。这就是所谓的脏读。
解决方案:A事务提交之后B事务才能读取到A修改之后的数据,不让读取修改但未提交的数据
2、提交读(Read Committed)
自定义名称:提交级别隔离(只有成功提交事务,则其他事务才能够看到)
可以理解为:A事务成功commit之后,其他事务才能够读取到A提交事务之后的最新数据,否则只能读取到A提交之前的原始数据。这样就解决了脏读问题。
潜在问题【对于同一记录进行修改操作】:A事务开启第一次读取数据,然后B事务开启对数据进行了修改并提交成功, 此时A事务还没有结束,又进行了一次读操作,然后便发现A事务中的两次读取的数据不一致。这就是所谓的不可重复读。同一个事务中两次读取的数据不一样。【这里有一个问题我也没搞明白,为什么在同一个事务中我要对同一条记录读取两次或者多次呢?我读一次存储在缓存中不就可以了?什么情况下会发生需要读两次的的情况?应用场景有哪些?有理解的朋友还望告知!】
解决方案:在一个事务对该行数据进行操作的时候,其他事务不允许进行修改。可以理解为添加一个行级别的锁
3、可重复读(Repeatable Read)
自定义名称:事务级别隔离(A事务中的数据不会受B事务中的修改操作影响,即使B事务提交之后,A事务再次查询的数据也不会发生变化)
可以理解为:在自己的事务中复制了一套相关的数据,该数据是私有的不受其他事务的影响。因此可以解决不可重复读的问题。这里虽然解决了不可重读的问题,但是却没有解决数据覆盖的问题,也就是B操作的数据是最原始的数据(和A未修改之前的数据一样),而并不是最新(A修改之后的数据)的数据。对于此隔离机制无法解决这个问题,需要使用行级锁来进行处理。
潜在问题【对于同表进行插入或删除操作】:A事务插入/删除了一条记录,但是B事务中却查询不到插入的新记录/依旧能查到删除的记录。这就是所谓的幻读。幻读是对于记录条数而言的,不是针对于某一条记录的数据而言的。这里需要注意!
解决方案:在有事务对该表进行操作的时候,不允许其他事务操作该表。添加表级锁。
4、串行读(Serializable)
自定义名称:表级别隔离(不允许同时有多个事务操作该表)
可以理解为:所有的事务串行操作该数据表。这样就可以解决幻读操作。
潜在问题:数据安全了 但是操作效率降低了。
解决方案:…………
四种隔离机制就是这样子,潜在的问题分别为:脏读,不可重复读,幻读和效率低下。脏读、幻读和效率低下的问题都能够很好的理解,可是不可重复读为什么也是个需要避免的问题呢?为什么在同一个事务中需要两个读取同一条数据呢?这个不太明白……
理解的时候不要看所谓的“读未提交”、“提交读”、“可重复读”和“串行读”,这只是描述了一种读取方式,并不算是一种隔离机制(个人理解)。
------end