initdb: invalid locale settings
实验1:
PostgreSQL在安装后需要初始化data,在用源码编译安装后,通过initdb初始化时出现了:
initdb: invalid locale settings; check LANG and LC_* environment variables
导致不能初始化。
实验2:
使用rpm包安装后,通过postgresql-11-setup initdb时,初始化是成功的,但是默认字符集却是SQL_ASCII:
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+-----------+-------------+-------------+----------------------
postgres | postgres | SQL_ASCII | C | C |
template0 | postgres | SQL_ASCII | C | C | =c/postgres +
| | | | | postgres=CTc/postgres
template0 | postgres | SQL_ASCII | C | C | =c/postgres +
| | | | | postgres=CTc/postgres
但是查看locale:
bash-4.2$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
系统字符集也没问题,是想要的en_US.UTF-8。
解决方法:
通过这两个实验发现是跟字符集相关,mysql可以通过配置文件修改默认字符集,但是postgresql是不可以的,一旦初始化server_encoding是不可以修改的:
postgres=# show server_encoding;
server_encoding
-----------------
SQL_ASCII
(1 row)
postgres=# alter system set server_encoding = 'UTF8';
ERROR: parameter "server_encoding" cannot be changed
postgres=#
而且template0的字符集是也是不可修改的,如果在SQL_ASCII情况下可以以template0为模板,通过在create语句后添加template=template0 encoding='UTF8’来创建UTF8字符集的新库。如果不像这么麻烦,也可以修改template1的字符集为UTF8,因为不指定template,会默认以template1为模板。
虽然修改了字符集,但是治标不治本。
实验1的情况还是无法初始化,对于使用initdb直接初始化data的情况,可以添加-E 'UTF8’来显示指定默认字符集来完成初始化。
对于实验2,使用的命令是postgresql-11-setup initdb,该命令不支持-E参数,还是不能在初始化时默认UTF8,而且locale查到的字符集也是en_US.UTF-8,没有问题,其实原因在于locales中没有相对应的语言包:
bash-4.2$ locale -a
C
POSIX
这种情况多出现在docker中,因为为了镜像能够小就阉割掉了很多东西,目前该容器就没有en_US.UTF-8语言包,安装方法:
yum remove glibc-common -y
yum install glibc-common -y
localedef -v -c -i en_US -f UTF-8 en_US.UTF-8
再执行locale -a就可以发现多了en_US.utf8,此时重新initdb,启动,发现:
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
(3 rows)
如果使用dockerfile来创建docker可以添加环境变量来设置默认字符集:
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8