问题描述
运行 pg 数据库后,查询支持的 locale,只有如下项目:
缺少对 zh_CN 的支持,需要排查问题。
信息收集
1. locale -a 的输出信息
locale -a 的输出信息表明存在 zh_CN 的 locale 支持
2. initdb 添加 -d 参数运行查看相关输出信息:
输出信息表明数据库的 locale 被设定为 en_US.UTF-8
3. 设置 LC_ALL 为 zh_CN.UTF-8 并给 initdb 程序添加 -d 参数测试
The database cluster will be initialized with locale "zh_CN.UTF-8".
initdb: error: locale "zh_CN.UTF-8" requires unsupported encoding "GBK"
Encoding "GBK" is not allowed as a server-side encoding.
Rerun initdb with a different locale selection.
使用 initdb: error: locale “zh_CN.UTF-8” requires unsupported encoding “GBK” 检索互联网,没有找到可用的信息。
4. 正常配置系统上设置 zh_CN.UTF-8 后启动时的相关信息:
The database cluster will be initialized with locale "zh_CN.UTF-8".
The default database encoding has accordingly been set to "UTF8".
initdb: could not find suitable text search configuration for locale "zh_CN.UTF-8"
The default text search configuration will be set to "simple".
经验操作
在我的 debian10 系统中,执行 sudo dpkg-reconfigure locales,选择如下项目生成 locale:
en_US.UTF-8
zh_CN.GB2312
zh_CN.GB18030
zh_CN.GBK
zh_CN.UTF-8
生成之后拷贝设备上的 /lib/locale/locale-archive 文件到异常环境中的相同目录中,然后重试,问题得到解决。
从 locale -v 参数中获取到的一些差异点
替换 /lib/locale/locale-archive 是我过去在解决一个终端中文乱码时搞过的内容,但是并不清楚 locale 是怎么使用这个文件的,通过查看 locale 的 manual 内容,发现可以指定一个 -v 参数获取一些额外的信息。
异常环境中执行 locale -a -v 信息,获取到的 zh_CN.utf8 locale 相关信息摘录如下:
locale: zh_CN.utf8 archive: /usr/lib/locale/locale-archive
-------------------------------------------------------------------------------
title | Chinese locale for Peoples *
email | bug-glibc-locales@gnu.org
language | Chinese
territory | P.R. of China
revision | 0.1
date | 2000-07-25
codeset | GBK
正常环境中执行 locale -a -v 信息,获取到的 zh_CN.utf8 locale 相关信息摘录如下:
locale: zh_CN.utf8 archive: /usr/lib/locale/locale-archive
-------------------------------------------------------------------------------
title | Chinese locale for Peoples *
email | bug-glibc-locales@gnu.org
language | Chinese
territory | China
revision | 0.1
date | 2000-07-25
codeset | UTF-8
对比发现,正常环境中 zh_CN.utf8 locale 的 codeset 为 UTF-8,异常环境中 zh_CN.utf8 locale 的 codeset 为 GBK,联系 initdb: error: locale “zh_CN.UTF-8” requires unsupported encoding “GBK” 报错信息,不难确定是异常环境中的 zh_CN.utf8 locale 的 codeset 为 GBK,而 PG 不支持 GBK 导致无法配置问题。
一点点延申
在 linux 中可以 locale-gen 来重新生成 locale,locale-gen 是一个 shell 脚本。locale-gen 最终通过调用 localedef 程序来生成相关的文件,这些生成的文件用于 c 库 setlocale,localeconv 等 locale 相关函数。
localedef 生成的内容有两种保存形式,一种是保存在 /usr/lib/locale/locale-archive 文件中,一种是保存在 /lib/locale 中以 locale 文件命令的子目录中。
保存在子目录中的一个示例如下:
root@debian:/tmp # ls -lh /lib/locale/C.UTF-8/
total 1.7M
-rw-r--r-- 1 root root 131 May 1 2019 LC_ADDRESS
-rw-r--r-- 1 root root 1.5M May 1 2019 LC_COLLATE
-rw-r--r-- 1 root root 197K May 1 2019 LC_CTYPE
-rw-r--r-- 1 root root 252 May 1 2019 LC_IDENTIFICATION
-rw-r--r-- 1 root root 23 May 1 2019 LC_MEASUREMENT
drwxr-xr-x 2 root root 4.0K Feb 1 2021 LC_MESSAGES
-rw-r--r-- 1 root root 270 May 1 2019 LC_MONETARY
-rw-r--r-- 1 root root 62 May 1 2019 LC_NAME
-rw-r--r-- 1 root root 50 May 1 2019 LC_NUMERIC
-rw-r--r-- 1 root root 34 May 1 2019 LC_PAPER
-rw-r--r-- 1 root root 47 May 1 2019 LC_TELEPHONE
-rw-r--r-- 1 root root 3.3K May 1 2019 LC_TIME
localedef 使用到的下面两个关键文件名称与功能如下:
/usr/share/i18n/charmaps
Usual default character map path.
/usr/share/i18n/locales
Usual default path for locale definition files.
charmaps 中保存 gzip 压缩过的语言编码集,locales 中保存组成一个独立 locale 完整条目的规则信息,包含如下几个项目:
category "i18n:2012";LC_IDENTIFICATION
category "i18n:2012";LC_CTYPE
category "i18n:2012";LC_COLLATE
category "i18n:2012";LC_TIME
category "i18n:2012";LC_NUMERIC
category "i18n:2012";LC_MONETARY
category "i18n:2012";LC_MESSAGES
category "i18n:2012";LC_PAPER
category "i18n:2012";LC_NAME
category "i18n:2012";LC_ADDRESS
category "i18n:2012";LC_TELEPHONE
category "i18n:2012";LC_MEASUREMENT
生成一个 locale 的主要过程是 localedef 将系统 /usr/share/i18n/locales 目录中不同语系的规则使用 /usr/share/i18n/charmaps 中的指定编码生成每个 LC_XXX 列表的内容。
参考链接
http://t.zoukankan.com/songyuejie-p-3925371.html
https://www.postgresql.org/docs/current/locale.html