插入数据到SQL Server是否locking整个表?

我正在使用entity framework ,并将logging插入到我们的数据库,其中包括blob字段。 blob字段最多可以有5 MB的数据。

在此表中插入logging时,是否locking整个表?

所以,如果你正在查询表中的任何数据,它会阻塞,直到插入完成(我知道有这方面的方法,但我说默认情况下)?

在它导致僵局之前需要多长时间? 这个时间取决于服务器的负载是多less,例如,如果没有太多的负载,会花费更长的时间导致死锁?

有什么方法可以监视并查看在特定时间被locking的内容吗?

如果每个线程都在单个表上进行查询,那么是否会出现阻塞的情况? 那么是不是只有当你有一个查询有一个连接并且在多个表上作用时才会发生死锁?

这是考虑到我的大部分代码只是一堆select语句,而不是长时间运行的事务或类似的东西。

圣牛,你在这里有很多问题,呵呵。 这里有几个答案:

在此表中插入logging时,是否locking整个表?

不是默认情况下,但如果你使用TABLOCK提示,或者如果你正在做某种批量加载操作,那么是的。

所以,如果你正在查询表中的任何数据将阻塞,直到插入完成(我知道有这方面的方法,但我说默认情况下)?

这一个变得有点棘手。 如果有人试图从表中locking的页面中select数据,那么是的,你会阻止他们。 您可以使用select语句上的NOLOCK提示或使用Read Committed Snapshot Isolation来解决此问题。 关于隔离级别的工作起点,请查看Kendra Little的隔离级别海报 。

在它导致僵局之前需要多长时间? 这个时间取决于服务器上的负载是多less,例如,如果没有太多的负载,会导致死锁需要更长的时间?

死锁不是基于时间的 – 它们是基于依赖关系的。 假设我们有这种情况:

  • 查询A持有一堆锁,并完成他的查询,他需要的东西被查询Blocking
  • 查询B也持有一堆锁,并完成他的查询,他需要的东西被查询Alocking

两个查询都不能前进(思考墨西哥的僵局),所以SQL Server将其称为绘图,在后面发射某人的查询,释放锁,并让其他查询继续进行。 SQL Serverselect受害者的基础是回滚哪一个将会更便宜。 如果你想看看,你可以在特定的查询上使用SET DEADLOCK_PRIORITY LOW来绘制背景上的目标,而SQL Server将会先射击它们。

有什么方法可以监视并查看在特定时间被locking的内容吗?

绝对有 – dynamicpipe理视图(DMV),你可以像sys.dm_tran_locks查询,但最简单的方法是使用亚当Machanic的免费sp_WhoIsActive存储过程 。 这是一个非常漂亮的sp_who替代品,你可以这样调用:

sp_WhoIsActive @get_locks = 1 

对于每个正在运行的查询,您将得到一个描述它所拥有的所有锁的小XML。 还有一个阻止列,所以你可以看到谁阻止了谁。 要解释被locking的锁,您需要检查lockingtypes的联机丛书描述 。

如果每个线程都在单个表上进行查询,那么会发生阻塞的情况吗? 那么是不是只有当你有一个查询有一个连接并且在多个表上作用时才会发生死锁?

信不信由你, 单个查询实际上可能会自己死锁 ,是的,查询只能在一个表上死锁。 要了解关于僵局的更多信息,请查看Jeremiah Peschka的“困难与僵局” 。

如果您可以直接控制SQL,则可以使用以下命令强制进行行级locking:

 INSERT INTO MyTable(Id, BigColumn) WITH (ROWLOCK) VALUES(...) 

这两个答案可能会有所帮助:

是否有可能在SQL Server中强制行级locking?

使用entity framework中的selectlocking表

要在Management Studio中查看当前持有的锁,请查看服务器下的,然后在pipe理/活动监视器下。 它有一个锁对象的部分,所以你应该能够看到插入是否真的造成问题。

死锁错误通常会很快返回。 死锁状态不会因等待locking时发生超时错误而发生。 SQL Server通过查找锁请求中的周期来检测到死锁。

我能想出的最好的答案是:这取决于。

检查的最佳方法是find连接SPID,并使用sp_lock SPID检查TABtypes上的locking模式是否为X. 您还可以使用SELECT OBJECT_NAME(objid)validation表名。 我也喜欢用下面的查询来检查locking。

  SELECT RESOURCE_TYPE,RESOURCE_SUBTYPE,DB_NAME(RESOURCE_DATABASE_ID) AS 'DATABASE',resource_database_id DBID, RESOURCE_DESCRIPTION,RESOURCE_ASSOCIATED_ENTITY_ID,REQUEST_MODE,REQUEST_SESSION_ID, CASE WHEN RESOURCE_TYPE = 'OBJECT' THEN OBJECT_NAME(RESOURCE_ASSOCIATED_ENTITY_ID,RESOURCE_DATABASE_ID) ELSE '' END OBJETO FROM SYS.DM_TRAN_LOCKS (NOLOCK) WHERE REQUEST_SESSION_ID = --SPID here 

在SQL Server 2008(及更高版本)中,可以禁用表上的locking升级,并在插入子句中强制执行WITH(ROWLOCK),以有效强制执行一个行锁。 这不能在SQL Server 2008之前完成(您可以使用ROWLOCK编写,但SQL Server可以select忽略它)。

我在这里会讲将军,而且我也没有太多的BLOB经验,因为我通常build议开发人员避免使用它们,尤其是在大于1 MB的情况下。