@SovietPower
2022-06-05T14:26:31.000000Z
字数 22742
阅读 1464
DB
1. 在Dokcer环境中启动之前实验创建的openGauss容器。
2. 连接到数据库db2022(将该会话记作 T1 )
PS H:\> docker exec -it opengauss3 bashroot@97375c3acbd1:/# su ommomm@97375c3acbd1:/$ gsql -d db2022 -r
3. 在 T1 中执行以下SQL语句,创建用于事务 隔离级别(Isolation Level) 测试的数据表
db2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLEdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2
4. 在 T1 中执行以下语句,查看并设置当前会话的参数
lockwait_timeout:控制单个锁的最长等待时间。当申请的锁等待时间超过设定值时,系统会报错。
update_lockwait_timeout:允许并发更新参数开启情况下,该参数控制并发更新同一行时单个锁的最长等待时间。当申请的锁等待时间超过设定值时,系统会报错。
延长update_lockwait_timeout,则多个事务并行执行时等待锁的时间更长,方便输入语句测试。
db2022=# select current_setting('transaction_isolation');current_setting-----------------read committed(1 row)db2022=# show update_lockwait_timeout;update_lockwait_timeout-------------------------2min(1 row)db2022=# set update_lockwait_timeout to 1200000;SETdb2022=# show update_lockwait_timeout;update_lockwait_timeout-------------------------20min(1 row)db2022=# \timingTiming is on.
5. 打开另一个PowerShell窗口,连接到数据库db2022(将该会话记作 T2 ),执行
db2022=# set update_lockwait_timeout to 1200000;SETdb2022=# \timingTiming is on.
read committed 隔离级别可以避免 Write Cycles 异常
Read Commited保证:
读数据时只能读到已经提交了的数据 (没有脏读)
写数据时只能覆盖已经提交了的数据 (没有脏写)
6.7. 在 T1,T2 中都执行以下语句,设置当前会话的事务隔离级别
db2022=# begin;BEGINTime: 0.315 msdb2022=# set transaction isolation level read committed;SETTime: 0.446 ms
8. 在 T1 中执行以下语句,对test表中id=1的记录进行更新
db2022=# update test set value = 11 where id = 1;UPDATE 1Time: 0.730 ms
9. 在 T2 中执行以下语句,同样对test表中id=1的记录进行更新
db2022=# update test set value = 12 where id = 1;此时,T2中的事务被阻塞UPDATE 1Time: 44844.698 ms
10. 在 T1 中执行以下语句,对test表中id=2的记录进行更新,然后提交事务
db2022=# update test set value = 21 where id = 2;UPDATE 1Time: 0.663 msdb2022=# commit;COMMITTime: 411.061 ms此时结束对T2中事务的阻塞
1. 在 T1 中执行以下语句,查询test表中的数据
此时 T2 修改未提交
db2022=# select * from test;id | value----+-------1 | 112 | 21(2 rows)Time: 0.615 ms
2. 在 T2 中执行以下语句,对test表中id=2的记录进行更新,然后提交事务
db2022=# update test set value = 22 where id = 2;UPDATE 1Time: 0.521 msdb2022=# commit;COMMITTime: 294.785 ms
3. 在 T2 中执行以下语句,查询test表中的数据
db2022=# select * from test;id | value----+-------1 | 122 | 22(2 rows)Time: 0.903 ms
read committed 隔离级别可以避免 Aborted Reads 异常
4. 在 T1 中执行以下语句,重置测试数据表
db2022=# drop table test;DROP TABLETime: 1656.834 msdb2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLETime: 9758.841 msdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2Time: 3422.961 ms
5. 在 T1 中执行以下语句,设置当前会话的事务隔离级别
db2022=# begin;BEGINTime: 0.375 msdb2022=# set transaction isolation level read committed;SETTime: 0.368 ms
6. 在 T2 中执行以下语句,设置当前会话的事务隔离级别
db2022=# begin;BEGINTime: 0.575 msdb2022=# set transaction isolation level read committed;SETTime: 0.459 ms
7. 在 T1 中执行以下语句,对test表中id=1的记录进行更新
db2022=# update test set value = 101 where id = 1;UPDATE 1Time: 0.956 ms
8. 在 T2 中执行以下语句,查询test表中数据
db2022=# select * from test;id | value----+-------1 | 102 | 20(2 rows)Time: 1.169 ms
9. 在 T1 中执行以下语句,撤销事务
db2022=# abort;ROLLBACKTime: 0.666 ms
10. 在 T2 中执行以下语句,查询test表中数据
db2022=# select * from test;id | value----+-------1 | 102 | 20(2 rows)Time: 0.776 msdb2022=# commit;COMMITTime: 0.526 ms
read committed 隔离级别可以避免 intermediate Reads 异常
1. 在 T1 中执行以下语句,重置测试数据表
db2022=# drop table test;DROP TABLETime: 3017.035 msdb2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLETime: 11315.591 msdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2Time: 2152.651 ms
2. 在 T1 中执行以下语句,设置当前会话的事务隔离级别
db2022=# begin;BEGINTime: 0.284 msdb2022=# set transaction isolation level read committed;SETTime: 0.495 ms
3. 在 T2 中执行以下语句,设置当前会话的事务隔离级别
db2022=# begin;BEGINTime: 0.389 msdb2022=# set transaction isolation level read committed;SETTime: 0.415 ms
4. 在 T1 中执行以下语句,对test表中id=1的记录进行更新
db2022=# update test set value = 101 where id = 1;UPDATE 1Time: 0.601 ms
5. 在 T2 中执行以下语句,查询test表中数据
db2022=# select * from test;id | value----+-------1 | 102 | 20(2 rows)Time: 0.716 ms
6. 在 T1 中执行以下语句,再次对test表中id=1的记录进行更新,然后提交
db2022=# update test set value = 11 where id = 1;UPDATE 1Time: 0.577 msdb2022=# commit;COMMITTime: 2151.811 ms
7. 在 T2 中执行以下语句,再次查询test表中数据
db2022=# select * from test;id | value----+-------2 | 201 | 11(2 rows)Time: 0.513 ms
read committed 隔离级别可以避免 Circular Information Flow 异常
8. 在 T1 中执行以下语句,重置测试数据表
在 T1 2 中执行以下语句,设置当前会话的事务隔离级别
db2022=# drop table test;DROP TABLEdb2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLEdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2db2022=# begin;BEGINdb2022=# set transaction isolation level read committed;SET
1. 在 T1 中执行以下语句,对test表中id=1的记录进行更新
db2022=# update test set value = 11 where id = 1;UPDATE 1
2. 在 T2 中执行以下语句,对test表中id=2的记录进行更新
db2022=# update test set value = 22 where id = 2;UPDATE 1
3. 在 T1 中执行以下语句,查询test表中数据
db2022=# select * from test;id | value----+-------2 | 201 | 11(2 rows)
4. 在 T2 中执行以下语句,查询test表中数据
db2022=# select * from test;id | value----+-------1 | 102 | 22(2 rows)
5. 在 T1 中执行以下语句,提交事务
db2022=# commitdb2022-# ;COMMIT
6. 在 T2 中执行以下语句,提交事务
db2022=# commit;COMMITdb2022=# select * from test;id | value----+-------1 | 112 | 22(2 rows)
read committed 隔离级别可以避免 Observed Transaction Vanishes 异常
7. 在 T1 中执行以下语句,重置测试数据表
在 T1 2 中执行以下语句,设置当前会话的事务隔离级别
db2022=# drop table test;DROP TABLEdb2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLEdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2db2022=# begin;BEGINdb2022=# set transaction isolation level read committed;SET
10. 打开一个新的PowerShell窗口,连接到数据库db2022(将该会话记作 T3 ),执行
db2022=# set update_lockwait_timeout to 1200000;SETdb2022=# \timingTiming is on.db2022=# begin;BEGINTime: 0.234 msdb2022=# set transaction isolation level read committed;SETTime: 0.431 ms
1. 在 T1 中执行以下语句,对test表中记录进行更新
db2022=# update test set value = 11 where id = 1;UPDATE 1Time: 0.585 msdb2022=# update test set value = 19 where id = 2;UPDATE 1Time: 0.509 ms
在 T2 中执行以下语句,对test表中记录进行更新
db2022=# update test set value = 12 where id = 1;阻塞
2. 在 T1 中执行以下语句,提交事务
db2022=# commit;COMMITTime: 106.829 msT2结束阻塞
3. 在 T3 中执行以下语句,查询test表中数据
db2022=# select * from test;id | value----+-------1 | 112 | 19(2 rows)Time: 0.971 ms
4. 在 T2 中执行以下语句,对test表中记录进行更新
db2022=# update test set value = 18 where id = 2;UPDATE 1Time: 0.562 ms
5. 在 T3 中执行以下语句,查询test表中数据
db2022=# select * from test;id | value----+-------1 | 112 | 19(2 rows)Time: 0.560 ms
6. 在 T2 中执行以下语句,提交事务
db2022=# commit;COMMITTime: 118.936 ms
7. 在 T3 中执行以下语句,查询test表中数据
db2022=# select * from test;id | value----+-------1 | 122 | 18(2 rows)Time: 0.778 ms
提交的事务不会丢失。
read committed 隔离级别不能避免 Predicate-Many-Preceders 异常
8. 在 T1 中执行以下语句,重置测试数据表
在 T1 2 中执行以下语句,设置当前会话的事务隔离级别
db2022=# drop table test;DROP TABLETime: 6818.855 msdb2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLETime: 211.857 msdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2Time: 135.669 msdb2022=# begin;BEGINTime: 0.283 msdb2022=# set transaction isolation level read committed;SETTime: 0.323 ms
1. 在 T1 中执行以下语句,查询test表中数据
db2022=# select * from test where value = 30;id | value----+-------(0 rows)Time: 0.839 ms
2. 在 T2 中执行以下语句,向test表中插入数据,然后提交
db2022=# insert into test (id, value) values(3, 30);INSERT 0 1Time: 0.656 msdb2022=# commit;COMMITTime: 36.350 ms
3. 在 T1 中执行以下语句,查询test表中数据
db2022=# select * from test where value % 3 = 0;id | value----+-------3 | 30(1 row)Time: 1.058 msdb2022=# commitdb2022-# ;COMMITTime: 0.319 ms
第二次查询的结果并不在第一次中,不可重复读。
read committed 隔离级别不能避免 Predicate-Many-Preceders for write
predicates 异常
4. 在 T1 中执行以下语句,重置测试数据表
在 T1 2 中执行以下语句,设置当前会话的事务隔离级别
db2022=# drop table test;DROP TABLETime: 136.073 msdb2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLETime: 229.252 msdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2Time: 67.571 msdb2022=# begin;BEGINTime: 0.325 msdb2022=# set transaction isolation level read committed;SETTime: 0.371 ms
7. 在 T1 中执行以下语句,更新表test中的数据
db2022=# update test set value = value + 10;UPDATE 2Time: 1.114 ms
8. 在 T2 中执行以下语句,删除表test中value为20的记录
db2022=# delete from test where value = 20;阻塞
9. 在 T1 中提交事务
10. 在 T2 中执行以下语句,查询表test中value为20的记录
db2022=# select * from test where value = 20;id | value----+-------1 | 20(1 row)Time: 0.805 ms
T2 删除了所有 value=20 的记录,但删除后依旧能查到 value=20 的记录。
read committed 隔离级别不能避免 Lost Update 异常
1. 在 T1 中执行以下语句,重置测试数据表
在 T1 2 中执行以下语句,设置当前会话的事务隔离级别
db2022=# drop table test;DROP TABLETime: 155.979 msdb2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLETime: 690.676 msdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2Time: 66.225 msdb2022=# begin;BEGINTime: 0.259 msdb2022=# set transaction isolation level read committed;SETTime: 0.453 ms
4. 在 T1 中执行以下语句,查询表test中id为1的记录
db2022=# select * from test where id = 1;id | value----+-------1 | 10(1 row)Time: 0.572 ms
5. 在 T2 中执行以下语句,查询表test中id为1的记录
db2022=# select * from test where id = 1;id | value----+-------1 | 10(1 row)Time: 0.942 ms
6. 在 T1 中执行以下语句,更新表test中id为1的记录
db2022=# update test set value = 11 where id = 1;UPDATE 1Time: 0.832 ms
7. 在 T2 中执行以下语句,更新表test中id为1的记录
db2022=# update test set value = 12 where id = 1;阻塞
8. 在 T1 2 中提交事务
db2022=# select * from test;id | value----+-------2 | 201 | 12(2 rows)Time: 0.777 ms
T1 的更新丢失。
read committed 隔离级别不能避免 Read Skew 异常
10. 在 T1 中执行以下语句,重置测试数据表
在 T1 2 中执行以下语句,设置当前会话的事务隔离级别
db2022=# drop table test;DROP TABLETime: 145.889 msdb2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLETime: 268.693 msdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2Time: 56.577 msdb2022=# begin;BEGINTime: 0.309 msdb2022=# set transaction isolation level read committed;SETTime: 0.480 ms
3. 在 T1 中执行以下语句,查询表test中id为1的记录
db2022=# select * from test where id = 1;id | value----+-------1 | 10(1 row)Time: 0.623 ms
4. 在 T2 中执行以下语句,查询并更新表test中的记录,然后提交事务
db2022=# select * from test where id = 1; --返回(1,10)id | value----+-------1 | 10(1 row)Time: 0.761 msdb2022=# select * from test where id = 2; --返回(2,20)id | value----+-------2 | 20(1 row)Time: 0.571 msdb2022=# update test set value = 12 where id = 1;UPDATE 1Time: 0.726 msdb2022=# update test set value = 18 where id = 2;UPDATE 1Time: 0.553 msdb2022=# commit;COMMITTime: 33.049 ms
5. 在 T1 中执行以下语句,查询表test中id为2的记录
db2022=# select * from test where id = 2;id | value----+-------2 | 18(1 row)Time: 0.572 msdb2022=# select * from test;id | value----+-------1 | 122 | 18(2 rows)Time: 0.580 ms
T1 分别读取了 id = 1, 2 的两次,结果为(1,10),(2,18),但这并不存在于数据库中。
repeatable read 隔离级别可以避免 Predicate-Many-Preceders 异常
6. 在 T1 中执行以下语句,重置测试数据表
在 T1 2 中执行以下语句,设置当前会话的事务隔离级别
db2022=# drop table test;DROP TABLETime: 1.196 msdb2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLETime: 181.163 msdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2Time: 0.920 msdb2022=# begin;WARNING: there is already a transaction in progressBEGINTime: 0.345 msdb2022=# set transaction isolation level repeatable read;ERROR: SET TRANSACTION ISOLATION LEVEL must be called before any queryTime: 498.818 ms
9. 在 T1 中执行以下语句,查询test表中数据
db2022=# select * from test where value = 30;id | value----+-------(0 rows)Time: 0.891 ms
10. 在 T2 中执行以下语句,向test表中插入数据,然后提交
db2022=# insert into test (id, value) values(3, 30);INSERT 0 1Time: 0.636 msdb2022=# commit;COMMITTime: 36.986 ms
1. 在 T1 中执行以下语句,查询test表中数据
db2022=# select * from test where value % 3 = 0;id | value----+-------(0 rows)Time: 0.702 msdb2022=# commit;COMMITTime: 0.442 ms
两次查询结果均相同。
repeatable read 隔离级别可以避免 Predicate-Many-Preceders for write
predicates 异常
2. 在 T1 中执行以下语句,重置测试数据表
在 T1 2 中执行以下语句,设置当前会话的事务隔离级别
db2022=# drop table test;DROP TABLETime: 143.159 msdb2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLETime: 279.746 msdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2Time: 117.401 msdb2022=# begin;BEGINTime: 0.249 msdb2022=# set transaction isolation level repeatable read;SETTime: 0.372 ms
5. 在 T1 中执行以下语句,更新表test中的数据
db2022=# update test set value = value + 10;UPDATE 2Time: 0.639 ms
6. 在 T2 中执行以下语句,删除表test中value为20的记录
db2022=# delete from test where value = 20;阻塞
7. 在 T1 中提交事务,T2 会报错
db2022=# delete from test where value = 20;ERROR: could not serialize access due to concurrent updateTime: 4675.140 ms
8. 在 T2 中执行以下语句,撤销事务
db2022=# abort;ROLLBACKTime: 0.325 ms
禁止了 T2 修改 T1 中修改的记录,就不会有“T2 删除了所有 value=20 的记录,但删除后依旧能查到 value=20 的记录”的问题。
repeatable read 隔离级别可以避免 Lost Update 异常
9. 在 T1 中执行以下语句,重置测试数据表
在 T1 2 中执行以下语句,设置当前会话的事务隔离级别
db2022=# drop table test;DROP TABLETime: 151.185 msdb2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLETime: 218.647 msdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2Time: 66.391 msdb2022=# begin;BEGINTime: 0.256 msdb2022=# set transaction isolation level repeatable read;SETTime: 0.424 ms
2. 在 T1 中执行以下语句,查询表test中id为1的记录
db2022=# select * from test where id = 1;id | value----+-------1 | 10(1 row)Time: 0.785 ms
3. 在 T2 中执行以下语句,查询表test中id为1的记录
db2022=# select * from test where id = 1;id | value----+-------1 | 10(1 row)Time: 0.715 ms
4. 在 T1 中执行以下语句,更新表test中id为1的记录
db2022=# update test set value = 11 where id = 1;UPDATE 1Time: 0.655 ms
5. 在 T2 中执行以下语句,更新表test中id为1的记录
db2022=# update test set value = 12 where id = 1;阻塞
6. 在 T1 中提交事务,T2 报错:
db2022=# update test set value = 12 where id = 1;ERROR: could not serialize access due to concurrent updateTime: 11860.582 ms
7. 在 T2 中撤销事务
repeatable read 隔离级别可以避免 Read Skew 异常(1)
8. 在 T1 中执行以下语句,重置测试数据表
在 T1 2 中执行以下语句,设置当前会话的事务隔离级别
db2022=# drop table test;DROP TABLETime: 145.764 msdb2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLETime: 212.357 msdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2Time: 66.831 msdb2022=# begin;BEGINTime: 0.228 msdb2022=# set transaction isolation level repeatable read;SETTime: 0.388 ms
1. 在 T1 中执行以下语句,查询表test中id为1的记录
db2022=# select * from test where id = 1;id | value----+-------1 | 10(1 row)Time: 0.577 ms
2. 在 T2 中执行以下语句,查询并更新表test中的记录,然后提交事务
db2022=# select * from test where id = 1; --返回(1,10)id | value----+-------1 | 10(1 row)Time: 0.814 msdb2022=# select * from test where id = 2; --返回(2,20)id | value----+-------2 | 20(1 row)Time: 0.472 msdb2022=# update test set value = 12 where id = 1;UPDATE 1Time: 0.553 msdb2022=# update test set value = 18 where id = 2;UPDATE 1Time: 0.493 msdb2022=# commit;COMMITTime: 33.217 ms
3. 在 T1 中执行以下语句,查询表test中id为2的记录
db2022=# select * from test where id = 2; --返回(2,20)id | value----+-------2 | 20(1 row)Time: 0.646 msdb2022=# commit;COMMITTime: 0.552 ms
T1 的两次读均没有被 T2 影响,即可重复读。
repeatable read 隔离级别可以避免 Read Skew 异常(2)
4. 在 T1 中执行以下语句,重置测试数据表
在 T1 2 中执行以下语句,设置当前会话的事务隔离级别
db2022=# drop table test;DROP TABLETime: 143.054 msdb2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLETime: 251.579 msdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2Time: 66.175 msdb2022=# begin;BEGINTime: 0.247 msdb2022=# set transaction isolation level repeatable read;SETTime: 0.342 ms
7. 在 T1 中执行以下语句,查询表test中的记录
db2022=# select * from test where value % 5 = 0;id | value----+-------1 | 102 | 20(2 rows)Time: 0.722 ms
8. 在 T2 中执行以下语句,更新表test中的记录,然后提交事务
db2022=# update test set value = 12 where value = 10;UPDATE 1Time: 0.882 msdb2022=# commit;COMMITTime: 52.269 ms
9. 在 T1 中执行以下语句,查询表test中的记录
db2022=# select * from test where value % 3 = 0; --返回空集id | value----+-------(0 rows)Time: 0.685 msdb2022=# commit;COMMITTime: 0.452 ms
两次结果依旧一致,即可重复读。
repeatable read 隔离级别可以避免 Read Skew 异常(3)
10. 在 T1 中重置测试数据表
在 T1 2 中设置当前会话的事务隔离级别
3. 在 T1 中执行以下语句,查询表test中id为1的记录
db2022=# select * from test where id = 1;id | value----+-------1 | 10(1 row)Time: 0.734 ms
4. 在 T2 中执行以下语句,查询并更新表test中的记录,然后提交事务
db2022=# select * from test; --返回(1,10),(2,20)id | value----+-------1 | 102 | 20(2 rows)Time: 0.733 msdb2022=# update test set value = 12 where id = 1;UPDATE 1Time: 0.530 msdb2022=# update test set value = 18 where id = 2;UPDATE 1Time: 0.581 msdb2022=# commit;COMMITTime: 36.597 ms
5. 在 T1 中执行以下语句,删除表test中value为20的记录
db2022=# delete from test where value = 20;ERROR: could not serialize access due to concurrent updateTime: 3.319 msdb2022=# abort;ROLLBACKTime: 0.259 ms
repeatable read 隔离级别不能避免 Write Skew 异常
6. 在 T1 中重置测试数据表
在 T1 2 中设置当前会话的事务隔离级别
9. 在 T1 中执行以下语句,查询表test中的记录
db2022=# select * from test where id in (1,2);id | value----+-------1 | 102 | 20(2 rows)Time: 1.076 ms
10. 在 T2 中执行以下语句,查询表test中的记录
db2022=# select * from test where id in (1,2);id | value----+-------1 | 102 | 20(2 rows)Time: 1.131 ms
1. 在 T1 中执行以下语句,更新表test中id为1的记录
db2022=# update test set value = 11 where id = 1;UPDATE 1Time: 0.735 ms
2. 在 T2 中执行以下语句,更新表test中id为2的记录
db2022=# update test set value = 21 where id = 2;UPDATE 1Time: 0.526 ms
3. 在 T1 2 中执行以下语句,提交事务
db2022=# commit;COMMITTime: 116.664 msdb2022=# select * from test;id | value----+-------1 | 112 | 21(2 rows)Time: 0.619 ms
T1 T2 均没注意到对方的修改,并分别作出了(不相交但可能重复的)修改。
repeatable read 隔离级别不能避免 Anti-Dependency Cycles 异常
5. 在 T1 中执行以下语句,重置测试数据表
在 T1 2 中执行以下语句,设置当前会话的事务隔离级别
8. 在 T1 中执行以下语句,查询表test中的记录
db2022=# select * from test where value % 3 = 0;id | value----+-------(0 rows)Time: 0.786 ms
9. 在 T2 中执行以下语句,查询表test中的记录
db2022=# select * from test where value % 3 = 0;id | value----+-------(0 rows)Time: 0.914 ms
10. 在 T1 中执行以下语句,向表test中插入新记录
db2022=# insert into test (id, value) values(3, 30);INSERT 0 1Time: 0.818 ms
1. 在 T2 中执行以下语句,向表test中插入新记录
db2022=# insert into test (id, value) values(4, 42);INSERT 0 1Time: 0.467 ms
2. 在 T1 2 中提交事务
4. 在 T1 或 T2 中执行以下语句
db2022=# select * from test where value % 3 = 0;id | value----+-------3 | 304 | 42(2 rows)Time: 0.689 ms
类似写偏斜。
serializable 隔离级别不能避免 Write Skew 异常
5. 在 T1 中执行以下语句,重置测试数据表
在 T1 2 中执行以下语句,设置当前会话的事务隔离级别
db2022=# drop table test;DROP TABLETime: 142.564 msdb2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLETime: 223.745 msdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2Time: 366.140 msdb2022=# begin;BEGINTime: 0.344 msdb2022=# set transaction isolation level serializable;SETTime: 0.381 ms
8. 在 T1 中执行以下语句,查询表test中的记录
db2022=# select * from test where id in (1,2);id | value----+-------1 | 102 | 20(2 rows)Time: 0.769 ms
9. 在 T2 中执行以下语句,查询表test中的记录
db2022=# select * from test where id in (1,2);id | value----+-------1 | 102 | 20(2 rows)Time: 0.849 ms
10. 在 T1 中执行以下语句,更新表test中id为1的记录
db2022=# update test set value = 11 where id = 1;UPDATE 1Time: 0.760 ms
1. 在 T2 中执行以下语句,更新表test中id为2的记录
db2022=# update test set value = 21 where id = 2;UPDATE 1Time: 0.536 ms
2. 在 T1 2 中执行以下语句,提交事务
db2022=# commit;COMMITTime: 116.416 msdb2022=# select * from test;id | value----+-------1 | 112 | 21(2 rows)Time: 0.568 ms
openGauss的serializable等价于repeatable read,不能避免写偏斜。
在新版本的PostgreSQL中,serializable可以避免Write Skew(报错"ERROR: could not serialize access due to read/write dependencies among transactions")。
serializable 隔离级别不能避免 Anti-Dependency Cycles 异常
4. 在 T1 中执行以下语句,重置测试数据表
在 T1 2 中执行以下语句,设置当前会话的事务隔离级别
7. 在 T1 中执行以下语句,查询表test中的记录
db2022=# select * from test where value % 3 = 0;id | value----+-------(0 rows)Time: 0.908 ms
8. 在 T2 中执行以下语句,查询表test中的记录
db2022=# select * from test where value % 3 = 0;id | value----+-------(0 rows)Time: 0.631 ms
9. 在 T1 中执行以下语句,向表test中插入新记录
db2022=# insert into test (id, value) values(3, 30);INSERT 0 1Time: 0.519 ms
10. 在 T2 中执行以下语句,向表test中插入新记录
db2022=# insert into test (id, value) values(4, 42);INSERT 0 1Time: 0.781 ms
1. 在 T1 2 中执行以下语句,提交事务
db2022=# commit;COMMITTime: 108.364 msdb2022=# select * from test;id | value----+-------1 | 102 | 203 | 304 | 42(4 rows)Time: 0.833 ms
openGauss的serializable等价于repeatable read。
在新版本的PostgreSQL中,serializable可以避免Anti-Dependency Cycles(报错"ERROR: could not serialize access due to read/write dependencies among transactions")。
1. 在 T1 中执行以下语句,创建数据表test
db2022=# drop table if exists test;DROP TABLETime: 146.183 msdb2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLETime: 186.755 ms
2. 在 T1 中执行以下语句,查询当前事务ID,然后插入数据
db2022=# begin;BEGINTime: 0.487 msdb2022=# select txid_current();txid_current--------------14727(1 row)Time: 119.613 msdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2Time: 1.225 msdb2022=# insert into test (id, value) values (3, 30), (4, 40);INSERT 0 2Time: 0.565 ms
3. 在 T1 中执行以下语句,查询表test中的记录(包含隐藏字段)
db2022=# select xmin, xmax, ctid, cmin, cmax, * from test;xmin | xmax | ctid | cmin | cmax | id | value-------+------+-------+------+------+----+-------14727 | 0 | (0,1) | 0 | 0 | 1 | 1014727 | 0 | (0,2) | 0 | 0 | 2 | 2014727 | 0 | (0,3) | 1 | 1 | 3 | 3014727 | 0 | (0,4) | 1 | 1 | 4 | 40(4 rows)Time: 0.924 ms
4. 在 T1 中执行以下语句,更新数据后查询表test中的记录(包含隐藏字段)
db2022=# update test set value = 11 where id = 1;UPDATE 1Time: 0.719 msdb2022=# delete from test where id = 4;DELETE 1Time: 0.468 msdb2022=# select xmin, xmax, ctid, cmin, cmax, * from test;xmin | xmax | ctid | cmin | cmax | id | value-------+------+-------+------+------+----+-------14727 | 0 | (0,2) | 0 | 0 | 2 | 2014727 | 0 | (0,3) | 1 | 1 | 3 | 3014727 | 0 | (0,5) | 2 | 2 | 1 | 11(3 rows)Time: 0.879 msdb2022=# commit;COMMITTime: 27.930 ms
ctid 为插入这条记录的 cid。
5. 在 T1 中执行以下语句,更新数据后查询表test中的记录(包含隐藏字段)
db2022=# begin;BEGINTime: 0.308 msdb2022=# select txid_current();txid_current--------------14728(1 row)Time: 0.444 msdb2022=# update test set value = 21 where id = 2;UPDATE 1Time: 0.578 msdb2022=# delete from test where id = 3;DELETE 1Time: 0.497 msdb2022=# update test set value = 22 where id = 2;UPDATE 1Time: 0.543 msdb2022=# select xmin, xmax, ctid, cmin, cmax, * from test;xmin | xmax | ctid | cmin | cmax | id | value-------+------+-------+------+------+----+-------14727 | 0 | (0,5) | 2 | 2 | 1 | 1114728 | 0 | (0,7) | 2 | 2 | 2 | 22(2 rows)Time: 0.649 msdb2022=# abort;ROLLBACKTime: 0.424 msdb2022=# select xmin, xmax, ctid, cmin, cmax, * from test;xmin | xmax | ctid | cmin | cmax | id | value-------+-------+-------+------+------+----+-------14727 | 14728 | (0,2) | 0 | 0 | 2 | 2014727 | 14728 | (0,3) | 1 | 1 | 3 | 3014727 | 0 | (0,5) | 2 | 2 | 1 | 11(3 rows)Time: 0.678 ms
即使abort,xmax还是相应更新了?
1. 在 T1 中执行以下语句,创建数据表test并插入数据
db2022=# drop table if exists test;DROP TABLETime: 151.743 msdb2022=# create table test (id int primary key, value int);NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"CREATE TABLETime: 240.563 msdb2022=# insert into test (id, value) values (1, 10), (2, 20);INSERT 0 2Time: 131.728 ms
2. 在 T1 中执行以下语句,设置事务隔离级别,查询事务ID和快照
db2022=# begin;BEGINTime: 0.344 msdb2022=# set transaction isolation level read committed;SETTime: 0.302 msdb2022=# select txid_current(),txid_current_snapshot(), xmin, xmax, ctid, cmin, cmax, * from test;txid_current | txid_current_snapshot | xmin | xmax | ctid | cmin | cmax | id | value--------------+-----------------------+-------+------+-------+------+------+----+-------14734 | 14734:14734: | 14733 | 0 | (0,1) | 0 | 0 | 1 | 1014734 | 14734:14734: | 14733 | 0 | (0,2) | 0 | 0 | 2 | 20(2 rows)Time: 0.966 ms
在 T2 中执行以下语句,设置事务隔离级别,查询事务ID和快照
db2022=# begin;BEGINTime: 0.318 msdb2022=# set transaction isolation level read committed;SETTime: 0.289 msdb2022=# select txid_current(),txid_current_snapshot(), xmin, xmax, ctid, cmin, cmax, * from test;txid_current | txid_current_snapshot | xmin | xmax | ctid | cmin | cmax | id | value--------------+-----------------------+-------+------+-------+------+------+----+-------14735 | 14734:14734: | 14733 | 0 | (0,1) | 0 | 0 | 1 | 1014735 | 14734:14734: | 14733 | 0 | (0,2) | 0 | 0 | 2 | 20(2 rows)Time: 0.997 ms
3. 在 T3 中执行以下语句,设置事务隔离级别,查询事务ID和快照
db2022=# begin;BEGINdb2022=# set transaction isolation level repeatable read;SETdb2022=# select txid_current(),txid_current_snapshot(), xmin, xmax, ctid, cmin, cmax, * from test;txid_current | txid_current_snapshot | xmin | xmax | ctid | cmin | cmax | id | value--------------+-----------------------+-------+------+-------+------+------+----+-------14736 | 14734:14734: | 14733 | 0 | (0,1) | 0 | 0 | 1 | 1014736 | 14734:14734: | 14733 | 0 | (0,2) | 0 | 0 | 2 | 20(2 rows)
4. 在 T1 中提交事务
5. 在 T2 中执行以下语句,查询事务ID和快照
db2022=# select txid_current(),txid_current_snapshot(), xmin, xmax, ctid, cmin, cmax, * from test;txid_current | txid_current_snapshot | xmin | xmax | ctid | cmin | cmax | id | value--------------+-----------------------+-------+------+-------+------+------+----+-------14735 | 14735:14735: | 14733 | 0 | (0,1) | 0 | 0 | 1 | 1014735 | 14735:14735: | 14733 | 0 | (0,2) | 0 | 0 | 2 | 20(2 rows)Time: 0.877 ms
6. 在 T3 中执行以下语句,查询事务ID和快照
db2022=# select txid_current(),txid_current_snapshot(), xmin, xmax, ctid, cmin, cmax, * from test;txid_current | txid_current_snapshot | xmin | xmax | ctid | cmin | cmax | id | value--------------+-----------------------+-------+------+-------+------+------+----+-------14736 | 14734:14734: | 14733 | 0 | (0,1) | 0 | 0 | 1 | 1014736 | 14734:14734: | 14733 | 0 | (0,2) | 0 | 0 | 2 | 20(2 rows)
说明:提交读每条语句都获取快照,可重复读只在获得txid时生成快照