暂无图片
暂无图片
3
暂无图片
暂无图片
暂无图片

数据库微观案例第48期

原创 彭冲 2024-09-02
291

本期内容如下:

  • 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生成清单,编排清单文件后进行恢复,往期的案例也有过介绍。

推荐阅读

与我联系

  • 微信公众号:象楚之行
  • 墨天轮:https://www.modb.pro/u/15675
  • 微信:skypkmoon

勤耕细作,用心积微;静待花开,量变质成。

最后修改时间:2024-12-30 16:14:30
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论