计算
弹性云服务器 ECS
Flexus云服务
裸金属服务器 BMS
弹性伸缩 AS
镜像服务 IMS
专属主机 DeH
函数工作流 FunctionGraph
云手机服务器 CPH
Huawei Cloud EulerOS
网络
虚拟私有云 VPC
弹性公网IP EIP
虚拟专用网络 VPN
弹性负载均衡 ELB
NAT网关 NAT
云专线 DC
VPC终端节点 VPCEP
云连接 CC
企业路由器 ER
企业交换机 ESW
全球加速 GA
安全与合规
安全技术与应用
Web应用防火墙 WAF
企业主机安全 HSS
云防火墙 CFW
安全云脑 SecMaster
DDoS防护 AAD
数据加密服务 DEW
数据库安全服务 DBSS
云堡垒机 CBH
数据安全中心 DSC
云证书管理服务 CCM
边缘安全 EdgeSec
威胁检测服务 MTD
CDN与智能边缘
内容分发网络 CDN
CloudPond云服务
智能边缘云 IEC
迁移
主机迁移服务 SMS
对象存储迁移服务 OMS
云数据迁移 CDM
迁移中心 MGC
大数据
MapReduce服务 MRS
数据湖探索 DLI
表格存储服务 CloudTable
云搜索服务 CSS
数据接入服务 DIS
数据仓库服务 GaussDB(DWS)
数据治理中心 DataArts Studio
数据可视化 DLV
数据湖工厂 DLF
湖仓构建 LakeFormation
企业应用
云桌面 Workspace
应用与数据集成平台 ROMA Connect
云解析服务 DNS
专属云
专属计算集群 DCC
IoT物联网
IoT物联网
设备接入 IoTDA
智能边缘平台 IEF
用户服务
账号中心
费用中心
成本中心
资源中心
企业管理
工单管理
国际站常见问题
ICP备案
我的凭证
支持计划
客户运营能力
合作伙伴支持计划
专业服务
区块链
区块链服务 BCS
Web3节点引擎服务 NES
解决方案
SAP
高性能计算 HPC
视频
视频直播 Live
视频点播 VOD
媒体处理 MPC
实时音视频 SparkRTC
数字内容生产线 MetaStudio
存储
对象存储服务 OBS
云硬盘 EVS
云备份 CBR
存储容灾服务 SDRS
高性能弹性文件服务 SFS Turbo
弹性文件服务 SFS
云硬盘备份 VBS
云服务器备份 CSBS
数据快递服务 DES
专属分布式存储服务 DSS
容器
云容器引擎 CCE
容器镜像服务 SWR
应用服务网格 ASM
华为云UCS
云容器实例 CCI
管理与监管
云监控服务 CES
统一身份认证服务 IAM
资源编排服务 RFS
云审计服务 CTS
标签管理服务 TMS
云日志服务 LTS
配置审计 Config
资源访问管理 RAM
消息通知服务 SMN
应用运维管理 AOM
应用性能管理 APM
组织 Organizations
优化顾问 OA
IAM 身份中心
云运维中心 COC
资源治理中心 RGC
应用身份管理服务 OneAccess
数据库
云数据库 RDS
文档数据库服务 DDS
数据管理服务 DAS
数据复制服务 DRS
云数据库 GeminiDB
云数据库 GaussDB
分布式数据库中间件 DDM
数据库和应用迁移 UGO
云数据库 TaurusDB
人工智能
人脸识别服务 FRS
图引擎服务 GES
图像识别 Image
内容审核 Moderation
文字识别 OCR
AI开发平台ModelArts
图像搜索 ImageSearch
对话机器人服务 CBS
华为HiLens
视频智能分析服务 VIAS
语音交互服务 SIS
应用中间件
分布式缓存服务 DCS
API网关 APIG
微服务引擎 CSE
分布式消息服务Kafka版
分布式消息服务RabbitMQ版
分布式消息服务RocketMQ版
多活高可用服务 MAS
事件网格 EG
企业协同
华为云会议 Meeting
云通信
消息&短信 MSGSMS
云生态
合作伙伴中心
云商店
开发者工具
SDK开发指南
API签名指南
Terraform
华为云命令行工具服务 KooCLI
其他
产品价格详情
系统权限
管理控制台
客户关联华为云合作伙伴须知
消息中心
公共问题
开发与运维
应用管理与运维平台 ServiceStage
软件开发生产线 CodeArts
需求管理 CodeArts Req
部署 CodeArts Deploy
性能测试 CodeArts PerfTest
编译构建 CodeArts Build
流水线 CodeArts Pipeline
制品仓库 CodeArts Artifact
测试计划 CodeArts TestPlan
代码检查 CodeArts Check
代码托管 CodeArts Repo
云应用引擎 CAE
开天aPaaS
云消息服务 KooMessage
云手机服务 KooPhone
云空间服务 KooDrive

GDS导入/导出类问题

更新时间:2024-11-27 GMT+08:00

GDS导入/导出容易遇到字符集的问题,特别是不同类型的数据库或者不同编码类型的数据库进行迁移的过程中,往往会导致数据入不了库,严重阻塞数据迁移场景相关业务。

区域支持

区域支持指的是应用遵守文化偏好的问题,包括字母表、排序、数字格式等。区域是在使用initdb创建一个数据库时自动被初始化的。默认情况下,initdb将会按照它的执行环境的区域设置初始化数据库,即系统已经设置好的区域。如果想要使用其他的区域,可以使用手工指定(initdb –locale=xx)。

如果想要将几种区域的规则混合起来,可以使用以下区域子类来控制本地化规则的某些方面。这些类名转换成initdb的选项名来覆盖某个特定分类的区域选择。

表1 区域支持

字段

描述

LC_COLLATE

字符串排序顺序。

LC_CTYPE

字符分类(什么是一个字符?它的大写形式是否等效?)

LC_MESSAGES

消息使用的语言Language of messages。

LC_MONETARY

货币数量使用的格式。

LC_NUMERIC

数字的格式。

LC_TIME

日期和时间的格式。

如果想要系统表现得没有区域支持,可以使用区域C或者等效的POSIX。使用非C或非POSIX区域的缺点是性能影响。它降低了字符处理的速度并且阻止了在LIKE中对普通索引的使用。因此,只能在真正需要的时候才使用它。

一些区域分类的值必须在数据库被创建时的就被固定。不同的数据库可以使用不同的设置,但是一旦一个数据库被创建,就不能在数据库上修改这些区域分类的值。LC_COLLATE和LC_CTYPE就属于上述情形。它们影响索引的排序顺序,因此它们必须保持固定,否则在文本列上的索引将会崩溃。这些分类的默认值在initdb运行时被确定,并且这些值在新数据库被创建时使用,除非在CREATE DATABASE命令中特别指定。其它区域分类可以在任何时候被更改,更改的方式是设置与区域分类同名的服务器配置参数。被initdb选中的值实际上只是被写入到配置文件postgresql.conf中作为服务器启动时的默认值。如果你将这些赋值从postgresql.conf中除去,那么服务器将会从其执行环境中继承该设置。

区域设置特别影响下面的SQL特性:

  • 在文本数据上使用ORDER BY或标准比较操作符的查询中的排序顺序
  • 函数upper、lower和initcap
  • 模式匹配操作符(LIKE、SIMILAR TO和POSIX风格的正则表达式);区域影响大小写不敏感匹配和通过字符类正则表达式的字符分类
  • to_char函数家族

因此,在上述场景遇到查询结果集不一致的情况,就可以猜测可能是字符集问题。

排序规则支持

排序规则特性允许指定每一列甚至每一个操作的数据的排序顺序和字符分类行为。这放松了数据库的LC_COLLATE和LC_CTYPE设置自创建以后就不能更改这一限制。

一个表达式的排序规则可以是"默认"排序规则,它表示数据库的区域设置。一个表达式的排序规则也可能是不确定的。在这种情况下,排序操作和其他需要知道排序规则的操作会失败。

当数据库系统必须要执行一次排序或者字符分类时,它使用输入表达式的排序规则。这会在使用例如ORDER BY子句以及函数或操作符调用(如<)时发生。应用于ORDER BY子句的排序规则就是排序键的排序规则。应用于函数或操作符调用的排序规则从它们的参数得来,具体如下文所述。除比较操作符之外,在大小写字母之间转换的函数会考虑排序规则,例如lower、upper和initcap。模式匹配操作符和to_char及相关函数也会考虑排序规则。

对于一个函数或操作符调用,其排序规则通过检查在执行指定操作时参数的排序规则来获得。如果该函数或操作符调用的结果是一种可排序的数据类型,万一有外围表达式要求函数或操作符表达式的排序规则,在解析时结果的排序规则也会被用作函数或操作符表达式的排序规则。

一个表达式的排序规则派生可以是显式或隐式。该区别会影响多个不同的排序规则出现在同一个表达式中时如何组合它们。当使用一个COLLATE子句时,将发生显式排序规则派生。所有其他排序规则派生都是隐式的。当多个排序规则需要被组合时(例如在一个函数调用中),将使用下面的规则:

  1. 如果任何一个输入表达式具有一个显式排序规则派生,则在输入表达式之间的所有显式派生的排序规则必须相同,否则将产生一个错误。如果任何一个显式派生的排序规则存在,它就是排序规则组合的结果。
  2. 否则,所有输入表达式必须具有相同的隐式排序规则派生或默认排序规则。如果任何一个非默认排序规则存在,它就是排序规则组合的结果。否则,结果是默认排序规则
  3. 如果在输入表达式之间存在冲突的非默认隐式排序规则,则组合被认为是具有不确定排序规则。这并非一种错误情况,除非被调用的特定函数要求提供排序规则的知识。如果它确实这样做,运行时将发生一个错误。

字符集

PG里面的字符集支持各种字符集存储文本,包括单字节字符集,比如ISO 8859系列,以及多字节字符集,比如EUC(扩展Unix编码Extended Unix Code)、UTF-8和Mule内部编码。MPPDB中目前主要使用的字符集包括GBK、UTF-8和LATIN1。所有被支持的字符集都可以被客户端透明地使用,但少数只能在服务器上使用(即作为一种服务器端编码,GBK编码在PG中只是客户端编码,不是服务端编码,MPPDB将GBK引入到服务端编码,这是很多问题的根源)。默认的字符集是在使用initdb初始化PG数据库时选择的。在创建一个数据库实例时可以重载字符集,因此可能会有多个数据库实例并且每一个使用不同的字符集。一个重要的限制是每个数据库的字符集必须和数据库LC_CTYPE(字符分类)和LC_COLLATE (字符串排序顺序)设置兼容。对于C或POSIX,任何字符集都是允许的,但是对于其他区域只有一种字符集可以正确工作。不过,在Windows上UTF-8编码可以和任何区域配合使用。

SQL_ASCII设置与其他设置表现得相当不同。如果服务器字符集是SQL_ASCII,服务器把字节值0-127根据ASCII标准解释,而字节值128-255则当作无法解析的字符。如果设置为SQL_ASCII,就不会有编码转换。因此,这个设置基本不是用来声明所使用的指定编码,因为这个声明会忽略编码。在大多数情况下,如果使用了任何非ASCII数据,那么使用SQL_ASCII设置都是不明智的,因为PG将无法帮助你转换或者校验非ASCII字符。

数据库系统支持某种编码,主要涉及三个方面:数据库服务器支持,数据访问接口支持以及客户端工具支持。

  • 数据库服务器字符编码

    数据库服务器支持某种编码,是指数据库服务器能够从客户端接收、存储以及向客户端提供该种编码的字符(包括标识符、字符型字段值),并能将该种编码的字符转换到其它编码(如UTF-8编码转到GBK编码)。

    指定数据库服务器编码:创建数据库时指定:CREATE DATABASE … ENCODING … //可以取ASCII、UTF-8、EUC_CN、……;

    查看数据库编码:show server_encoding。

  • 数据库访问接口编码

    数据库访问接口支持某种编码,是指数据库访问接口要做到能对该种编码的字符进行正确读写,不应出现数据丢失、数据失真等情况。以JDBC接口为例:

    JDBC接口一般根据JVM的file.encoding设置client_encoding:set client_encoding to file_encoding;

    将String转换成client_encoding编码的字节流,传给服务器端:原型String.getBytes(client_encoding) ;

    收到服务器的字节流后,使用client_encoding构造String对象作为getString的返回值给应用程序:原型String(byte[], …, client_encoding)。

  • 客户端编码

    客户端工具支持某种编码,是指客户端工具能够显示从数据库读取该种编码的字符,也能通过本工具将该种编码的字符提交到服务器端。

    指定会话的客户端编码:SET CLIENT_ENCODING TO 'value';

    查看数据库编码:Show client_encoding。

GDS导入/导出遇到的字符集问题和解决办法

问题一:0x00字符无法入库:ERROR: invalid byte sequence for encoding "UTF8": 0x00

原因:PG本身不允许文本数据中出现0x00字符,基线问题,其他数据库不存在该问题。

解决方法:

  1. 替换0x00字符。
  2. Copy、GDS都有“compatible_illegal_chars”这个选项,把这个开关打开(COPY命令、GDS外表可Alter),会把单字节/多字节的非法字符替换成“(空格)”/“?”。这样可以顺利导入数据,但会更改原数据。
  3. 建立encoding为SQL_ASCII的库,然后client_encoding也设置为SQL_ASCII(COPY命令中可设置,GDS外表也可设置),这种情况下可以避免字符集的特殊处理和转换,所有库内相关的排序、比较以及处理全部按照单字节处理。

问题二: GBK字符无法导入UTF-8库

原因:缺少GBK到UTF-8的转换函数。

解决方法:目前在r8c10已经补充了缺少的转换函数,包含106个字符,会尽快同步到r7c10的发货版本。具体字符,参考如下。

问题三:GBK转义符\(0x5C)问题。

原因:gbk本身作为server端编码存在很多问题,违背了PG的设计原则,即ascii码不能作为多字节字符的一部分(多字节字符每个字节的首位必须为1),不遵循这个原则可能会出现误判的问题。例子如下所示,gbk多字节字符可能会使用'\'作为第二个字符。

/* Else, it's the traditional escaped style */
for (bc = 0, tp = inputText; *tp != '\0'; bc++)
{
if (tp[0] != '\\')
tp++;

上述问题属于PG基线的代码实现问题。当然可以通过枚举所有可能出现的非法情形来解决,但是实现难度比较大,更为关键的是会增加判断逻辑降低处理效率,这也是社区坚决不允许引入gbk、SJIS(日文)等字符集的原因所在。

解决方法:尽量不使用GBK作为server端字符编码,可使用utf-8替换。另外,尽量不使用SQL_ASCII作为server端编码,无论导入的数据是什么字符集,SQL_ASCII都会按单字节入库,内部逻辑也都会按单字节处理,同样会遇到上述问题。GBK中包含0x5C的两字节字符参考如下。

我们使用cookie来确保您的高速浏览体验。继续浏览本站,即表示您同意我们使用cookie。 详情

文档反馈

文档反馈

意见反馈

0/500

标记内容

同时提交标记内容