diff --git "a/content/zh/post/liuxu/checkpoint-segments\351\273\230\350\256\244\345\200\274\350\277\207\345\244\247\346\225\205\351\232\234\345\244\204\347\220\206.md" "b/content/zh/post/liuxu/checkpoint-segments\351\273\230\350\256\244\345\200\274\350\277\207\345\244\247\346\225\205\351\232\234\345\244\204\347\220\206.md" new file mode 100644 index 0000000000000000000000000000000000000000..33659a1c39ff748c34b3095c74e11ea3bfffc615 --- /dev/null +++ "b/content/zh/post/liuxu/checkpoint-segments\351\273\230\350\256\244\345\200\274\350\277\207\345\244\247\346\225\205\351\232\234\345\244\204\347\220\206.md" @@ -0,0 +1,136 @@ ++++ + +title = "checkpoint\_segments默认值过大故障处理" + +date = "2020-12-16" + +tags = ["openGauss故障处理"] + +archives = "2020-12" + +author = "刘旭" + +summary = "checkpoint\_segments默认值过大故障处理" + +img = "/zh/post/liuxu/title/title.png" + +times = "15:30" + ++++ + +# checkpoint\_segments默认值过大故障处理 + +## 适用版本 + +openGauss 1.0.1 build或更早的版本。 + +## 故障现象 + +在非归档模式、没有打开流了复制槽时,例如: + +``` +postgres=# show archive_mode; + archive_mode +-------------- + off +(1 row) +postgres-# select * from pg_replication_slots; + pg_xlog_location_diff | slot_name | plugin | slot_type | datoid | database | active | xmin | catalog_xmin | restart_lsn | dummy_standby +-----------------------+-----------+--------+-----------+--------+----------+--------+------+--------------+-------------+--------------- +(0 rows) +``` + +openGauss所产生的WAL日志会在pg\_xlog目录下无限增长。 + +1.检查和WAL日志相关的参数。 + +``` +postgres=# show checkpoint_segments; + checkpoint_segments +--------------------- + 64 +(1 row) +postgres=# show checkpoint_completion_target; + checkpoint_completion_target +------------------------------ + 0.5 +(1 row) +postgres=# show wal_keep_segments; + wal_keep_segments +------------------- + 16(1 row) +``` + +- WAL日志文件: + + openGauss将WAL日志记录写入存储在pg\_xlog子目录中的WAL段文件之一中,如果旧文件已被填充,则切换为新文件。WAL文件的数量将根据以下几个配置参数以及服务器活动而变化。 + + +- WAL日志文件的数量主要由以下三个参数控制: + + checkpoint\_segments,checkpoint\_completion\_target和wal\_keep\_segments。 + + 其数量通常大于 以下两种情形下会自动清理: + + - (2+checkpoint\_completion\_target)×checkpoint\_segments+1 + - checkpoint\_segments+wal\_keep\_segments+1 + + +2.当对数据库起启1000个(包含insert)并发持续一段时间之后,pg\_xlog中日志文件会无限增多。 + +``` +--并发的SQL: +begin; +select /*1*/c4,c8,c2,c3,c9,c1,c12 from gaussdb.T1 where c1 ='536e32a24bd6add28b7b2b0afa2dc071'; +update /*2*/gaussdb.T1 set c8 = 1 where c1 = (select c1 from (select c1 from gaussdb.t1 where c1>'ABCDEFHIJKG' limit 600) order by random() limit 1); +insert /*3*/into gaussdb.T5 select TO_HEX((random()*(2*10^9))::integer)|| TO_HEX((random()*(2*10^9))::integer), rpad('*',4000,'*'),floor(random()*(2-0)+0),to_char(sysdate,'YYYYMMDDHH24Miss'); +select /*4*/ c1,c2 from gaussdb.T9 where c2 = '649b6f83dd7c09802a4db01bf6f60e09'; +select /*5*/ c3 from gaussdb.T4 where c2 = '936d8e56c15519f1311776e67afec6ad'; +insert /*11*/into gaussdb.T6 select TO_HEX((random()*(2*10^9))::integer)|| TO_HEX((random()*(2*10^9))::integer),rpad('*',4000,'*'),floor(random()*(2-0)+0) ,to_char(sysdate,'YYYYMMDDHH24Miss'); +select /*6*/ c2 from gaussdb.T3 where c1= '69c24b9556de148b798a0be38b12f214bf2f95495be47f76a4dce485d8259ca4'; +select /*7*/ c1,c4 from gaussdb.T8 where c7= '92a42e90cd73ad0ec5c51b57f20efb91'; +select /*8*/ c2,c3 from gaussdb.T5 where c1 = '69d26e7833f5da78afc944407d68d58b'; +select /*9*/c3,c4 from gaussdb.T4 where c1 = '577527b30a83d08ba4a95f2bf42add89b3ccc1fb0560e8e1a15f45dde8ff0879'; +insert /*10*/into gaussdb.T2 select TO_HEX((random()*(2*10^9))::integer)|| TO_HEX((random()*(2*10^9))::integer),md5(random()::text),md5(random()::text),md5(random()::text),TO_HEX((random()*(2*10^9))::integer)|| TO_HEX((random()*(2*10^9))::integer),floor(random()*(19999999999-10000000001)+10000000001) ,floor(random()*(2-0)+0),floor(random()*(3-1)+1),floor(random()*(3-1)+1) ,to_char(sysdate,'YYYYMMDD'),floor(random()*(3-1)+1) ,to_char(sysdate,'YYYYMMDDHH24Miss'),to_char(sysdate,'YYYYMMDDHH24Miss') ; +end; + +--查看pg_xlog目录及文件个数 +[root@bms-f408-0001 dn1]# du -sm * | sort -nr|head +31360 pg_xlog +1173 base +418 pg_location +[omm@bms-f408-0001 ~]$ cd /opt/data/cluster/dn1/pg_xlog +[omm@bms-f408-0001 pg_xlog]$ ls -lR|grep "^-"|wc -l +1960 +``` + +## 故障原因 + +引用原文: + +In version 9.4(Postgre) or earlier, the parameter _checkpoint\_segments_ is a pain in the neck. If it is set at a small number, checkpoint occurs frequently, which causes a decrease in performance, whereas if set at a large number, the huge disk space is always required for the WAL files, some of which is not always necessary. + +简单描述: + +当前数据库如果使用或者基于内核开发(Postgre9.4或者更早的版本),checkpoint\_segments =64的默认值会使得数据库在pg\_xlog目录中无限生成WAL日志文件,从而会引发空间不足的问题。 + +## 解决方案 + +1. 在线修改checkpoint\_segments的默认参数(64)到更小\(16、8、4都可以\)。例如:alter system set to checkpoint\_segments = 8 ; +2. 或修改当前版本中checkpoint\_segments的默认值到更小(16、8、4)。 +3. 或使用或者基于内核开发(Postgre9.5的版本)。 + +- Write Ahead Logging — WAL概述: + +在计算机科学领域,WAL是Write Ahead Logging的首字母缩写,它是将更改和操作都写入事务日志的协议或规则。而在openGauss数据库中,WAL是Write Ahead Log的首字母缩写也是用作事务日志的同义词,用于写入事务日志(WAL)有关的已实现机制。可以理解为oracle数据库中的redolog。 + +- 关于WAL Segment: + +默认情况下,WAL Segment是一个16 MB的文件,它在内部分成8192字节(8 KB)的页面。第一页具有由结构XLogLongPageHeaderData定义的标头数据,而所有其他页的标题具有由结构XLogPageHeaderData定义的页信息。在页面标题之后,XLOG记录从头开始按降序写入每个页面。图例如下: + + + +- WAL Segment文件管理 + +openGauss将XLOG记录写入存储在pg\_xlog子目录中,如果旧文件已被填充,则切换为新文件。WAL文件的数量将根据几个配置参数以及服务器活动而变化。WALSegment文件的数量主要由以下三个参数控制:checkpoint\_segments,checkpoint\_completion\_target和wal\_keep\_segments。 + diff --git a/content/zh/post/liuxu/figures/11.png b/content/zh/post/liuxu/figures/11.png new file mode 100644 index 0000000000000000000000000000000000000000..d50f42be3ef89d53af941f4dbcb451213223e3d0 Binary files /dev/null and b/content/zh/post/liuxu/figures/11.png differ diff --git a/content/zh/post/liuxu/figures/22.png b/content/zh/post/liuxu/figures/22.png new file mode 100644 index 0000000000000000000000000000000000000000..832ab5c99a206768d26b757afdce2b81e62ed384 Binary files /dev/null and b/content/zh/post/liuxu/figures/22.png differ diff --git "a/content/zh/post/liuxu/openGauss\345\206\205\345\255\230\344\274\230\345\214\226\350\241\250\346\234\200\344\275\263\345\256\236\350\267\265.md" "b/content/zh/post/liuxu/openGauss\345\206\205\345\255\230\344\274\230\345\214\226\350\241\250\346\234\200\344\275\263\345\256\236\350\267\265.md" new file mode 100644 index 0000000000000000000000000000000000000000..51b3c314c0b369d89e72017c6e5d03ede9efbc7d --- /dev/null +++ "b/content/zh/post/liuxu/openGauss\345\206\205\345\255\230\344\274\230\345\214\226\350\241\250\346\234\200\344\275\263\345\256\236\350\267\265.md" @@ -0,0 +1,811 @@ ++++ + +title = "openGauss内存优化表最佳实践" + +date = "2020-12-17" + +tags = ["openGauss最佳实践"] + +archives = "2020-12" + +author = "刘旭" + +summary = "openGauss内存优化表最佳实践" + +img = "/zh/post/liuxu/title/title.png" + +times = "18:30" + ++++ + +# openGauss内存优化表最佳实践 + +## 适用版本 + +openGauss 1.0.1 build和更高版本。 + +## 用途 + +概述MOT(内存优化表)的特性,如何在openGauss数据库中创建和使用MOT。 + +## MOT概述 + +openGauss引入了MOT存储引擎,它是一种事务性行存储,针对多核和大内存服务器进行了优化。MOT是openGauss数据库最先进的生产级特性(Beta版本),它为事务性工作负载提供更高的性能。MOT完全支持ACID特性,并包括严格的持久性和高可用性支持。企业可以在关键任务、性能敏感的在线事务处理(OLTP)中使用MOT,以实现高性能、高吞吐、可预测低延迟以及多核服务器的高利用率。 + + + +**使用MOT** + +1. 授予用户权限 + + ``` + postgres=# select usename,usesysid from pg_user; + usename | usesysid + ---------+---------- + omm | 10 + (1 row) + 要使omm用户能够创建和访问MOT(DDL、DML、SELECT),以下语句只执行一次 + GRANT USAGE ON FOREIGN SERVER mot_server TO omm; + ``` + +2. 创建/删除MOT + + 检查参数 + + ``` + postgres=# show enable_incremental_checkpoint; + enable_incremental_checkpoint + ------------------------------ + on + ``` + + 如果enable\_incremental\_checkpoint显示为on,则修改为off,并重启数据库 + + ``` + alter system set enable_incremental_checkpoint='off'; + gs_om -t stop + gs_om -t start + postgres=# show enable_incremental_checkpoint; + enable_incremental_checkpoint + ------------------------------- + off + (1 row) + ``` + + 创建MOT表mot\_1,并创建索引 + + ``` + postgres=# create FOREIGN table mot_1 + postgres-# (o_w_id integer not null, + postgres(# o_d_id integer not null, + postgres(# o_id integer not null, + postgres(# o_c_id integer not null, + postgres(# o_carrier_id integer, + postgres(# o_ol_cnt integer, + postgres(# o_all_local integer, + postgres(# o_entry_d timestamp, + postgres(# primary key (o_w_id, o_d_id, o_id)); + NOTICE: CREATE FOREIGN TABLE / PRIMARY KEY will create constraint "mot_1_pkey" for foreign table "mot_1" + CREATE FOREIGN TABLE + + postgres=# create index mot_1_index1 on mot_1(o_w_id, o_d_id, o_c_id, o_id) ; + CREATE INDEX + ``` + + 插入200000随机数据。 + + ``` + postgres=# insert into mot_1 select ceil(random()*(10000-1)+1),ceil(random()*(10000-10)+10),ceil(random()*(10000-100)+100),ceil(random()*(10000-1)+1),ceil(random()*(1000-1)+1),ceil(random()*(1000-1)+1),ceil(random()*(1000-1)+1),sysdate + postgres-# FROM generate_series(1,200000); + INSERT 0 200000 + Time: 4202.304 ms + ``` + + 通过执行计划查看MOT表 + + 说明:执行计划中-\>Memory Engine表示从内存中获取数据 + + ``` + postgres=# explain select * from mot_1; + QUERY PLAN + ------------------------------------------------------------------- + Foreign Scan on mot_1 (cost=0.10..20000.00 rows=200000 width=36) + -> Memory Engine returned rows: 0 + (2 rows) + ``` + + select所有列数据不包含where条件 + + ``` + postgres=# select * from mot_1 limit 5; + o_w_id | o_d_id | o_id | o_c_id | o_carrier_id | o_ol_cnt | o_all_local | o_entry_d + --------+--------+------+--------+--------------+----------+-------------+--------------------- + 2 | 291 | 8858 | 4033 | 274 | 681 | 655 | 2020-11-26 11:03:34 + 2 | 962 | 7972 | 1996 | 684 | 646 | 399 | 2020-11-26 11:03:34 + 2 | 1750 | 1415 | 1597 | 758 | 508 | 163 | 2020-11-26 11:03:34 + 2 | 2315 | 2449 | 1049 | 418 | 585 | 61 | 2020-11-26 11:03:34 + 2 | 2444 | 4531 | 274 | 461 | 120 | 503 | 2020-11-26 11:03:34 + (5 rows) + ``` + + select所有列数据包含索引列 + + _说明:内存表可以通过索引访问数据__ Index Scan on: mot\_1\_pkey1_ + + ``` + postgres=# explain select * from mot_1 where o_w_id = 2 limit 4; + QUERY PLAN + -------------------------------------------------------------------- + Limit (cost=0.00..4.00 rows=4 width=36) + -> Foreign Scan on mot_1 (cost=0.00..211.00 rows=211 width=36) + -> Memory Engine returned rows: 0 + -> Index Scan on: mot_1_pkey1 + Index Cond: (mot_1.o_w_id = 2) + + postgres=# select * from mot_1 where o_w_id = 2 limit 4; + o_w_id | o_d_id | o_id | o_c_id | o_carrier_id | o_ol_cnt | o_all_local | o_entry_d + --------+--------+------+--------+--------------+----------+-------------+--------------------- + 2 | 291 | 8858 | 4033 | 274 | 681 | 655 | 2020-11-26 11:03:34 + 2 | 962 | 7972 | 1996 | 684 | 646 | 399 | 2020-11-26 11:03:34 + 2 | 1750 | 1415 | 1597 | 758 | 508 | 163 | 2020-11-26 11:03:34 + 2 | 2315 | 2449 | 1049 | 418 | 585 | 61 | 2020-11-26 11:03:34 + ``` + + 两张表关联查询 + + 新建MOT表mot\_2 + + ``` + postgres=# create FOREIGN table mot_2 + postgres-# (o_w_id integer not null, + postgres(# o_d_id integer not null, + postgres(# o_id integer not null); + CREATE FOREIGN TABLE + Time: 3.359 ms + ``` + + 查看执行计划(mot\_2表无索引),通过Hash Join的方式做表关联 + + ``` + postgres=# explain select a.o_w_id,b.o_id from mot_2 a,mot_1 b where a.o_w_id = b.o_w_id; + QUERY PLAN + -------------------------------------------------------------------------------- + Hash Join (cost=11250.10..1156750.00 rows=500 width=8) + Hash Cond: (b.o_w_id = a.o_w_id) + -> Foreign Scan on mot_1 b (cost=0.10..20000.00 rows=200000 width=8) + -> Memory Engine returned rows: 0 + -> Hash (cost=10000.00..10000.00 rows=100000 width=4) + -> Foreign Scan on mot_2 a (cost=0.10..10000.00 rows=100000 width=4) + -> Memory Engine returned rows: 0 + (7 rows) + ``` + + 查看执行计划(mot\_2有单列索引),通过访问索引Nested Loop的方式访问数据 + + ``` + postgres=# create index mot_2_index1 on mot_1(o_w_id) ; + CREATE INDEX + Time: 437.916 ms + + postgres=# explain select a.o_w_id,b.o_id from mot_2 a,mot_1 b where a.o_w_id = b.o_w_id; + QUERY PLAN + -------------------------------------------------------------------------- + Nested Loop (cost=0.10..111000.00 rows=500 width=8) + -> Foreign Scan on mot_2 a (cost=0.10..10000.00 rows=100000 width=4) + -> Memory Engine returned rows: 0 + -> Foreign Scan on mot_1 b (cost=0.00..1.00 rows=1 width=8) + Filter: (a.o_w_id = o_w_id) + -> Memory Engine returned rows: 0 + -> Index Scan on: mot_2_index1 + Index Cond: (b.o_w_id = $0) + (8 rows) + ``` + + update单表非索引字段 + + 将update o\_w\_id=2的非索引字段 + + ``` + postgres=# select count(*) from mot_1 where o_w_id=2; + count + ------- + 21 + (1 row) + ``` + + 已更新21条 + + ``` + postgres=# update mot_1 set o_all_local = 2020,o_ol_cnt=9090 where o_w_id=2; + UPDATE 21 + Time: 0.672 ms + ``` + + update单表索引字段 + + 将update o\_w\_id=2的索引字段 + + ``` + postgres=# select count(*) from mot_1 where o_w_id=2; + count + ------- + 21 + (1 row) + ``` + + 无法更新 + + ``` + postgres=# update mot_1 set o_w_id=2020 where o_w_id=2; + ERROR: Update of indexed column is not supported for memory table + Time: 0.302 ms + ``` + + update含有子查询 + + mot\_2 o\_w\_id = 2的数据\(2000条\) + + ``` + postgres=# select count(o_w_id) from mot_2; + count + ------- + 2000 + (1 row) + ``` + + 更新mot\_1中o\_w\_id in(select o\_w\_id from mot\_2 where o\_w\_id = 2)的数据 + + ``` + postgres=# update mot_1 set o_all_local = 2020,o_ol_cnt=9090 where o_w_id in (select o_w_id from mot_2 where o_w_id = 2); + UPDATE 21 + Time: 13.429 ms + ``` + + 查询mot\_1中o\_all\_local = 2020 and o\_ol\_cnt=9090的数据 + + ``` + postgres=# Select * from mot_1 where o_all_local = 2020 and o_ol_cnt=9090; + o_w_id | o_d_id | o_id | o_c_id | o_carrier_id | o_ol_cnt | o_all_local | o_entry_d + --------+--------+------+--------+--------------+----------+-------------+--------------------- + 2 | 291 | 8858 | 4033 | 274 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 962 | 7972 | 1996 | 684 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 1750 | 1415 | 1597 | 758 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 2315 | 2449 | 1049 | 418 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 2444 | 4531 | 274 | 461 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 2761 | 2627 | 7693 | 169 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 3300 | 3947 | 167 | 997 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 3921 | 424 | 4765 | 557 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 4216 | 2304 | 4065 | 829 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 5401 | 8904 | 8009 | 856 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 5416 | 9478 | 2939 | 959 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 5696 | 9749 | 7707 | 330 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 5935 | 2938 | 324 | 210 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 6680 | 4998 | 5906 | 439 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 6983 | 2343 | 18 | 87 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 7274 | 3141 | 6374 | 941 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 7292 | 6505 | 9174 | 989 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 7740 | 3702 | 8976 | 958 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 7828 | 7520 | 1161 | 387 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 8223 | 9573 | 7540 | 622 | 9090 | 2020 | 2020-11-26 11:03:34 + 2 | 8327 | 4427 | 8846 | 519 | 9090 | 2020 | 2020-11-26 11:03:34 + (21 rows) + + Time: 110.945 ms + ``` + + delete单表(删除o\_w\_id = 3的所有数据) + + ``` + postgres=# select count(*) from mot_1 where o_w_id = 3; + count + ------- + 26 + (1 row) + + postgres=# delete from mot_1 where o_w_id = 3; + DELETE 26 + postgres=# commit; + COMMIT + postgres=# select count(*) from mot_1 where o_w_id = 3; + count + ------- + 0 + (1 row) + ``` + + delete带有子查询(删除在mot\_2表中 o\_w\_id = 5的mot\_1表的所有数据) + + ``` + postgres=# delete from mot_1 where o_w_id in (select o_w_id from mot_2 where o_w_id = 5 ); + DELETE 15 + postgres=# commit; + COMMIT + ``` + + truncate操作(truncate mot\_2表) + + ``` + postgres=# truncate table mot_2; + TRUNCATE TABLE + ``` + + 事务的commit和rollback + + truncate(commit) + + 结论: + + 1、truncate操作可以rollback。 + + 2、当会话1执行truncate之后(没有commit),会话2对该表执行select操作处于等待状态。 + + 3、会话1执行commit或者rollback之后,其它会话可以正常dml操作。 + + 会话1 + + ``` + postgres=# truncate table mot_2; + TRUNCATE TABLE + postgres=# select count(*) from mot_2; + count + ------- + 0 + (1 row) + postgres=# commit; + COMMIT + postgres=# + ``` + + 会话2 + + ``` + postgres=# select * from mot_2; + 等待状态… + 等待会话1 commit之后 + postgres=# select * from mot_2; + o_w_id | o_d_id | o_id + --------+--------+------ + (0 rows) + ``` + + truncate(rollback) + + insert mot\_2表 2000条数据 + + ``` + postgres=# insert into mot_2 select ceil(random()*(10000-1)+1),ceil(random()*(10000-10)+10),ceil(random()*(10000-100)+100) FROM generate_series(1,2000); + + INSERT 0 2000 + postgres=# postgres=# commit; + COMMIT + postgres=# select count(*) from mot_2; + count + ------- + 2000 + (1 row) + ``` + + ``` + postgres=# truncate table mot_2; + TRUNCATE TABLE + postgres=# select count(*) from mot_2; + count + ------- + 0 + (1 row) + postgres=# rollback; + ROLLBACK + postgres=# select count(*) from mot_2; + count + ------- + 2000 + (1 row) + ``` + + update\(commit和rollback\) + + 结论: + + 1、会话1做update操作(commit之前),会话2依然可以对同一批数据做出不同的更改,不会出现悲观锁等待。 + + 2、最终的数据以最先commit的操作为准。 + + 会话1 + + ``` + select * from mot_2 where o_w_id = 5573; + postgres=# select * from mot_2 where o_w_id = 5573; + o_w_id | o_d_id | o_id + --------+--------+------ + 5573 | 8453 | 7777 + 5573 | 2162 | 7777 + (2 rows) + ``` + + 会话2 + + ``` + select * from mot_2 where o_w_id = 5573; + postgres=# select * from mot_2 where o_w_id = 5573; + o_w_id | o_d_id | o_id + --------+--------+------ + 5573 | 8453 | 7777 + 5573 | 2162 | 7777 + (2 rows) + ``` + + 会话1 + + ``` + postgres=# update mot_2 set o_id = 9999 where o_w_id = 5573; + UPDATE 2 + ``` + + 会话2 + + ``` + postgres=# update mot_2 set o_id = 3333 where o_w_id = 5573; + UPDATE 2 + ``` + + --在会话1没有commit或者rolllback时,会话2可以修改同一批数据,修改成功 + + 会话1 --看到的是当前会话已修改o\_id=9999的数据 + + ``` + select * from mot_2 where o_w_id = 5573; + postgres=# select * from mot_2 where o_w_id = 5573; + o_w_id | o_d_id | o_id + --------+--------+------ + 5573 | 8453 | 9999 + 5573 | 2162 | 9999 + (2 rows) + ``` + + 会话2 --看到的是当前会话已修改o\_id=3333的数据 + + ``` + postgres=# select * from mot_2 where o_w_id = 5573; + o_w_id | o_d_id | o_id + --------+--------+------ + 5573 | 8453 | 3333 + 5573 | 2162 | 3333 + (2 rows) + ``` + + 会话1 --先提交 + + ``` + postgres=# commit; + COMMIT + postgres=# select * from mot_2 where o_w_id = 5573; + o_w_id | o_d_id | o_id + --------+--------+------ + 5573 | 8453 | 9999 + 5573 | 2162 | 9999 + (2 rows) + ``` + + 会话2 --不提交,查询依然o\_id=3333的数据 + + ``` + postgres=# select * from mot_2 where o_w_id = 5573; + o_w_id | o_d_id | o_id + --------+--------+------ + 5573 | 8453 | 3333 + 5573 | 2162 | 3333 + (2 rows) + ``` + + 会话2 --后提交 + + ``` + postgres=# commit; + WARNING: AbortTransaction while in COMMIT state + ERROR: Commit: could not serialize access due to concurrent update(0) + postgres=# select * from mot_2 where o_w_id = 5573; + o_w_id | o_d_id | o_id + --------+--------+------ + 5573 | 8453 | 9999 + 5573 | 2162 | 9999 + (2 rows) + ``` + + insert\(commit和rollback\) + + 结论: + + 1、会话1做insert操作(commit之前),会话1可以查看新插入的数据,会话2无法查看到新插入的数据。 + + 2、等会话1做了commit之后,会话2可以看见新插入的数据。 + + 会话1 + + ``` + postgres=# \set AUTOCOMMIT off + postgres=# select count(*) from mot_2; + count + ------- + 2000 + (1 row) + postgres=# insert into mot_2 select ceil(random()*(10000-1)+1),ceil(random()*(10000-10)+10),ceil(random()*(10000-100)+100) FROM generate_series(1,2000); + INSERT 0 2000 + postgres=# postgres=# select count(*) from mot_2; + count + ------- + 4000 + (1 row) + postgres=# commit; + COMMIT + ``` + + 会话2 + + ``` + postgres=# \set AUTOCOMMIT off + postgres=# select count(*) from mot_2; + count + ------- + 2000 + (1 row) + + postgres=# select count(*) from mot_2; + count + ------- + 4000 + (1 row) + ``` + + update\(commit和rollback\) + + 结论:和insert原理相同 + + 会话1 + + ``` + postgres=# select count(*) from mot_1 where o_w_id=2; + count + ------- + 21 + (1 row) + + postgres=# + postgres=# update mot_1 set o_all_local = 5555 where o_w_id=2; + UPDATE 21 + postgres=# select count(*) from mot_1 where o_w_id=2 and o_all_local =5555; + count + ------- + 21 + (1 row) + + postgres=# commit; + COMMIT + ``` + + 会话2 + + ``` + postgres=# select count(*) from mot_1 where o_w_id=2 and o_all_local =5555; + count + ------- + 0 + (1 row) + + postgres=# select count(*) from mot_1 where o_w_id=2 and o_all_local =5555; + count + ------- + 21 + (1 row) + ``` + + 数据库stop、start之后MOT表的数据是否存在。 + + 结论:数据库MOT表的数据依然存在 + + ``` + postgres=# select count(*) from mot_1; + count + -------- + 199959 + (1 row) + postgres=# select count(*) from mot_2; + count + ------- + 4000 + (1 row) + postgres-# \q + [omm@bms-f408-0001 ~]$ gs_om -t stop + Stopping cluster. + ========================================= + Successfully stopped cluster. + ========================================= + End stop cluster. + [omm@bms-f408-0001 ~]$ gs_om -t start + Starting cluster. + ========================================= + ========================================= + Successfully started. + [omm@bms-f408-0001 ~]$ gsql -d postgres -p26000 + gsql ((openGauss 1.0.1 build 3a33fded) compiled at 2020-11-04 15:58:51 commit 0 last mr ) + Non-SSL connection (SSL connection is recommended when requiring high-security) + Type "help" for help. + + postgres=# select count(*) from mot_1; + count + -------- + 199959 + (1 row) + + postgres=# select count(*) from mot_2; + count + ------- + 4000 + (1 row) + ``` + + 通过create table as 从实体表创建MOT表。 + + 结论:不支持 + + ``` + postgres=# create table tbl_1(aid integer not null,bid integer); + CREATE TABLE + postgres=# insert into tbl_1 values(1001,9001); + INSERT 0 1 + postgres=# create FOREIGN table mot_from_tbl_1 as select * from tbl_1; + ERROR: syntax error at or near "as" + LINE 1: create FOREIGN table mot_from_tbl_1 as select * from tbl_1; + ^ + postgres=# create table tbl_2 as select * from tbl_1; + ``` + + 通过create forrign table as 从MOT表创建MOT表 + + 结论:不支持 + + ``` + postgres=# create FOREIGN table mot_3 as select * from mot_2; + ERROR: syntax error at or near "as" + LINE 1: create FOREIGN table mot_3 as select * from mot_2; + ^ + postgres=# create FOREIGN table mot_3 select * from mot_2; + ERROR: syntax error at or near "select" + LINE 1: create FOREIGN table mot_3 select * from mot_2; + ``` + + MOT表相互通过insert into select的方式插入数据。 + + 结论:支持 + + ``` + postgres=# create FOREIGN table mot_3 + postgres-# (o_w_id integer not null, + postgres(# o_d_id integer not null, + postgres(# o_id integer not null); + CREATE FOREIGN TABLE + postgres=# insert into mot_3 select * from mot_2; + INSERT 0 4000 + postgres=# commit; + ``` + + 通过insert into select 的方式从普通表向MOT表插入数据。 + + 结论:不支持 + + ``` + postgres=# create table tbl_1(aid integer not null,bid integer); + ERROR: relation "tbl_1" already exists + postgres=# insert into tbl_1 values(1001,9001); + INSERT 0 1 + postgres=# create FOREIGN table mot_tbl_1(aid integer not null,bid integer); + CREATE FOREIGN TABLE + postgres=# select count(*) from mot_tbl_1; + count + ------- + 0 + (1 row) + + postgres=# insert into mot_tbl_1 select * from tbl_1; + ERROR: Cross storage engine query is not supported + ``` + + openGauss MOT和其它数据库相关特性对比 + + +
+ | ++ | ++ | ++ | +
+ | ++ | ++ | ++ | +
+ | ++ | ++ | ++ | +
+ | ++ | ++ | ++ | +
+ | ++ | ++ | ++ | +
+ | ++ | ++ | ++ | +
+ | ++ | ++ | ++ | +
+ | ++ | ++ | ++ | +
+ | ++ | ++ | ++ | +
+ | ++ | ++ | ++ | +