∈"> ∉"> ] > Contrôle de concurrence des SGBDs

Traîtement distribué des données

Master 1 ISD

Contrôle de concurrence

kn@lmf.cnrs.fr

Transactions

Contexte

On se place dans le contexte : 1 source de donnée ↔ plusieurs utilisateurs.
On considère les bases de données relationnelles classiques.
Comment gèrent elles les accès concurrent ?

Qu'est-ce qu'une transaction ?

Une transaction est une suite d'opérations exécutée sur la base de données de manière complète :

Modèle ACID

Les transactions d'une base de données relationnelle suivent le modèle ACID :

On s'intéresse uniquement à atomicité et isolation.
La cohérence est une conséquence de l'atomicité et de l'isolation et du fait que les opérations de base (INSERT, DELETE, …) vérifient les contraintes.
La durabilité repose sur des aspects systèmes et bas niveau (journal d'opération, re-jeu du journal en cas de défaillance, copies multiples, …)

Isolation et sérialisabilité

Ordonnanceur naïf

Un ordonnanceur naïf (utilise une file de priorité pour exécuter les transactions en séquence) remplit ces contraintes. Mais :

Ordonnanceur avancé

Notations (un peu de théorie)

On abstrait une transaction comme une suite de lecture et écriture d'objets

On note rT(X) pour « la transaction T lit (read) l'objet X.

On note wT(X) pour « la transaction T écrit (write) l'objet X.

Intuitivement il ne faut pas voir X comme une valeur mais plutôt comme un emplacement sur le disque (ou une adresse).

Conflits

Certaines opérations peuvent être ré-ordonnées sans incidence sur le résultat final.

Par exemple : on peut changer l'ordre de deux lectures (entre elles), sans modifier le résultat final d'une transaction.

Si ré-ordonner deux opérations change le résultat final, ces deux opérations sont en conflit.

Quelles opérations peuvent causer un conflit ?

Deux opérations sont en conflit, si :

T1 T2
rT1(A)
rT2(A)
wT1(A)
rT2(A)

Conflit de mise en séquence

Détection de conflit

Étant données n transactions T1, …, Tn, comment détecter si elles sont sérialisables ?

Verrous

Transactions sérialisables en pratique

Le SGBD va faire en sorte de n'autoriser que les transactions sérialisables, et refuser les autres

Plusieurs techniques possibles

Verrouillage en deux phases (2-Phase Locking ou 2PL)

Protocole de vérouillage simple qui garanti la sérialisabilité

Utilisé par tous les SGBD modernes (mais ils vont plus loin)

Sûr, mais trop restrictif (à pleine mieux que mise en séquence)

Solution : avoir plusieurs types de verrous :

Niveaux d'isolation

SQL dans tout ça

La sérialisabilité totale n'est pas toujours nécessaire et est couteuse en ressources

SQL définit 4 niveau d'isolation (i.e. manière dont sont cloisonnées les transaction). On présente les deux principaux:

READ COMMITTED

Dans ce mode les verrous en lecture sont relaché immédiatement

BEGIN; | BEGIN; SELECT age FROM T WHERE id=1 | -- age vaut 42 | UPDATE T SET age = age + 1 WHERE id = 1 | COMMIT; SELECT age FROM T WHERE id=1 | -- age vaur 43 |

C'est souvent ce que l'on veut

SERIALIZABLE

Utilisation du protocole 2PL les verrous de lecture sont relaché en fin de transaction, un snapshot est fait au début de la transaction.

BEGIN; | BEGIN; SET TRANSACTION ISOLATION | SET TRANSACTION ISOLATION LEVEL LEVEL SERIALIZABLE; | SERIALIZABLE; SELECT age FROM T WHERE id=1 | -- age vaut 42 | UPDATE T SET age = age + 1 WHERE id = 1 | COMMIT; SELECT age FROM T WHERE id=1 | -- age vaur 42 |

Deadlocks

La présence de verrous implique la possibilité de deadlock

Souvent causé par des verrous de granularité fine (T1 verouille la ligne 'a' et 'b', T2 vérouille la ligne 2 et 1)

Le SGBD détecte les deadlocks et annule arbitrairement l'une des transaction (avec une erreur).

Verrous et SQL (simplifié)

Chaque ordre SQL manipule un type de verrou différent :

Rappels JDBC

Connexion à une base

Class.forName("org.postgresql.Driver"); connection = DriverManager.getConnection("jdbc:postgresql://host:port/" + base, username, password);

Exécution d'ordres SQL (version simple) (1/2)

Statement stmt = connection.createStatement(); stmt.executeUpdate("DROP TABLE MOVIE CASCADE "); stmt.addBatch("CREATE TABLE MOVIE (…)"); stmt.addBatch("CREATE TABLE PEOPLE (…)"); stmt.addBatch("CREATE TABLE ACTOR (…)"); stmt.addBatch("CREATE TABLE DIRECTOR (…)"); stmt.executeBatch();

Exécution d'ordres SQL (version simple) (2/2)

Statement stmt = connection.createStatement(); ResultSet res = stmt.executeQuery("SELECT * FROM …"); while (res.next()) { String name = res.getString(1); int age = res.getInt("age_col"); … }

Exécution d'ordres SQL (version avancée)

Il existe des sous-interfaces à l'interface Statement:

… bien d'autres choses