问题描述
当应用程序频繁读写某个表或者资源时,容易出现死锁现象。出现死锁时,SQL Server会选择终止其中一个事务,并且向发起该事务的客户端发送类似如下的错误信息:
Error Message:Msg 1205, Level 13, State 47, Line 1Transaction (Process ID 53) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.解决方案
- 使用客户端连接实例。具体操作,请参见连接SQL Server实例。 
- 监控相关视图。 - 执行如下SQL语句,循环监控 - SYS.SYSPROCESSES。- WHILE 1 = 1 BEGIN SELECT * FROM SYS.SYSPROCESSES WHERE BLOCKED <> 0; WAITFOR DELAY '[$Time]'; END;说明- 您可以自定义 - [$Time]循环间隔时间,此处以- 00:00:01为例。- 系统显示类似如下:  说明 说明- 监控结果中 - blocked列的值为阻塞该会话的阻塞源会话ID,- waitresource为被阻塞的会话等待的资源。从上述结果可以看到,spid 53和spid 56相互阻塞,形成了死锁。
- 执行如下SQL语句,循环监控 - sys.dm_tran_locks和- sys.dm_os_waiting_tasks等视图。- while 1=1 Begin SELECT db.name DBName, tl.request_session_id, wt.blocking_session_id, OBJECT_NAME(p.OBJECT_ID) BlockedObjectName, tl.resource_type, h1.TEXT AS RequestingText, h2.TEXT AS BlockingText, tl.request_mode FROM sys.dm_tran_locks AS tl INNER JOIN sys.databases db ON db.database_id = tl.resource_database_id INNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address = wt.resource_address INNER JOIN sys.partitions AS p ON p.hobt_id = tl.resource_associated_entity_id INNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_id INNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_id CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1 CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2 waitfor delay '[$Time]' End- 系统显示类似如下:  - 返回参数说明如下: - 参数 - 说明 - DBName- request_session_id操作的数据库。 - request_session_id- 当前请求的会话ID,即被阻塞的会话。 - blocking_session_id- 阻塞源会话ID。 - BlockedObjectName- 被阻塞的会话操作的对象。 - resource_type- 等待的资源类型。 - RequestingText- 当前会话执行的语句,即被阻塞的语句。 - BlockingText- 阻塞源会话执行的语句。 - request_mode- 当前会话请求的锁模式。 
- 如果您的实例版本是RDS SQL Server 2012,还可以使用SQL Server Profiler来监控和抓取死锁图谱,如下所示:  - 抓取的死锁图谱如下所示:  
 
调优建议
可以参考以下步骤,进行调优。
- 关闭阻塞源会话,可以帮助快速解除阻塞。 
- 查看是否有长时间未提交的事务,及时提交事务。 
- 如果有S锁导致的死锁,并且您的应用允许脏读,可以使用 - WITH (NOLOCK)查询提示。例如在查询中写入- SELECT * FROM table WITH (NOLOCK);使查询在执行时避免申请锁,从而避免死锁。
- 检查应用程序逻辑,按顺序访问某个资源。 
相关操作
您可以在RDS控制台查看RDS SQL Server数据库中的死锁及其详细信息。更多详情,请参见死锁。