- PR -

[PostgreSQL]トランザクション

1
投稿者投稿内容
liwings
会議室デビュー日: 2006/02/07
投稿数: 4
投稿日時: 2006-10-25 11:49
いつも参考にさせていただいております。

[悩み]
トランザクションの処理が思ったように動きません。

[環境]
OS:RedHatES4_0
DB:PostgreSQL8_1_4
言語:JAVA1.5

[やりたいこと]
例えば10件のレコードを登録する際に重複登録の際にはスキップして登録を実行するがそれ以外のSQLExceptionが発生した場合は、ロールバックする。

[現象]
例えば、10件のinsertを実行した場合、5件目で重複登録となりExceptionが発生する。
スキップして6件目の登録を実行するが、「すでにトランザクションは異常となっている」というようなメッセージが出て登録することが出来ない。

org.postgresql.util.PSQLException: ERROR: current transaction is aborted, commands ignored until end of transaction block
  at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1525)
  at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1309)
  at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:188)
  at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:452)
  at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:354)
  at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:308)

[ソース]
Connection conn = 〜;
conn.setAutoCommit(false);
Statement st = conn.createStatement();
try {
 st.execute("BEGIN TRANSACTION");
 st.execute("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
 for(int i=0;i<10;i++){
  try{
    st.executeUpdate("INSERT INTO 〜");
  }catch(SQLException e){
    if(重複登録 == true){
      continue;
    }else{
      throw e;
      break;
    }
  }
 }

 if(正常処理確認) {
  conn.commit();
 } else {
  con.rollback();
 }
} catch(SQLException e) {
 conn.rollback();
}


と、こんな感じ。

「conn.setAutoCommit」が鍵であるような気がする。

■パターン1
conn.setAutoCommit(false);
SQLExceptionが発生したらそれ以降の実行文は全て無効になってしまう。

■パターン2
conn.setAutoCommit(true);
トランザクション無視のロールバック不可能。

結局、
SQLExceptionの種類によってトランザクション中の処理をcommitしたりrollbackしたりすることは出来ないのでしょうか?

誰か、教えてください。



[ メッセージ編集済み 編集者: liwings 編集日時 2006-10-25 11:51 ]
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2006-10-25 13:01
例外処理で、二重登録をスキップするのはあまりスマートなやり方ではないと思います。

登録前に存在チェックを行って、あればスキップ。無ければ登録とした方がよい気がします。

ただしこの場合において、複数のセッションから同時多発的に更新を行う場合は、テーブルをロックする必要は発生します。

またPostgreSQLって、更新エラーが発生すると、未コミットの更新内容はすべてご破算されてしまいます。
AutoCommitにしていれば別ですが。
ぷさいくろう
ぬし
会議室デビュー日: 2006/08/30
投稿数: 1034
投稿日時: 2006-10-25 14:20
セーブポイントを使うか
insert into select
1

スキルアップ/キャリアアップ(JOB@IT)