旁征博引-详解SQL四种标准的事务隔离级别

旁征博引-详解SQL四种标准的事务隔离级别

1 错误的读现象

要了解事务隔离级别之前,让我们来了解为什么需要对事务进行隔离,很简单,就是因为在多个事务并发,交错执行过程中容易出现数据错误,为了保障数据的一致和安全,我们就需要对事务进行隔离,那么事务并发的过程会出现哪些错误呢?
在ANSI/ISO 标准SQL92中提到了三种不同出错的读现象(Read Phenomena),接下来我们来一一介绍:

  • 脏读 Read out of invalid data 脏读又称无效数据读取,那么为什么会读取到无效的数据呢?
    我们知道,在一个含有UPDATE语句更新数据的事务中,UPDATE语句更新了数据,但是由于某种原因事务回滚了,而在这个过程中,即在UPDATA语句更新数据后、事务回滚之前,该数据被另外一个事务读取了,那么这个数据就是一个无效的数据,该无效数据的读出就称之为“脏读”。
    举个栗子,在银行存取的时候,假设某一账户的余额为1000,事务T1更新了账户余额1200,另一事务T2读取了该数据1200,结果另一边的事务T1因为某种原因回滚了操作,账户余额又为1000了,那么这1200就被脏读,这1200也可以称为脏数据
  • 不可重复读 Unrepeatable reads 也称之为”Read-write conflict,它是一种与事务交错执行相关的计算错误(is a computational anomaly associated with interleaved execution of transactions),是指对于一个事务范围内的两次相同的读出操作,却得到不相同的数据,为什么会造成这样的结果呢?
    假设给定一个schedule,它有两个事务T1和T2
    在这里插入图片描述
    在上面的例子我们可以看到,在事务T1两个读操作R的间隔中,另外一个事务T2执行了读操作并修改了数据,这样就导致了事务T1读到不同的数据。

注意区别脏读和不可重复读
脏读是一个事务读取到无效的数据,即在另一个事务数据更新后、未提交数据库前读取到的数据,那么在数据更新前和提交数据库后读取的数据就不是脏数据了
不可重复读读取的就是另一个数据更新前和提交数据库后的数据,那么这些数据就不是脏数据了,虽然读取的数据不是脏数据,但这些数据却是不一致,这和脏读一样都是致命的问题。

  • 幻读 Phantom reads 幻读是不可重复读的一种特殊情况,它是指,在一个事务过程中,另外一个事务向正在被读的记录中添加或删除一行。
    在这里插入图片描述在上面的例子中,事务T1两次读取操作的间隔中,新增加的数据,那么就可能导致两次读取的数据不一致。

简单区别一下不可重复读和幻读,幻读是不可重复读的一种特殊情况,它特殊之处在于,两次得到的记录数不同,可能多一行可能少一行。

2 隔离级别

那么如何避免上述的情况呢?接下来我们来介绍SQL标准的四种事物隔离级别:

  1. 读未提交 READ UNCOMMITTED
    该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。
    该级别不能防止脏读、不可重复读和幻读
  2. 读已提交 READ COMMITTED
    该隔离级别表示一个事务只能读取另一个事务已经提交的数据。
    该级别可以防止脏读。
    大多数情况下推荐值。
  3. 可重复读 REPEATABLE READ
    该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。
    该级别可以防止脏读、不可重复读。
  4. 串行操作 SERIALIZABLE
    所有的事务依次执行,这样事务之间就完全不可能干扰。
    该级别可以防止脏读、不可重复读和幻读。
    严重影响程序性能,通常情况下不会使用该级别。
  • Oracle默认的事务隔离级别是读已提交
  • MySQL默认的事务隔离级别是可重复读

值得注意的是,MySQL在5.5.8版本后默认的存储引擎是InnoDB,InnoDB存储引擎默认的隔离级别当然也是可重复读Repeatable Read,但InnoDB存储引擎采用了Next-Key Lock的锁算法,因此避免了幻读的产生。

3 查看和设置事务隔离级别

接下来我们已MySQL为例来查看和设置事务隔离级别

  1. 首先我们可以通过系统变量transaction_isolationglobal.transaction_isolation来查看当前会话或者全局的事务隔离级别,有两种方式来查看系统变量:
    方式一:SELECT @@transaction_isolation
    在这里插入图片描述
    方式二:SHOW VARIABLES LIKE 'transaction_isolation
    在这里插入图片描述
    2.设置事务隔离级别的语法
SET [ GLOBAL | SESSION ] TRANSACTION ISOLATION LEVEL
{
	READ UNCOMMITTED
	| READ COMMITTED
	| REPEATABLE READ
	| SERIALIZABLE
}

我们可以看到GLOBALSESSION是可选的

  1. 如果使用了GLOBAL关键字,那么就表示设置的事务隔离级别面向全局会话的,注意的是,设置的全局会话事务隔离级别在当前会话不会生效,只会在接下来新的会话后才生效
  2. 如果使用了SESSION关键字,表示设置本次会话的事务隔离级别
  3. 如果都没有使用,那么就表示设置一次操作的事物隔离级别,在下一事务操作中使用该事务隔离级别,并且随着该事务的提交而失效。

4 参考

百度百科-脏读
百度百科-脏数据
wikipedia Read-write confilct
wikipedia Isolation(database systems)
CSDN博客-SQL标准中的事务四种隔离级别
百度经验-MySQL如何查看和设置事务隔离级别

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值