You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

疑问

  1. 这是PostgreSQL 15的Bug吗?还是我遗漏了配置?
  2. 是否存在无需避免同会话使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 21:30:10