J'ai deux questions sur l'utilisation de SELECT… FOR UPDATE, le verrouillage au niveau des lignes dans une fonction Postgres:
Peu importe les colonnes que je sélectionne? Ont-ils une relation avec les données que je dois verrouiller puis mettre à jour?
SELECT * FROM table WHERE x=y FOR UPDATE;
contre
SELECT 1 FROM table WHERE x=y FOR UPDATE;
Je ne peux pas faire de sélection dans une fonction sans enregistrer les données quelque part, donc j'enregistre dans une variable fictive. Cela semble bizarre; est-ce la bonne façon de faire les choses?
Voici ma fonction:
CREATE OR REPLACE FUNCTION update_message(v_1 INTEGER, v_timestamp INTEGER, v_version INTEGER)
RETURNS void AS $$
DECLARE
v_timestamp_conv TIMESTAMP;
dummy INTEGER;
BEGIN
SELECT timestamp 'Epoch' + v_timestamp * interval '1 second' INTO v_timestamp_conv;
SELECT 1 INTO dummy FROM my_table WHERE userid=v_1 LIMIT 1 FOR UPDATE;
UPDATE my_table SET (timestamp) = (v_timestamp_conv) WHERE userid=v_1 AND version < v_version;
END;
$$ LANGUAGE plpgsql;
Peu importe les colonnes que je sélectionne?
Non, ça n'a pas d'importance. Même si SELECT 1 FROM table WHERE ... FOR UPDATE
est utilisé, la requête verrouille toutes les lignes qui remplissent les conditions.
Si la requête extrait des lignes d'une jointure et que nous ne voulons pas verrouiller les lignes de toutes les tables impliquées dans la jointure, mais uniquement les lignes de tables spécifiques, un SELECT ... FOR UPDATE OF list-of-tablenames
la syntaxe peut être utile:
http://www.postgresql.org/docs/9.0/static/sql-select.html#SQL-FOR-UPDATE-SHARE
Je ne peux pas faire de sélection dans une fonction sans enregistrer les données quelque part, donc j'enregistre dans une variable fictive. Cela semble bizarre; est-ce la bonne façon de faire les choses?
Dans Pl/PgSql, utilisez une commande PERFORM
pour ignorer le résultat de la requête:
http://www.postgresql.org/docs/9.2/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-NORESULT
Au lieu de:
SELECT 1 INTO dummy FROM my_table WHERE userid=v_1 LIMIT 1 FOR UPDATE;
utilisation:
PERFORM 1 FROM my_table WHERE userid=v_1 LIMIT 1 FOR UPDATE;