数据库原理之------事务隔离级别

在介绍数据库提供的各种隔离级别之前,我们先看看如果不考虑事务的隔离性,会发生的几种问题:

更新丢失:两事务同时更新,一个失败回滚覆盖另一个事务的更新。
脏读:事务T1读取到事务T2修改了但是还未提交的数据,之后事务T2又回滚其更新操作,导致事务T1读到的是脏数据。
不可重复读:事务T1读取某个数据后,事务T2对其做了修改,当事务T1再次读该数据时得到与前一次不同的值。
虚读(幻读):事务T1读取在读取某范围数据时,事务T2又插入一条数据,当事务T1再次数据这个范围数据时发现不一样了,出现了一些“幻影行”。
不可重复读和脏读的区别:脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。
幻读和不可重复读的异同:都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。

事务隔离的级别

为此我们需要通过提供不同类型的“锁”机制针对数据库事务进行不同程度的并发访问控制,由此产生了不同的事务隔离级别:隔离级别(低->高)。SQL、SQL2标准定义了四种隔离级别:
读未提交(1000)、读已提交(1100)、可重复读(1110)、串行化(1111)。(其中1指能够解决的问题,按顺序如下:更新丢失、脏读、不可重复读、幻读)

●读未提交(Read Uncommitted)

含义解释:只限制同一数据写事务禁止其他写事务。解决”更新丢失”。(一事务写时禁止其他事务写)

名称解释:可读取未提交数据

所需的锁:排他写锁

●读提交(Read Committed)

含义解释:只限制同一数据写事务禁止其它读写事务。解决”脏读”,以及”更新丢失”。(一事务写时禁止其他事务读写)

名称解释:必须提交以后的数据才能被读取

所需的锁:排他写锁、瞬间共享读锁

●可重复读(Repeatable Read)

含义解释:限制同一数据写事务禁止其他读写事务,读事务禁止其它写事务(允许读)。解决”不可重复读”,以及”更新丢失”和”脏读”。(一事务写时禁止其他事务读写、一事务读时禁止其他事务写)

注意没有解决幻读,解决幻读的方法是增加范围锁(range lock)或者表锁。

名称解释:能够重复读取

所需的锁:排他写锁、共享读锁

●串行化(Serializable)

提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。(一事务写时禁止其他事务读写、一事务读时禁止其他事务读写)

限制所有读写事务都必须串行化实行。

下表是各隔离级别对各种异常的控制能力。
这里写图片描述
  以上四种隔离级别最高的是Serializable级别,最低的是Read uncommitted级别,当然级别越高,执行效率就越低。像Serializable这样的级别,就是以锁表的方式(类似于Java多线程中的锁)使得其他的线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况。

常见数据库的事务隔离默认级别

MySQL 可重复读(Repeatable Read)

Oracle 读提交(Read Committed)

SQLServer 读提交(Read Committed)

  在MySQL数据库中,支持上面四种隔离级别,默认的为Repeatable read (可重复读);此外,MySQL的Repeatable Read隔离级别也解决了幻读问题(通过Next-key lock加锁方法即范围锁解决不可重复读和幻读问题,如select * from t where a>10会对key为[10,infinite)范围的行加锁,这样其他事务就不能对此范围内key对应的行更改)达到了SQL、SQL2标准中的Serializable级别。

在Oracle数据库中,只支持Serializable (串行化)级别和Read committed (读已提交)这两种级别,其中默认的为Read committed级别。

记住:设置数据库的隔离级别一定要是在开启事务之前

  如果是使用JDBC对数据库的事务设置隔离级别的话,也应该是在调用Connection对象的setAutoCommit(false)方法之前。调用Connection对象的setTransactionIsolation(level)即可设置当前链接的隔离级别。

参考自:https://www.cnblogs.com/z-sm/p/7245981.html

猜你喜欢

转载自blog.csdn.net/qq_33583322/article/details/79725212
今日推荐