PostgreSQL 15.4全文检索+UTF-8多字节字符+plperl扩展Bug问询
PostgreSQL 15.4 与 plperl 会话冲突导致多字节字符全文检索报错问题
问题现象
仅在PostgreSQL 15.4中出现,PostgreSQL 14无此问题。需同时满足3个条件才会触发报错:
- 执行
TEXT @@ to_tsquery()语句 - TEXT列包含UTF-8多字节字符
- 同一会话中先调用过简单的plperl函数
报错信息
ERROR: invalid multibyte character for locale HINT: The server's LC_CTYPE locale is probably incompatible with the database encoding.
复现步骤
$ createdb -U postgres test $ psql -U postgres test psql (15.4) Type "help" for help. test=# \l test List of databases Name | Owner | Encoding | Collate | Ctype | ICU Locale | Locale Provider | Access privileges ------+----------+----------+-------------+-------------+------------+-----------------+------------------- test | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | libc | (1 row) test=# CREATE EXTENSION IF NOT EXISTS plperl; CREATE EXTENSION test=# CREATE FUNCTION public.simple_quoter(text) RETURNS TEXT LANGUAGE plperl AS $_X$ return "'$_[0]'" $_X$; CREATE FUNCTION test=# CREATE TABLE t (c TEXT); CREATE TABLE test=# INSERT INTO t VALUES ('Queensrÿche'); INSERT 0 1 test=# SELECT * FROM t WHERE to_tsquery('english','Queen:*') @@ to_tsvector('english',c); ERROR: invalid multibyte character for locale HINT: The server's LC_CTYPE locale is probably incompatible with the database encoding.
创建plperl扩展和simple_quoter函数后,编写repro.sql文件:
SELECT simple_quoter('hi'); SELECT c @@ to_tsquery('english','Queen:*') FROM t;
执行该文件同样报错,但单独会话执行全文检索语句则正常。
环境信息
- 数据库初始化未指定特殊locale参数,系统及数据库编码均为UTF-8
- 操作系统:Arch Linux(2023年9月3日最新版)
- PostgreSQL构建版本:pkgver=15.4 pkgrel=2
疑问
- 这是PostgreSQL 15的Bug吗?还是我遗漏了配置?
- 是否存在无需避免同会话使用plperl的解决办法?
解答
1. 是否为PostgreSQL 15的Bug?
这是PostgreSQL 15系列中plperl扩展与全文检索模块的交互Bug。PostgreSQL 15对plperl的locale处理逻辑做了调整,调用plperl函数后会意外修改会话的locale相关上下文,导致后续全文检索处理多字节UTF-8字符时出现locale兼容性误判。你的配置无问题,数据库编码与LC_CTYPE完全匹配,排除配置遗漏的可能。
2. 同会话下的解决办法
重置会话locale
在调用plperl函数后,执行以下语句重置会话LC_CTYPE参数,之后即可正常执行全文检索:SET LC_CTYPE = 'en_US.UTF-8';切换为ICU Locale Provider
重新初始化数据库时指定使用ICU作为Locale Provider,规避libc locale的上下文冲突:createdb -U postgres -T template0 --locale-provider=icu --icu-locale=en-US test_icu使用ICU locale的数据库不会触发该问题。
升级PostgreSQL版本
该问题在PostgreSQL 15.5及以上小版本或16稳定版中已被修复,建议升级到最新版本彻底解决。
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

