我SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
在大多数通用 SQL 查询中都使用它,主要是因为我在最初学习该语言时就已经深入了解了这一点。
据我了解,这种隔离级别的行为方式与WITH (NO LOCK)
我只倾向于使用的方式相同SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
。
- 有没有时候我应该使用
WITH (NO LOCK)
overSET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
. - 是否会
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
阻止其他用户被锁定在我正在阅读的表格之外? - if
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
用于停止锁,但我只是读取数据,使用它有什么意义?只有系统密集型查询会生成锁吗?在运行将在 5-10 秒内返回的查询时是否值得使用它? - 我被告知
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
在读取将用于更新的数据时不要使用,大概是为了避免更新脏数据。这会是唯一的原因吗? - 对于我正在处理的数据库类型,有一个生产和测试环境。我们很少会查询生产环境,但是当我需要时,我通常会
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
在我的查询中使用。我知道这可能会导致脏读。除了接收可能最终不会提交到数据库的数据(因此将我的结果丢弃)之外,还有哪些其他类型的“脏读”可能?
对不起,大量的问题。
太可怕了,你是这样学的(对不起!)。
READ UNCOMMITTED
让你读每一行,是的。甚至那些目前用于INSERT
,UPDATE
,DELETE
操作的人。如果您需要快速查看某些数据或任务关键SELECT
语句中的块将非常有害,这将非常有用。事实上,你冒着诚信的风险。您可能会读取一行,该行当前已被删除或正在更改中。您也可能会读取错误的值。这可能真的不常见,但它可能会发生。我的意思是什么?好吧,想想一个非常宽的行(它有很多列和很多长
nvarchar
列)。此行发生更新并设置新值。在极少数情况下,您可能会只阅读半行。例如,如果用户更改了他的登录值,则可能会发生另一件事。他更改了他的邮件+密码。邮件已设置,但密码未设置。这样你就有了一个不一致的状态。我建议忘记
READ UNCOMMITTED
. 只需在真正需要的地方使用它。您的另一种选择是启用
READ_COMMITTED_SNAPSHOT
数据库选项 - 因此您可以使用READ COMMITTED SNAPSHOT
tempdb 中启用的行版本控制。这样,您只需阅读行的另一个(旧)版本。这不会阻止您的查询。但是您也可能会读取旧值,但读取的是一致的旧值。另一个想法可以
WITH(READPAST)
代替WITH(NOLOCK)
. 您将读取表的旧状态(有点像 中的SNAPSHOT ISOLATION
),但您将跳过所有当前锁定的行。正如公认的答案所述,忘记使用 READ UNCOMMITTED 隔离级别(除非真的需要),因为您可能会读取错误的数据。但是要回答您问题中的第三个要点,我认为有两种情况很有用:
在编写和测试 SQL Server SSIS 包时,包的步骤可能会包装在事务中。如果您通过在 SSIS 调试器中逐步运行包来测试包,您可能希望在表上有锁时检查表。使用 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 允许您在调试包时使用 SQL Server Manager Studio 检查表。
在 SQL Server Manager Studio 中,您可能希望通过将 T-SQL 代码包装在事务中来测试 T-SQL 代码,以便您可以选择回滚更改。例如,在测试数据库上,您可能希望将数据恢复到初始状态作为测试的一部分。如果您正在测试事务包装的代码,并且想要在事务进行时检查锁定的表,您可以使用 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 来检查另一个窗口中的值。
我接受这些是 READ UNCOMMITTED 的相当晦涩的用途,但我发现它们在测试环境中很有用。
在大多数数据库中,绝大多数活动,甚至插入、删除和更新,都在显式事务之外。
当然,
READ UNCOMMITTED
(脏读)在这些情况下可以提供不正确的信息,但该信息在 5 秒前是正确的。脏读产生真正糟糕结果的时候是事务失败并且必须回滚时,或者对通常使用显式事务一起更新的两个表运行查询时。
同时,在具有 100(或更多)比 1 的读写比率的典型大型繁忙数据库上,每个不使用脏读的单个(读取)查询都会减慢系统速度,因为它需要获取和检查对于锁,它使事务更有可能失败(通常是由于死锁),这可能导致更严重的数据库完整性问题。
相反,使用脏读使系统更快、更可靠(部分原因是性能的提高使得不一致性不太可能发生)。
当然,有时它们不应该被使用。我不喜欢将数据库设置为默认使用
READ UNCOMMITTED
隔离级别,甚至SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
在 SQL 脚本和 SP 的开头使用显式语句 - 在不应该发生脏读的情况下发生脏读的可能性太大。相反,(NOLOCK)
提示是一种更好的方法,因为它们明确表明程序员考虑过他们在做什么,并决定对于这个特定查询中的这个特定表,脏读是安全的。如果您正在编写应用程序以将资金从一个银行账户转移到另一个银行账户,那么您不应该使用 Dirty Reads。但大多数应用程序不需要那种程度的偏执狂。