sql >> データベース >  >> RDS >> Sqlserver

SQLServerでの暗黙的なトランザクションのしくみ

    SQLServerには4つのトランザクションモードがあります。これらの1つは暗黙的なモードです。

    SQL Serverでは、暗黙的なトランザクションとは、前のトランザクションが完了したときに新しいトランザクションが暗黙的に開始されることですが、各トランザクションはCOMMITで明示的に完了します。 またはROLLBACK ステートメント。

    これは、トランザクションが暗黙的に開始および終了される自動コミットモードと混同しないでください。

    4つのトランザクションモード

    SQL Serverは、次のトランザクションモードで動作できます。

    トランザクションモード 説明
    トランザクションの自動コミット 個々のステートメントはトランザクションです。
    暗黙のトランザクション 新しいトランザクションは、前のトランザクションが完了すると暗黙的に開始されますが、各トランザクションは、通常はCOMMITを使用して明示的に完了します。 またはROLLBACK DBMSに応じたステートメント。
    明示的なトランザクション START TRANSACTIONなどの行で明示的に開始 、BEGIN TRANSACTION または同様のもので、DBMSに応じて、関連するステートメントで明示的にコミットまたはロールバックされます。
    バッチスコープのトランザクション 複数のアクティブな結果セット(MARS)にのみ適用されます。 MARSセッションで開始される明示的または暗黙的なトランザクションは、バッチスコープのトランザクションになります。

    暗黙モードと自動コミット

    SQL Serverでは、特定のステートメントが実行されると、トランザクションが自動的に開始されます。見えないBEGIN TRANSACTIONが前に付いているかのようです ステートメント。

    ほとんどの場合、これらのトランザクションも、目に見えないCOMMIT TRANSACTIONがあったかのように、暗黙的にコミットされます。 声明。このようなトランザクションは、自動コミットモードであると言われます 。

    その他の場合、目に見えないCOMMIT TRANSACTIONはありません 目に見えないBEGIN TRANSACTIONと一致させる 声明。トランザクションは、明示的にコミットするか、COMMIT TRANSACTIONでロールバックするまで、進行中のままです。 またはROLLBACK TRANSACTION 声明。この場合、トランザクションは暗黙モードであると言われます 。

    トランザクションが暗黙モードで実行されるか自動コミットモードで実行されるかは、IMPLICIT_TRANSACTIONSによって異なります。 設定。

    暗黙のトランザクションを開始するステートメント

    次のステートメントは、SQLServerで暗黙的なトランザクションを開始します。

    • ALTER TABLE
    • BEGIN TRANSACTION
    • CREATE
    • DELETE
    • DROP
    • FETCH
    • GRANT
    • INSERT
    • OPEN
    • REVOKE
    • SELECTSELECT GETDATE()など、テーブルから選択しないものを除く またはSELECT 1*1
    • TRUNCATE TABLE
    • UPDATE

    これらのT-SQLステートメントを実行するときはいつでも、トランザクションを開始します。ほとんどの場合、トランザクションは自動的にコミットされます。したがって、明示的に行う必要なしにトランザクションを開始および終了しました。

    ただし、IMPLICIT_TRANSACTIONSによっては 設定すると、トランザクションを明示的にコミットする必要がある場合があります。

    IMPLICIT_TRANSACTIONSの場合 OFFです

    IMPLICIT_TRANSACTIONSの場合 設定はOFF 、上記のステートメントは、自動コミットモードでトランザクションを実行します。つまり、を開始します トランザクションを暗黙的に終了します。

    つまり、BEGIN TRANSACTIONが見えないようなものです。 ステートメントと非表示のCOMMIT TRANSACTION ステートメント、すべて1つのステートメントから。

    この場合、トランザクションをコミットまたはロールバックするために何もする必要はありません。すでに完了しています。

    IMPLICIT_TRANSACTIONSの場合 ONです

    IMPLICIT_TRANSACTIONSの場合 設定はON 、上記のステートメントの動作は少し異なります。

    IMPLICIT_TRANSACTIONSの場合 設定はON 、上記のステートメントは非表示のBEGIN TRANSACTIONを取得します ステートメントですが、対応するCOMMIT TRANSACTIONを取得しません ステートメント。

    これは、トランザクションを自分で明示的にコミットまたはロールバックする必要があることを意味します。

    ただし、トランザクションモードが暗黙的である場合、非表示のBEGIN TRANSACTIONはありません。 トランザクションがすでに進行中の場合に発行されます。

    コンセプトを示す例を次に示します。

    SELECT @@TRANCOUNT AS TransactionCount;
    SET IMPLICIT_TRANSACTIONS OFF;
    SELECT TOP 1 ProductName, ProductPrice FROM Products;
    SELECT @@TRANCOUNT AS TransactionCount;

    結果:

    +--------------------+
    | TransactionCount   |
    |--------------------|
    | 0                  |
    +--------------------+
    (1 row affected)
    Commands completed successfully.
    +-------------------------+----------------+
    | ProductName             | ProductPrice   |
    |-------------------------+----------------|
    | Left handed screwdriver | 25.99          |
    +-------------------------+----------------+
    (1 row affected)
    +--------------------+
    | TransactionCount   |
    |--------------------|
    | 0                  |
    +--------------------+
    (1 row affected)

    この場合、IMPLICIT_TRANSACTIONSを設定します OFFSELECTを実行します 声明。これは、SELECT ステートメントは自動コミットモードで実行されたため、トランザクションは暗黙的に開始および終了しました。

    @@TRANCOUNT 返された0 、つまり、その時点で実行されているトランザクションはありませんでした。

    今回もIMPLICIT_TRANSACTIONSを設定したことを除いて、ここにあります。 ONへ 。

    SELECT @@TRANCOUNT AS TransactionCount;
    SET IMPLICIT_TRANSACTIONS ON;
    SELECT TOP 1 ProductName, ProductPrice FROM Products;
    SELECT @@TRANCOUNT AS TransactionCount;

    結果:

    +--------------------+
    | TransactionCount   |
    |--------------------|
    | 0                  |
    +--------------------+
    (1 row affected)
    Commands completed successfully.
    +-------------------------+----------------+
    | ProductName             | ProductPrice   |
    |-------------------------+----------------|
    | Left handed screwdriver | 25.99          |
    +-------------------------+----------------+
    (1 row affected)
    +--------------------+
    | TransactionCount   |
    |--------------------|
    | 1                  |
    +--------------------+
    (1 row affected)

    最後の@@TRANCOUNT 1の値を返しています 。これは、トランザクションがまだ進行中であることを意味します。

    @@TRANCOUNT BEGIN TRANSACTIONの数を返します 現在の接続で発生したステートメント。明示的に発行したわけではありませんが、暗黙的に発行されました。

    したがって、@@TRANCOUNTをデクリメントするには、実際にこのトランザクションをコミットする(またはロールバックする)必要があります。 0まで 。

    COMMIT TRANSACTION;
    SELECT @@TRANCOUNT AS TransactionCount;

    結果:

    +--------------------+
    | TransactionCount   |
    |--------------------|
    | 0                  |
    +--------------------+
    (1 row affected)

    したがって、暗黙的なトランザクションのコードには、COMMITが含まれている必要があります。 ステートメント:

    SELECT @@TRANCOUNT AS TransactionCount;
    SET IMPLICIT_TRANSACTIONS ON;
    SELECT TOP 1 ProductName, ProductPrice FROM Products;
    COMMIT TRANSACTION;
    SELECT @@TRANCOUNT AS TransactionCount;

    結果:

    +--------------------+
    | TransactionCount   |
    |--------------------|
    | 0                  |
    +--------------------+
    (1 row affected)
    Commands completed successfully.
    +-------------------------+----------------+
    | ProductName             | ProductPrice   |
    |-------------------------+----------------|
    | Left handed screwdriver | 25.99          |
    +-------------------------+----------------+
    (1 row affected)
    Commands completed successfully.
    +--------------------+
    | TransactionCount   |
    |--------------------|
    | 0                  |
    +--------------------+
    (1 row affected)

    ANSI_DEFAULTS

    暗黙のトランザクションが予期せず有効になっている場合は、ANSI_DEFAULTSが原因である可能性があります。 設定。


    1. 異種データ型の3つのフィールドの複数列インデックス

    2. PostgreSQLインストールのバイナリ形式でpg_repack拡張機能をコンパイルする

    3. PHP/MySQLビルドツリーメニュー

    4. HAS_DBACCESS()–ユーザーがSQLServerのデータベースにアクセスできるかどうかを検出します