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

postgresqlでの明らかなトランザクション分離違反

    はい、いいえ-いつものように、それは異なります。 ドキュメント 厳密に言うと:

    つまり、単にSELECTはSELECT FOR UPDATE / DELETE/UPDATEとは異なります。

    簡単なテストケースを作成して、その動作を観察できます。

    セッション1

    test=> START TRANSACTION;
    START TRANSACTION
    test=> SELECT * FROM test;
     x
    ----
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
    (10 rows)
    
    
    test=> DELETE FROM test;
    DELETE 10
    test=>
    

    別のセッション2にログインします:

    test=> START TRANSACTION;
    START TRANSACTION
    test=> SELECT * FROM test;
     x
    ----
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
    (10 rows)
    
    
    test=> SELECT * FROM test WHERE x = 5 FOR UPDATE;
    

    最後のコマンドの後SELECT ... FOR UPDATE セッション1は「ハング」し、何かを待っています......

    セッション1に戻る

    test=> insert into test select * from generate_series(1,10);
    INSERT 0 10
    test=> commit;
    COMMIT
    

    セッション2に戻ると、次のように表示されます。

    test=> SELECT * FROM test WHERE x = 5 FOR UPDATE;
     x
    ---
    (0 rows)
    
    
    test=> select * from test;
     x
    ----
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
    (10 rows)
    

    つまり、単純なSELECT SELECT ... FOR UPDATEの間、まだ変更は表示されません。 行が削除されたことを確認します。ただし、セッション1によって挿入された新しい行は表示されません

    実際、表示されているシーケンスは次のとおりです。

    • プロセスAがトランザクションを開始します
    • プロセスAはテーブルTからすべてを削除します
    • プロセスBがトランザクションを開始します
    • プロセスBは、テーブルTの1つの行で更新の選択を試みます
    • プロセスBは「ハング」し、セッションAがコミットまたはロールバックを実行するまで待機します
    • プロセスAは、受信データからテーブルTを再作成します
    • プロセスAはトランザクションをコミットします
    • プロセスBが空になり(0行-セッションAのコミット後)、ロールバックを呼び出します



    1. MySQL乗算サブクエリ結果

    2. PHPpdomysqlのデフォルトの文字セットは何ですか

    3. PHPを使用してmysqlから値を読み取るにはどうすればよいですか?

    4. mysqlを自動的に起動するにはどうすればよいですか? (linux-cliのみ)