本期内容如下:
- LLVM与PG的版本依赖关系
- 分区切割保留原分区名
- 预编译与热更新问题
- 导入导出过滤问题
1.LLVM与PG的版本依赖
客户Redhat 8.9系统使用PG 14.9,升级操作系统后,LLVM版本由15变为16,升级后数据库出现如下错误:
ERROR: could not load library "/usr/pgsql-14/lib/llvmjit.so": libLLVM-15.so: cannot open shared object file: No such file or directory; nested exception is org.postgresql.util.PSQLException:
复制
PG官网没有单独页面说明与LLVM之间的版本依赖关系,不过各个Release Notes有零散的描述,正好整理为如下表格。
PG版本 | LLVM最高版本 | 时间 |
---|---|---|
11.11、12.6、13.2 | 11-12 | 2021-02-11 |
14.0 | 12 | 2021-09-30 |
11.13、12.8、13.4 | 13 | 2021-08-12 |
11.16、12.11、13.7、14.3 | 14 | 2022-05-12 |
11.18、12.13、13.9、14.6、15.1 | 15 | 2022-11-10 |
12.17、13.13、14.10、15.5、16.1 | 16-17 | 2023-11-09 |
12.19、13.15、14.12、15.7、16.3 | 18 | 2024-05-09 |
注:PG 17对LLVM将有最低版本的要求,最低版本要求为10,而PG 18最低版本的要求为14。
从上面的表格,可以看出PG 14使用LLVM 16的最低小版本是14.10,而当前使用的小版本是14.9。
2.分区切割保留原分区名
Oracle里使用分区切割功能时,支持切割使用原分区名称,PG 17 Beta版本支持了SPLIT PARTITION切割分区的功能,正好验证这个兼容性,示例如下:
CREATE TABLE sales(
id serial,
sales_count int,
sales_date date not null
) PARTITION BY RANGE(sales_date);
CREATE TABLE sales_20240510 PARTITION OF sales FOR VALUES FROM (minvalue) TO (date'2024-05-11') ;
CREATE TABLE sales_maximize PARTITION OF sales FOR VALUES FROM (date'2024-05-11') TO (MAXVALUE);
复制
上面我们设计了两个分区,第一个分区sales_20240510包含20240510之前的数据,第二个分区sales_maximize包含20240511之后的数据,现在对第二个分区sales_maximize进行切割:
ALTER TABLE sales SPLIT PARTITION sales_maximize INTO (
PARTITION sales_20240731
FOR VALUES FROM (date'2024-05-11') TO (date'2024-08-01'),
PARTITION sales_maximize
FOR VALUES FROM (date'2024-08-01') TO (MAXVALUE)
);
复制
注意:切割sales_maximize时,切割为sales_20240731 和sales_maximize,仍然保留了原来的分区名,并新增一个分区。
不过有一个坏消息:PLIT PARTITION| MERGE PARTITION可能会延期到18,目前受CVE漏洞影响被回退了。
3.预编译结果集与DDL热更新问题
同一个session里JDBC使用PreparedStatement执行查询语句时,如果查询表又执行DDL语句,查询结果集的字段结构发生变化,再执行查询语句可能会发生服务端返回的热更新类型与缓存结果集的类型不一致而报错:
ERROR: cached plan must not change result type
复制
业务端使用JAVA的复现示例如下:
conn.setAutoCommit(false);
String sql = "SELECT * FROM test_table WHERE data = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "test1"); pstmt.executeQuery().close();
pstmt.setString(1, "test2"); pstmt.executeQuery().close();
pstmt.setString(1, "test3"); pstmt.executeQuery().close();
pstmt.setString(1, "test4"); pstmt.executeQuery().close();
pstmt.setString(1, "test5"); pstmt.executeQuery().close();
conn.commit();
stmt.execute("ALTER TABLE test_table ALTER COLUMN data type varchar(50)");
conn.commit();
pstmt.setString(1, "test6"); pstmt.executeQuery().close();
复制
注意:这里pstmt执行5次后触发了服务端cache plan,再执行DDL,第6次复现热更新冲突。5次后缓存执行计划是PG的设计机制,也可以加一个JDBC参数prepareThreshold=1,执行1次后缓存。
针对热更新的这种场景,JDBC里可以设置prepareThreshold=0,来禁用服务端cache plan。在openGauss系的MogDB 5.0版本,增加了一个服务端参数plan_cache_type_validation,设置为off也可以解决这个问题。
4.导出与导入排除过滤表问题
导入过滤及导出过滤这两个功能也是比较实用的功能,PG 17对pg_dump工具新增filter选项读取文件
$ pg_dump --filter=/tmp/t.list
复制
filter文件支持白名单或黑名单
include | exclude
复制
支持的对象类型
- extension
- foreign_data
- table
- table_and_children
- table_data
- table_data_and_children
- schema
示例如下:
cat /tmp/t.list include table foo include table sometable.* exclude table_data some.foobar
复制
PG 17对pg_restore工具也增加了filter选项读取文件来进行恢复。
g_restore工具也支持白名单或黑名单
include | exclude
复制
支持的对象类型为
- function
- index
- schema
- table
- trigger
openGauss对gs_dump功能也增加了两个选项来读取文件进行过滤
- –include-table-file
- –exclude-table-file
除此之外,不管PG或者openGauss,我们还可以使用dump清单这个高级功能,对-Fc导出的dump文件先使用-l生成清单,编排清单文件后进行恢复,往期的案例也有过介绍。
推荐阅读
- 数据库微观案例第47期
- 数据库微观案例第46期
- 数据库微观案例第45期
- 数据库微观案例第44期
- 数据库微观案例第43期
- 数据库微观案例第42期
- 数据库微观案例第41期 |NULL值案例
- 数据库微观案例第40期
- PostgreSQL智慧碎片|微观案例 |宏观收获
- PostgreSQL小案例集|4月刊
与我联系
- 微信公众号:象楚之行
- 墨天轮:https://www.modb.pro/u/15675
- 微信:skypkmoon
勤耕细作,用心积微;静待花开,量变质成。