我已经通过整个Microsoft站点来了解SQL Server 2008 R2中的隔离级别。但在采用之前,我想听取SO专家的建议。
我有一个基于PHP的网页,主要用作仪表板。用户(不超过5个)每天将上传批量数据(大约40,000行),大约70个用户只能访问数据库。请注意,我已经为这5个用户上传了固定的时间表,但我想错误地证明任何数据丢失的证据。请帮我解决以下问题:
70个用户将拥有下载选项,如果所有或大多数用户同时尝试下载,是否有可能损坏数据库?我该如何避免相同的?
专家的任何建议......
此致 Yuvraj S
答案 0 :(得分:6)
隔离级别实际上是关于保留读取数据的共享锁的时间长度。但正如列文已经提到的那样:那些不关于防止数据库中的“腐败” - 这些都是为了防止读者和作者互相攻击。
首先:任何写入操作(INSERT
,UPDATE
)将始终要求对该行执行独占锁定,并且排他锁定为与其他任何东西都不兼容 - 所以如果要更新的给定行已被锁定,任何UPDATE
操作都必须等待 - 没办法解决这个问题。
对于读取数据,SQL Server取出共享锁 - 隔离级别是关于持有多长时间。
默认隔离级别(READ COMMITTED
)表示:SQL Server将尝试在一行上获取共享锁,如果成功,则读取该行的内容并释放该锁马上再来。因此锁只存在于正在读取的行的短暂时间段内。共享锁与其他共享锁兼容,因此任意数量的读取器都可以同时读取相同的行。但是,共享锁会阻止独占锁,因此共享锁会在同一行上阻止UPDATE
。
然后还有READ UNCOMMITTED
隔离级别 - 基本上没有锁定;这意味着,它还可以读取当前正在更新和独占锁定的行 - 因此您可能会获得未提交的数据 - 最终可能不会真正在数据库中结束的数据(如果事务更新它被回滚) - 小心这个!
下一级别是REPEATABLE READ
,在这种情况下,获取的共享锁一直保持到当前事务终止。这会锁定更多的行并且持续更长的时间 - 读取是可重复的,因为您读取的那些行被锁定在“背后”的更新中。
最终级别为SERIALIZABLE
,其中行的整个范围(由WHERE
中的SELECT
子句定义)将被锁定,直到当前事务终止。
<强>更新强>
不仅仅是下载部分(对我来说是辅助部分)我担心有5个用户同时尝试更新一个数据库。
好吧,不用担心 - SQL Server将肯定处理这个没有任何问题!
如果这5个(甚至50个)并发用户正在更新不同的行 - 他们甚至不会注意到其他人在附近。更新将会发生,在此过程中不会有任何数据受到伤害 - 一切都很好。
如果其中一些用户尝试更新同一行,则会对其进行序列化。第一个将能够获得该行的独占锁定,进行更新,释放锁定然后继续。现在第二个用户将有机会获得它 - 获得独占锁定,更新数据,释放锁定,继续。
当然:如果你没有采取任何措施,第二个用户的数据将只覆盖第一次更新。这就是需要进行并发检查的原因。您应该检查数据是否在您读取数据和写入数据之间发生了变化;如果它被改变,则意味着其他人已经同时更新了它 - &gt;你需要为这种情况考虑并发冲突解决策略(但这本身就是另一个问题......)