Open棟梁Project - マイクロソフト系技術情報 Wiki
SQL Serverは参照処理にもロック(共有ロック)を
かけるということを知っておくことが重要です。
ロックの種類は
によって変わってきます。(ただし、DDLによるロックもある)
各ロックの互換性についても考慮が必要です。
また、指定された分離レベルを実現するため、
トランザクション中のロックがホールドされるか?
・・・などで、ロックの動きが変わってきます。
こちら(SQL Server 問題の分析方法)も参考にして下さい。
SQLトレースを取って問題を起こしているSQLを確認できます。
以下の様な問題に起因していることが多いです。
よくあるパターンに、
があります。
また、統計情報が更新されていないと、
インデックス・シークが適用されず、
により、広範囲にロックがかかることがあります。
なお、統計情報の更新タイミングについては、
を参照して下さい。
以下のSQLで、
ロックをホールドしておきます。
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE BEGIN TRANSACTION SELECT * FROM Shippers WHERE ShipperID = 1 --COMMIT
ロック状況の監視には、
で紹介されているSQLを使用できそうです。
(sys.dm_tran_locks 動的管理ビューを使用する)
SELECT resource_type as オブジェクトの種類, resource_associated_entity_id as エンティティID, request_mode as ロックの種類, request_type as 要求の種類, request_status as 状態 From sys.dm_tran_locks WHERE [resource_type]<>'Northwind';
※ Northwindの所にはDB名を入力する。
SQL Server 2005 以降では、代わりに sys.dm_tran_locks 動的管理ビューを使用
上記の「エンティティID」をCASEを使って自己解決するバージョンです。
SELECT resource_type as オブジェクトの種類, (CASE WHEN resource_type = N'ALLOCATION_UNIT' THEN (SELECT OBJECT_NAME(sp.object_id) + N':' + si.name FROM sys.allocation_units LEFT JOIN sys.partitions sp ON container_id = hobt_id LEFT JOIN sys.indexes si ON sp.object_id = si.object_id AND sp.index_id = si.index_id WHERE allocation_unit_id = resource_associated_entity_id) WHEN resource_type = N'OBJECT' THEN OBJECT_NAME(CONVERT(bigint, resource_associated_entity_id)) WHEN resource_type IN(N'HOBT', N'KEY', N'PAGE') THEN (SELECT OBJECT_NAME(sp.object_id) + N':' + si.name FROM sys.partitions sp LEFT JOIN sys.indexes si ON sp.object_id = si.object_id AND sp.index_id = si.index_id WHERE hobt_id = resource_associated_entity_id) ELSE CONVERT(nvarchar(40), resource_associated_entity_id) END) as エンティティID, request_mode as ロックの種類, request_type as 要求の種類, request_status as 状態 From sys.dm_tran_locks WHERE [resource_type]<>'Northwind';
非クラスター化インデックス再構築時の同時実行性について « SE の雑記
http://engineermemo.wordpress.com/2011/06/18/%E9%9D%9E%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E3%83%BC%E5%8C%96%E3%82%A4%E3%83%B3%E3%83%87%E3%83%83%E3%82%AF%E3%82%B9%E5%86%8D%E6%A7%8B%E7%AF%89%E6%99%82%E3%81%AE%E5%90%8C%E6%99%82%E5%AE%9F%E8%A1%8C/
以下の2つのトランザクションで、ブロッキングされます。
ポイントは、参照処理が、インデックスをキー範囲ロックしている点です。
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; BEGIN TRANSACTION; INSERT INTO [Northwind].[dbo].[Orders] ([OrderID], ・・・) VALUES (11078, ・・・); 若しくは DELETE FROM [Northwind].[dbo].[Orders] WHERE [OrderID] = 11078; --COMMIT TRANSACTION --ROLLBACK TRANSACTION
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; BEGIN TRANSACTION; SELECT * FROM [Northwind].[dbo].[Orders] WHERE [OrderID] BETWEEN 11070 AND 11080 --COMMIT TRANSACTION --ROLLBACK TRANSACTION
こちらが後発なので、共有ロックをホールドしなくてもブロックされる。
このため、
というケースもありました(本番環境では再現せずでした)。