2012-05-04 1 views
2

Je suis intéressé, ce qui est la meilleure pratique pour éviter ce petit problème :)PostgreSQL: 2+ clients, contrainte unique -> condition de course

permet de prendre 2 clients, les deux tentent d'insérer des lignes dans la table avec contrainte unique .
Supposons que c'est une colonne "url".

À un moment donné, il peut apparaître la situation suivante:
    1) Le client A semble, est-il url "a" dans le tableau
    2) Le client A obtient réponse, qu'il n'y a pas que url
    3) le client a va insérer url "un"
    4) B client recherche, est-il url "a" dans le tableau
    5) B obtient client réponse, qu'il n'y a cette URL
    6) Client Une URL inséré "un"
    7) Le client B va insérer url "un", mais obtient clé doublon

Ai-je comprends bien, que la meilleure façon pour l'éviter - faites simplement des essais au niveau de l'application?

Répondre

2

Vous pouvez éviter l'erreur avec des verrous explicites retirés au début d'une transaction, mais cela peut être mauvais pour la concurrence et le débit.

http://www.postgresql.org/docs/current/interactive/explicit-locking.html

Si vous ne bloquez pas les tentatives simultanées, vous devez traiter d'une façon ou retries une autre. Plutôt que de mettre cette logique dans le code de l'application, vous pouvez l'encapsuler dans une fonction. La logique serait similaire à l'exemple merge_db():

http://www.postgresql.org/docs/current/interactive/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING

1

Si vous exécutez dans le niveau d'isolation SERIALIZABLE, le client B sera obligé d'attendre la transaction A à remplir avant que la valeur de l'URL est renvoyée. Comme cette valeur n'existe pas encore, vous ne pouvez pas placer un verrou sur l'enregistrement (il n'y a pas d'enregistrement), donc le verrouillage d'espace sur l'index sera utilisé à la place. Mais comme @kgrittn mentionné, cela affecterait négativement les performances et la concurrence. Il est donc préférable de gérer l'erreur de clé en double

+2

Ce serait une bonne réponse pour certaines autres bases de données, au moins dans certaines configurations, mais elle est incorrecte pour PostgreSQL, ce qui était la question. Dans PostgreSQL, le niveau d'isolation de transaction SERIALIZABLE utilise l'isolation de cliché sérialisable, pas le verrouillage strict de phase, donc aucun blocage ne se produit; il y aurait toujours une erreur. http://wiki.postgresql.org/wiki/Serializable http://www.postgresql.org/docs/current/interactive/mvcc-intro.html – kgrittn

Questions connexes