[翻译]:SQL死锁-锁与事务级别

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介: 原文:[翻译]:SQL死锁-锁与事务级别其实这一篇呢与解决我项目中遇到的问题也是必不可少的。上一篇讲到了各种锁之间的兼容性,里面有一项就是共享锁会引起死锁,如何避免呢,将我们的查询都设置中read uncommitted是否可行呢?其结果显示,当我们当所有的查询都设置成read uncommitted后,后面共享锁死锁基本消除了,看来还是管用的。
原文: [翻译]:SQL死锁-锁与事务级别

其实这一篇呢与解决我项目中遇到的问题也是必不可少的。上一篇讲到了各种锁之间的兼容性,里面有一项就是共享锁会引起死锁,如何避免呢,将我们的查询都设置中read uncommitted是否可行呢?其结果显示,当我们当所有的查询都设置成read uncommitted后,后面共享锁死锁基本消除了,看来还是管用的。好了下面接着翻译:

Last time we discussed a few major lock types that SQL Server uses. Shared(S), Exclusive(X) and Update(U). Today I’d like to talk about transaction isolation levels and how they affect locking behavior. But first, let’s start with the question: “What is transaction?”

上一次我们讨论了一些主要的SQL SERVER锁类型:共享锁(S),排它锁(X),以及更新锁(U)。今天我们来讲事务级别是如何影响锁的行为的。但在这之前,我们需要从一个问题开始:“什么是事务”?

Transaction is complete unit of work. Assuming you transfer money from checking account to saving, system should deduct money from the checking and add it to the saving accounts at once. Even if those are 2 independent operations, you don’t want it to “stop at the middle”, well at least in the case if bank deducts it from the checking first :) If you don’t want to take that risk, you want them to work as one single action.

事务是一个完整的单元工作模式。假如你从支票帐户中将钱转移到储蓄卡中,银行系统首先会从你的支票帐户中扣钱,然后再往你的储蓄卡中存钱。即使这是两个相互独立的操作,你也不想让其在中间的某一步停止,至少不能停止在银行将你的钱从支票帐户中扣除之后:) 。如果你不冒这个风险,那么你希望这两步操作最好是一步操作来完成。

There is useful acronym – ACID – that describes requirements to transaction:

这里有一个非常有用的编写-ACID,它将描述事务的需求:

  • (A) – Atomicity or “all or nothing”. Either all changes are saved or nothing changed.

        (A)-它代表所有或者是无,要么全部保存要么不保存任何数据

  • (C) – Consistency. Data remains in consistent stage all the time

        (C)-数据每时每刻要保持一致性

  • (I) – Isolation. Other sessions don’t see the changes until transaction is completed. Well, this is not always true and depend on the implementation. We will talk about it in a few minutes

        (I)-数据隔离,其它的会话看不到事务未提交的数据。这句并不总是正确的,有时依赖于系统的实现,我们后续会讲到。

  • (D) – Durability. Transaction should survive and recover from the system failures

        (D)-数据可以回滚,当事务执行出现异常的情况下

There are a few common myths about transactions in SQL Server. Such as:

下面是一些公共的关于事务的错误观点,例如:

  • There are no transactions if you call insert/update/delete statements without begin tran/commit statements. Not true. In such case SQL Server starts implicit transaction for every statement. It’s not only violate consistency rules in a lot of cases, it’s also extremely expensive. Try to run 1,000,000 insert statements within explicit transaction and without it and notice the difference in execution time and log file size.

       当我们直接写insert/update/delete这句语句时,如果没有显示的写begin tran/commit 这类语句就不存在事务。这是不正确的,实际上SQL SERVER 会隐式的为每次SQL操作都加了事务。这不光违反了数据一致性规则且往往造成的后果是非常昂贵的。可以去尝试往一个表中插入1000000条数据,第一种显示的加上事务语句,第二种不加事务语句,执行之后对比下执行的时间以及日志大小的不同。

  • There is no transactions for select statements. Not true. SQL Server uses (lighter) transactions with select statements.

        当执行select语句时没有事务。这是不正确的,SQL SERVER会使用轻量级的事务。

  • There is no transactions when you have (NOLOCK) hint. Not true. (NOLOCK) hint downgrades the reader to read uncommitted isolation level but transactions are still in play.

        当们们在select语句后面加了nolock后,就没有事务了。这也是不正确的。nolock只是降低了事务必有隔离级别为read uncommitted而已并不是没有事务。

Each transaction starts in specific transaction isolation level. There are 4 “pessimistic” isolation levels: Read uncommitted, read committed, repeatable read and serializable and 2 “optimisitic” isolation levels: Snapshot and read committed snapshot. With pessimistic isolation levels writers always block writers and typically block readers (with exception of read uncommitted isolation level). With optimistic isolation level writers don’t block readers and in snapshot isolation level does not block writers (there will be the conflict if 2 sessions are updating the same row). We will talk about optimistic isolation levels later.

每个事务都在指定的事务级别中,这里有四种悲观事务必有隔离级别:Read uncommitted (允许脏读),read committed(不允许脏读),repeatable(可重复读),serialzable以及两种经过优化后的事务级别:Snapshot 以及read committed snapshot。

     注:这里事务隔离级别比较多,我理解不也太多,就省略掉了。我们比较常见的就是前面的两种,允许脏读以及不允许脏读的情况。至于后面的有关镜像相关的内容这里我不做多的翻译。

Regardless of isolation level, exclusive lock (data modification) always held till end of transaction. The difference in behavior is how SQL Server handles shared locks. See the table below:

排它锁不管事务级别,它总是占用锁到整个事务结束:


So, as you can see, in read uncommitted mode, shared locks are not acquired – as result, readers (select) statement can read data modified by other uncommitted transactions even when those rows held (X) locks. As result any side effects possible. Obviously it affects (S) lock behavior only. Writers still block each other.

所以,就像你看到的,如果在允许脏读的模式下,是不需要申请共享锁的,可以读取到其实事务还未完全提交的数据,即使这些数据已经被加上了排它锁。但这只影响共享锁,对于写的会话仍然会存在相互阻塞甚至死锁的情况。

In any other isolation level (S) locks are acquired and session is blocked when it tries to read uncommitted row with (X) lock. In read committed mode (S) locks are acquired and released immediately. In Repeatable read mode, (S) locks are acquired and held till end of transaction. So it prevents other session to modify data once read. Serializable isolation level works similarly to repeatable read with exception that locks are acquired on the range of the rows. It prevents other session to insert other data in-between once data is read.

共享锁可以任意事务隔离级别中发生,当它尝试去读取其它事务未提交的数据(行上加了排它锁)时就是会阻塞。在Read committed 模式下,共享锁的申请以及释放都是非常迅速的。在Repeatable read模式下,共享锁被申请后一直占用到事务结束,它保证其它会话不编辑其已经读取到的数据。Serializable 模式的工作方式和Repeatable非常相似,但它会锁定一定范围的数据,访问其它会话插入数据。

注:这块还没理解到位,后续有时间再补充下。

You can control that locking behavior with “set transaction isolation level” statement – if you want to do it in transaction/statement scope or on the table level with table hints. So it’s possible to have the statement like that:

在你的事务中或者是表级间的查询你可以通过设置事务隔离级别来控制锁行为,就像下面的查询语句:

So you access Table1 in read uncommitted isolation level and Table2 in serializable isolation level.

这条语句的作用就是你可以对Table1读取其它事务未提交的数据,以serializable隔离级别读取Table2的数据。

It’s extremely easy to understand the difference between transaction isolation levels behavior and side effects when you keep locking in mind. Just remember (S) locks behavior and you’re all set.

这将非常容易理解事务隔离级别行为之间的差别以及它们的副作用,你只需要记住共享锁以及你所有的设置。

Next time we will talk why do we have blocking in the system and what should we do to reduce it.

下一次我们将会讲到为什么我们的系统中会存在阻塞以及我们如何做才能减少阻塞的发生

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
27天前
|
SQL 存储 数据库
sql事务、视图和索引
sql事务、视图和索引
14 0
|
1月前
|
存储 关系型数据库 MySQL
最全MySQL面试60题(含答案):存储引擎+数据库锁+索引+SQL优化等
最全MySQL面试60题(含答案):存储引擎+数据库锁+索引+SQL优化等
157 0
|
3月前
|
SQL 关系型数据库 MySQL
Mysql系列-3.Mysql的SQL优化和锁(中)
Mysql系列-3.Mysql的SQL优化和锁
40 0
|
2月前
|
SQL Java API
Flink超时问题之Flink sql cdc锁超时如何解决
Apache Flink是由Apache软件基金会开发的开源流处理框架,其核心是用Java和Scala编写的分布式流数据流引擎。本合集提供有关Apache Flink相关技术、使用技巧和最佳实践的资源。
|
2月前
|
SQL Oracle 关系型数据库
[SQL]事务
[SQL]事务
40 0
|
7月前
|
SQL 关系型数据库 MySQL
数据库基本概念(SQL,索引,视图,事务,日志等)(二)
数据库基本概念(SQL,索引,视图,事务,日志等)(二)
194 0
|
3月前
|
SQL 关系型数据库 MySQL
Mysql系列-3.Mysql的SQL优化和锁(下)
Mysql系列-3.Mysql的SQL优化和锁
43 0
|
3月前
|
SQL 存储 关系型数据库
Mysql系列-3.Mysql的SQL优化和锁(上)
Mysql系列-3.Mysql的SQL优化和锁
37 0
|
9月前
|
SQL 存储 数据库
|
4月前
|
SQL 缓存 关系型数据库
Mysql数据库 16.SQL语言 数据库事务
Mysql数据库 16.SQL语言 数据库事务
57 0