Aller au contenu

Migration vers 9.3 et supérieures

Augmentation de la consommation mémoire de work_mem

Depuis PostgreSQL 9.3, la mémoire assignée par work_mem peut enfin être totalement allouée (c’était une limitation des versions précédentes). Cela signifie aussi que probablement, vous aurez plus de mémoire allouée en tant que work_mem dans une instance 9.3 que dans les versions précédentes.

Commit Delay

Le paramètre commit_delay n’est maintenant modifiable que par les superutilisateurs. Cela n’a que peu d’importance, ce paramètre n’étant que très rarement modifié.

Renommage de replication_timeout

À partir de PostgreSQL 9.3, replication_timeout devient wal_sender_timeout.

Renommage de unix_socket_directory

Le paramètre unix_socket_directory a été remplacé par unix_socket_directories: cela permet d’avoir plusieurs répertoires pouvant contenir un socket Unix de connexion à l’instance, chacune, par exemple, dans un répertoire ayant des permissions différentes (pour restreindre l’accès à l’instance).

Noms de journaux de transaction

Les noms de journaux de transaction peuvent maintenant se terminer par FF. Jusque-là, les 16 derniers mégaoctets d’un tronçon de 4 Go étaient sautés. Cela peut avoir un impact si vous avez un script vérifiant la présence de toute une série de journaux de transactions dans un répertoire.

CREATE TABLE

Les messages de NOTICE de création d’objets supplémentaires à la création d’une table sont maintenant du DEBUG2.

Sous PostgreSQL 9.2 :

postgres=# CREATE TABLE test (a int PRIMARY KEY);
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"
CREATE TABLE

Sous PostgreSQL 9.3 :

postgres=# CREATE TABLE test (a int PRIMARY KEY);
CREATE TABLE

Cela pourrait gêner des scripts de déploiement qui vérifient ces informations.

Triggers en cascade

Voici un exemple très simplifié illustrant le problème :

  • une table detail ;
  • une table sum ;
  • la table sum est maintenue à jour par des triggers sur detail ;
  • un trigger sur sum en cas de DELETE supprime tous les détails associés.
CREATE FUNCTION delete_detail() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
  UPDATE sum SET sum=sum-old.value WHERE sum.name=old.name;
  -- En théorie il faudrait gérer une exception au cas où on aurait une mise
  -- à jour en parallèle
  RETURN old;
END
$$;

CREATE FUNCTION delete_sum() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
  DELETE FROM detail WHERE detail.name=old.name;
  -- En théorie il faudrait gérer une exception au cas où on aurait une mise
  -- à jour en parallèle
  RETURN old;
END
$$;

CREATE FUNCTION insert_detail() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
  UPDATE sum SET sum=sum+new.value WHERE sum.name=new.name;
  IF not found THEN
    insert into sum (name,sum) values (new.name,new.value);
  END IF;
  -- En théorie il faudrait gérer une exception au cas où on aurait une mise
  -- à jour en parallèle
  RETURN new;
END
$$;

CREATE FUNCTION update_detail() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
  UPDATE sum SET sum=sum+new.value-old.value WHERE sum.name=new.name;
  -- En théorie il faudrait gérer une exception au cas où on aurait une mise
  -- à jour en parallèle
  RETURN new;
END
$$;

CREATE TABLE detail (
    name text,
    value bigint
);

CREATE TABLE sum (
    name text,
    sum bigint
);

CREATE TRIGGER delete_trigger BEFORE DELETE ON detail FOR EACH ROW EXECUTE PROCEDURE delete_detail();
CREATE TRIGGER delete_trigger_sum BEFORE DELETE ON sum FOR EACH ROW EXECUTE PROCEDURE delete_sum();
CREATE TRIGGER insert_trigger BEFORE INSERT ON detail FOR EACH ROW EXECUTE PROCEDURE insert_detail();
CREATE TRIGGER update_trigger BEFORE UPDATE ON detail FOR EACH ROW EXECUTE PROCEDURE update_detail();

Sous PostgreSQL 9.2 :

postgres=# INSERT INTO detail VALUES ('test',1);
INSERT 0 1
postgres=# INSERT INTO detail VALUES ('test',1);
INSERT 0 1
postgres=# SELECT * FROM sum;
 name | sum 
------+-----
 test |   2
(1 ligne)

postgres=# DELETE FROM sum;
DELETE 0
postgres=# SELECT * FROM sum;
 name | sum 
------+-----
 test |   0
(1 ligne)

Sous PostgreSQL 9.3 :

postgres=# INSERT INTO detail VALUES ('test',1);
INSERT 0 1
postgres=# INSERT INTO detail VALUES ('test',1);
INSERT 0 1
postgres=# SELECT * FROM sum;
 name | sum 
------+-----
 test |   2
(1 ligne)

postgres=# DELETE FROM sum;
ERROR:  tuple to be updated was already modified by an operation triggered by the current command
ASTUCE : Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.

Le trigger de la table detail essaye de s’exécuter sur la table sum, alors que celui-ci a normalement été supprimé. En 9.3, l’erreur est bien interceptée au lieu d’entraîner la bizarrerie de PostgreSQL 9.2.

Foreign key et ON UPDATE SET NULL/SET DEFAULT

Voici un exemple :

CREATE TABLE parent (a int, b int, c int, primary key (a,b));
CREATE TABLE enfant (d int primary key, a int, b int, foreign key (a,b) references parent(a,b) on update set null);
INSERT INTO parent VALUES (1,1,1);
INSERT INTO enfant VALUES (1,1,1);
UPDATE parent SET b=0;

Sous PostgreSQL 9.2 :

postgres=# SELECT * FROM enfant ;
 d | a | b 
---+---+---
 1 | 1 | ¤
(1 ligne)

(ici , ¤ représente NULL)

Sous PostgreSQL 9.3 :

postgres=# SELECT * FROM enfant ;
 d | a | b 
---+---+---
 1 | ¤ | ¤
(1 ligne)

L’ancien comportement est celui du standard SQL-92. Le nouveau celui des standards plus récents.