什么是阻塞以及它是如何发生的?

jra*_*ara 20 sql-server locking

我试图在 SQL Server 中找到一些关于阻塞的信息,但我找不到关于它是什么以及它是如何发生的简明解释。你能帮我解惑吗?

Ric*_*ard 24

类比

有时,在远离计算机的地方使用类比会有所帮助。

假设你有一个球和两个孩子。任何时候只有一个孩子可以拿到球。但是,如果其中一个孩子拿到球并且因为分心(例如看电视)而没有放手,那么另一个孩子将无法玩球。

另一个孩子被阻止使用该资源。

例如,如果我们将其与电视进行比较,那么几个孩子可以同时看电视。

如果我们转向数据库世界,我们会看到使用资源有不同的方式(就像我们上面的两个例子)。我们可以执行“读取”,也可以执行“写入”。

当我们要读取数据时,没有理由别人也不能读取数据——就像两个人在看电视一样。但是,如果我们想写入数据,那么我们需要确保没有其他人在查看它。如果他们在我们写的时候读它,他们会得到“脏”读。(这意味着,他们会看到部分写出的数据,这将是无效的。)

为了确保这些脏读永远不会发生,我们有两种主要类型的锁,读锁和排他锁。

读锁

您可以在任何给定时间从同一个数据源读取多个不同的连接。但是为了确保在读取数据时没有人更改该数据,他们取出了读取锁。

一旦一个连接对一段数据有读锁,所有其他连接必须等到读锁被释放后才能写入数据。然而,其他人可以在同一条数据上取出他们自己的读锁。

排他锁

如果一个连接想要更新/插入/删除一条数据,他们必须取出一个排他锁。这可以防止任何其他连接也取消对数据的锁定(使该锁定独占该连接)。

当一个连接对数据有排他锁时,其他连接不能读取数据。这有助于通过确保在写入数据时没有人可以读取数据来防止脏读。

阻塞

“阻塞”只是一个术语,表示一个连接在另一个连接想要读取或写入资源时持有对资源的锁定。这并不一定意味着所有者连接不会释放它,只是它当前持有它。

将此与儿童拿着球的情况进行比较。拿着球的孩子阻止了所有其他孩子拿着球。

僵局

我知道你没有问这个,但这只是解决死锁的又一步(它与阻塞非常直接相关)。

当你有两个连接,每个连接都有一个锁,但他们想要彼此的资源时,就会发生死锁。在这种情况下,这就像两个孩子每个人都有一个球,但想要对方的球。

像孩子一样,这些联系根本不愿意分享。每个连接都需要访问这两个资源才能继续。但是,它们处于永久阻塞状态。在这种状态下,父级 (DBMS) 必须进入并选择一个失败者,以便其中一个子级(连接)可以访问这两种资源。

一旦“获胜”连接完成,它就会释放资源,然后另一个(“失败”)连接可以再次尝试访问这两个资源。

因此,死锁的概念是您有两个相互阻塞的资源。


在这里,您可以阅读有关 SQL Server 必须提供的所有不同类型的锁以及可能导致阻塞/死锁的不同资源的更多信息。这篇文章很旧,但它仍然适用于 SQL Server 2000 到 2008 R2。(在 SQL Server 的更高版本中添加了更多类型的锁,但这将为您提供一个起点。)

  • 对于 SQL Server,这是自动完成的(前提是数据库 [可以检测死锁](http://msdn.microsoft.com/en-us/library/ms178104.aspx))。例如,如果它实际上是一个 [实时锁](http://blog.sqlauthority.com/2008/03/21/sql-server-introduction-to-live-lock-what-is -活锁/)。 (2认同)

Aar*_*and 5

理查德的精彩解释,但只是想添加官方文档的链接。这些主题是为 SQL Server 2000 编写的,但许多概念今天仍然相同:

理解和避免阻塞

了解 SQL Server 中的锁定

编辑 - 一些补充:

所有 3 位都是非常著名的 SQL Server 作者和/或 MVP。