今天在一MogDB 数据库中创建 GBK 字符集的 database 的时候报:ERROR: encoding “GBK” does not match locale “en_US.UTF-8”。
1 2 3 MogDB= ERROR: encoding "GBK" does not match locale "en_US.UTF-8" DETAIL: The chosen LC_CTYPE setting requires encoding "UTF8" .
这个创建 GB
K 字符集的数据库,我前天还在另一个 MogDB 实例创建的,相同的语句,为啥这个实例就不行了呢。于是进行了一点研究,记录如下。
通过报错是说:字符集(编码)GBK
与 locale "en_US.UTF-8"
不匹配。LC_CTYPE
的设置,需要设置 UTF8
的编码。
检查 数据库的 LC_CTYPE
的参数:
1 2 3 4 5 6 MogDB= # show LC_CTYPE; lc_ctype en_US.UTF-8 (1 row )
可以看到 LC_CTYPE
设置为 en_US.UTF-8
。
检查目前的database
信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 MogDB= List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges | Compatibility -----------+-------+----------+-------------+-------------+--------------------+--------------- co | omm | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/omm +| A | | | | | omm=CTc/omm +| | | | | | co_rp=CTc/omm +| | | | | | co_rp=APm/omm | f001 | omm | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/omm +| A | | | | | omm=CTc/omm +| | | | | | u_f001=CTc/omm +| | | | | | u_f001=APm/omm | futf | omm | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | A postgres | omm | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | A template0 | omm | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/omm +| A | | | | | omm=CTc/omm | template1 | omm | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/omm +| A | | | | | omm=CTc/omm | testdb | omm | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/omm +| A | | | | | omm=CTc/omm +| | | | | | testdblink=CTc/omm+| | | | | | testdblink=APm/omm |
可以看到,目前的数据库的编码都是 utf8
,Collae
和Ctype
都是 en_US.UTF-8
。
然后我又找到之前的MogDB 实例,检查发现有以下几点不同:
LC_CTYPE
参数设置为 C
\l
查看数据库的属性的 Collate
和Ctype
也都是 C
,具体 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 MogDB= # show LC_CTYPE; lc_ctype C (1 row ) MogDB= # \l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges | Compatibility co | ogm | GBK | C | C | | A postgres | ogm | UTF8 | C | C | | A template0 | ogm | UTF8 | C | C | = c/ ogm + | A | | | | | ogm= CTc/ ogm | template1 | ogm | UTF8 | C | C | omm= CTc/ ogm + | A | | | | | = c/ ogm + | | | | | | ogm= CTc/ ogm |
进一步发现这俩实例的创建是不同的。
不能创建 GBK
的MogDB 的实例是安装 官方文档的 手动安装章节进行安装的:https://docs.mogdb.io/zh/mogdb/v5.0/manual-installation
初始化数据库的时候使用的如下脚本:
1 gs_initdb --pgdata=/opt/mogdb/data --nodename=primary --pwpasswd=Enmo@123 --encoding=UTF-8 --locale=en_US.UTF-8
也就是指定了 --encoding=UTF-8 --locale=en_US.UTF-8
,其实问题的关键是指定了 --locale=en_US.UTF-8
,这就导致默认创建的数据库都是 locale
为 en_US.UTF-8
,而 与locale "en_US.UTF-8"
匹配的编码( encoding) 是"UTF8"
,所以默认创建的编码只能是 UTF8
。
那数据库实例已经初始化完成了,怎么创建GBK的数据库呢,总不能重新初始化吧,这库都运行了一段时间了呢。
经过确认是不需要重新初始化的,可以通过以下命令进行手动指定
1 create database hhgbk ENCODING= 'GBK' LC_COLLATE= 'zh_CN.gbk' LC_CTYPE= 'zh_CN.gbk' ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 MogDB= List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges | Compatibility -------+-------+----------+-----------+-----------+-------------------+--------------- hhgbk | omm | GBK | zh_CN.gbk | zh_CN.gbk | | A (1 row) MogDB= List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges | Compatibility -----------+-------+----------+-------------+-------------+--------------------+--------------- co | omm | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/omm +| A | | | | | omm=CTc/omm +| | | | | | co_rp=CTc/omm +| | | | | | co_rp=APm/omm | f001 | omm | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/omm +| A | | | | | omm=CTc/omm +| | | | | | u_f001=CTc/omm +| | | | | | u_f001=APm/omm | futf | omm | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | A hhgbk | omm | GBK | zh_CN.gbk | zh_CN.gbk | | A postgres | omm | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | A template0 | omm | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/omm +| A | | | | | omm=CTc/omm | template1 | omm | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/omm +| A | | | | | omm=CTc/omm | testdb | omm | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/omm +| A | | | | | omm=CTc/omm +| | | | | | testdblink=CTc/omm+| | | | | | testdblink=APm/omm |
这样就可以。可以看到 hhgbk
数据库是一股清流,是GBK
的编码。
而另一个MogDB 实例是通过 ptk
工具进行安装的,通过查找 ptk
日志可以看到他 初始化实例的脚本如下:
1 gs_initdb --pgdata=/data/mogdb/data --nodename=primary --pwpasswd=Enmo@123 --encoding=UTF-8 --no-locale
也就是 ptk 工具是 加的 --no-locale
参数,而手动安装的是加了 --locale=en_US.UTF-8
参数。
然后查看官方手册的 CREATE DATABASE :
https://docs.mogdb.io/zh/mogdb/v5.0/CREATE-DATABASE
注意 :如果创建兼容性为A的数据库,建议设置lc_collate =’C’,否则可能导致跟需要兼容的数据库中排序结果有差异。推荐创建兼容性为A的数据库使用以下命令:
1 > create database db1 DBCOMPATIBILITY= 'A' ENCODING= 'UTF8' LC_COLLATE= 'C' LC_CTYPE= 'C' ;
也就是A 模式下建议使用 设置lc_collate =’C’,而create database 默认就是A模式。
继续查看官方文档的gs_initdb https://docs.mogdb.io/zh/mogdb/v5.0/gs_initdb
参数
参数说明
–no-locale
和–locale=C等价。
也就是 --no-locale
和 --locale=C
等价。
另:
我也找了个云上提供服务器的 pg 数据库的配置,设置的也是 C。
1 2 3 4 5 6 7 8 9 10 11 f001=> \l List of databases Name | Owner | Encoding | Collate | Ctype | ICU Locale | Locale Provider | Access privileges -----------+-------------+----------+---------+-------+------------+-----------------+----------------------------- f001 | default | UTF8 | C | C | | libc | music2 | default | LATIN9 | C | C | | libc | postgres | cloud_admin | UTF8 | C | C | | libc | template0 | cloud_admin | UTF8 | C | C | | libc | =c/cloud_admin + | | | | | | | cloud_admin=CTc/cloud_admin template1 | cloud_admin | UTF8 | C | C | | libc | =c/cloud_admin + | | | | | | | cloud_admin=CTc/cloud_admin
那这个 C 是什么意思呢?
C”是系统默认的locale,”POSIX”是”C”的别名。所以当我们新安装完一个系统时,默认的locale就是C或POSIX。
https://pubs.opengroup.org/onlinepubs/009695399/functions/setlocale.html
“POSIX” [CX] [Option Start] Specifies the minimal environment for C-language translation called the POSIX locale. If setlocale() is not invoked, the POSIX locale is the default at entry to main(). [Option End] “C” Equivalent to “POSIX”.
参考:
https://docs.mogdb.io/zh/mogdb/v5.0/gs_initdb
https://docs.mogdb.io/zh/mogdb/v5.0/character-set-support
https://docs.mogdb.io/zh/mogdb/v5.0/manual-installation
https://docs.mogdb.io/zh/mogdb/v5.0/ptk-based-installation
原文作者:
Hi.MogDB
原文链接:
https://hi.mogdb.org/posts/54e5665e/
许可协议: 知识共享署名-非商业性使用 4.0 国际许可协议