Niveau d’isolation : READ UNCOMMITTED

Tout est permis !

      Les systèmes de gestion de bases de données relationnelles sont connus pour leurs propriétés ACID. Le I signifie ISOLATION. De multiples transactions peuvent être gérées simultanément par un SGBDR. Le standard SQL définit plusieurs niveaux d’isolation fixant les règles régissant la concurrence entre ces transactions. Dans cet article nous allons nous intéresser au niveau le plus permissif, le READ UNCOMMITTED. Ce niveau autorise les lectures sales (dirty reads), c’est à dire de lire dans une transaction des données qui ont été manipulées par d’autres transactions mais pas validées.
      Démonstration avec PostgreSQL 9.6 :

select version(); version ------------------------------------------------------------------------------------------ PostgreSQL 9.6.1 on x86_64-pc-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit (1 ligne) - session 0 CREATE TABLE t1(c1 SMALLINT); CREATE TABLE COMMIT; COMMIT -- session 1 INSERT INTO t1(c1) VALUES(1); INSERT 0 1 -- session 2 START TRANSACTION; START TRANSACTION SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SET SELECT * FROM t1; c1 ---- (0 ligne) -- session 1 COMMIT; COMMIT -- session 2 SELECT * FROM t1; c1 ---- 1 (1 ligne)

      PostgreSQL accepte la syntaxe mais traite le niveau d’isolation READ UNCOMMITTED comme le niveau READ COMMITTED. Le premier "SELECT * FROM t1" de la session 2 ne voit pas la ligne de t1 insérée précédemment par une transaction en cours dans la session 1. Il est impossible d’avoir des lectures sales avec PostgreSQL. Il faut souligner que ce comportement est compatible avec le standard SQL. En effet le standard impose de NE PAS avoir de lecture sales à partir du niveau READ COMMITTED mais il n’impose pas d’avoir des lectures sales en READ UNCOMMITTED.
      A présent un test avec Oracle Database dans sa version 11.2.0.2 :

Connected to: Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production -- session 0 SQL> CREATE TABLE t1(c1 SMALLINT); Table created. -- session 1 SQL> INSERT INTO t1 VALUES(1); 1 row created. -- session 2 SQL> SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED * ERROR at line 1: ORA-02179: valid options: ISOLATION LEVEL { SERIALIZABLE | READ COMMITTED }

      Oracle Database refuse tout simplement la syntaxe. Le niveau READ UNCOMMITTED n’est donc implémenté ni par PostgreSQL, ni par Oracle. Ce niveau ne présente que très rarement un intérêt fonctionnel. Il pourrait présenter un intérêt en réduisant le verrouillage, et donc les temps d’attente, dans le cas où le niveau READ COMMITTED n’est pas requis. Puisque READ UNCOMMITTED permet de voir des données non validées, plus besoin d’empêcher une transaction d’écrire des données en cours de lecture par une autre transaction. Alors, est-ce une limitation de PostgreSQL et Oracle ?

MVCC à la rescousse

      Et bien...non, pas de limitation ! Oracle comme PostgreSQL permettent en effet des lectures non bloquantes sans verrouillage même aux niveaux READ COMMITTED et supérieurs. Un mécanisme, présent dans PostgreSQL depuis la version 6.x sortie en 1996, permet de présenter à chaque transaction une vision adéquate de la base. Ce mécanisme est appelé MVCC (multiversion concurrency control). Grâce à lui, les lectures ne bloquent jamais les écritures et réciproquement, quel que soit le niveau d’isolation. Tom Kyte explique cela en détail pour Oracle dans cet article traduit en français. A noter que le SGBDR critiqué en filigrane dans l’article est SQL Server. La critique était sans doute pertinente mais elle n’est plus d’actualité car SQL Server dispose également d’un mécanisme MVCC depuis la version 2005.

Mise à jour : 08/11/2016