multi-version read consistency in Oracle、MySQL、PostGreSQL
在多人同时访问与修改数据时, 最大的难题之一是:一方面要力争最大的并发访问,与此同时还要确保每个用户能以一致的方式读取和修改数据。
ANSI/ISO SQL 标准定义了4 种事务隔离级别,对于相同的事务,采用不同的隔离级别分别有不同的结果。
这些隔离级别是根据3 个“现象”定义的,如dirty read、nonrepeatable read、phantom read。Oracle 明确地支持READ COMMITTED(读已提交)和SERIALIZABLE(可串行化)隔离级别,在Oracle 中READ COMMITTED 则有得到读一致查询所需的所有属性,在其他数据库中的读READ COMMITTED 可能会有不同的答案, 最近有个客户在测试migrate oracle to postgreSQL测试发现一个批处理的结果并非一致,于是做一个小小的测试验证一下。
Oracle
## session 1
SQL> CREATE TABLE test (id INT PRIMARY KEY);
Table created.
SQL> INSERT INTO test VALUES (1);
1 row created.
SQL> INSERT INTO test VALUES (2);
1 row created.
SQL> alter table test add ctime date;
Table altered.
SQL> select * from test;
ID CTIME
---------- -------------------
1
2
SQL> update test set ctime=sysdate;
2 rows updated.
SQL> set time on
12:22:03 SQL>
12:22:03 SQL>
12:22:03 SQL>
begin
DELETE FROM test WHERE id=1;
INSERT INTO test VALUES (1,sysdate);
end;
/
PL/SQL procedure successfully completed.
12:22:06 SQL> select * from test;
ID CTIME
---------- -------------------
2 2022-08-19 12:21:31
1 2022-08-19 12:22:06
## session 2
SQL> set time on
12:21:47 SQL>
12:22:10 SQL>
begin
DELETE FROM test WHERE id=1;
INSERT INTO test VALUES (1,sysdate);
12:22:11 4 end;
12:22:12 5 /
-- hang
## session 1
12:22:24 SQL> commit;
Commit complete.
## session 2
12:22:10 SQL>
begin
DELETE FROM test WHERE id=1;
INSERT INTO test VALUES (1,sysdate);
12:22:11 4 end;
12:22:12 5 /
PL/SQL procedure successfully completed.
12:23:00 SQL> select * from test;
ID CTIME
--------------- -----------------
1 20220819 12:22:36
2 20220819 12:21:31
SELECT s.sid, s.serial#,decode(bitand(flag,power(2,28)),0,'READ COMMITTED',1,'SERIALIZABLE') isolation_level
FROM v$transaction t
JOIN v$session s ON t