pg 数据库不能使用 zh_CN.UTF-8:initdb: error: locale “zh_CN.UTF-8“ requires unsupported encoding “GBK“

问题描述

运行 pg 数据库后,查询支持的 locale,只有如下项目:

pg 数据库不能使用 zh_CN.UTF-8:initdb: error: locale “zh_CN.UTF-8“ requires unsupported encoding “GBK“
缺少对 zh_CN 的支持,需要排查问题。

信息收集

1. locale -a 的输出信息

pg 数据库不能使用 zh_CN.UTF-8:initdb: error: locale “zh_CN.UTF-8“ requires unsupported encoding “GBK“

locale -a 的输出信息表明存在 zh_CN 的 locale 支持

2. initdb 添加 -d 参数运行查看相关输出信息:

pg 数据库不能使用 zh_CN.UTF-8:initdb: error: locale “zh_CN.UTF-8“ requires unsupported encoding “GBK“

输出信息表明数据库的 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 的 codesetUTF-8,异常环境中 zh_CN.utf8 locale 的 codesetGBK,联系 initdb: error: locale “zh_CN.UTF-8” requires unsupported encoding “GBK” 报错信息,不难确定是异常环境中的 zh_CN.utf8 locale 的 codeset 为 GBK,而 PG 不支持 GBK 导致无法配置问题。

一点点延申

linux 中可以 locale-gen 来重新生成 localelocale-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

上一篇:git 中文乱码解决


下一篇:【Python】mkdocs 生成帮助文档