Migration Postgres 7.xx auf 8.xx

Hallo Forum,

ich habe ein Problem mit einer migrierten Datenbank unter Postgres 8.2.1.

Ich habe (exemplarisch) folgende Tabellen:

CREATE TABLE papa
(
id varchar(40) NOT NULL,
name varchar(40),
CONSTRAINT papa_pkey PRIMARY KEY (id)
)
WITH OIDS;

und

CREATE TABLE kind
(
id varchar(40) NOT NULL,
kid varchar(40) NOT NULL,
name varchar(40),
CONSTRAINT kind_pkey PRIMARY KEY (id, kid),
CONSTRAINT kind_id_fkey FOREIGN KEY (id) REFERENCES papa (id) ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH OIDS;

In der 7.xx-Datenbank konnte ich mit folgendem SQL den Primärschlüssel
von “papa” und den Fremdschlüssel von “kind” in einer Transaktion umstellen.

update kind set id=‘Versuch’ where id=‘erst’;
update papa set id=‘Versuch’ where id=‘erst’;

Dies funktionierte sowohl aus pgadmin3 als auch mit Python und pyPgSQL als
DB-Adapter. In der 8.xx-Version bekomme ich nun immer:

ERROR: insert or update on table “kind” violates foreign key constraint “kind_id_fkey”
DETAIL: Key (id)=(Versuch) is not present in table “papa”.

Leider basieren große Teile meiner Anwendung darauf, dass ich innerhalb
einer Transaktion einen nicht konsistenten Zustand habe. Wie kann ich
den 8.xx-Server dazu bewegen, sich an dieser Stelle wie ein 7.xx-Server
zu verhalten.

Vielen Dank für die Tipps im Voraus

Bonobo

Schlecht.

Du könntest versuchen, diese Constraints deferrable anzulegen und dann, vor der TX, mit ‘set constraints all deferred’ zu hantieren.

Hallo Akretschmer,

das man innerhalb einer Transaktion (aus Sicht der Transaktion)
eine inkonsistenten Zustand hat, ist nichts ungewöhnliches (Beispiel
Buchung, erste Halbbuchung “vernichtet” Geld, zweite Halbbuchung
“erzeugt” den fehlenden Betrag wieder. Zwischen den Halbbuchungen
“fehlt” Geld. Es ist nur wichtig, dass diese Transaktion als GANZES
durchgeführt wird (das A und I in ACID)).

Bis Release 7.xx hatte ich auch bei Postgres den Eindruck, dass dieses
Verständnis einer Transaktion so unterstützt ist. Wenn das in Release 8.2.1
nicht mehr der Fall ist, muss ich vermutlich von Postgres auf eine der
kommerziellen DB’s wechseln, was mich sehr ärgern würde.

So Long

Bonobo

Es ging um Foreign Key Constraints. Ich glaube nicht, daß bei 7.x man dagegen verstoßen konnte, ohne es explizit der DB zu sagen, das man dies, innerhalb einer Transaktion, auch will.
Das heißt nicht, das es nicht geht, man muß es der DB halt nur sagen. Guggst Du:

test=# create table master (id serial primary key, name text);
NOTICE:  CREATE TABLE will create implicit sequence "master_id_seq" for serial column "master.id"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "master_pkey" for table "master"
CREATE TABLE
Time: 358.515 ms
test=*# create table slave (id serial primary key references master deferrable, name text);
NOTICE:  CREATE TABLE will create implicit sequence "slave_id_seq" for serial column "slave.id"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "slave_pkey" for table "slave"
CREATE TABLE
Time: 239.736 ms
test=*# alter table master add constraint fk foreign key (id) references slave (id) deferrable;
ALTER TABLE
Time: 8.712 ms
test=*# commit;
COMMIT
Time: 19.443 ms
test=# insert into master values (1, 'master');
ERROR:  insert or update on table "master" violates foreign key constraint "fk"
DETAIL:  Key (id)=(1) is not present in table "slave".
test=!# rollback;
ROLLBACK
Time: 0.507 ms
test=# begin;
BEGIN
Time: 0.989 ms
test=*# set constraints all deferred;
SET CONSTRAINTS
Time: 0.522 ms
test=*# insert into master values (1, 'master');
INSERT 0 1
Time: 1.483 ms
test=*# insert into slave values (1, 'slave');
INSERT 0 1
Time: 64.769 ms
test=*# commit;
COMMIT
Time: 9.145 ms
test=#

Das erste Insert schlägt fehl, weil ich halt auch ein recht blödes Tabellendesign habe: Beide Tables, master und slave, verweisen jeweils auf die andere. Henne-Ei-Problem, ganz klassisch.
Ich kann aber sagen, daß die Constraint-Prüfung erst am Ende der TX erfolgt, und ich denke, daß ist genau das, was Du suchst.


Andreas