-2

我们正在使用 MS SQL 2008 R2 运行数据库系统,客户端软件使用 Entity Framework 4 访问它。我们还有合并复制,服务器在虚拟环境中运行。

我们在其中一台服务器上遇到性能问题。当我们进行调查时,我们发现我们有很多共享读锁会阻止更新,这似乎是我们问题的根源。为了暂时解决这个问题,我们尝试实施Read_Commited_snapshot

ALTER DATABASE MyDB
SET ALLOW_SNAPSHOT_ISOLATION ON;

ALTER DATABASE MyDB
SET READ_COMMITTED_SNAPSHOT ON;

并用 验证了这一点 select is_read_committed_snapshot_on,snapshot_isolation_state_desc,* from sys.databases where name = 'MyDB'。在此之后,所有核心上的 cpu 负载达到 100% 大约 1 小时,然后开始在 20-40% 左右空闲。但是我们仍然存在性能问题。在进行性能监控时,我仍然可以看到一些大型实体框架查询首先创建了几个对象锁,然后开始创建页面锁(共享)。这怎么可能,我在这里错过了什么?

哦..顺便说一下,我已经尝试过重启服务器,根据托管公司的说法,虚拟托管环境看起来不错。

4

1 回答 1

1

很容易证明锁定没有被消除READ_COMMITTED_SNAPSHOT(甚至NOLOCK); 只有阻塞可以被消除(并且不一定在所有情况下,例如更改表会明显导致阻塞,并且提示可能TABLOCKX会阻塞某些类型的其他操作) .

在一个窗口中执行此操作:

CREATE DATABASE floob;
GO

ALTER DATABASE floob SET ALLOW_SNAPSHOT_ISOLATION ON;
GO

ALTER DATABASE floob SET READ_COMMITTED_SNAPSHOT ON;
GO

USE floob;
GO

CREATE TABLE dbo.splunge([object_id] INT, x CHAR(4000));

INSERT dbo.splunge([object_id], x) 
  SELECT [object_id], name 
  FROM sys.all_columns;

现在在一堆其他窗口中,执行此操作(也可以随意洒一些NOLOCK提示):

BEGIN TRANSACTION;
SELECT * FROM dbo.splunge;

请注意,它们都不会阻止任何其他人(即使有些执行更新甚至表修改,只要这些已提交)。但是在您启动了其中的几个之后,您可以在另一个窗口中检查sys.dm_tran_locks并验证共享锁确实是在数据库级别获取的,并且您不应该混淆锁定和阻塞:

SELECT resource_type, request_mode, request_type, request_owner_type
  FROM sys.dm_tran_locks 
  WHERE resource_database_id = DB_ID(N'floob')
    AND request_session_id <> @@SPID;

结果应该是一堆这些,每个查询窗口一个:

resource_type  request_mode  request_type  request_owner_type
-------------  ------------  ------------  ----------------------------
DATABASE       S             LOCK          SHARED_TRANSACTION_WORKSPACE

快照隔离可以解决您的一些性能问题,但不是全部。也许您应该查看 EF 正在生成的查询并尝试调整这些查询,而不是试图通过某种方式说服 SQL Server 它永远不必锁定任何东西来提高性能......

于 2013-09-26T17:50:28.517 回答