事务的并发操作可能出现的问题

中文 英文 描述
脏读 Dirty Reads 事务2读到了事务1未提交的事务,事务1随后回滚,但事务2读到了事务1的“中间数据”。 在Read Uncommitted隔离级别下会发生,其它级别不会。
(update&read)
丢失更新 Lost Updates 两个事务对同一个行分别进行更新,其中一个更新覆盖了另一个,导致丢失了一个更新。 在Read Committed的隔离级别下仍能发生,Repeatable Read能够避免它发生。
为什么官方文档里没有提到Lost Updates这个现象?
官方文档:Transaction Isolation Levels
(read&update)
不可重复读 Non-repeatable Reads 事务2在事务1的两次读取之间更新了数据导致事务1两次读到不一样的数据。 在Repeatable Read隔离级别下解决,和Lost Update一样,本质都是因为在此隔离级别下S锁持有到事务结束使其它事务无法在本事务执行过程中更新数据。
(read&update)
幻读 Phantom Reads 当一个事务执行一个query两次, 但得到不同行数的结果集。 幻读和不可重复读不一样地方在于,解决不可重复读问题时针对的是已有数据,因此可以持有它们的S锁,使其它事务请求X锁时等待;而幻读是新插入的数据。
(insert\delete)

事务

  • 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。

  • 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。

我一直纳闷这个“一致”是什么意思,然后在#引用.1.这本书里看到了解释:数据库在某一时刻的状态反应的是真实世界在这个时刻的数据,真实世界被抽象成数据,然后真实世界不停运行,数据库中的数据就像真实世界的一个切面,只不过真实世界是连续的,而数据库的数据是真实世界某一个时刻的状态,是离散的。随着真实世界的运行,当数据库中的数据从一个时刻到下一个时刻且数据都是“正确的”的时候,就称数据库从一个一致性状态到了另一个一致性状态,保证这种“一致性”的手段就是“数据库约束”,它对数据的正确性进行校验。不过,这种校验是片面的,数据的正确性也取决于业务逻辑(后台代码),但在数据库层面能做的就是“数据库约束”。

  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。

  • 持久性(Durability):即便发生断电等意外情况,已被提交的事务对数据库的修改应该永久保存在数据库中(硬盘上)。这点一般通过日志来保证。

事务的隔离级别

隔离级别影响锁模式的表现。

Read Uncommitted

  • 不要求SELECT时请求S锁,因此它不会阻塞X锁或者被X锁阻塞,因此可以发生脏读。

  • The intention of this isolation level is for systems primarily focused on reporting and business intelligence, not online transaction processing.

  • 别用。

Read Committed

  • 要求SELECT时请求S锁,因此它会阻塞X锁或者被X锁阻塞,因此可以避免脏读。

  • 它是SQL Server默认的隔离级别。

  • 由于S锁不会持有到事务结束,而是在SELECT完成后就释放了, 因此可能发生幻读和不可重复读。

    • 幻读:INSERT, DELETE

    • 不可重复读:UPDATE

Repeatable Read

  • 要求SELECT时请求S锁,并持续到事务结束,因此避免了事务过程中其它事务对数据的修改,因此可以避免幻读和不可重复读。

  • 可重复读:在当前的事务中可再次读取(R),读取的结果没有被修改(CUD)。

Serializable

  • 最高级别的隔离级别

  • 相比直接在所需的行上加锁,可串行化隔离级别在所需的行和下一行(索引顺序)上获得一个range lock。因此它可以避免插入新的数据,从而避免幻读现象。

  • 上图是SQLite中的页的结构,但DBMS设计思路是类似的。在一个页中,存储着多个Key,这些Key按顺序排列在一个数组中,所谓的“下一个”就是这个索引的下一个。

  • 如果key存在

    • 如果next key存在:

      • 在non-unique index的情况下,在当前请求的key和next key上范围锁。
      • 在unique index的情况下,理论上在key上获取S锁就足够,但SQL Server仍会获取范围锁
    • 如果next key不存在:taken on the ‘infinity’ value.
  • 如果key不存在

    • 如果next key存在:taken on the next key.
    • 如果next key不存在: taken on the ‘infinity’ value.
  • 在无限大上的范围锁会锁定 >= 当前key的范围

  • BETWEEN 在请求的key上和next key上获取范围锁

  • WHERE 在请求的key及前后获取范围锁

create table foo (c1 int)

go

insert into foo values (1)

insert into foo values (2)

insert into foo values (3)

insert into foo values (4)

insert into foo values (5)

create unique clustered index foo_ci on foo(c1)

set tran isolation level serializable

begin tran

select * from foo where c1 between 2 and 4 

SELECT dtl.request_session_id,
dtl.resource_database_id,
dtl.resource_associated_entity_id,
dtl.resource_type,
dtl.resource_description,
dtl.request_mode,
dtl.request_status
FROM sys.dm_tran_locks AS dtl
WHERE dtl.request_session_id = @@SPID;

引用

  1. 《SQL Server 2017 Query Performance Tuning 5th Edition》
  2. dotnettutorials: sql-server-concurrent-transactions
  3. stackoverflow: what are range locks
  4. techcommunity.microsoft: SQL Server Range Lock
  5. Microsoft: Transaction Isolation Levels

SQL Server事务及隔离级别的更多相关文章

  1. SQL Server事务的隔离级别

    SQL Server事务的隔离级别 ########## 数据库中数据的一致性 ########## 针对并发事务出现的数据不一致性,提出了4个级别的解决方法:  隔离级别  第一类丢失更新  脏读 ...

  2. SQL Server事务的隔离级别和锁

    背景        当用户并发尝试访问同一数据的时,SQL Server尝试用锁来隔离不一致的数据和使用隔离级别查询数据时控制一致性(数据该如何读取),说起锁就会联想到事务,事务是一个工作单元,包括查 ...

  3. SQL Server事务、隔离级别详解(二十九)

    前言 事务一直以来是我最薄弱的环节,也是我打算重新学习SQL Server的出发点,关于SQL Server中事务将分为几节来进行阐述,Always to review the basics. 事务简 ...

  4. SQL Server 事务与隔离级别实例讲解

    上班途中,你在一处ATM机前停了下来.正当你在敲入密码的时候,你的一位家人也正在镇上的另一处TAM机上输入密码.你打算从某个还有500元余额的账户上转出400元,而你的家人想从同一账户取走300元.倘 ...

  5. SQL SERVER 2008 数据库隔离级别代码演示

    SQL SERVER 2008 数据库隔离级别代码演示   个隔离级别(其实这是SQL 工业标) 种隔离级别,本身没有优劣之分,完全取决于应用的场景. 本质上,他们是在 隔离性(紊乱程度) 和 灵活性 ...

  6. SQL Server 事务隔离级别详解

    标签: SQL SEERVER/MSSQL SERVER/SQL/事务隔离级别选项/设置数据库事务级别 SQL 事务隔离级别 概述 隔离级别用于决定如果控制并发用户如何读写数据的操作,同时对性能也有一 ...

  7. SQL Server 事务隔离级别

    一.事务隔离级别控制着事务的如下表现: 读取数据时是否占用锁以及所请求的锁类型. 占用读取锁的时间. 引用其他事务修改的行的读操作是否: 在该行上的排他锁被释放之前阻塞其他事务. 检索在启动语句或事务 ...

  8. 【转】SQL Server 事务隔离级别详解

    SQL 事务隔离级别 概述 隔离级别用于决定如果控制并发用户如何读写数据的操作,同时对性能也有一定的影响作用. 步骤 事务隔离级别通过影响读操作来间接地影响写操作:可以在回话级别上设置事务隔离级别也可 ...

  9. SQL Server 之 事务与隔离级别实例讲解

    SQL Server 之 事务与隔离级别实例讲解 SQL Server 实现了6个隔离级别来防止并发情况下,类似企图并发的访问或修改同一数据时问题的发生.本文将带你体验全部6个隔离级别.正如你接下来将 ...

  10. SQL Server中的事务与其隔离级别之脏读, 未提交读,不可重复读和幻读

    原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫.所以花了点时间,把 SQL Server 数据库中 ...

随机推荐

  1. requests高级用法、代理池搭建

    requests高级用法 1.自动携带cookie的session对象 # session对象---->已经模拟登录上了一些网站--->单独把cookie 取出来 import reque ...

  2. Django: 获取头信息

    如何获取请求头信息 使用如下函数request.META.get("HTTP_请求头函数"),需要注意的是,请求头变量需要全部大写. 其他注意事项如下所示: 如果headerkey ...

  3. Windows 环境下载、安装、使用(.Net 5.0) Redis 数据库及常见问题的解决

    〇.前言 Redis (Remote Dictionary Server 远程字典服务)是一个使用 ANSI C 编写的开源.包含多种数据结构,支持网络.基于内存.可选持久性的键值对存储数据库,是现在 ...

  4. Log4j的Maven依赖及其配置文件

    Maven配置 <!--Log4j依赖文件--> <dependency> <groupId>log4j</groupId> <artifactI ...

  5. papricice

    2023-07-14 题目 题目传送门 题目大意 给定一个 \(n\) 个点的树,这 \(n\) 个点编号为 \(1\) 到 \(n\). 现在要选择断掉两条边,会形成三个连通块,假设这三个连通块内的 ...

  6. ETL之apache hop系列1-ETL概念与hop简介

    ETL 简单介绍 ETL概念 ETL,是英文Extract-Transform-Load的缩写,用来描述将数据从来源端经过抽取(extract).转换(transform).加载(load)至目的端的 ...

  7. 《Python魔法大冒险》 001 序章:少年小鱼的不平凡一天

    在一个普通的城市里,生活着一个名叫小鱼的少年.他是一名初中生,但在班级里,他的学习成绩总是垫底.同学们经常取笑他,有时甚至戏称他为"倒数王". 放学后,小鱼一个人走在回家的路上,他 ...

  8. [python] 第一个爬虫, 爬妹子写真集图片

    效果图 版本以及需要用到的第三方库 python 2.7 bs4 (安装命令: pip install bs4) - 代码 #!/usr/bin/env python #coding:UTF-8 #脚 ...

  9. 在微服务环境下,远程调用feign和异步线程存在请求数据丢失问题

    一.无异步线程得情况下feign远程调用: 0.登录拦截器: @Component public class LoginUserInterceptor implements HandlerInterc ...

  10. [MAUI]实现动态拖拽排序列表

    @ 目录 创建页面元素 创建可绑定对象 创建绑定服务类 拖拽(Drag) 拖拽悬停,经过(DragOver) 释放(Drop) 限流(Throttle)和防抖(Debounce) 项目地址 上一章我们 ...