トランザクションでロールバックされない処理

BEGIN
— 任意の処理 ..(A)
ROLLBACK

とすれば、(A)で何をしてもロールバックしてくれるものだと思っていたらそれは勘違いのようです。
 
たとえばシーケンスなど

create sequence seq;
 
BEGIN;
SELECT nextval(‘seq’); — (B)
SELECT nextval(‘seq’); — (C)
ROLLBACK;
SELECT nextval(‘seq’); — (D)

としても (B) == (D) にはならず、BEGIN, ROLLBACK で囲まなかった場合と同じになります。
 
PGSQL-JP ML によると
http://www.drive.ne.jp/iMA/showmail.pl?pgsql-jp=3098

 

素人的な考えだと、transaction 内での処理なんだから、値を戻して
くれてもよさそうなものなのに、と思うのですが。。

#Oracle でも sequence は戻らないと聞いたので、出来ないのが普通
#なのかなあ?

 
他にも戻らないものとしては、
create table
create index
create sequence
があります(他にもあるかも)。商用DBでも多分同じです。

公式 PGSQL ML の引用

It’s normal behaviour.
 
Sequences are locked only for duration of nextval call, not for
transaction! So, one sequence may be used simultaneously
by many transactions. No way to rollback sequence changes.
 
意訳: シーケンスのロックは nextval 呼び出しについてのロックであり、トランザクションのためのロックではありません。一つのシーケンスが同時に複数のトランザクションで利用されうるため、シーケンスの変更をロールバックする方法は存在しません。

ということですが、単純に、一つのテーブルで serial (bigserial)として利用していて、他で nextval が呼ばれないことをシステム的に保証していれば、テーブルロックを使い、ROLLBACK 時にシーケンスを元に戻してやれば、一応実現は可能かなと思います。