0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

异构数据库排序一致性填坑教程

jf_78858299 来源:基础技术研究 作者:陈伟 2023-03-29 13:43 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

不同数据库对于字符值的排序规则各不相同,要达成在不同数据库上对于同样数据集执行查询语句的输出结果顺序一致性目标,则必须进行相应的设置或改写,本文通过对五种数据库的分析,对该问题进行了较为深入的分析。

01

概述.

在异构数据库之间进行数据迁移之后,为验证数据一致性,就需要比对源库和目标库的同表数据是否一致。

为了提高比对效率,一般而言会将数据排序并抽取出来后进行比对。

在实际过程中发现,指定了ORDER BY的同样两条SQL语句在不同数据库执行后,输出结果集的顺序经常会不同,本文关注该问题的产生并提供了相应的解决方案。

02

数据准备.

本文涉及的数据库为:

  • Oracle
  • MySQL
  • Postgres
  • Gauss(华为open Gauss)
  • GoldiLocks(科蓝)

所有的数据库均采用UTF8编码,且MySQL数据库不区分大小写建表。

在各数据库中创建一张测试表LEXSORT,该表仅有一个字符列NAME,具体语句如下:

CREATE TABLE LEXSORT ( NAME VARCHAR(10) );

然后将以下数据插入该表中:

INSERT INTO LEXSORT VALUES ('0');
INSERT INTO LEXSORT VALUES ('9');
INSERT INTO LEXSORT VALUES ('a');
INSERT INTO LEXSORT VALUES ('z');
INSERT INTO LEXSORT VALUES ('A');
INSERT INTO LEXSORT VALUES ('Z');
INSERT INTO LEXSORT VALUES ('_');
INSERT INTO LEXSORT VALUES ('~');
INSERT INTO LEXSORT VALUES (NULL);

03

查询结果.

在各个数据库中执行如下查询语句:

SELECT * FROM LEXSORT ORDER BY NAME;

其输出结果见下图:

图片

通过上面的结果可以发现:

其一,Oracle、Gauss和GoldiLocks的缺省排序保持一致,而与MYSQL和Postgres的各不相同。

其二,数据排序的不同体现在两个方面上

  • NULL值与非NULL字符值之间的顺序
  • 非NULL字符值之间的顺序

那么,这背后的机制是什么呢?又该如何解决呢?

04

数据库分析.

其实,产生这一现象的原因是各数据库的缺省排序规则各不相同所致。要解决这一问题,就需要从各数据库自身出发,了解其排序规则,并分别进行设置,才可能达到在不同数据库之间的一致性。

具体如何操作,后文将为您逐一展开。

Oracle数据库

**Oracle数据库提供了控制排序规则的参数,可以在系统级别和会话级别分别进行设置,一般而言,为了不影响其他应用,我们在会话级别进行设置即可。

**

1. NULL值的排序规则

Oracle支持在ORDER BY字句的每个字段上进行控制。可以指定为NULLS FIRST或NULLS LAST,即NULL值排在前面还是后面,缺省为NULLS LAST,即NULL值排在其它非NULL值的后面。

Postgres、Gauss和GoldiLocks也采用了同样的处理,后文不再赘述。

2. 非NULL值的排序规则

Oracle提供了控制参数NLS_SORT来指定排序规则,缺省的排序规则为BINARY,即按照字符串中每个字符的编码值进行排序,另一个常用排序规则为BINARY_CI,即按照二进制值进行排序,同时字母(A-Z,a-z)不区分大小写。

根据以上规则重新修改一下SQL语句或会话设置:

ALTER SESSION SET NLS_SORT=BINARY;
ALTER SESSION SET NLS_SORT=BINARY_CI;
SELECT * FROM LEXSORT ORDER BY NAME NULLS FIRST;

此时不同组合后查询的输出结果见下图:

图片

在上图中我们会注意到,不区分大小写排序时字符“_”的位置似乎有些“飘忽不定”。为了解决这个问题,我们把这些字符对应的编码数值出来看一下:

图片

根据编码值就会发现,“飘忽不定”的符号“_”的编码正好位于大写字母和小写字母之间,与它存在同样情况的还有5个字符。这就意味着,Oracle在采用BINARY_CI方式忽略字母大小写排序时,会自动将所有的字母视为了小写字母。

MySQL数据库

MySQL数据库在排序控制方面较弱,首先对于NULL值,MySQL自动视为NULLS FIRST,在ORDER BY字句中无相应的控制选项。

再看一下字母的排序,MySQL在建表时可以指定区分大小写或不区分大小写,一旦指定无法再修改,除非重新建表。

因此对于区分大小写的库,其排序规则会与Oracle的BINARY规则保持一致。

那么不区分大小写的呢?其实在前面的截图中已经有了体现,不过为了清晰起见,我们将Oracle设置为NULL FIRST和不区分大小写,单独拿出来再进行一下比较:

图片

此时我们会发现Oracle和MySQL的排序依然不一致!发生问题的依然是那个“飘忽不定”的“_”。

显然,稍加分析后我们就会知道,在不区分大小写的情形下,MySQL自动将所有字母视为了大写字母进行排序,正是因为这个区别,位于大写和小写字母之间的那六个字符又一次给我们惹了麻烦。

这样,不区分大小写建表的MySQL数据库与Oracle数据库的排序一致性就不存在完美的解决方案!

Postgres数据库

Postgres数据库的缺省排序对我来说一直是个迷……

图片

上图中,符号排在最前面,而“~”的编码却比“_”大,相当于降序;然后是数字和字母,而此时又是升序。鉴于本人对Postgres的研究有限,此处暂不作深究,只专注如何解决排序一致性问题。

Postgres提供了collate语句用以调整排序规则。将排序规则设置为C(必须用双引号括起来且为大写字母)或ucs_basic(如果用双引号括起则必须为小写)则代表按照字符编码排序,此时会区分大小写。

不区分大小写且又要按照编码值进行排序,目前暂未找到合适的方法。

需要注意指定collate和null first时的SQL语句顺序问题,当二者都需指定时示例语句如下,具体的输出结果大家可以自行测试:

SELECT * FROM LEXSORT ORDER BY NAME COLLATE ucs_basic NULLS FIRST;

Gauss数据库

大家都知道Open Gauss实际上是基于Postgres进行的定制,它在增加部分功能的同时也删减了部分Postgres的功能。不过对于ORDER BY子句,Gauss依然保留了Postgres的能力,也就是说collate子句同样适用于Gauss数据库,不过Gauss数据库的缺省排序规则即为按照字符编码值进行排序。

同时,Gauss数据库提供了排序函数NLSSORT,解决了不区分大小排序的问题,此时其排序结果与Oracle保持一致。使用该函数时需指定排序规则,不区分大小写的规则为generic_m_ci,具体SQL示例语句如下:

SELECT * FROM LEXSORT ORDER BY NLSSORT(NAME,'nls_sort=generic_m_ci');
SELECT * FROM LEXSORT ORDER BY NLSSORT(NAME,'nls_sort=generic_m_ci') NULLS FIRST;

几种不同组合的查询结果见下图(未写明null first时均为nulls last):

图片

****GoldiLocks数据库 ****

该数据库除了NULLS FIRST/LAST处理与Oracle保持一致外,并没有可以修改排序规则的参数,不过其缺省的排序规则即为按照字符编码值进行排序。因此在排序一致性方面依然可以与Oracle、Postgres、Gauss做到很好的兼容。

05

总结.

虽然本文起源于数据比对场景,不过通过上面的分析,我们可以意识到,排序一致性问题也是异构数据库迁移时必须考虑的问题之一。试想一下,如果不做SQL语句改造,原有的业务查询语句在新数据库中结果集排序可能会发生变化,进而导致后续处理结果也可能发生变化。

通过分析我们也发现,大多数数据库的排序一致性可以通过设置会话参数或修改SQL语句等来实现保持不变,不过部分数据库,例如本例中的MySQL,却缺乏完美的解决方案,那么我们就必须要分析其影响并进行应对。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据库
    +关注

    关注

    7

    文章

    3993

    浏览量

    67726
  • Oracle
    +关注

    关注

    2

    文章

    301

    浏览量

    37322
  • 数据集
    +关注

    关注

    4

    文章

    1230

    浏览量

    26041
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    如何解决数据库与缓存一致性

    缓存一致性 每次逢年过节的时候抢票非常艰难,放票的时候那么多人同时去抢票,如果所有人查询、购票等都去访问数据库,那数据库的压力得有多大,这时候很多都会引入缓存, 把车票信息放入缓存,这样可以减少
    的头像 发表于 09-25 15:25 1757次阅读
    如何解决<b class='flag-5'>数据库</b>与缓存<b class='flag-5'>一致性</b>

    理解数据库的事务:ACID,CAP和一致性

    理解数据库的事务,ACID,CAP和一致性
    发表于 05-04 16:25

    一致性规划研究

    针对一致性规划的高度求解复杂度,分析主流一致性规划器的求解策略,给出影响一致性规划器性能的主要因素:启发信息的有效,信念状态表示方法的紧凑
    发表于 04-06 08:43 12次下载

    加速器一致性接口

    Zynq PS上的加速器一致性接口(Accelerator Coherency Port, ACP)是个兼容AXI3的64位从机接口,连接到SCU(Snoop Control Unit),为PL
    发表于 11-17 15:04 4328次阅读

    速度不可测的异构多智能体系统一致性分析

    近年来,随着异构系统在实际中的广泛应用,异构多智能体系统一致性分析成为研究热点。针对阶部分智能体控制输入有界、二阶智能体速度不可测的异构
    发表于 11-17 15:08 9次下载

    时延异构多自主体系统的群一致性分析

    针对由阶自主体和二阶自主体构成的异构多自主体系统的静态群一致性问题,分别提出了在固定连接拓扑和切换连接拓扑结构下的静态群一致性算法。通过构造Lyapunov-Krasovskii函数
    发表于 12-19 18:48 0次下载
    时延<b class='flag-5'>异构</b>多自主体系统的群<b class='flag-5'>一致性</b>分析

    分布式大数据一致性检测

    关系数据库中可能存在数据一致性现象,关系数据库数据质量的个主要问题是存在违反函数依赖情况,为
    发表于 01-12 16:29 0次下载

    优化模型的乘偏好关系一致性改进

    针对乘偏好信息下的决策问题,引入乘偏好关系的有序一致性、满意一致性以及一致性指数等概念,建立以偏差变量最小化为目标函数的优化模型,进而构
    发表于 03-20 17:28 0次下载

    缓存与数据库一致性问题如何解决

    最近不是正好在研究 canal 嘛,刚巧前两天看了篇关于解决缓存与数据库一致性问题的文章,里边提到了种解决方案是结合 canal 来操作的,所以阿Q就想趁热打铁,手动来实现
    的头像 发表于 03-24 14:34 1112次阅读
    缓存与<b class='flag-5'>数据库</b><b class='flag-5'>一致性</b>问题如何解决

    什么是数据库营销

    数据库一致性(database consistency)由组值定义,数据库系统中的所有数据点都必须与这些值保持
    的头像 发表于 07-13 11:38 1062次阅读
    什么是<b class='flag-5'>数据库</b>营销

    虹科干货 | 什么是数据库一致性

    数据库一致性(database consistency)由组值定义,数据库系统中的所有数据点都必须与这些值保持
    的头像 发表于 07-13 13:56 1074次阅读
    虹科干货 | 什么是<b class='flag-5'>数据库</b><b class='flag-5'>一致性</b>?

    Redis缓存与Mysql如何保证一致性

    基本流程就是客户端A请求,先去删除缓存,然后将数据写入数据库,此时客户端B查询先去查询缓存,缓存没有返回,去查数据库,此时还没有完成主从同步,拿到是从的旧
    的头像 发表于 12-02 14:23 1582次阅读
    Redis缓存与Mysql如何保证<b class='flag-5'>一致性</b>?

    DDR一致性测试的操作步骤

    DDR一致性测试的操作步骤  DDR(双数据率)一致性测试是对DDR内存模块进行测试以确保其性能和可靠。在进行DDR一致性测试时,需要遵循
    的头像 发表于 02-01 16:24 3471次阅读

    深入理解数据备份的关键原则:应用一致性与崩溃一致性的区别

    深入理解数据备份的关键原则:应用一致性与崩溃一致性的区别 在数字化时代,数据备份成为了企业信息安全的核心环节。但在备份过程中,两个关键概念——应用
    的头像 发表于 03-11 11:29 1755次阅读
    深入理解<b class='flag-5'>数据</b>备份的关键原则:应用<b class='flag-5'>一致性</b>与崩溃<b class='flag-5'>一致性</b>的区别

    异构计算下缓存一致性的重要

    在众多回复中,李博杰同学的回答被认为质量最高。他首先将缓存一致性分为两个主要场景:是主机内CPU与设备间的一致性;二是跨主机的一致性
    的头像 发表于 10-24 17:00 2522次阅读
    <b class='flag-5'>异构</b>计算下缓存<b class='flag-5'>一致性</b>的重要<b class='flag-5'>性</b>