【问题标题】:How Read Committed Isolation Level prevents dirty readsRead Committed Isolation Level 如何防止脏读
【发布时间】:2012-03-31 23:00:17
【问题描述】:

我从一个简单的问题开始:

根据脏读定义 WikipediaMsdn

我们有 2 个并发事务,T1 和 T2

脏读发生在,当 T1 正在更新一行并且 T2 正在读取 T1“尚未提交”的行时

但是在Read Committed Level,共享锁在数据被读取后立即释放(不是在事务结束甚至语句结束时)

那么 Read Committed 如何防止脏读? Bkaz 一旦更新行 T2 上释放的共享锁可以读取更新的行并且 t1 可以回滚整个操作,那么我们手头上有一个脏读 t1

【问题讨论】:

    标签: sql-server dirtyread read-committed


    【解决方案1】:

    当 SQL Server 在已提交读隔离级别执行语句时,它会逐行获取短期共享锁。这些共享锁的持续时间刚好够读取和处理每一行;服务器通常在进行下一行之前释放每个锁。因此,如果您在已提交读操作下运行一个简单的选择语句并检查锁(例如,使用 sys.dm_tran_locks),您通常一次最多会看到一个行锁。这些锁的唯一目的是确保语句只读取和返回已提交的数据。锁之所以起作用,是因为更新总是获取一个排他锁,它会阻止任何试图获取共享锁的读者

    盗自here

    【讨论】:

    • 克里斯即使短暂的共享锁持续时间很长,它也无法确保 T1 无法回滚事务,该锁将被释放,并且 T2 可以读取稍后将回滚的更新行
    • @raoofhojat - 错误。短暂的共享锁用于读取。更新总是获得一个排他锁,直到事务提交才释放。
    • -但是我们没有更新读提交级别的锁以确保 T1 正在编辑的行在之后不会被 T2 读取(看看我的 senario),那么读提交如何保证没有脏读
    • @raoofhojat - 已提交的读取请求共享锁,更新使用独占锁,该锁会阻止任何尝试获取共享锁的读者。
    【解决方案2】:

    它可以防止脏读,因为 T1 对该行有一个锁定,因此 T2 无法读取以后可能回滚的“尚未提交”的行。

    Read Committed 试图解决的问题是:

    T1 创建一个事务并写一些东西

    T2 读到了一些东西

    T1 回滚事务

    现在 T2 有一个从未真正存在过的数据。

    根据数据库的结构,有两种“好”的可能性:

    T1 创建一个事务并写一些东西

    T2 等待 T1 结束交易

    T2 在 T1 开始事务之前读取数据库的“快照”(称为使用行版本控制读取已提交)

    (MSSQL 上默认是第一个选项)

    例如,这里有各种隔离级别的比较:http://msdn.microsoft.com/en-us/library/ms345124(SQL.90).aspx(请参阅 SQL Server 2005 中提供的隔离级别)

    【讨论】:

    • 你说“T1 在行上有一个锁,所以 T2 不能读取可以稍后回滚的'尚未提交'的行”但是如果 T1 在行结束之前有这个锁事务,为什么我们要对整个事务进行可重复读取隔离,我可以说清楚吗?
    • @raoofhojat 可重复是另一个级别的隔离。这意味着 T2 读取,T1 写入和提交,T2 重新读取,如果可重复,他应该能够重新读取第一次的相同值。这可以通过两种方式获得:T1 在第一次读取期间获取锁,因此 T2 不能在中间写入并且必须等待 T1 事务结束,或者您使用完整快照(如果您查看,这不仅仅是行版本控制)在餐桌上)
    • 我知道可重复是另一种隔离级别,你说'T2 无法读取以后可能回滚的“尚未提交”行',如果它是什么提交的读取然后提交读取可以锁定读取直到事务结束,然后它可以处理重复读取
    • @raoofhojat 已提交读取不会为读取锁定。如果解锁而不锁定,它将读取。所以读完后T1就可以锁定了。可重复读取将锁定 + 读取并保持锁定。
    猜你喜欢
    • 1970-01-01
    • 2022-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    • 1970-01-01
    • 2015-04-26
    相关资源
    最近更新 更多