1. 问题
前几天在其中一个QQ群里,群友在SSMS尝试打开表或存储过程对象列表浏览时,遇一个1222的错误,根本无法浏览系统对象。
Figure-1: SSMS报1222错
乍一看,我首先反应是可能是连接远程的SQL Server;如果本地的也出现这种错误,估计是系统对象被锁。后来经过测试,果然把这个错误重视出来。
2. 重现与分析问题
创建一个存储过程,存储过程里面使用了显式事务,但不提交事务,创建时没有报错。但执行时会报错。如果这里这个存储过程被删除了,就会出现这个报错。
Figure-2: 创建测试的存储过程
执行存储过程,报了一个错误。提示BEGIN和COMMIT数目不配置。
Figure-3: 执行存储
最后删除存储过程,没有报错。
Figure-4: 删除存储过程
这时,刷新下SSMS的Object Exploer指定的数据库,然后去打开表或存储过程的列表,就会报1222错误。查询相关的锁,发现测试的存储过程使用的表被和相关页面被锁。
USE AdventureWorks2008R2 GO SELECT lo.request_session_id AS [session_id] ,DB_NAME(lo.resource_database_id) AS [database_name] ,lo.resource_type ,lo.resource_subtype AS [subtype] ,lo.resource_description AS [description] ,lo.request_mode as [mode] ,lo.request_owner_type as [owner_type] ,lo.request_status as [status] ,CASE WHEN lo.resource_type = ‘OBJECT‘ THEN OBJECT_NAME(lo.resource_associated_entity_id) WHEN lo.resource_associated_entity_id IS NULL OR lo.resource_associated_entity_id = 0 THEN NULL ELSE OBJECT_NAME(p.[object_id]) END AS associated_entity ,wt.blocking_session_id ,wt.resource_description FROM sys.dm_tran_locks AS lo LEFT JOIN sys.partitions AS p ON lo.resource_associated_entity_id = p.partition_id LEFT JOIN sys.dm_os_waiting_tasks AS wt ON lo.lock_owner_address = wt.resource_address WHERE lo.request_session_id > 50 AND lo.resource_database_id = DB_ID() AND lo.request_session_id <> @@SPID ORDER BY session_id ASC,resource_type ASC; GO
Code-1: 查询锁
Figure-5: 查询结果
3. 解决与结论
找到执行存储过程的session id,然后Kill掉就行了。所以,使用显式事务时,一定要小心事务要提交或回滚,尤其是使用了多个BEGIN TRAN时。问题是解决了,还是忍不住上网再找下有没有人遇到过类型的问题。果然,人家很久之前就讨论过了。请参考:
http://www.sqlservercentral.com/Forums/Topic310216-5-1.aspx
https://support.microsoft.com/en-us/kb/308518
时间: 2024-10-29 19:11:22