0

このコードは機能しています:

CREATE SYNONYM S FOR [ServerIP].[MyDatabase].[dbo].[MyTable]
SELECT * FROM S
DROP SYNONYM S

そして、これは機能していません。

BEGIN TRAN              
    CREATE SYNONYM S FOR [ServerIP].[MyDatabase].[dbo].[MyTable]
    SELECT * FROM S
    DROP SYNONYM S
COMMIT TRAN

sysschobjs および sysobjvalues で resource_type = KEY を使用して、SELECT ステートメント (request_mode は X) を実行すると排他ロックが発生します。

なぜたむろするのか誰か説明できますか?

PS サンプルは、外部トランザクションが呼び出し側 SP で呼び出される、より複雑なコードを簡略化したものです。

4

1 に答える 1

0

問題は、シノニムがトランザクションの範囲外(および現在の接続も)にアクセスできることであると思います。SSMS の異なるタブで 2 つのコード セットを実行してみてください。

別のタブの 2 番目のクエリは、最初のクエリが完了するまで 10 秒間待機します。

-- first tab:
    BEGIN TRAN              
        CREATE SYNONYM S FOR [ServerIP].[MyDatabase].[dbo].[MyTable]
        waitfor delay '00:00:10'
        SELECT * FROM S
        DROP SYNONYM S
    COMMIT TRAN

-- second tab:
BEGIN TRAN              
    CREATE SYNONYM S FOR [ServerIP].[MyDatabase].[dbo].[MyTable]
    SELECT * FROM S
    DROP SYNONYM S
COMMIT TRAN

これらのクエリを実行すると、2 番目のクエリはCREATEステートメントで失敗しますが、select から行が返され、トランザクションがコミットされるのを待ちません。

-- first tab:
CREATE SYNONYM S FOR [ServerIP].[MyDatabase].[dbo].[MyTable]
waitfor delay '00:00:10'
SELECT * FROM S
DROP SYNONYM S

--second tab:
CREATE SYNONYM S FOR [ServerIP].[MyDatabase].[dbo].[MyTable]
SELECT * FROM S
DROP SYNONYM S

複数のセッションが同じシノニムを削除して作成しようとするのを防ぐために考えられる解決策:

  1. 同義語を使用しないでください:)
  2. 最初にシノニムが存在するかどうかを確認します (ただし、その特定の名前のシノニムが正しいテーブルを指しているという保証はありません)。 if not exists(select * from sys.synonyms where name = 's') create synonym s for [MyDatabase].[dbo].[MyTable]
  3. プロシージャのすべてのインスタンスで使用される永続的なシノニムを作成します
于 2013-10-30T17:59:06.960 に答える