トランザクションの基本

例えばお金の振込みという操作は、預金を減らす操作と増やす操作の組み合わせとなる。
この場合、片方だけが実行されるということが許されない。
何らかの理由で処理が完結されない場合は、最初の状態に戻る必要がある。
このような処理は、トランザクションとしてまとめる必要がある。

準備

  1. 次のSQLをファイルとして作成。(account141.sql)

    
    
  2. ログイン画面から実行。

    oddtbs=> \i account141.sql
    ...
    oddtbs=> select * from account;
      number  | name | deposit
    ----------+------+---------
     56400011 | 田中 | 1000000
     56400012 | 鈴木 | 1000000
    (2 rows)
    

振込み操作

  1. 次のSQLをファイルとして作成。(transfer141.sql)

    
    
  2. ログイン画面から実行。

    oddtbs=> \i transfer141.sql
    UPDATE 1
    
    ※ 5秒間待つ。
    ...
    
    UPDATE 1
    
  3. 確認。

    oddtbs=> select * from account;
      number  | name | deposit
    ----------+------+---------
     56400011 | 田中 |  900000
     56400012 | 鈴木 | 1100000
    (2 rows)
    
    ※ 処理が完結しているので問題ない。
    

問題点

  1. 最初の状態に戻す。

    oddtbs=> \i account141.sql
    ...
    oddtbs=> select * from account;
      number  | name | deposit
    ----------+------+---------
     56400011 | 田中 | 1000000
     56400012 | 鈴木 | 1000000
    (2 rows)
    
  2. 振り込み操作。

    oddtbs=> \i transfer141.sql
    UPDATE 1
    
    ※ 中断している間に画面を強制終了。
    
  3. 再度画面を起動し、ログインして確認。

    oddtbs=> select * from account;
      number  | name | deposit
    ----------+------+---------
     56400012 | 鈴木 | 1000000
     56400011 | 田中 |  900000
    (2 rows)
    
    ※ 処理が途中までしか実行されていない。これはあってはならない。
    

トランザクションの使用

上記のような場合は、一連の処理をトランザクションとしてまとめる必要がある。

START TRANSACTION または BEGIN;
...
...
COMMIT または END;
  1. 最初の状態に戻す。

    oddtbs=> \i account141.sql
    ...
    oddtbs=> select * from account;
      number  | name | deposit
    ----------+------+---------
     56400011 | 田中 | 1000000
     56400012 | 鈴木 | 1000000
    (2 rows)
    
  2. 次のSQLをファイルとして作成。(transfer142.sql)

    
    
  3. ログイン画面から実行。

    oddtbs=> \i transfer142.sql
    START TRANSACTION
    UPDATE 1
    
    ※ 5秒間待つ。
    ...
    
    UPDATE 1
    COMMIT
    
  4. 確認。

    oddtbs=> select * from account;
      number  | name | deposit
    ----------+------+---------
     56400011 | 田中 |  900000
     56400012 | 鈴木 | 1100000
    (2 rows)
    
    ※ 処理が完結しているので問題ない。
    

問題発生によるロールバック

  1. 最初の状態に戻す。

    oddtbs=> \i account141.sql
    ...
    oddtbs=> select * from account;
      number  | name | deposit
    ----------+------+---------
     56400011 | 田中 | 1000000
     56400012 | 鈴木 | 1000000
    (2 rows)
    
  2. 振り込み操作。

    oddtbs=> \i transfer142.sql
    START TRANSACTION
    UPDATE 1
    
    ※ 中断している間に画面を強制終了。
    
  3. 再度画面を起動し、ログインして確認。

    oddtbs=> select * from account;
      number  | name | deposit
    ----------+------+---------
     56400011 | 田中 | 1000000
     56400012 | 鈴木 | 1000000
    (2 rows)
    
    ※ 最初の状態に戻っている。
    

このように、途中まで進んだトランザクション中の処理が取り消されて元に戻ることをロールバックという。

明示的なロールバック

上記は異常があったためロールバックしたが、明示的にロールバックすることもできる。

START TRANSACTION または BEGIN;
...
...
ROLLBACK または ABORT;
  1. 次のSQLをファイルとして作成。(transfer143.sql)

    
    
  2. ログイン画面から実行。

    oddtbs=> \i transfer143.sql
    START TRANSACTION
    UPDATE 1
    
    ※ 5秒間待つ。
    ...
    
    UPDATE 1
    ROLLBACK
    
  3. 確認。

    oddtbs=> select * from account;
      number  | name | deposit
    ----------+------+---------
     56400011 | 田中 | 1000000
     56400012 | 鈴木 | 1000000
    (2 rows)
    
    ※ ロールバックしている。