
暂无个人介绍
查询优化概念查询变换的概念非常简单,就是基于关系代数的等价变换规则,将查询的一种形式转换为另外一种等价但更为高效的形式,通过这种转换,既可以保证查询结果的正确性,又可以提升查询的执行效率。优化器可以完成的变换非常多,如果将每一种变换视为一种改写规则的话,几百个规则也是比较常见的。其中有些变换(规则),总是可以让查询变得更为高效,我们称其为启发式变换,但有些则不一定,需要基于代价来决定。本篇文章将介绍PolarDB实现的一个启发式查询变换——join消除。该功能在PolarDB for MySQL 8.0.2.2.9版本上线。join消除join可以说是所有SQL语句中最为常见的算子,当然也是最为耗时的算子,一个join操作,需要将作为两边的关系(表),根据join条件中指定的连接列,拼接到一起向上层算子输出,笼统的来说,这是一个具有M * N运算复杂度的操作,和scan/aggregation等相比要高出一个因数,因此如何实现好的join算法、如何决定最好的join执行顺序,是每个数据库系统不得不面对的核心问题。那么从另外一个角度出发,是不是可以基于SQL查询中的某些特定语义,从一开始就想办法消除掉不必要的join操作呢?例如如下这种非常简单的情况:create table t1 (id int, PRIMARY KEY(id)); create table t2 (id int, t1_id int, constraint `t1_id_fk` foreign key (`t1_id`) references `t1` (`id`) ); select t2.id from t2 join t1 on t2.t1_id = t1.id;可以看到t2的t1_id列是t1 id列的外键,因此对t2的每一行,一定有且只有一行t1的数据可以和t2 join上,同时整个查询最终并不需要t1表的数据,查询可以简化为:select t2.id from t2;这避免了对t1表的访问和大量行的连接操作,可以想见会有非常明显的性能提升。PolarDB实现PolarDB的优化器基于MySQL,原始是没有任何join消除能力的,在线上值班过程中,遇到有客户从MariaDB迁移过来后发现查询性能回退非常多的情况。排查后发现,MariaDB是具有join消除能力的,客户的查询从原来的3表left join变为了单表,执行时间大大缩短。为此我们调研了MariaDB的实现,觉得其原理是有参考性的,但实现中所能覆盖的场景还不全面,在一些简单情况以及复杂嵌套的场景下(semi-join),支持的还很不够,因此基于MySQL 8.0的codebase做了自己的实现。基本原理基本的思路并不复杂,考虑如下这个joinouter_table LEFT JOIN (inner_table) ON condition(outer_table,inner_table)由于是LEFT JOIN,外表的数据是不会丢失的,如果同时可以保证:1. 对外表的任一行,内表能匹配join条件的行数有且仅有一行;2. 在LEFT JOIN以外,不再有其他地方需要引用内表的数据。则这个LEFT JOIN就可以安全的消除掉。如何保证这种唯一性呢?第一个想到的自然就是唯一/主键索引,如果内表的join列是唯一索引列,自然是满足输出一行这个要求。但实际的查询不可能总是这么简单,我们可以考虑如下几种情况:● 唯一索引包含多列?● inner table包含多张表?● inner table中包含新的left join?● inner table本身是个derived table?看似简单的join消除问题一下子就变得复杂,但我们可以通过逐步分解,通过判定每一个子问题来完成是否可消除的判断:● 一个LEFT JOIN的内部(单表/多表),只有当所有表都保证唯一输出一行时,整个LEFT JOIN才能消除;● 对内侧的每个单表,当其join条件中涉及的所有列,是某个唯一索引的超集时,该表才能保证输出一行;● 如果内侧再次包含有LEFT JOIN,则要先深度递归进去,判断这个内侧的LEFT JOIN是否可以消除,消除后再返回来考察外层;● 如果内层包含derived table且derived table中包含group by,则从外层来看,group by列也就是derived table的主键列。遵循以上的思路依次处理每个子问题,就可以实现对各种复杂场景的可消除性的判定。具体算法和代码这里就先略过了。看下上面几个问题的具体效果:create table t1 (a int); create table t2 (a int primary key, b int); create table t3 (a int primary key, b int); 1. inner table包含多张表? select t1.a from t1 left join (t2 join t3) on t2.a=t1.a and t3.a=t1.a; => select t1.a from t1; 2. inner table中包含新的left join? select t1.* from t1 left join (t2 left join t3 on t3.a=t2.b) on t2.a=t1.a; => select t1.* from t1; 3. inner table本身是个derived table? select t1.* from t1 left join ( select t2.b as v2b, count(*) as v2c from t2 left join t3 on t3.a=t2.b group by t2.b ) v2 on v2.v2b=t1.a; => select t1.* from t1;当然各种其他场景还有很多,但只要遵循前面提到的几个判定原则,就都可以逐一的完成消除。与PostgreSQL的对比PG在计算层的能力一直是其比较引以为傲的点,其统计信息和代价模型是非常优秀的,加上更完备的join ordering算法,确实可以生成较高质量的执行计划。不过在查询变换方面,Postgres的能力也只能说相当一般(有机会后续会写文章介绍PG的优化器),它也实现了left join消除的功能,基本思路与PolarDB的一致,基于内表的唯一性判定,但其支持的场景就更为简单了:● 只能支持left join的内侧是一个base relation,或者是一个subquery;这严重限制了join消除应用的范围,不过好的一点是,当内侧是个subquery(derived table)时,它不仅支持基于group by列的唯一性检查,对于distinct / set operation,都有相应的判断机制,具体实现可参见:query_is_distinct_for(Query *query, List *colnos, List *opids)这个函数,不过其思路和实现都非常简单,PolarDB后续也会类似去扩展下。与MariaDB的对比我们也针对各种场景和MariaDB做了一些对比,发现在对一些场景的支持上,MariaDB的策略比较粗糙或不太合理:● 对semi-join的处理在MariaDB中,如果一个子查询在LEFT JOIN的ON条件中,就直接阻止了它转为semi-join,目的是为了让它仍然保留为一个谓词条件,从而在join消除的逻辑中避免对semijoin的复杂处理,但很明显这个存在误伤:如果这个LEFT JOIN本身无法被消除,semi-join岂不是也不能用了?仍然沿用上面t0/t1/t2/t3的schema:EXPLAIN SELECT count(*) FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b = t3.b AND EXISTS ( SELECT t0.a FROM t0 WHERE t0.a = t3.b ) ) ON t1.a = t2.a;这里由于t2.b = t3.b这样的join条件,t3.b不是唯一键,这个查询是无法消除join的,而MariaDB的执行计划如下:+------+--------------------+-------+--------+---------------+---------+---------+-----------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+--------------------+-------+--------+---------------+---------+---------+-----------+------+-------------+ | 1 | PRIMARY | t1 | ALL | NULL | NULL | NULL | NULL | 4 | | | 1 | PRIMARY | t2 | eq_ref | PRIMARY | PRIMARY | 4 | test.t1.a | 1 | Using where | | 1 | PRIMARY | t3 | ALL | NULL | NULL | NULL | NULL | 2 | Using where | | 2 | DEPENDENT SUBQUERY | t0 | ALL | NULL | NULL | NULL | NULL | 4 | Using where | +------+--------------------+-------+--------+---------------+---------+---------+-----------+------+-------------+可以看到t0的相关子查询选择了最原始的执行方式,如果t0表的数据量大,性能会非常糟糕,而PolarDB仍然支持:+----+--------------+-------------+------------+--------+---------------------+---------------------+---------+--------------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+--------------+-------------+------------+--------+---------------------+---------------------+---------+--------------+------+----------+-------------+ | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | NULL | | 1 | SIMPLE | t2 | NULL | ALL | PRIMARY | NULL | NULL | NULL | 2 | 100.00 | Using where | | 1 | SIMPLE | t3 | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 100.00 | Using where | | 1 | SIMPLE | <subquery2> | NULL | eq_ref | <auto_distinct_key> | <auto_distinct_key> | 5 | je_test.t3.b | 1 | 100.00 | Using where | | 2 | MATERIALIZED | t0 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | NULL | +----+--------------+-------------+------------+--------+------------------t0还是通过semi-join MATERIALIZATION的方式来实现,效率会高很多。对序列LEFT JOIN的处理即使在一些简单场景下,MariaDB的处理也不完备:EXPLAIN SELECT count(*) FROM t1 LEFT JOIN t2 ON t1.a = t2.a LEFT JOIN t3 ON t2.b = t3.a;MariaDB由于算法和实现的限制,效果如下:+------+-------------+-------+--------+---------------+---------+---------+-----------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+-------------+-------+--------+---------------+---------+---------+-----------+------+-------------+ | 1 | SIMPLE | t1 | ALL | NULL | NULL | NULL | NULL | 4 | | | 1 | SIMPLE | t2 | eq_ref | PRIMARY | PRIMARY | 4 | test.t1.a | 1 | Using where | +------+-------------+-------+--------+---------------+---------+---------+-----------+------+-------------+在这样一个简单查询中,很明显t2/t3都是可以消除掉的,但MariaDB竟然只能处理t3表的join消除。PolarDB实现的则更为彻底:+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+ | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | NULL | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+性能提升join的消除是一个必然产生收益的启发式变换,根据表的数据量、访问方式的不同,产生的性能差异可能千差万别,但一般来说,性能都会有很大提升,这里就用一个线上客户的实际查询做个对比:SELECT count(*) FROM `shop_customer` `sc` LEFT JOIN `car` `ca` ON `sc`.`car_id` = `ca`.`id` LEFT JOIN `company` `co` ON `sc`.`company_id` = `co`.`id`; => SELECT count(*) FROM `shop_customer` `sc`;很明显最后可以变成单表的查询,在消除前,执行时间是7.5s,消除后是0.1s,提升了75倍。比上述效果更凸显的例子比比皆是,尤其是内层包含多张表的嵌套时。总体来说,join的开销通常情况下都比较大,能够消除都会有明显提升。总结我们目前还在增加很多更先进的查询变换能力,毕竟MySQL原生可以支持的还太少了,但这也是逐步补充的过程,需要针对线上的客户场景和实际需求作为素材不断积累。在这个过程中我们遇到了3个最基础的问题:1. MySQL的各个原有变换,加的都比较"随意",其自身和原有处理流程的耦合导致增加新变换很困难;2. 变换执行时机不合理,不同变换之间是存在一定前后依赖关系的,这种关系并没有很好的被利用;3. 某些变换并不一定带来收益,需要基于统计信息 + 代价来做决定,这种决定MySQL是完全不支持的,变了就是变了,无论效果好坏。为了解决这3个基本问题,团队在做的一个非常重要和复杂的事情,就是重构MySQL的查询变换流程:1. 解耦原有的resolve + transform交错的流程,把变换作为单独的步骤,以"规则"为单位,各自独立完成,这样变换就可以通过添加新规则而不断独立扩展;2. 在基于规则的抽象后,引用枚举框架来枚举不同变换(规则)间的先后顺序,通过反复迭代也可使得相互依赖的规则都可以按照更优的顺序被执行;3. 实现CBO模块的可重入+可重用能力,这样可以基于代价来决定是否执行变换。
01-概述在日常数据库操作中,用户总是谈DDL色变,原因在于总是担心DDL的执行会影响业务SQL,这里面最核心的因素在于DDL持有的MDL表锁导致的锁堵塞问题。另一方面,由于DDL类型众多,用户难以区分不同类型DDL的锁行为,无法判断执行DDL可能导致的后果,这进一步加剧了该问题的复杂度。通过多年大量线上实例的经验积累, 我们非常理解用户在面对这类MDL锁问题时的困惑。本文整理总结了云原生数据库PolarDB MySQL内核团队在全链路MDL锁治理方面的经验和进展,鞭策我们为“DDL无锁”、为用户可以毫无担忧地执行DDL而持续努力。针对MDL锁的背景知识,我们有持续的内核月报在介绍相关原理,感兴趣的读者可以自行查询《常用SQL语句的MDL加锁及源码分析》[1]和《MDL锁实现分析》[2]。在开始全文前,我们首先回顾用户主要关注哪些方面的DDL锁问题:1.什么时候拿锁很不幸的是,无论是MySQL内核原生的DDL,还是各种第三方插件(gh-ost、pt-osc,以及云厂商们的“无锁变更”),几乎所有的DDL都会申请表级别的MDL互斥锁。这里的核心原因在于:DDL的目标是表结构/表定义变更,它必然会修改元数据/字典信息,因此DDL依赖MDL锁来完成元信息、文件操作和相应缓存信息的正确更新。当DDL修改元数据时,它申请表级别的MDL互斥锁,从而堵塞并发的元数据查询/修改操作,继而可以线程安全地更新元信息缓存,从而保证所有线程用正确版本的元数据解析对应版本的表数据。说到这里,很多熟悉MySQL的读者一定会问,那为什么gh-ost等第三方插件在做DDL时似乎呈现出一种类似“无锁”的表现呢?其实这里的核心差别在于,MySQL内核和第三方插件,在处理“拿不到锁”这个问题时采用了完全不一样的策略。2.拿不到锁会导致什么问题(雪崩vs饥饿,本文关注的核心问题)相比于第三方插件,MySQL内核的MDL拿锁机制简单粗暴:当DDL申请MDL-X(互斥锁)时,如果目标表存在未提交的长事务或大查询,DDL将持续等待获取MDL-X锁。由于MDL-X锁具有最高的优先级,DDL在等待MDL-X锁的过程中将阻塞目标表上所有的新事务,这将导致业务连接的堆积和阻塞,继而可能带来整个业务系统「雪崩」的严重后果。为了避免这个问题,MySQL社区开发了很多外部工具,比如pt-osc和github的gh-ost。它们均采用拷表方式实现,即创建一个空的新表,通过select + insert的方式拷贝存量数据,然后通过触发器或者Binlog的方式拷贝增量数据,最后通过rename操作切换新表和旧表。云厂商的各种工具,例如DMS的无锁变更也与这些外部工具原理类似。但很遗憾,这种方式也存在明显的劣势:1. 可能由于大事务/大查询的存在,DDL持续拿不到锁,持续等待直到反复失败(「饥饿」);2. 不管是Instant DDL(例如秒级加列),还是仅增加二级索引,第三方工具都无脑选择了全表重建的方式,通过大幅牺牲性能来追求稳定性。我们之前的测试表明(月报链接[3]),相比于内核原生的DDL执行方式(INSTANT / INPLACE / COPY),gh-ost有着10倍甚至几个数量级的性能下降,这在数据量快速增长的今天是完全无法忍受的。不管是第三方插件,还是MySQL内核,很遗憾,任何一种方式都不能在所有场景里都达到最优。PolarDB MySQL内核团队尝试在保留最佳性能的前提下,同时解决雪崩和饥饿这两个问题。3.拿到锁又会导致什么问题(持有锁的时间,Fast DDL将在后续文章中介绍)在解决了「拿不到锁」的问题后,我们同样要解决「拿到锁后」会有什么问题,即如果互斥锁持有时间过久,同样会导致业务堆积雪崩等问题。熟悉MySQL的用户都知道,MySQL有三种DDL类型,分别是「INSTANT DDL」、「INPLACE DDL」和「COPY DDL」。其中,Online DDL(用户常说的“非锁表”DDL,包括INSTANT DDL和绝大多数INPLACE DDL)在执行DDL期间绝大多数时刻并不锁表,只在修改元数据时短暂持有表的MDL-X锁(持有时间一般秒级),用户体验良好。当前的MySQL 8.0已经实现了常见高频DDL的Online能力,例如增加索引、秒级加列,加减主键等等。但是,因为涉及一些SQL层的操作,目前依然存在COPY类型的DDL,它在执行DDL期间「全程锁表」(只能读不能写),例如修改表的字符集、修改列类型等操作。针对这类COPY DDL,PolarDB MySQL的解决方案是扩展Online DDL(不锁表)的范围,例如支持Instant Modify Column(秒级修改列类型),例如尝试在SQL层支持所有DDL的Online能力,我们将这类能力统称为「Fast DDL」,笔者后续会统一介绍这方面的工作,本文不再赘述。相比于MySQL,PolarDB的集群架构使得这一问题变得更加复杂:MDL锁不仅要关注单个节点,更要关注集群多个节点/集群同步链路上的锁问题,需要集群维度的全链路解决方案。熟悉MySQL的用户,对基于Binlog的MySQL主备集群一定非常熟悉。在依赖Binlog的MySQL主备复制集群上,主备节点是逻辑隔离的。也就是说,主节点的MDL锁行为,并不会对备节点的MDL锁有任何影响,因此MySQL只需要考虑单个节点的MDL锁问题。然而,PolarDB MySQL是基于共享存储的架构。以一写多读集群为例,写节点和多个只读节点共享同一个分布式存储,依赖物理复制完成不同节点之间的数据同步。写节点在做DDL操作时,多个只读节点都会看到DDL过程中的实时数据。因此,PolarDB的MDL表锁,是一个集群维度的分布式锁,需要考虑多节点上的锁堵塞问题。基于PolarDB的架构特征,结合多年线上运维经验,我们认为从集群维度看,要实现用户体验良好的DDL锁机制,需要达到以下几个目标:1. 解决雪崩问题。不管是RW写节点上的大事务/大查询,还是只读节点集群上任何一个节点的大事务/大查询,抑或是RW->RO物理复制链路上任何可能的堵塞点,都可能导致DDL拿不到锁,从而触发业务雪崩。针对这类问题,PolarDB MySQL在去年发布了Non-Block DDL功能(用户文档[4],月报链接[3]),可以保证即使在无法获得MDL-X锁的情况下,依然允许新事务访问目标表,从而保证整个业务系统的稳定。该功能受到了很多客户的欢迎,多个客户认为这个功能是执行DDL的刚需能力;2. 解决饥饿问题。Non-Block DDL在拿不到锁时,通过Retry等方式避免DML的堆积和雪崩。然而如果存在大事务或者大查询,DDL可能一直拿不到锁而持续失败。进一步的,随着PolarDB MySQL的大客户越来越多,单实例不乏10+个只读节点的用户,这大大增加了集群维度出现大查询/大事务的概率,导致DDL拿不到锁。针对这类问题,PolarDB MySQL最近推出了Preemptive DDL能力(用户文档[5]),即赋予DDL最高的MDL锁权限,在满足条件的情况下主动kill堵塞它的事务/查询,保证DDL的顺利执行;3. 解决表「数据变更」、「元信息/元信息缓存变更」和「文件操作」 这三者之间的数据一致性和实时性问题。众所周知,TP数据库对事务的要求极高,而DDL过程中涉及的数据变更、表结构变更和文件操作这三者之间需要在任何一个时间点都要满足Consistency的要求。而在基于共享存储的PolarDB MySQL中,这一问题变得更加复杂:不仅在所有阶段(正常数据同步、数据库Recovery、按时间点还原等等)需要满足多节点在数据变更、表结构变更和文件操作这三者的一致性要求,而且需要保证良好的性能,满足强实时性的要求。针对这类问题,PolarDB MySQL做了一系列的优化,由于这部分内容要求的数据库背景和对代码的理解要求过高,并且用户业务无需感知,本文不展开介绍这一部分的工作;4. 解决DDL过程中RW->RO物理复制链路的堵塞问题。上线五年以来,PolarDB MySQL支持了大量行业,不同行业的业务场景对DDL的要求是不同,具体表现在: ● 高频DDL导致的高性能MDL锁需求,例如SaaS等行业场景,DDL是个非常常见和高频的操作。PolarDB需要避免分布式MDL锁和物理复制的耦合性,避免因为锁堵塞等行为影响整个集群的数据同步;● DDL伴随高负载的业务压力,例如在大压力场景下加索引。这种场景会产生大量的redo日志,PolarDB需要保证DDL过程下物理复制链路的稳定性、低延迟。针对上述问题,PolarDB MySQL在物理复制全链路做了优化(用户文档[6]),采用了异步线程池和反馈机制,解耦了MDL锁同步和物理复制的强耦合性,并优化了DDL过程中redo日志的同步&复制速度(用户文档[7]),满足了大压力DDL场景下的同步要求;5. 持续演进的能力:DDL & DML MVCC。如前文所述,在极限情况下,用户依然需要手动执行Preemptive DDL来解决饥饿问题。我们一直在想,有没有更理想的方式,用户可以完全无感知MDL锁的存在。熟悉InnoDB的读者一定知道,InnoDB提供了行级别的MVCC能力,即使修改某行数据的事务没有提交,这时候另一个事务查询同一行数据时,事务根据它的时间戳,通过undo list构建出对应的版本,无需等待锁的释放。细心的读者一定会问,为什么DDL没有提供DDL和DML互不堵塞这种MVCC的能力?原因在于,DDL操作涉及了文件操作/表数据/元信息/表结构缓存等多种信息的变更,因此为了达到DDL & DML的MVCC能力,涉及大量的模块/代码修改,带来的代码切口过大,稳定性风险较高。但是为了满足客户的诉求,PolarDB内核团队一直在这条路径上试图找到工程上的最优路径。在PolarDB 8.0.2的下个版本中,我们将提供给用户这一实验室功能,即满足Instant Add Column这种高频DDL与DML的「MVCC」能力,后续我们会陆续支持Add Index等高频DDL与DML的MVCC能力。02-Non-Block DDL(雪崩问题)2.1 功能概述如前文所述,非阻塞DDL(用户文档[4],月报链接[3])用于解决因MDL锁堵塞而导致的业务雪崩问题。非阻塞DDL功能采用了和第三方插件(gh-ost、pt-osc)类似的拿锁逻辑:当DDL操作获取MDL锁失败时,拿锁线程会进入短暂的Sleep阶段,接着重新尝试获取MDL锁。通过此种方式,非阻塞DDL保证了DDL执行过程中,业务真正的online。非阻塞DDL目前已经灰度一段时间,受到大量用户的欢迎,后面会尝试默认开启此功能。此外,我们将在8.0.2的2.2.15版本中,支持集群维度的Non-Block DDL:如果主节点已经获取MDL锁,但是只读节点同步MDL锁堵塞(当前默认堵塞时间为50s,由参数loose_replica_lock_wait_timeout控制),Non-Block DDL会在集群维度重试拿锁的操作,从而实现集群维度的非阻塞DDL。2.2 测试效果可以通过设置参数loose_polar_nonblock_ddl_mode为ON来打开非阻塞DDL功能(用户文档[4]),下面给出使用sysbench模拟用户业务,对比开启Non-Block DDL功能和使用原生DDL功能对业务的影响。1. 在目标表sbtest1上开启一个事务但不提交,该事务将持有目标表sbtest1的MDL锁。begin; select * from sbtest1;2. 在新会话中,分别在开启和关闭Non-Block DDL情况下,对表sbtest1进行加列操作,观察TPS的变化情况。# 由于当前session 1大查询持有MDL锁,当前DDL无法获取MDL锁,被堵塞 alter table sbtest1 add column d int;▶︎ 关闭Non-Block DDL功能TPS持续跌零,默认超时时间为31536000,严重影响用户业务。▶︎ 开启Non-Block DDL功能TPS周期性下降,但未跌零。对用户业务影响较小,能保证业务系统的稳定。03-Preemptive DDL (饥饿问题)3.1 功能概述上文非阻塞DDL解决了DDL获取MDL锁阻塞导致的业务雪崩问题,但是如果DDL迟迟无法获取MDL锁,会导致DDL执行频繁失败。目前线上值班偶尔会遇到由于RO上面存在大查询、长事务导致的DDL执行失败问题,并返回错误ERROR 8007 (HY000): Fail to get MDL on replica during DDL synchronize。由于此报错与PolarDB共享存储的架构相关,与传统MySQL不一致,用户经常会一头雾水,无从下手。当前已有官方文档(执行DDL操作提示“获取不到MDL锁”[8])介绍这类问题的解决方案,用户可以根据此文档找到只读节点上持有表MDL锁的事务,手动进行Kill,来保证DDL同步MDL锁的成功。但是这种方式在部分场景下依然非常晦涩,一方面用户进行kill操作的时间窗口有限(当前同步MDL锁超时时间为50秒,可通过loose_replica_lock_wait_timeout进行调整),另一方面随着PolarDB上面客户不断增多,出现了许多10+个只读节点的集群,手动kill操作显得狼狈且低效,为此我们提供了抢占式DDL功能。当只读节点通过物理复制,解析到当前表上有DDL操作时,只读节点会尝试获取表的MDL锁。如果此时表上存在大查询或长事务时,开启Preemptive DDL后(用户文档[5]),如果只读节点在预期时间内无法获得MDL锁,便会尝试kill掉占有MDL锁的线程,从而保证MDL锁同步的成功,解决DDL的饥饿问题。3.2 测试效果可以通过设置参数loose_polar_support_mdl_sync_preemption为ON来打开抢占式DDL功能。下面给出DDL同步MDL锁被只读节点长事务堵塞时,开启和关闭抢占式DDL的实验效果。▶︎ 关闭抢占式DDL功能1. 在只读节点上查询test.t1:mysql> use test Database changed #大查询,执行100s mysql> select sleep(100) from t1;2. 在主节点进行加列操作,被block,执行失败:mysql > alter table t1 add column c int; ERROR 8007 (HY000): Fail to get MDL on replica during DDL synchronize由于只读节点存在大查询,同步MDL锁失败,DDL执行失败,并回滚。▶︎ 开启抢占式DDL功能1. 在只读节点上查询test.t1:mysql> use test Database changed #大查询,执行100s mysql> select sleep(100) from t1;2. 在主节点进行加列操作操作,被block,等待一段时间,发生抢占,执行成功:mysql> alter table t1 add column c int; Query OK, 0 rows affected (11.13 sec) Records: 0 Duplicates: 0 Warnings: 0开启抢占式DDL功能后,加列操作完成,同时可以看到只读节点(右图),大查询连接已经断开。04-多版本DD:DDL & DML的MVCC能力4.1 功能概述不管是Non-Block DDL还是Preemptive DDL,都是在有互斥锁的场景下,尽可能最优地满足用户的DDL变更需求。然而,用户在部分场景下依然要感知MDL锁的存在,例如在极限场景下,用户依然需要手动触发Preemptive DDL,来解决DDL饥饿的问题。我们一直在探索,是否可以实现DDL与DML更细粒度的并发控制,类似于InnoDB MVCC能力。然而,如前文所述,DDL是个复杂操作,其执行过程涉及文件操作/表数据变更/元信息变更/表缓存处理等一系列流程。因此,考虑到MySQL代码的强耦合性,我们对这一目标做了切分,在控制代码切口和稳定性风险的情况下,逐步支持这一能力。在第一阶段,我们优先支持线上高频DDL与DML的MVCC能力,即按照statement维度,满足Instant Add Column与DML的MVCC能力(用户文档待新版本8.0.2上线)。为了兼容MySQL的默认表现,我们不仅支持DDL和未提交事务的并发,而且支持DD的readview,使得跨越了DDL的DML事务可以选择以RC或者RR的隔离级别读取表结构信息,从而让用户自行决定使用新或者旧的表定义。4.2 测试效果具体的效果如下:步骤一:开启会话A,创建一个新的表t1并插入一些数据;随后开启一个新事务,在事务中进行数据的插入和更新操作,但事务不提交:步骤二(DDL不会被未提交的事务所堵塞):开启一个新的会话B,查询performance_schema,此时t1的MDL正被会话A中未提交的事务持有。进行DDL操作(add column),该操作可以立即完成,而不会被未提交的事务阻塞。步骤三(跨DDL的事务可以选择访问表时使用的隔离级别):回到第一个会话A,将表访问的隔离级别参数table_def_isolation设置REPEATABLE-READ,因为DDL的执行在该事务之后,因此新增的列c不可见,该事务将始终看到与事务开始时一致的表定义。将table_def_isolation设置为READ-COMMITTED,因为DDL已经提交,列c将对该事务可见。提交事务后,DD的readview随之释放,随后将只能看到最新的表结构。05-全链路优化的分布式MDL锁(多节点数据同步问题)目前的云原生数据库,不论是PolarDB,或者其它厂商数据库,都以“存算分离”+“共享存储”的形态提供一写多读的能力。对这类架构感兴趣的读者,可以阅读我们之前的相关月报(PolarDB 物理复制解读[9],PolarDB 物理复制热点页优化[10])。对这类针对存算分离场景下IO优化感兴趣的读者,可以阅读我们去年发表在VLDB上的相关论文(CloudJump: Optimizing Cloud Databases for Cloud Storages[11])。简单来说,云原生数据库依赖物理复制(Redo日志)完成不同节点之间的数据同步,而DDL触发的元数据/表数据/文件变更同样随着物理复制完成多节点的同步,这三者之间依赖分布式MDL锁提供实时&一致性的保证。然而,当MDL锁和物理复制相耦合时,会产生一系列的问题,尤其是日志流 / 锁同步 / 文件操作这三者之间的一致性问题。这里,我们介绍与用户密切相关的两类问题:5.1 异步元数据锁同步高频DDL场景下分布式MDL锁的稳定性&实时性。尤其是在MDL锁被堵塞时,不能影响正常物理日志的进行。为了解决这个问题,PolarDB设计了全新的分布式MDL锁机制(用户文档[6],已默认开启),主要体现在以下两个方面:● 异步MDL锁复制:将分布式MDL锁与物理复制相互解耦,实现了即使在等待MDL锁时,只读节点仍能继续解析并应用物理日志,保证了物理复制的实时性;● 并行MDL锁:为了优化高频DDL场景下分布式MDL锁的性能,我们采用一组线程池来并发响应MDL锁的需求。即使某个MDL锁被堵塞,也不会影响其它线程去获取MDL锁,并且这部分线程池会随着DDL的情况动态调整,保证了MDL锁同步的高并发。5.2 DDL物理复制优化高压力DDL场景下物理复制的稳定性&实时性。PolarDB中的数据是通过B-Tree来维护索引的,然而大部分Slow DDL操作(如增加主键或二级索引、Optimize Table等)往往需要重建或新增B-Tree索引,导致大量物理日志的产生。而针对物理日志进行的操作往往出现在DDL执行的关键路径上,增加了DDL操作的执行时间。此外,物理复制技术要求只读节点解析和应用这些新生成的物理日志,DDL操作而产生的大量物理日志可能严重影响只读节点的日志同步进程,甚至导致只读节点不可用等问题。针对上述问题,PolarDB提供了DDL物理复制优化功能(用户文档[7],已默认开启),主要体现在以下两个方面:● 主节点加快DDL写日志速度:在主节点写物理日志和只读节点应用物理日志的关键路径上做了全面的优化,使得主节点在执行创建主键DDL操作的执行时间最多可减少20.6%;● 只读节点加快物理复制速度:只读节点解析DDL的复制延迟时间最多约可减少至原来的0.4%,并且明显降低了CPU / Memory / IO的硬件开销。以下面测试数据为例,在主节点上不论执行1个DDL还是8个DDL,只读节点非常稳定,没有明显抖动。06-总结DDL是PolarDB所有SQL操作中最繁重的一种,DDL的易用性是PolarDB良好使用体验非常重要的一环。本文总结介绍了PolarDB在全链路MDL锁治理的经验和进展,把简单留给客户,把复杂留给自己,持续优化用户的使用体验。后续将总结介绍PolarDB在Fast DDL方面的工作,PolarDB内核团队将始终如一地为用户打造最佳的云原生数据库。用户文档及相关技术链接[1] 常用SQL语句的MDL加锁及源码分析 : http://mysql.taobao.org/monthly/2018/02/01/[2] MDL锁实现分析 : http://mysql.taobao.org/monthly/2015/11/04/[3] 非阻塞DDL月报介绍 : http://mysql.taobao.org/monthly/2022/10/01/[4] 非阻塞DDL用户文档 :https://help.aliyun.com/document_detail/436462.html[5] 抢占式DDL用户文档 : https://help.aliyun.com/document_detail/2326304.html[6] PolarDB 并行元数据锁同步 : https://help.aliyun.com/document_detail/200678.html[7] DDL物理复制优化 : https://help.aliyun.com/document_detail/198213.html[8] 执行DDL操作提示“获取不到MDL锁” : https://help.aliyun.com/document_detail/611732.html[9] PolarDB 物理复制解读 : http://mysql.taobao.org/monthly/2018/12/05/[10] PolarDB 物理复制热点页优化 : http://mysql.taobao.org/monthly/2021/03/04/[11] VLDB论文链接CloudJump: Optimizing Cloud Databases for Cloud Storages :https://www.vldb.org/pvldb/vol15/p3432-chen.pdf
一、DTS链路内ETL介绍DTS是一个数据迁移和同步服务,通常用于数据搬迁或实时数据传输。DTS在数据同步链路基础上,提供流式数据ETL数据处理功能,支持使用DSL(Domain Specific Language)脚本语言灵活地定义数据处理逻辑二、DTS链路内ETL适用场景2.1 数据脱敏对敏感信息如电话号码,身份证号,地址等进行打码等方式脱敏, 如: 针对电话号码脱敏原始数据: 18700001111ETL处理之后的数据: 187****11112.2 数据归一化根据规则将一组数据映射到另一组数据,如根据成绩将成绩 >=60分的归类为A, 将成绩小于60分的时归类为B原始数据5999ETL处理之后的数据BA2.3 同步过程中附加列业务A有以下用户表CREATE TABLE USER_INFO ( USER_ID INT NOT NULL, USER_NAME VARCHAR(32), PRIMARY KEY(USER_ID) )在使用DTS数据同步时,希望在不改变源库表结构的前提下同步到其他的分析数据库上,并记录数据更时间 UPDATE_TIME原始数据:USER_IDUSER_NAME31846731张三ETL处理之后的数据:USER_IDUSER_NAMEUPDATE_TIME31846731张三2023-04-01 12:51:462.4 数据过滤"ETL数据过滤"和"DTS SQL条件过滤任务数据" 功能对比ETL数据过滤SQL条件过滤作用域DTS实例级表级别语法DSL 语法SQL 语法字段内容数据库表字段内容,DTS附加的字段(如DML 类型,日志提交时间等)数据库表字段内容条件表达式DTS附加属性和数据表达式组成过滤条件( 如过滤值ID=10的DELETE日志同步)SQL表达式推荐使用方法:DTS SQL条件过滤任务数据 适用于依据表内容进行数据过滤;ETL数据过滤适用于实例级配置,以及结合增量日志属性进行数据过滤2.5 数据类型转换根据规则将数据从一种类型映射到另一种类型,如将VARCHAR类型映射到INT类型原始数据12345699.99ETL处理之后的数据1234561002.6 非法值处理再异构数据库同步过程中, 存在一系列不兼容数据类型,例如Oracle同步到MySQL的链路,Oracle TIMESTAMP('4712BC-01-01 00:00:00' to '9999-12-31 23:59:59')与MySQL TIMESTAMP(0000-00-00 00:00:00, 1970-01-01 00:00:00 to 2038-01-19 03:14:07) 数据类型范围不兼容,需要进行数据转换原始数据0001-01-01 00:00:01ETL处理之后的数据1970-01-01 00:00:01三、适用DTS控制台配置链路内ETL的方法3.1 登陆DTS新版控制台并配置任务参考公有云DTS文档:https://help.aliyun.com/document_detail/211600.html 配置任务。DTS任务配置有 配置源库及目标库信息、配置任务对象及高级配置、高级配置、预检查、购买 五个步骤,配置ETL功能在 高级配置 步骤,参考3.23.2 配置ETL功能参考公有云DTS文档: https://help.aliyun.com/document_detail/411259.htm 在配置任务对象及高级配置步骤的高级配置中,配置ETL功能选择是,在输入框中按照数据处理DSL语法填写数据处理语句单击下一步保存任务并预检查,完成后续步骤四、链路内ETL DSL语言介绍4.1 链路内ETL DSL概览4.2 DTS Record 概念介绍如下:DTS Record是DTS数据同步进程使用的中间数据存储,一个DTS Record代表一行记录;关系数据库中代表一行记录,MongoDB代表一个Document。所有DTS ETL处理都是基于DTS Record进行的。关系型数据库链路中 DTS Record包含表结构信息,在编写ETL DSL脚本时需要考虑到DTS Record结构的稳定,也就是针对同一个表经过不同DSL分支处理产生的表结构相同4.2.1 INSERT DTS Record全量数据同步阶段的都是INSERT DTS Record,增量数据同步阶段,源库日志中的INSERT日志 对应INSERT DTS Record。INSERT DTS Record内容如下,不包含前镜像值(插入之前的值),只包含后镜像值(插入的值)。只能获取后镜像值,只能设置后镜像值。操作类型值类型业务字段: USER_ID业务字段: USER_NAMEDTS附加字段INSERT前镜像(__BEFORE__)后镜像(__AFTER__)1000李四4.2.2 UPDATE DTS Record增量数据同步阶段,源库日志中的UPDATE日志对应UPDATE DTS Record,UPDATE DTS Record不会出现在全量同步阶段。UPDATE DTS Record内容如下,包含前镜像值(修改之前的值)和后镜像值(修改之后的值)。可以获取前镜像值和后镜像值,可以设置前镜像和后镜像值。操作类型值类型业务字段: USER_ID业务字段: USER_NAMEDTS附加字段UPDATE前镜像(__BEFORE__)1000张三后镜像(__AFTER__)1000李四4.2.3 DELETE DTS Record增量数据同步阶段,源库日志中的DELETE日志对应DELETE DTS Record,DELETE DTS Record不会出现在全量同步阶段。UPDATE DTS Record内容如下,只包含前镜像值(删除之前的值),无后镜像值。只能获取前镜像值,只能设置前镜像值。操作类型值类型业务字段: USER_ID业务字段: USER_NAMEDTS附加字段DELETE前镜像(__BEFORE__)1000李四后镜像(__AFTER__)4.3 ETL DSL语法介绍DTS链路内ETL语言是由基础的操作(operator)和值表达式(column_exp,value_exp)组成。operator有e_set、e_if、e_if_else、e_switch、e_compose、e_split、record_function组成,值表达式由列引用、基础数据类型、基础函数组成,组合参考如下语言描述operator: e_set(column_exp,value_exp [,column_exp,value_exp]*) | e_if(condition_exp, operator) | e_if_else(condition_exp,operator,operator) | e_switch(condition_exp,operator[,condition_exp,operator]* [default=operate]?) | e_compose(operator [, operator]* ) | e_split(column_exp) | e_drop() | record_function()一个完整的ETL配置,对应一个完整的operator, 可以是e_set、e_if、e_if_else、e_switch、e_compose、e_split、record_function其中的一种,也可以是符合语法的嵌套组合,当前不限制嵌套层次4.3.1 基础数据类型数据类型数据范围例子8字节有符号数e_set(id,1000)DECIMAL类型e_set(dollar, 6.88)字符串e_set(user_name, '张三')DATETIME类型0000-00-01 00:00:00~9999-12-30 23:59:59e_set(gmt_modify, DATETIME("2018-01-01 11:11:11"))BOOLEAN类型TRUEFALSEe_set(del_flag, true))e_set(del_flag, false))NULL值NULLe_set(del_flag, null))4.3.2 值表达式数据类型需求ETL脚本列引用使用id列填充sequence列e_set(sequence, id)表达式使用当前时间填充CURRENT列使用dollar * 6.88填充rmb列e_set(current, dts_now())e_set(rmb, dollar*6.88)4.3.3 DTS附加字段附加列名称值__DB__源库名称__TB__源表名称__OPERATION__DML类型(__OP_INSERT__, __OP_UPDATE__, __OP_DELETE__)中的一个,全量迁移只有__OP_INSERT____COMMIT_TIMESTAMP__源库日志提交时间,全量迁移为时间戳0(1970-01-01 08:00:00)__BEFORE__DTS Record 的前镜像__AFTER__DTS Record 的后镜像4.3.4 设置字段的值设置字段的值使用 e_set(column_exp,value_exp [,column_exp,value_exp]*), 可以设置一个字段的值e_set(id, 1000)也可以设置多个字段的值, [,column_exp,value_exp]* 可以重复一次或者多次e_set(id, 1000, user_name, '张三')4.3.5 条件控制语句4.3.5.1 e_if(condition_exp, operator)当表达式condition_exp的值为true是,执行operator。如:忽略user_name是张三的记录e_if(user_name =='张三', e_drop())4.3.5.2 e_if_else(condition_exp, operator_true, operator_false)当表达式condition_exp的值为true是,执行operator_true, 否则执行operator_false。如:当user_name是张三时,将dollar字段改成1000000,否则将dollar改成99e_if(user_name =='张三', e_set(dollar, 1000000), e_set(dollar,99))4.3.5.3 e_switch(condition_exp,operator[,condition_exp,operator]* [default=operate]?)当condition_exp为true时执行紧跟该condition_exp的operator, 只会执行第一个condition_exp为true的分支。如:user_name是张三的记录的dollar字段改成1000000, user_name是李四的记录的dollar字段改成8888,user_name是其他值的记录的dollar改成0e_switch( user_name=='张三', e_set(dollar, 1000000), user_name=='李四', e_set(dollar,99), default=e_set(dollar,0) )4.3.5.4 e_compose(operator [, operator]* )e_compose是一个辅助operator,用来将多个operator包装在一起。e_compose包装起来的每一个operator都会执行如e_compose( e_set(id, id*1000), e_switch( user_name=='张三', e_set(dollar, 1000000), user_name=='李四', e_set(dollar,99), default=e_set(dollar,0) ) )4.3.6 基础函数4.3.6.1 数值运算功能语法取值范围返回值示例加法op_sum(value1, value2)value1:整数或浮点数value2:整数或浮点数若参数均为整数,则返回整数,否则返回浮点数。op_sum(`col1`, 1.0)减法op_sub(value1,value2)value1:整数或浮点数value2:整数或浮点数若参数均为整数,则返回整数,否则返回浮点数。op_sub(`col1`, 1.0)乘法op_mul(value1,value2)value1:整数或浮点数value2:整数或浮点数若参数均为整数,则返回整数,否则返回浮点数。op_mul(`col1`, 1.0)除法op_div_true(value1, value2)value1:整数或浮点数value2:整数或浮点数若参数均为整数,则返回整数,否则返回浮点数。op_div_true(`col1`, 2.0), 若col1=15,则返回7.5。取模op_mod(value1, value2)value1:整数或浮点数value2:整数或浮点数若参数均为整数,则返回整数,否则返回浮点数。op_mod(`col1`, 10),若col1=23,则返回34.3.6.2 逻辑运算功能语法取值范围返回值示例是否相等op_eq(value1, value2)value1:整数、浮点数、字符串value2:整数、浮点数、字符串boolean类型,true或falseop_eq(`col1`, 23)是否大于op_gt(value1, value2)value1:整数、浮点数、字符串value2:整数、浮点数、字符串boolean类型,true或falseop_gt(`col1`, 1.0)是否小于op_lt(value1, value2)value1:整数、浮点数、字符串value2:整数、浮点数、字符串boolean类型,true或falseop_lt(`col1`, 1.0)是否大于等于op_ge(value1, value2)value1:整数、浮点数、字符串value2:整数、浮点数、字符串boolean类型,true或falseop_ge(`col1`, 1.0)是否小于等于op_le(value1, value2)value1:整数、浮点数、字符串value2:整数、浮点数、字符串boolean类型,true或falseop_le(`col1`, 1.0)AND运算op_and(value1, value2)value1:boolean类型value2:boolean类型boolean类型,true或falseop_and(`is_male`, `is_student`)OR运算op_or(value1, value2)value1:boolean类型value2:boolean类型boolean类型,true或falseop_or(`is_male`, `is_student`)4.3.6.3 字符串函数功能语法取值范围返回值示例将字符串中所有大写字符转换为小写字符str_lower(value)value:字符串字符串str_lower(`col1`)将字符串中所有小写字符转换为大写字符str_upper(value)value:字符串字符串str_upper(`col1`)删除字符串中指定的字符str_strip(value1, value2)value1: 字符串value2: 字符串字符串str_strip(`col1`, 'abc')截断字符串cond之后的部分substring_after(value, cond)value: 字符串cond: 字符串字符串substring_after(`col`, 'abc')截断字符串cond之前的部分substring_before(value, cond)value1: 字符串cond: 字符串字符串substring_before(`col`, 'efg')截断字符串cond1和cond2之间的部分substring_between(value, cond1, cond2)value: 字符串cond1: 字符串cond2: 字符串字符串substring_between(`col`, 'abc','efg')字符串转换数字cast_string_to_long(value)value:字符串整数cast_string_to_long(`col`)数字转换字符串cast_long_to_string(value)value:整数字符串cast_long_to_string(`col`)4.3.6.4 时间函数功能语法取值范围返回值示例当前系统时间dt_now()无DATETIME,精确到秒dts_now()dt_now_millis()无DATETIME,精确到毫秒dt_now_millis()UTC时间戳转DATETIMEdt_fromtimestamp(value)value:整数DATETIME,精确到毫秒dt_fromtimestamp(1626837629)DATETIME转UTC时间戳dt_totimestamp(value)value: DATETIME整数dt_totimestamp(`col`)DATETIME转字符串dt_str(value, format)value:DATETIMEformat:字符串, yyyy-MM-dd HH:mm:ss 格式表示字符串dt_str(`col1`, 'yyyy-MM-dd HH:mm:ss')字符串转DATETIMEdt_strptime(value,format)value:字符串format:字符串, yyyy-MM-dd HH:mm:ss 格式表示DATETIMEdt_strptime('2021-07-21 03:20:29', 'yyyy-MM-dd hh:mm:ss')五、链路内ETL典型场景5.1 数据脱敏5.1.1 隐藏电话号码,身份证号等e_set(phone, str_marsk(phone,3,6,'*'))原始数据18700001111ETL处理之后的数据187****11115.2 使用表过滤使用条件控制语句和DTS附加字段 __DB__和__TB__组合,可以在指定表上执行ETL逻辑。如针对user_db.user_info表进行脱敏e_if ( __DB__ == 'user_db' AND 'user_info' == __TB__, e_set(phone, str_marsk(phone,3,6,'*')) )DTS附加列__DB__,__TB__和普通字符串一样,可以直接使用字符串函数。如下表名满足正则表达式user_[0-9]+,进行数据脱敏e_if( regex_match(__TB__, 'user_[0-9]+'), e_set(phone, str_marsk(phone,3,6,'*')) )5.2 数据过滤过滤符合条件的DML,如过滤user_name是张三的记录e_if(user_name == '张三', e_drop())过滤增量迁移中的DELETE操作e_if(__OPERATION__ == __OP_DELETE__, e_drop())5.3 非法数据处理使用 e_if(condition, e_set) 语句,通过condition条件提出到非法记录,再通过e_set语句修改非法记录5.4 多表汇聚场景主键冲突解决方案多个单元表的数据同步汇聚到中心表时,各单元表存在相同主键,汇聚存在主键冲突丢数据的问题解决方法:新增字段region_idcreate table user_info( id int not null auto_increment primary key, user_name varchar(32) )create table global_user_info( id int not null auto_increment, user_name varchar(32), region_id varchar(32), primary key(id,region_id) )e_set(`region_id`,'cn-hangzhou')通过ETL重新分配各个单元的id到不冲突的值域create table user_info_0001( id int not null auto_increment primary key, user_name varchar(32) )create table global_user_info( id int not null auto_increment, user_name varchar(32), primary key(id,region_id) )e_set(`id`,case_string_to_long(substring_after_last(`id`,'_')) * 10000000 + id)5.5 将JSON展开为表的字段参数名称类型默认值介绍例子field_name字符串无需要展开的字段名称,区分大小写'user_info'fmt='simple'字符串fmt='simple'JSON展开名称规则,可选simple,fullfmt='full'sep='_'字符串sep='_'Json字段名称层级之间的链接符, 如{"userInfo":{"userName:"hy"}} 展开后userInfo_userNamesep='_'mapping字符串无需要展开的字段名称映射规则mapping='{"username":"user_name"}'如下将 user_info: {"user_info":{"username":"hy","password":"******"}} 展开到字段 user_name和user_passwordfmt='simple': 使用当前JSON字段名称e_expand_json('user_info',fmt='simple',mapping='{"username":"user_name","password":"user_password"}')fmt='full': 使用全路径JSON字段名称e_expand_json('user_info',fmt='full',seq=':',mapping='{"user_info:username":"user_name","user_info:password":"user_password"}')5.6 数据路由根据计算规则,将数据路由到不同的表中,使用e_set(__DB__, new_db_name), e_set(__TB__, new_table_name); new_db_name和new_table_name 可以是字符串、返回值是字符串结果的函数调用、以及表达式e_set(`__TB__`,`hy_0`) e_set(`__DB__`, `hy_0`)5.7 物理删除改为逻辑删除目的表新增 del_flag varchar(2)字段,使用'Y'标识删除记录,使用'N'标识为删除记录,并转换DELETE SQL为UPDATE SQL;ETL脚本如下e_if_else( op_eq(__OPERATION__,__OP_DELETE__), e_set(`del_flag`,'Y'), e_set(`def_flag`, 'N', __OPERATION__, __OP_UPDATE) )
以下文章作者为阿里云RDS产研团队 背景2023年5月7日,阿里云瑶池数据库RDS MySQL和RDS PostgreSQL倚天ARM架构全系列目录价下调,最高降幅40%。产品商业策略调整的背后,是持续的软硬件协同技术优化带来的红利释放。首先,ARM架构相对于传统的X86架构,在计算性能和能耗效率上具有较大的优势。阿里云RDS产研团队投入大量的研发资源,逐步优化ARM架构数据库的性能,使其可以更加稳定、高效地运行。随着技术逐步成熟,成本也相应降低,这使得降价成为了一个可行的选择。其次,伴随着信息化转型的改革浪潮以及云计算的蓬勃发展,越来越多的企业开始将数据库迁移到云上,对于高性能、低成本的云数据库诉求也越来越多。阿里云RDS倚天ARM架构数据库降价可以更好地满足市场客户需求,作为企业数据资产的重要载体,数据库的高性价比可以明显地降低企业TCO。综上所述,阿里云RDS MySQL和RDS PostgreSQL倚天ARM架构数据库同时做到了成本更低、性能更优,使得ARM架构数据库具备极致的性价比,帮助客户降本增效,进一步推动云计算市场的发展。RDS针对倚天ARM架构技术优化■ 硬件层面Prefetch预取策略优化倚天710上默认的Prefetch预取策略不适合数据库的访问场景,RDS产研团队和平头哥芯片团队一起进行了针对性的调整,从预取算法的选择,预取量的控制,预取过程中对L2的使用等方面,选取了一组最适合数据库场景的预取策略。■ OS层面为了更好适配ARM架构,RDS内核团队和OS团队一起,根据ARM架构倚天710特点在OS上进行了深度调优。❙ 调度算法优化自Linux内核版本2.6.23以来,CFS(Completely Fair Scheduler)成为默认的Linux内核调度程序。CFS为了保证对每个可运行任务的公平处理,会通过累计 vruntime,保证任务调度的公平。在ARM服务上,频繁的线程调度会带来较大的性能开销。基于此,我们针对OS的调度策略做了针对性优化,重点对sched_min_granularity_ns, sched_wakeup_granularity_ns, sched_migration_cost_ns等参数进行了调整,保证RDS在ARM服务器下的性能。❙ 开启代码段大页在传统X86服务器上,为了保证MySQL的性能稳定,默认关闭了大页。在ARM服务器上,新版本的OS支持了单独的代码段大页,即只对代码段开启大页,数据段不使用大页,从而降低代码段的TLB miss率,提升性能。对于PostgerSQL引擎,无论ARM还是X86,默认都开启了代码段大页。❙ 网卡中断优化通过“网卡中断聚合”的方式,针对SMP IRQ affinity和RPS做了相关调整,主要减少在处理网络中断时频繁的上下文切换带来的性能损耗,将多个网络队列绑定到一个核上,聚合处理能带来CPU icache使用效率提升。大致示意图如下:❙ 编译优化在ARM服务器上,为了提升OS的运行效率,RDS内核团队和OS团队一起,在OS编译过程中引入了PGO(Profile Guided Optimization)的方式,针对数据库的典型负载,对OS进行针对性的编译优化,保证OS在数据库场景下的运行效率。■ 数据库层面❙ 编译优化倚天710芯片支持了armv8.6指令集,数据库在编译过程中进行了相应适配,保证指令高效使用。同时在编译过程中启用了LTO(Link Time Optimization)和PGO(Profile Guided Optimization),分别从代码链接优化和运行时profiling反馈优化两个方面,提升数据库的性能。此外,在内存管理上,采用的Jemalloc替换默认的内存分配机制,保障内存分配与回收的高效。❙ 锁优化锁冲突是数据库并发场景下最常见的性能瓶颈点,数据库内核层面结合倚天710芯片的特点进行了针对性的优化,通过重新设计spinlock的实现、优化指令操作等方式,有效降低了并发场景下的锁冲突问题。❙ Double WriteMySQL数据库通过double write机制来保证数据写的安全性,但是double write机制也带来了更大的IO压力,特别是在云盘场景下。为此,数据库打通块存储和文件系统,实现了16K原子写的能力,在此能力的保障下,率先可以在ARM体系下安全地关闭double write,降级写IO的压力,极大提升IO Bound场景下的性能。❙ 热点函数优化数据针对并发访问场景下的典型热点函数进行了针对性优化,对包括:memcpy、crc32、hash_sort等热点函数进行了指令级的优化,充分发挥倚天710芯片的特点,保证数据库的性能。❙ 特色场景优化倚天710芯片在压缩场景下具有明显的性能优势,依托于倚天710芯片提供的硬件加速能力,RDS PostgerSQL在压缩表场景上进行了优化,开启压缩表后,在存储成本显著降低的情况下性能无退化。倚天710为云而设计,体现云原生优势倚天710 CPU是专门为云而生的云原生处理器芯片,主要体现在如下几个方面:❙ 倚天710芯片无超线程概念,用户使用ECS规格享受的是极致的物理核性能体验,无论用户业务负载压力多大,均不会造成业务性能衰减。在此基础上,芯片设计充分考虑云用户不同规格虚拟机在性能上的可预期性,例如CPU缓存qos特性等,不同规格的划分均具备可预期的线性性能变化,帮助客户充分应对复杂的业务变化。❙ 倚天710芯片与CIPU实现了1+1大于2的效果。倚天710将自身算力优势和CIPU IO优势结合,使得倚天ECS在用户业务场景取得了优异的性能表现。同时,通过以CIPU为核心的理念,倚天ECS的成本和稳定性均得到了很好优化。通过CIPU为核心,我们采用多单路的机型设计方式,在保证低爆炸半径的前提下,提升部署密度,有效降低倚天ECS使用成本。RDS MySQL为例经过深度优化性能超过普通自建MySQL 在经过一系列的软硬件优化以后,我们以一个规格为8C32G 100G数据的实例进行Sysbench跑分压测,其中RDS ARM指RDS on 倚天深度优化的实例、X86自建指客户基于X86架构的ECS实例自建同等规格数据库、ARM自建指客户基于倚天架构的ECS实例自建同等规格数据库,具体性能数据如下:寄语RDS产研团队经过软硬协同的一系列优化,使得倚天ARM架构数据库性能进一步提升并释放技术红利。在稳定性方面,RDS ARM架构规格承诺与X86一致的高SLA保障,高可用规格最高SLA 99.99%。产品功能和使用体验上也与X86规格完全一致,应用无适配门槛。期望未来给大家带来更多的技术上的变革,普惠RDS云数据库客户。更多产品相关介绍详见官网:https://www.aliyun.com/activity/database/rds_armRDS MySQL Serverless开通免费试用啦!阿里云推出“飞天免费试用计划”,面向国内1000万云上开发者,提供云产品免费试用。RDS MySQL Serverless 现推出3个月【免费试用】,快来领取吧!点击文末「这里」即刻开启云上实践之旅!
教程简介通过本教程,您将学习使用数据传输服务DTS(Data Transmission Service),将自建MySQL迁移至RDS MySQL实例。DTS支持结构迁移、全量数据迁移以及增量数据迁移,同时使用这三种迁移类型可以实现在自建应用不停服的情况下,平滑地完成自建MySQL数据库的迁移上云。数据传输服务DTS(Data Transmission Service)是阿里云提供的实时数据流服务,支持多种数据源间的数据交互,集数据同步、迁移、订阅、集成、加工于一体,助您构建安全、可扩展、高可用的数据架构。更多信息,请参见数据传输服务DTS的官方文档。我能学到什么熟悉DTS可视化的管理界面。了解使用DTS配置数据迁移实例的方法。步骤一:准备环境及资源耗时:15分钟开始教程前,请按以下步骤准备环境和资源:确保自建MySQL数据库版本为5.1、5.5、5.6、5.7或8.0版本。创建目标RDS MySQL实例,其存储空间大于自建MySQL数据库已占用空间。并创建用于迁移的具有读写权限的数据库账号。具体操作,请参见创建RDS MySQL实例和创建账号。了解自建MySQL数据库上云的注意事项及限制。详情请参见MySQL间的迁移。访问阿里云免费试用。单击页面右上方的登录/注册按钮,并根据页面提示完成账号登录(已有阿里云账号)、账号注册(尚无阿里云账号)或实名认证(根据试用产品要求完成个人实名认证或企业实名认证)。成功登录后,在产品类别下选择数据库 > 数据管理工具,在数据迁移的数据传输 DTS卡片上单击立即试用,根据页面提示填写申请表单信息。本示例选择迁移链路地域为华东1(杭州),其他保持默认配置。您也可以根据实际情况进行配置。配置说明配置说明功能试用数据传输服务的功能,固定为数据迁移。迁移链路地域目标数据库实例所属的地域。迁移链路规格数据迁移实例性能的规格,当前仅支持small。资源组数据迁移实例所属的资源组。更多信息,请参见资源组。试用数量试用迁移实例的数量,固定为1。阅读并勾选服务协议后,单击立即试用。步骤二:在自建MySQL创建用于数据迁移的账号耗时:5分钟1.登录自建MySQL数据库。2.在自建MySQL数据库中执行如下命令,创建用于数据迁移的账号。CREATE USER 'username'@'host' IDENTIFIED BY 'password';参数说明username待创建的账号。host允许该账号登录的主机,如果允许该账号从任意主机登录数据库,可以使用百分号(%)。password账号的密码。3.例如,创建一个账号,账号名为dtsmigration,密码为Dts123456,并允许该账号从任意主机登录数据库,命令如下:CREATE USER 'dtsmigration'@'%' IDENTIFIED BY 'Dts123456';4.执行如下命令,为创建的账号进行授权。为账号授予指定库表的权限,命令格式和需要修改的参数如下:GRANT privileges ON databasename.tablename TO 'username'@'host' WITH GRANT OPTION;参数说明privileges授予该账号的操作权限,如SELECT、INSERT、UPDATE等,如果要授予该账号所有权限,则使用ALL。库表结构迁移需要SELECT权限;全量迁移需要SELECT权限;增量迁移需要SELECT、REPLICATION CLIENT、REPLICATION SLAVE、SHOW VIEW以及建库建表的权限。databasename数据库名。如果要授予该账号具备所有数据库的操作权限,则使用星号(*)。tablename表名。如果要授予该账号具备所有表的操作权限,则使用星号(*)。username待授权的账号,需要与步骤2中创建的账号一致。本示例需为dtsmigration。host允许该账号登录的主机,如果允许该账号从任意主机登录数据库,则使用百分号(%)。为账号授予建库建表的权限,命令格式和需要修改的参数如下:GRANT CREATE ON *.* TO 'username'@'host' WITH GRANT OPTION;参数说明username待授权的账号,需要与步骤2中创建的账号一致。host允许该账号登录的主机,如果允许该账号从任意主机登录数据库,则使用百分号(%)。5.本示例授予dtsmigration账号具备所有数据库和表的所有权限,并允许该账号从任意主机登录数据库,命令如下:GRANT ALL ON *.* TO 'dtsmigration'@'%';步骤三:配置迁移任务耗时:10分钟1.在DTS控制台单击左侧导航栏的数据迁移,进入迁移任务的列表页面。2.在页面上方选择迁移实例所属地域。3.单击创建任务,配置源库及目标库信息。类别配置说明无任务名称DTS会自动生成一个任务名称,建议配置具有业务意义的名称(无唯一性要求),便于后续识别。源库信息选择已有的实例DTS控制台暂不支持选择已有实例,您无需选择,只需要输入下方的数据库信息。数据库类型选择MySQL。接入方式根据源库的部署位置进行选择,本文以公网IP为例介绍配置流程。实例地区选择源自建MySQL数据库所部署的地域,本示例选择华东1(杭州)。若实例地区中没有您自建MySQL数据库部署的地域,您可以选择一个距离您部署地域近的地区。主机名或IP地址填入源自建MySQL数据库的访问地址,本示例中填入部署MySQL数据库服务的公网IP地址。获取本地设备公网IP地址的方式可能因你所处的网络环境或操作不同而不同。以下是不同系统通过命令方式获取本地设备公网IP地址的参考方法:Linux操作系统:打开终端,输入curl ifconfig.me命令后回车。Windows操作系统:打开命令提示符,输入curl ip.me命令后回车。macOS操作系统:打开终端,输入curl ifconfig.me命令后回车。端口填入源自建MySQL数据库的服务端口(需开放至公网),默认为3306。数据库账号填入在源自建MySQL创建的数据库账号,本示例填入dtsmigration。数据库密码填入该数据库账号对应的密码。目标库信息选择已有的实例DTS控制台暂不支持选择已有实例,您无需选择,只需要输入下方的数据库信息。数据库类型选择MySQL。接入方式选择云实例。实例地区选择目标RDS MySQL实例所属地域。RDS实例ID选择目标RDS MySQL实例ID。数据库账号填入目标RDS MySQL实例的数据库账号。数据库密码填入该数据库账号对应的密码。连接方式根据需求选择非加密连接或SSL安全连接。如果设置为SSL安全连接,您需要提前开启RDS MySQL实例的SSL加密功能,详情请参见设置SSL加密。4.配置完成后,单击页面右下角的测试连接以进行下一步。5.如果您的自建数据库具备白名单安全设置,您需要复制弹跳框中的DTS服务器IP地址,并加入自建数据库的白名单安全设置中。然后单击测试连接以进行下一步。DTS会自动将对应地区DTS服务的IP地址添加到目标阿里云数据库实例的白名单,您无需手动添加。6.配置任务对象。本示例的迁移类型同时选中库表结构迁移、全量迁移和增量迁移,并在源库对象框中选择待迁移的对象,其他保持默认配置。您也可以根据实际情况进行配置。配置说明配置说明迁移类型如果只需要进行全量迁移,请同时选中库表结构迁移和全量迁移。为保障数据一致性,数据迁移期间请勿在源实例中写入新的数据。如果需要进行不停机迁移,请同时选中库表结构迁移、全量迁移和增量迁移。目标已存在表的处理模式预检查并报错拦截:检查目标数据库中是否有同名的表。如果目标数据库中没有同名的表,则通过该检查项目;如果目标数据库中有同名的表,则在预检查阶段提示错误,数据迁移任务不会被启动。如果目标库中同名的表不方便删除或重命名,您可以更改该表在目标库中的名称,请参见库表列名映射。忽略报错并继续执行:跳过目标数据库中是否有同名表的检查项。择为忽略报错并继续执行,可能导致数据不一致,给业务带来风险,例如:表结构不一致的情况下,可能导致只能迁移部分列的数据或迁移失败。表结构一致的情况下,在目标库遇到与源库主键的值相同的记录,则会保留目标库中的该条记录,即源库中的该条记录不会迁移至目标库中。目标库对象名称大小写策略您可以配置目标实例中迁移对象的库名、表名和列名的英文大小写策略。默认情况下选择DTS默认策略,您也可以选择与源库、目标库默认策略保持一致。更多信息,请参见目标库对象名称大小写策略。源库对象在源库对象框中选择待迁移对象,然后单击将其移动至已选择对象框。迁移对象选择的粒度为库、表、列。若选择的迁移对象为表或列,其他对象(如视图、触发器、存储过程)不会被迁移至目标库。系统库(如sys)不支持迁移。已选择对象如需移除已选择的对象,请在已选择对象框中选择待移除的对象,然后单击将其移动至源库对象框。如需更改迁移对象在目标实例中的名称,请右击已选择对象中的迁移对象,设置方式,请参见库表列名映射。如果使用了对象名映射功能,可能会导致依赖这个对象的其他对象迁移失败如需按库或表级别选择迁移的SQL操作,请在已选择对象中右击待迁移对象,并在弹出的对话框中选择所需迁移的SQL操作。如需设置WHERE条件过滤数据,请在已选择对象中右击待迁移的表,在弹出的对话框中设置过滤条件。设置方法请参见通过SQL条件过滤任务数据。7.单击下一步高级配置,进行高级配置。本示例保持默认配置,无需手动配置,您也可以根据实际情况进行配置。配置说明类别配置说明数据校验配置数据校验方式若您需要配置数据校验任务,配置方法请参见配置数据校验。高级配置设置告警是否设置告警,当迁移失败或延迟超过阈值后,将通知告警联系人。不设置:不设置告警。设置:设置告警,您还需要设置告警阈值和告警联系人。更多信息,请参见在配置任务过程中配置监控报警。复制源表Online DDL工具执行过程的临时表到目标库若源库使用数据管理DMS(Data Management)或gh-ost执行Online DDL变更,您可以选择是否迁移Online DDL变更产生的临时表数据。DTS任务暂不支持使用pt-online-schema-change等类似工具执行Online DDL变更,否则会导致DTS任务失败是:迁移Online DDL变更产生的临时表数据。Online DDL变更产生的临时表数据过大时,可能会导致迁移任务延迟。否,适配DMS Online DDL:不迁移Online DDL变更产生的临时表数据,只迁移源库使用数据管理DMS(Data Management)执行的原始DDL数据。此方案会导致目标库锁表。否,适配gh-ost:不迁移Online DDL变更产生的临时表数据,只迁移源库使用gh-ost执行的原始DDL数据,同时您可以使用默认的或者自行配置gh-ost影子表和无用表的正则表达式。此方案会导致目标库锁表。源库触发器迁移方式请按照您的实际业务选择源库触发器的迁移方式。关于迁移方式的介绍,详情请参见同步或迁移源库中的触发。源库、目标库无法连接后的重试时间在迁移任务连接失败时,DTS会立即进行持续的重试连接,默认持续重试时间为120分钟,您也可以在取值范围(10~1440分钟)内自定义重试时间,建议设置30分钟以上。如果DTS在设置的重试时间内重新连接上源库、目标库,迁移任务将自动恢复。否则,迁移任务将失败。由于连接重试期间,DTS将收取任务运行费用,建议您根据业务需要自定义重试时间,或者在源和目标库实例释放后尽快释放DTS实例。源库、目标库出现其他问题后的重试时间在迁移任务启动后,若源库或目标库出现非连接性的其他问题(如DDL或DML执行异常),则DTS会报错并会立即进行持续的重试操作,默认持续重试时间为10分钟(源库、目标库出现其他问题后的重试时间的值需要小于源库、目标库无法连接后的重试时间的值),您也可以在取值范围(1~1440分钟)内自定义重试时间,建议设置10分钟以上。如果DTS在设置的重试时间内相关操作执行成功,迁移任务将自动恢复。否则,迁移任务将会失败。配置ETL功能选择是否配置ETL功能。是:配置ETL功能,并在文本框中填写数据处理语句,详情请参见在DTS迁移或同步任务中配置ETL。否:不配置ETL功能。是否去除正反向任务的心跳表sql根据业务需求选择是否在DTS实例运行时,在源库中写入心跳SQL信息。是:不在源库中写入心跳SQL信息,DTS实例可能会显示有延迟。否:在源库中写入心跳SQL信息,可能会影响源库的物理备份和克隆等功能。8.上述配置完成后,单击页面下方的下一步保存任务并预检查。如果预检查失败,请单击失败检查项后的查看详情,并根据提示修复后重新进行预检查。如果预检查产生警告:对于不可以忽略的检查项,请单击失败检查项后的查看详情,并根据提示修复后重新进行预检查。对于可以忽略无需修复的检查项,您可以依次单击点击确认告警详情、确认屏蔽、确定、重新进行预检查,跳过告警检查项重新进行预检查。如果选择屏蔽告警检查项,可能会导致数据不一致等问题,给业务带来风险。9.预检查通过率显示为100%时,单击下一步购买。10.在购买页面,选择数据迁移实例的链路规格。类别配置说明信息配置链路规格DTS为您提供了不同性能的迁移规格,迁移链路规格的不同会影响迁移速率,您可以根据业务场景进行选择,详情请参见数据迁移链路规格说明。11.配置完成后,阅读并选中《数据传输(按量付费)服务条款》。12.单击购买并启动,迁移任务开始初始化,您可在数据迁移列表界面查看具体进度。步骤四:完成耗时:3分钟观察数据迁移实例的进度:在迁移任务列表页面,您可以查看迁移实例的运行状态。当状态为运行中时,表示实例已进入增量迁移阶段,增量迁移任务不会主动结束;当状态为已完成时,表示实例的所有任务已完成。更多信息,请参见查看任务进度。步骤五:清理及后续耗时:2分钟清理本教程使用的DTS迁移实例只能免费试用3个月。实例到期后,您可以手动释放。具体操作,请参见释放按量付费实例。如果一直未释放该实例,实例将在试用时间结束后,按照正常价格计费,计费标准请参见计费项。DTS任务释放后,您还需手动删除添加的DTS服务的IP地址。在阿里云数据库实例的白名单中,您需要删除名称包含dts的IP白名单分组;在IDC自建数据库或其他云数据库,您需要删除的DTS服务的IP地址,请参见迁移、同步或订阅本地数据库时需添加的IP白名单。若您使用的目标数据库为试用的RDS MySQL,请根据阿里云免费试用提供的试用规则及时释放或续费。后续对于运行的实例,您还可以调整实例的迁移速率、查看实例的热点表、体验实例规格升级等。具体操作,请参见:调整迁移速率查看热点表信息体验实例规格升级
教程简介在本教程中,您将学习如何快速创建MongoDB副本集实例并联接MongoDB数据库读写数据。云数据库MongoDB(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份恢复、性能优化等功能。副本集架构适用于读多写少或有临时活动的突发业务场景。我能学到什么学会如何创建MongoDB副本集实例。学会如何连接MongoDB副本集实例并读写数据。步骤一:准备环境及资源耗时:15分钟开始教程前,请按以下步骤准备环境和资源:访问阿里云免费试用。单击页面右上方的登录/注册按钮,并根据页面提示完成账号登录(已有阿里云账号)、账号注册(尚无阿里云账号)或实名认证(根据试用产品要求完成个人实名认证或企业实名认证)。成功登录后,在产品类别列表中,选择数据库>NoSQL数据库。在云数据库MongoDB 1核2GB 3个月卡片上单击立即试用。在配置MongoDB实例信息面板,配置信息。配置项说明本教程示例地域实例的地域。请根据您所在的地理位置就近选择地域,实例将创建在该地域,创建后无法变更地域。 若需通过ECS连接MongoDB实例,请确保MongoDB实例与ECS实例为同地域,否则它们无法通过内网互通,只能通过外网连接,无法发挥最佳性能。华东1(杭州)系列固定为标准版【推荐】。标准版【推荐】可用区类型选择可用区类型。单可用区:主节点和备节点位于同一可用区。多可用区:主节点和备节点位于不同可用区,满足同城容灾需求。单可用区可用区选择实例所属可用区。当选择可用区类型为多可用区时,您还需要指定备可用区1和备可用区2,且备可用区1、备可用区2需要与主可用区不同。杭州 可用区G数据库版本选择数据库版本。MongoDB 4.2主备节点数选择副本集实例的节点数量。三节点只读节点数选择副本集实例的只读节点数量。无只读节点存储引擎固定为WiredTiger。WiredTiger存储类型固定为SSD本地盘。SSD本地盘资源组选择管理实例的资源组。默认资源组网络类型固定为专有网络。专有网络专有网络选择实例所属专有网络。您可以直接使用Default VPC,如果没有默认VPC,也可以前往VPC控制台创建。Default VPC虚拟交换机选择实例所属交换机。您可以直接使用Default Switch,如果没有默认交换机,也可以前往VPC控制台创建。Default Switch规格副本集实例的CPU和内存规格。固定为1核2GB(通用型)。1核2GB(通用型)存储空间固定为20 GB。20 GB用户名固定为root。root密码设置设置root账号的密码。您可以选择以下任意一种方法:立即设置:立即设置密码。创建后设置:在实例运行期间设置密码,设置方法请参见重置密码。立即设置密码如果您选择立即设置密码,请按照页面提示输入root账号的密码。请勿在实际业务中使用本教程的示例密码。Password01使用时长固定为3个月。3个月使用数量固定为1。1同意协议后,单击立即试用,并根据页面提示完成试用申请。实例创建需要10~15分钟创建集群,之后您就可以在副本集实例列表看到新创建的集群。按如下要求准备ECS,创建ECS实例的方法,请参见自定义购买实例。所在地域与云数据库MongoDB相同,并建议所在可用区相同(以减少网络延时)。网络类型为专有网络,须确保使用与云数据库MongoDB相同的专有网络ID。操作系统为CentOS 7.9 64位。您可以前往阿里云免费试用查看您的阿里云账号是否具有云服务器ECS试用资格。如有试用资格,可通过试用ECS来完成教程。如无试用资格,则需使用自有ECS资源才能完成教程。不建议使用生产环境中的自有ECS资源,也不要将教程中的测试数据和自有ECS资源的数据混用。测试完成后及时清理测试数据,避免影响自有资源正常运行。步骤二:设置白名单耗时:2分钟MongoDB实例默认禁止所有IP地址访问,在连接实例前,您需要将ECS实例的IP地址或IP地址段添加到MongoDB实例的白名单中。登录MongoDB控制台。在左侧导航栏,单击副本集实例列表。在页面左上角,选择目标实例所在的资源组和地域,本教程中资源组为默认资源组,地域为华东1(杭州)。单击目标实例ID。在左侧导航栏单击数据安全性,选择白名单设置。在default默认分组的操作列,单击修改。在允许访问IP名单文本框中,输入ECS实例的主私网IP,单击确定。您可以登录ECS管理控制台,在左侧导航栏选择实例与镜像>实例,在实例页面,单击目标实例ID,在实例详情页面的网络信息区域查看主私网IP。步骤三:连接实例耗时:5分钟本教程以通过Mongo Shell连接MongoDB副本集实例为例。登录ECS服务器。登录方法,请参见通过密码或密钥认证登录Linux实例。在ECS服务器上安装Mongo Shell。下载Mongo Shell,您可以前往MongoDB官网获取Mongo Shell下载地址,本教程使用的Mongo Shell的Version为1.8.0,Platform为Linux Tarball 64-bit,Package为tgz。wget <Mongo Shell下载地址>解压Mongo Shell文件。tar -xzvf mongosh-1.8.0-linux-x64.tgz切换到Mongo Shell所在的目录mongosh-1.8.0-linux-x64/bin。cd mongosh-1.8.0-linux-x64/bin使用./mongosh 连接云数据库MongoDB副本集实例。获取ConnectionStringURI高可用连接地址的方法:在MongoDB控制台副本集实例列表页,单击实例ID。在左侧导航栏单击数据库连接,在私网连接 - 专有网络区域复制ConnectionStringURI高可用连接地址。将ConnectionStringURI高可用连接地址中root:后的****替换为root账号的密码。./mongosh "mongodb://root:****@dds-bp12855676d4f2d411****.mongodb.rds.aliyuncs.com:3717/admin"当界面显示admin>,表示连接成功。步骤四:创建数据库和集合并写入数据耗时:2分钟成功连接MongoDB实例后,创建并进入test数据库。use test;在test数据库中创建mongo集合。返回结果中ok取值为1.0时,表示创建成功,其他取值表示创建失败。db.createCollection("mongo");写入两组文档{"name": "test"}和{"count": "10"}至mongo集合。db.runCommand({insert: "mongo", documents: [{"name": "test"},{"count": "10"}]});步骤五:完成耗时:1分钟执行命令,查看mongo集合中的文档。db.getCollection("mongo").find({});[ { '_id': ObjectId("63bd29f8e52fddefeb59****"), 'name': "test" }, { '_id': ObjectId("63bd29f8e52fddefeb59****"), 'count': "10" } ]步骤六:清理及后续耗时:5分钟清理云数据库MongoDB该MongoDB实例只能免费试用3个月。实例到期后,您可以手动释放。具体操作,请参见释放实例。如果一直未释放该实例,实例试用到期后也会自动释放,实例到期释放规则,请参见到期或欠费说明。如需继续使用该实例,您可以手动进行续费。具体操作,请参见续费说明。云服务器ECS如果是按量付费的ECS实例:如果无需继续使用实例,可以登录ECS控制台,找到目标实例,在操作列单击,搜索并单击释放设置,根据界面提示释放实例。如果需要继续使用实例,请至少在试用到期1小时前为阿里云账号充值,确保账户金额不小于100.00元人民币。到期未续费的实例会因欠费而被自动停机,停机15天内实例将保留,15天后实例和数据都将被自动释放。如果是包年包月的ECS实例:包年包月实例到期会自动释放,释放实例的同时释放数据。如果需要继续使用实例,请在试用到期前及时续费。到期未续费的实例会因欠费而被自动停机,停机15天内实例将保留,15天后实例和数据都将被自动释放。后续您可以将自建数据库迁移至MongoDB实例,具体操作,请参见:将ECS上单节点或副本集架构的自建MongoDB迁移上云使用DTS迁移副本集架构的自建MongoDB数据库上云使用MongoDB工具将自建数据库迁移至副本集实例
教程简介在本教程中,您将学习如何创建并通过公网连接和使用RDS MySQL Serverless实例。RDS MySQL Serverless实例是阿里云针对中小型企业或个人开发者推出的一款数据库。提供了CPU、内存的实时弹性能力,提供计算资源按需计费的能力,具有资源用量低、简单易用、弹性灵活和价格低廉等优点。我能学到什么了解如何创建RDS MySQL Serverless实例。学会如何通过公网连接RDS MySQL Serverless实例并使用。步骤一:准备环境及资源耗时:5分钟开始教程前,请按以下步骤准备环境和资源:安装MySQL Workbench 8.0.31,用于在本地连接RDS MySQL Serverless实例。客户端下载,请前往MySQL Workbench官方网站。访问阿里云免费试用。单击页面右上方的登录/注册按钮,并根据页面提示完成账号登录(已有阿里云账号)、账号注册(尚无阿里云账号)或实名认证(根据试用产品要求完成个人实名认证或企业实名认证)。成功登录后,在产品类别下选择数据库 > 关系型数据库,然后选择云数据库 RDS MySQL Serverless,单击立即试用。在云数据库 RDS MySQL Serverless面板,完成参数信息配置。除以下本教程所使用的关键参数外,其他参数保持默认即可,实际操作时,建议根据您的业务需求选择。参数本教程取值说明试用时长3个月RDS MySQL Serverless支持免费试用3个月,固定配置。地域华东1(杭州)本教程使用本地客户端连接RDS实例,选择距离您所处位置最近的地域,可以降低网络时延。数据库类型MySQL数据库引擎类型,本教程介绍RDS MySQL Serverless实例。数据库版本号8.0RDS MySQL Serverless当前支持MySQL 8.0和MySQL 5.7。RCU上限2RCU为RDS MySQL Serverless的计费单位,1个RCU的性能约为1核(最大)2 GB,RDS MySQL Serverless的更多信息,请参见RDS MySQL Serverless实例简介。RCU下限0.5存储空间50GB实例的存储空间。专有网络vpc-bp1ov****如果没有专有网络和虚拟交换机,请根据提示,单击前往控制台创建,具体创建方法,请参见创建和管理专有网络。创建的VPC地域需要与本步骤的地域相同,创建的交换机所属可用区需要与本步骤的可用区相同。虚拟交换机vsw-bp14j****同意协议后,单击立即试用,并根据页面提示完成试用申请。完成试用申请后,将会自动为您创建实例。您可以访问RDS实例列表,在页面上方选择试用申请时配置的地域,如华东1(杭州),然后刷新页面查看,实例创建需要约3~10分钟,当实例状态为运行中时,即可正常使用。步骤二:创建账号耗时:2分钟访问RDS实例列表,在上方选择华东1(杭州)地域,然后单击目标实例ID。在左侧导航栏单击账号管理,然后单击创建账号,在创建账号窗口,配置如下参数,然后单击确定。参数本教程取值说明数据库账号testuser根据控制台提示,输入符合要求的账号名称。账号类型高权限账号高权限账号可以管理所有普通账号和数据库,本教程以高权限账号为例。新密码Test_pw123根据控制台提示,输入符合要求的账号名称。此密码仅为本教程示例,请勿在实际业务中使用。确认密码备注说明这是一个测试账号备注该账号的相关信息,便于后续账号管理。最多支持256个字符。步骤三:设置白名单耗时:2分钟创建RDS MySQL Serverless实例后,暂时还无法访问该实例,您需要设置RDS实例的白名单,将客户端所在设备的IP加入白名单后,RDS实例才能允许客户端访问。本教程以本地客户端为例介绍如何连接RDS实例,因此,需要将本地设备的公网IP加入到白名单分组中。在左侧导航栏单击白名单与安全组,然后在白名单设置页签,单击添加白名单分组。在添加白名单分组窗口,配置分组名称和组内白名单,然后单击确定。参数本教程取值说明分组名称mywhitelist白名单分组的名称,自定义,根据控制台提示,输入符合要求的白名单分组名称。组内白名单222.91.XX.XX允许访问RDS的内网IP或公网IP,本教程以公网客户端连接RDS实例为例,此参数配置为客户端所在设备的公网IP。单击加载本机公网IP(如果本机开启了网络代理,请先关闭),RDS将自动获取当前登录阿里云控制台的设备的公网IP并加入白名单中。步骤四:开通外网地址耗时:2分钟RDS实例默认不开通外网地址,仅支持通过内网访问,本教程使用外网连接,因此需要开通外网地址。在左侧导航栏单击数据库连接,即可查看RDS实例的内网地址和内网端口,本教程使用公网连接,因此,需要单击开通外网地址。在弹出的提示对话框中单击确定。开通外网地址默认选中将0.0.0.0/0加入白名单,该配置意味着对所有公网IP开放,请谨慎使用,您也可以手动取消选中。开通外网地址后,刷新页面,在数据库连接页面即可查看并复制外网地址和外网端口。此信息将在连接实例时使用。步骤五:连接实例耗时:2分钟本教程以Workbench 8.0.31为例,介绍如何连接RDS MySQL Serverless实例,如果您购买了其他引擎的RDS实例,请使用各数据库引擎支持的客户端。1.打开本地MySQL客户端。2.单击MySQL Connections后的。3.在Setup New Connection对话框中配置Connection Name、Hostname、Port和Username。参数本教程取值说明Connection Namerdsmysql用于标识一个连接,自定义。Hostnamerm-bp****.rds.aliyuncs.comRDS实例的连接地址,填写开通外网地址步骤获取的外网地址。Port3306RDS实例的端口,填写开通外网地址步骤获取的外网端口。Usernametestuser填写本教程创建的数据库高权限账号名。4.单击图①处的Store in Vault...,然后在图②处配置Password,在图③处单击ok。Password为创建账号步骤设置的高权限账号的密码,本教程为Test_pw123,请以您实际设置密码为准。5.单击Test Connection。如果测试连接成功,则单击确认窗口中的OK后,再单击Setup New Connection窗口中的OK。如果测试连接不成功,请检查连接参数配置是否正确,更多解决方法,请参见解决无法连接实例问题。6.在Workbench首页,找到已创建好的连接,单击进入数据库管理页面。7.如果出现如图内容,即表示连接成功,您可以在Workbench中对RDS实例中的数据进行操作。步骤六:使用数据库耗时:3分钟连接RDS实例后,您可以和正常使用自建数据库一样对RDS实例进行操作(DDL、DML等)。1.创建测试数据库testdb和测试表test_table,并插入一条数据。-- 创建测试数据库testdb CREATE DATABASE testdb; -- 进入测试数据库 USE testdb; -- 创建一个名为test_table的测试表 CREATE TABLE test_table ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(50) NOT NULL, age INT NOT NULL, PRIMARY KEY (id) ); -- 向test_table表中插入一条数据 INSERT INTO test_table (name, age) VALUES ('John', 25), ('Mary', 30), ('Bob', 35); 2.查询test_table表中数据。 SELECT * FROM test_table; 3.修改test_table表中数据。 UPDATE test_table SET name = 'Johnny', age = 26 WHERE id = 1; 步骤七:完成耗时:1分钟使用SELECT * FROM test_table;命令,可以查看到修改后的表数据。步骤八:清理及后续耗时:1分钟清理本教程使用的RDS MySQL Serverless实例只能免费试用3个月。实例到期后,您可以手动释放。具体操作,请参见释放实例。如果一直未释放该实例,实例将在试用时间结束后,按照正常价格计费,计费标准请参见Serverless费用。其他引擎的RDS实例在免费使用时间结束后,将自动进入实例回收站,如果您还需要使用,可在回收站中恢复重建,具体操作,请参见实例回收站。后续您可以将自建数据库的数据迁移至RDS实例,具体操作,请参见:从自建MySQL迁移至RDS MySQL实例。
教程简介通过本教程,您将学习通过热备切换实现阿里云PolarDB MySQL版Serverless集群的高可用。 集群中的只读节点开启热备功能后,主备切换可实现快速切换和事务保持。本教程采用测试工具SysBench持续对PolarDB MySQL版的Serverless集群注入流量,并在流量注入过程中手动触发数据库crash来观察数据库的切换速度和事务保持能力。我能学到什么熟悉通过装有mysql client的ECS实例创建PolarDB MySQL版的Serverless集群的数据库命令。了解利用SysBench测试PolarDB MySQL版的Serverless集群的方法。体验PolarDB MySQL版Serverless集群的故障容灾能力。环节一:准备环境和资源本环节耗时:18分钟开始教程前,请按以下步骤准备环境和资源:1. 准备云服务器ECS实例。由于要进行SysBench性能测试,ECS实例的操作系统需要选择为CentOS 7.7 64位。ECS实例安全组的出方向要放行MySQL默认使用的3306端口,具体操作请参见添加安全组规则。您可以前往阿里云免费试用查看您的阿里云账号是否具有云服务器ECS试用资格。如有试用资格,可通过试用ECS来完成教程。如无试用资格,则需使用自有ECS资源才能完成教程。不建议使用生产环境中的自有ECS资源,也不要将教程中的测试数据和自有ECS资源的数据混用。测试完成后及时清理测试数据,避免影响自有资源正常运行。2.访问阿里云免费试用。单击页面右上方的登录/注册按钮,并根据页面提示完成账号登录(已有阿里云账号)、账号注册(尚无阿里云账号)或实名认证(根据试用产品要求完成个人实名认证或企业实名认证)。3.成功登录后,在产品类别下选择数据库 > 关系型数据库,在PolarDB for MySQL Serverless卡片上单击立即试用。4.在配置PolarDB for MySQL Serverless集群信息面板,完成参数配置。完成本教程需要的配置信息如下(实际操作请根据业务需求按需配置):地域和可用区:如需使用私网IP访问PolarDB MySQL版集群,此处选择的地域必须与ECS实例相同,可用区可以不同。VPC网络和交换机:如果您已创建符合您网络规划的VPC和交换机,直接选择该VPC和交换机。如果您未创建符合您网络规划的VPC和交换机,可以使用默认的VPC和交换机。如果以上已创建的和默认的VPC和交换机无法满足您的要求,可以自行创建VPC和交换机,详情请参见创建和管理专有网络。如需使用私网IP访问PolarDB MySQL版集群,此处选择的VPC网络必须与ECS实例相同,否则ECS实例和PolarDB MySQL版集群无法通过VPC网络互通。其他参数:保持默认值或按需修改。5.同意协议后,单击免费试用,并根据页面提示完成试用申请。开通成功后,需要10~15分钟创建集群,之后您就可以在集群列表中看到新创建的集群。环节二:创建数据库账号本环节耗时:5分钟1.登录PolarDB控制台,单击左侧集群列表,然后选择云产品资源提供的地域。例如:华东1(杭州)。2.创建数据库账号。在集群列表页面,单击集群ID,进入基本信息页面。单击左侧导航栏配置与管理>账号管理。单击左上方创建账号。参考说明配置账号信息,然后单击确定。请记录此处创建的数据库账号及密码,后续步骤中会反复使用。数据库账号:输入数据库账号名称,例如:temp。账号类型:选择高权限账号。密码:设置账号密码。确认密码:再次输入密码。3.设置数据库白名单。连接数据库需要设置数据库白名单,单击左侧导航栏配置与管理>集群白名单。在配置白名单界面将默认的白名单地址127.0.0.1更改为ECS实例的公网IP或者私网IP,然后点击确定使白名单地址生效。查看ECS实例IP地址的方法请参见查看IP地址。环节三:开启只读节点的热备功能耗时:10分钟1.在PolarDB控制台单击左侧集群列表,然后选择集群所在地域。例如:华东1(杭州)。2.为只读节点开启热备。在集群列表页面,单击集群ID,进入基本信息页面。在基本信息页面的数据库节点区域,单击右上角的切换图标切换视图。在数据库节点区域,找到需要设置热备功能的只读节点,单击操作列下的开启热备。开启热备功能会进行节点角色切换,大约需要6分钟,请您耐心等待。只读节点的状态变为运行中,表示热备开启完成。3.单击左侧导航栏的参数配置,在参数配置页面将集群的loose_innodb_trx_resume参数值设置为ON。参数打开表示事务续传功能开启。具体操作请参见设置集群参数和节点参数。该参数修改生效大概需要两分钟时间,请您耐心等待。当loose_innodb_trx_resume参数的值为ON时,表示参数修改完成。环节四:安装mysql-client和SysBench耗时:5分钟1.登录ECS实例。2.在ECS中依次执行命令安装mysql-client。通过mysql --version命令如果能看到mysql的版本号,说明mysql安装成功。mkdir package cd package # 下载mysql对应的安装包 wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm # 安装mysql yum -y install mysql57-community-release-el7-10.noarch.rpm yum -y install * --nogpgcheck mysql-community-server3.在ECS中依次执行命令安装SysBench。通过sysbench --version命令如果能看到SysBench的版本号,说明SysBench安装成功。yum install gcc gcc-c++ autoconf automake make libtool bzr mysql-devel git mysql unzip ##如果出现GPG keys的校验报错,请在该命令后面加上--nogpgcheck wget https://labfileapp.oss-cn-hangzhou.aliyuncs.com/Universities/sysbench.zip ##下载sysbench unzip sysbench.zip ##解压缩 cd sysbench ##打开sysbench目录 git checkout 1.0.18 ##切换到sysbench 1.0.18版本 ./autogen.sh ##运行autogen.sh ./configure --prefix=/usr --mandir=/usr/share/man make ##编译 make install4.执行命令配置SysBench client,使内核可以利用所有的CPU核数处理数据包,同时减少CPU核数之间的上下文切换。如果您购买的ECS实例的CPU核数低于4核,无需执行该命令。本文档中的f表示使用4个核,请根据您实际购买的ECS实例CPU核数进行配置。如果您购买的是8核的ECS实例,就用ff表示。sudo sh -c 'for x in /sys/class/net/eth0/queues/rx-*; do echo f>$x/rps_cpus; done' sudo sh -c "echo 32768 > /proc/sys/net/core/rps_sock_flow_entries" sudo sh -c "echo 4096 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt"环节五:模拟故障容灾耗时:150分钟1.在ECS上执行命令(会提示输入密码,密码为创建数据库账号时为示例账号temp设置的密码),在PolarDB MySQL版Serverless集群中创建数据库testdb,用于后续的SysBench流量注入。如果使用ECS实例的公网IP地址访问PolarDB MySQL版Serverless集群,此处的集群地址请使用PolarDB MySQL版集群的公网地址;如果使用ECS实例的私网IP地址访问PolarDB MySQL版Serverless集群,此处的集群地址请使用PolarDB MySQL版集群的私网地址。PolarDB的连接地址包括主地址和集群地址,本教程中请使用集群地址。关于如何查看集群的连接地址,请参见查看连接地址和端口。端口号默认3306。用户名是之前步骤中创建的PolarDB数据库账号的用户名(temp)。命令执行成功后,登录PolarDB控制台,在集群详情页面中单击登录数据库,使用已创建的账号temp和密码登录到DMS中,如果发现DMS中目标实例下存在数据库testdb,说明数据库创建成功。mysql -h 集群地址 -P 端口号 -u 用户名 -p -e 'create database testdb'2.使用SysBench模拟对数据库进行持续的流量注入。整个压测流量注入的时间较长,如果使用ECS实例的公网IP地址访问PolarDB MySQL版Serverless集群,大约需要1~2个小时;如果使用ECS实例的私网IP地址访问PolarDB MySQL版Serverless集群,大约需要10分钟。具体时间取决您的网络情况,请您耐心等待。sysbench --db-driver=mysql --mysql-host=<集群地址> --mysql-port=<端口号> --mysql-user=<用户名> --mysql-password=<密码> --mysql-db=testdb --table_size=25000 --tables=250 --events=0 --time=600 oltp_write_only prepare3.运行workload。为了您能及时观测到SysBench的TPS跌零现象,请提前登录PolarDB控制台并在运行workload的过程中直接执行第4 - 5步模拟故障容灾。sysbench --db-driver=mysql --mysql-host=<集群地址> --mysql-port=< 端口号> --mysql-user=<用户名> --mysql-password=<密码> --mysql-db=testdb --table_size=25000 --tables=250 --events=0 --time=600 --threads=8 --percentile=95 --report-interval=1 oltp_write_only run4.登录PolarDB控制台,在集群详情页面中单击登录数据库,使用已创建的账号temp和密码登录。5.在PolarDB MySQL版Serverless集群的DMS中执行命令,该命令可激活Serverless集群中的模拟故障容灾功能。call dbms_fault.crash();环节六:完成耗时:3分钟观察数据库的容灾恢复情况:在ECS终端中,观察压测的执行情况。压测的执行情况可以反应业务的连接情况。 如下图您可以看到,在触发故障容灾后,SysBench的TPS出现了跌零,持续10秒左右后立即恢复,并恢复正常的压测。在触发故障容灾后到恢复正常的压测期间,并没有出现报错,数据库连接也未发生中断。环节七:清理及后续耗时:5分钟清理完成教程后,请及时清理测试数据和试用资源。SysBench模拟流量数据清理sysbench --db-driver=mysql --mysql-host=集群地址 --mysql-port=端口号 --mysql-user=用户名 --mysql-password=密码 --mysql-db=testdb --table_size=25000 --tables=250 --events=0 --time=600 --threads=8 --percentile=95 oltp_write_only cleanupPolarDB MySQL版Serverless集群的试用时长为3个月,到期未释放可能产生欠费。如不再使用Serverless集群,请登录PolarDB控制台,找到目标集群,在操作列单击更多>释放,按照界面提升手动释放集群。ECS提供的试用实例有按量付费实例和包年包月实例。如果您试用的ECS实例为试用实例,请在试用中心确认您试用的实例类型,并参考以下规则清理:按量付费实例如果无需继续使用实例,可以登录ECS控制台,找到目标实例,在操作列单击,搜索并单击释放设置,根据界面提示释放实例。如果需要继续使用实例,请至少在试用到期1小时前为阿里云账号充值,确保账户金额不小于100.00元人民币。到期未续费的实例会因欠费而被自动停机,停机15天内实例将保留,15天后实例和数据都将被自动释放。包年包月实例包年包月实例到期会自动释放,释放实例的同时释放数据。如果需要继续使用实例,请在试用到期前及时续费。到期未续费的实例会因欠费而被自动停机,停机15天内实例将保留,15天后实例和数据都将被自动释放。后续在试用有效期期间,您还可根据希望测试的其它业务场景继续使用PolarDB MySQL版Serverless集群。
采访 | 王一鹏本期访谈由阿里云开发者社区、阿里云数据库事业部、InfoQ联合出品5G、AI 和云计算等技术的崛起,把数据库这项传统的底层技术推入到了数智化转型的前沿阵地。新应用诞生的新数据处理需求迫使数据库不得不快速做出反应以紧跟技术潮流,不被淘汰掉。在面对如此多的需要实时响应的场景时,几乎每一个月就更新一次的 ClickHouse 成为了新数据库时代的一匹黑马。ClickHouse 于 2008 年创建, 是一个用于在线实时数据分析(OLAP)的列式数据库管理系统,十年前由 Yandex 公司首次开发,主要为了给 Yandex.Metrica 提供支持,Metrica 是一个和百度统计、Google Analytics 类似的网站数据分析服务,当时仅次于 Google Analytics,是世界第二大网络分析平台。ClinkHouse 的大规模数据分析性能极强,通过提供一个真正的基于列的 DBMS,它允许系统以亚秒级的延迟从 PB 级的原始数据生成报告。当时的系统已经可以提供每秒十万行的服务器吞吐量,ClinkHouse 将这一速度提高到每秒数亿行。经过 8 年磨砺,2016 年起,ClickHouse 开始走出 Yandex 并作为开源解决方案为用户提供支持。虽然商业化时间不长,但得益于极高的查询处理速度和数据存储效率等优势,在此后几年,ClickHouse 的受欢迎程度成倍增长,2017 年,ClickHouse 引入国内。如今 ClickHouse 的开发者和用户已经遍布全球各地。国外的 Uber、eBay、CloudFlare、Cisco,国内的阿里巴巴、腾讯、字节、携程、有赞等许多头部大厂都在深度使用 ClickHouse 技术。其中,阿里云在 3 年前就上线了全托管的 ClickHouse 云产品,目前有超大规模的商业化 ClickHouse 云上集群。不管是大数据还是 DevOps 或是其他领域,只要涉及在线分析场景,都能找到 ClickHouse 的影子,越来越多的企业将 ClickHouse 作为实时分析引擎来使用。作为 ClickHouse 的最初设计者、Github 上 ClickHouse 开源项目的主要提交者,Alexey Milovidov 也是高性能 C++、分析应用程序和 SQL 数据库方面的专家。2019 年 9 月,为了让 ClickHouse 的技术潜力得到充分发挥,创始人 Alexey Milovidov 决定整合资源成立一家 100% 专注于 ClickHouse 的公司。担任联合创始人和总裁的 Yury Izrailevsky 此前曾在谷歌领导开发者平台和无服务器云产品。公司同时引入了 Aaron Katz 领导的世界级业务团队,这都会帮助 ClickHouse 取得更好的发展。ClickHouse 注册成立公司后,宣布筹集到 5000 万美元 A 轮融资,而在随后的两个月,ClickHouse 再次宣布完成 2.5 亿美元 B 轮融资,此次融资后,ClickHouse 估值达到 20 亿美元。Alexey Milovidov 表示:“我们已经赢得了一个由贡献者、开发者和用户组成的伟大社区,他们的支持说明了我们产品的质量。”那么,从研发至今,ClickHouse 经历了怎样的演进迭代历程?当前数据库行业面临哪些挑战?AIGC 的火热发展会给数据库带来哪些新机遇?未来行业到底需要一个什么样的 OLAP 数据库?以下为本次访谈视频实录和精华文字整理:ClickHouse 的演进与迭代王一鹏:非常感谢 Alexey 和林亮老师接受我们的采访。第一个问题想跟 Alexey 聊聊 ClickHouse 数据库的发展历程。ClickHouse 从研发至今已经过去了十多年的时间了,行业对 OLAP 的数据库需求也发生了一些变化,相对应的,ClickHouse 这些年做了哪些迭代和演进,能不能请 Alexey 给我们介绍一下?Alexey:最初,开发 ClickHouse 的目的是让它只服务公司内部的业务,所以它对我们来说足够用了。但自从它开源之后,我们看到很多公司也开始使用 ClickHouse,用法都不太一样,会有不同的优先排序、不同的需求,所以我们会看到有不同的应用案例。当我们只在一个公司内部使用 ClickHouse,它是非常完美的,但当它走入成千上万家不同的公司时,所产生的效果就会不一样了。不过在不同的用例中反复打磨后,产品的质量有了明显的改进,另外,它很重要的演进就是拓展了一些不同寻常的用例。如果非要举出一个 ClickHouse 的特点,那就是它的设计能满足某一个应用的实际生产需求,这样的特点让 ClickHouse 变得越来越强大。王一鹏:我们知道 ClickHouse 的性能很强大,但当它进入到企业环境中后,我们就需要考虑它的弹性能力以及云端部署的问题了。2021 年起,ClickHouse 注册成立了公司开始,独立运营团队就在集中精力解决云端部署的问题,我们想了解下,目前 ClickHouse 上云的进展怎么样了?围绕着云端部署做了哪些工作?Alexey:ClickHouse 是很灵活的,如果用户想要的话,它可以向上扩容到成千的服务器,但是扩容到数千服务器这个过程本身并不容易,它的演进也是另外一个方式,也就是扩展到另外一个架构上,是一种跨架构的扩容。我们知道这种存储对于我们来说是非常常见的,但是它不需要移动数据就能实现扩容,它能够有更好的扩容效果,像阿里云现在就是在使用这样的方式。王一鹏:这中间还涉及到一些问题,比如 ClickHouse 在数据一致性还是存在一些需要解决的问题,也正在解决吧?Alexey:你的意思是更新和删除分析数据库中的数据吗?王一鹏:是的。Alexey:是的,这个问题并不容易解决,但是现在有很多的系统,假装在解决这个问题。这类系统就是所谓的 HTAP,但问题是现存的系统并不适合,或者说这些系统不是针对分析型需求设计的。如果要优化分析处理,必须应用一些特殊的方法来更新或删除数据才能解决问题,不能只靠数据位置的转变就把复杂的事情变简单了。王一鹏:接下来这个问题也想问一下林亮老师,阿里云这次和 ClickHouse 的合作,是否跟云原生改造工作有关,能不能简单介绍一下具体内容?林亮:我们这边从两年多前就上线了阿里云 ClickHouse 的版本,经过这段时间的演进,收到了很多用户的反馈和需求,他们在使用 ClickHouse 的过程中也遇到过这样或那样的问题。目前,据我们所知,阿里云拥有超大规模的商业化ClickHouse云上集群,我们积攒了很多的用户、用例和他们的需求。本次阿里云和 ClickHouse 公司的独家合作,就是希望能够在中国大陆和亚太为用户提供一站式的产品。这次合作中就包括了云原生 ClickHouse 的内核。这当中有哪些技术点是客户真正需要的,我们在合作的前期也都进行过讨论。在阿里云瑶池峰会上我们提到的 SharedMergeTree,它可以把整个弹性做得比原来社区版本更高效。刚才提到的轻量更新和删除,这些都是过往用户遇到的痛点。接下来一两年内,我们可能会发布解决上述痛点问题的新版本,所以很期待新的 Serverless ClickHouse 这个产品能够帮助客户更好地构建分析型场景。王一鹏:Serverless 版本预计在什么时间发布?林亮:Serverless 版本现在正在研发和推进过程中,我们希望在今年年中或者下半年内发布,我们已经开放了早期的白名单注册,我们的内测版本可以提前给到大家来试用一下。就数据库来讲,上云是必选项吗?王一鹏:也想问问 Alexey 怎么看这次在国内和阿里云的合作,对于 ClickHouse 来说意味着什么?Alexey:我们会在中国寻找一些云的合作伙伴,目前为止,阿里云对我们来说是最给力的合作伙伴。王一鹏:现在,大家普遍认为我们正处于云原生时代。在两位看来,对于 ClickHouse 在内的大数据和数据库类的项目来说,上云是不是一种必然选项?林老师刚刚也提到,服务弹性扩缩容也会对原来的性能有一定的影响。ClickHouse 最开始服务的业务场景可能并不包括云上场景,但是现在在阿里云上的服务就是云上场景,所以这是不是必然的选项?先请林亮老师聊聊。林亮:就上云问题而言,我们看到目前用户使用数据的方式变得越来越复杂,首先是数据量增长越来越快,随着一些热点的发生,计算也出现很多不可预期性,复杂的查询对系统也带来了一定影响。另一方面,整个用户都在考虑如何能够更好地降本增效,能够更高效地使用当前的系统。回看整个云时代,从本质上来讲,云是把很多以前每个厂家不同小的“水井”合并在一起,汇聚成了无边无际的江河湖海。当更多的应用上云后,云的资源量使用更大,整个边际成本就开始往下降,这些红利就返回给了客户。像 ClickHouse 的云、阿里云自己的产品等这些云原生产品都是在更好地满足客户不同的数据处理和分析的需求,运用云本身所提供的高可用、易运维等特性更好地支持他们的应用场景。对于是否一定要上云的问题,其实用户的选择各有不同,有些客户出于安全和合规等考虑,依然是在线下的。但是如今,Gartner 分析师也指出,数据库的未来就是上云,可以看到,现在绝大数的客户都在往云上迁移,我们也相信这会是数据库未来的发展趋势和演进方向。王一鹏:现在上云的场景和 ClickHouse 最开始设计的场景好像是完全不同的,最初设计 ClickHouse 时它的场景是单机的,但自从独立成立公司后,看起来上云变成了公司非常重要的战略,所以 Alexey 是怎么看待这个问题的?Alexey:云确实是很重要的战略,但 ClickHouse 的优势是在任何地方都可以运行,包括在云上、本地部署、边缘设备上它都能完美地运行。所以显然它也应该匹配云上的需求,云是使用 ClickHouse 最简单的方式,而且有可能是最好的方式。王一鹏:但是中间还是经过了相当多的改造工作的吧?因为我知道业内有很多公司和团队其实在围绕 ClickHouse 做改造。Alexey:确实有很多部分需要专门为了云重新开发,比如我们不得不专门为云环境实现一个表引擎,原来的 ReplicatedMergeTree 对云架构匹配不是特别好,尤其当使用对象存储的时候。我们要做一些不一样的事情,我们需要让计算节点能独立于存储节点扩展,实现在所有计算节点之间并行查询,当我们使用不同的存储时都要做到非常高效的查询。云的对象存储和本地磁盘、内存等是不一样的,需要做不少工作,对象存储是另一种完全不同的“怪兽”。王一鹏:这些刚才我们提到的发生在公司和组织间的改造,会和我们商业化的路径或者上云的路径形成一种竞争关系吗?这个问题 Alexey 怎么看?Alexey:肯定会有竞争关系,竞争是很正常的,这在我们意料之中,大家其实也想效仿 ClickHouse 与我们进行竞争。换个角度看,ClickHouse 和我们正走在行业前列,引领这个行业,让其他人在后面追随。王一鹏:Alexey 提到这个问题恰好是我接下来要问的问题,既然有竞争关系,肯定也要分析彼此的优势在哪里?因为我们是研发了 ClickHouse 这个产品,我们除了更熟悉它,还有哪些其他方面的优势?Alexey:其实会有一些很有意思的方向,我只举几个例子。比如 ClickHouse 不仅是分析型数据库,它也是一个流处理平台。想象一下,如果同时使用 ClickHouse 和 Kafka,但出于某种原因你对 Kafka 不满意,觉得 Kafka 还不足以满足需求,你想把 ClickHouse 单独使用,而恰巧 ClickHouse 具备了独立处理、生成、转换数据流在内所有工作,那这时你一定会爱上 ClickHouse。还有一种可能,比如让 ClickHouse 具备批处理能力和 ELT,甚至更强的能力,比如内置 AI 能力,这样用户就能基于 AI 模型来写函数,这些想法听起来是不是也很让人兴奋?王一鹏:那您能从团队和人才能力层面聊聊这个问题吗?因为现在很多团队都在做改造,ClickHouse 公司作为 ClickHouse 项目的创始团队,理论上来讲应该是最了解这个产品的,是不是意味未来在发行版或改造版迭代时,我们仍然是最适合大家场景的、最能满足大家需求的这样一个产品?Alexey:其实,我们团队的大部分成员已经是 ClickHouse 的贡献者,他们已经对 ClickHouse 原代码很熟悉了,他们知道 ClickHouse 是怎样运作的,他们了解 ClickHouse 代码和架构目标就是要尽可能简单和易于使用。我们可以看阅读源代码、阅读注释,我们更熟悉 ClickHouse 的代码库,这就是为什么我们社区有很多贡献者。王一鹏:看来竞争对手先要成为 ClickHouse 社区的主要贡献者,然后再参与到其中来对吧?Alexey:是的,有一些从前的社区贡献者后来成立了新公司,可能会直接跟我们竞争,但这也没关系。竞争可以带来一些新构思,我们对此非常欢迎。王一鹏:林亮老师怎么看待这个问题?林亮:就像 Alexey 说的,其实有更多的人参与到这里面来也能更好地帮助整个社区成长。那么为什么 ClickHouse 在阿里云上会更好?据我们了解,阿里云上的 ClickHouse 集群目前是国内最大的 ClickHouse 集群,这里有多年来积累下来的客户场景、最佳实践和用例,此外,多年来我们和客户一起打磨下来的、更贴近场景的功能是很有竞争力的。另外,阿里云本身所能提供的安全性、可靠性和整个基础设施迭代上的保证,能够更好地支持这些 To B 企业安心地基于 ClickHouse 来构建企业级应用。最后,我们已经运营了 ClickHouse 差不多两到三年的时间,我们也期待后面跟 ClickHouse 的合作碰撞出更多火花,让产品能够基于阿里云能力之上,借助 ClickHouse 本身的技术的实力和优势,真正打造出一款最具竞争力的分析型数据库,帮助用户更好的成长。王一鹏:现在国内最大的 ClickHouse 集群是在阿里云客户服务这里吗?林亮:从我们了解到的信息是这样的,无论是单客户还是整体客户体量上我们都是比较大的。数据库未来的发展趋势王一鹏:另一个问题想问一下林亮老师,目前业内很多开发者认为大数据行业整体的技术是比较复杂的,涉及到的组件、工具都比较多。ClickHouse 最初面世的时候,大家觉得它是在 OLAP 这个场景下把性能推到了极致。接下来行业内的从业者会面临两个选择,一个是大数据的工具和要写的代码呈现出融合的趋势,大家没有那么复杂的场景和工具需要考虑。还有一个方向仍然是百花齐放的状态,比如你在 OLAP 场景用什么、OLTP 场景用什么,工具依然相当分散,林老师觉得接下来的演进趋势会是哪一种?林亮:我觉得有两个演进的趋势:一个趋势是融合。我们也看到业界有两种融合的方向,一种融合是指我们一直在提的湖仓一体,我们看到无论是 SnowFlake 还是 Databricks,都开始把它的湖往仓这个方向扩展。另一个融合就是我们刚才提到的 HTAP(在线和离线的结合),我们也看到有很多的数仓在往这个方向发展,就是在单产品之内把自己边界真正做到融合的覆盖不同的场景。此外还有我们在瑶池峰会上发布的整体的一站式解决方案,让数据库各个产品之间数据能够更好地自由流通,而不需要搭建这么复杂的组合方案。去年 AWS 在 re:Invent 上发布的 Aurora 和 Redshift zero-ETL,其实也是这样的思路和方向。整体目标也是希望用户的数据处理架构和设施搭建起来能够更方便。另一个趋势是多样化。我们也看到,无论从场景还是使用上,数据分析变得越来越复杂。所以我们觉得后面还是会针对不同的场景和特殊用例思考怎么做得更极致、更高效来设计产品。我觉得业界这种多样化的趋势还会存在的,随着这些场景和产品出来,它们可能后面又会被融合到当前的系统里去,所以我觉得整体上融合和多样化会是并行发展的趋势。本身技术上不一定融合好或者多样化就好,更多还是怎么能够更好地解决用户场景,要让用户真正做到一站式数据的使用,帮助他们真正地解决问题。王一鹏:Alexey 怎么看这个问题,您觉得融合还是会继续各个领域分别发展?Alexey:我觉得有些公司在将不同的技术用于不同的用例中,但我觉得这不是最佳的方案。如果用十几、二十几个技术,那么架构就会变得更加复杂,甚至可能会崩溃。我觉得很多场景还是在融合,我也看到了不同技术融合在一起的可能性,包括数据分析处理、交易处理、流处理,甚至键值数据库 ETL,他们在用更简单、更加高效的方式将解决方案融合在一起。为什么不把一个产品变成全能产品呢?虽然不是马上就能实现,但我看到了有这样融合的可能性。如果一个数据库就能解决的问题,为什么要用另外一个数据库呢?如果要用到搜索,为什么分析型数据库不能做搜索?为什么要用专门的数据库进行机器学习的向量搜索?我认为其实不需要专门的数据库,很多个需求都可以融合到一个解决方案中,也可以行之有效。当然有的时候融合并没有那么容易。王一鹏:可能阻碍大家做融合的第一个问题是性能,是不是融合到一起势必要牺牲一些性能,ClickHouse 最开始引得大家这么大的关注,在社区内火的这么快,也是因为 ClickHouse 性能非常突出,Alexey 觉得做融合数据库时会不会牺牲掉一些性能?Alexey:我认为这主要是聚焦方向的问题,当团队不大的时候一定要找到优先级排序。对于 ClickHouse 来说,最优先考虑的始终是性能和速度,如果说同一时间任务太多、太分散,有可能最后给到大家的就是一个半吊子的解决方案,哪个方面都不能做到极致。我不希望给到大家一个很普通的东西或者半成品。虽然不能什么都要,但要做就一定要做到最极致。AI 大火,为数据库行业带来哪些机遇?王一鹏:接下来我们来聊一聊最近非常火的 AI。这里想问问林老师,您认为 AI 能够给数据分析和整个数据库行业带来哪些新的机会或者机遇?过去 AI 技术和数据分析多有结合,典型的就是 BI 的场景,但是好像这些年发展下来,至少在国内的发展没有达到大家的预期,接下来 ChatGPT 通用人工智能的发展会给数据分析带来什么新的机会吗?林亮:这部分内容我不是专家,我的观点可能是抛砖引玉了。我觉得 AI 和数据库的互相推动主要体现在两个方面:一方面是数据库本身对数据的清洗、数据的管理能够给 AI 带来很好的思路。因为很多企业最核心的数据和最有价值的数据还是存在数据库里,这些已经清洗过的、最有价值的数据对 AI 一个很好的输入。另一方面,数据库本身所提供的无论是权限,还有对应的可靠性、可用性的能力,是他们想使用 AI 一个更重要的点。很多企业跟我们聊的时候会说,ChatGPT 非常火,但要把这个技术变成一个企业级应用的时候,一些数据处理的技术是相当关键的,数据库这么多年积累下来的技术会对这方面的工作有很大帮助。王一鹏:后面会不会大家在用一个大数据产品的时候,就没有 UI 的概念,可能提一些(Promote)实现比较复杂的数据服务或者获取一个数据赋能给它的结果?这些对于数据库来说都会是利好吧?林亮:对,我觉得这会是大的方向。整体来说,我们之前一直提到,数据湖最大的问题就是数据太多了,不同的 format、不同的信息散落在各个地方,怎么更好地聚集在一起,更好地分析湖上的数据,这也是湖仓一体系统需要解决的问题。这些东西通过数据库汇总到一起,整个上层 GPT 就可以更好地分析。再往前一步讲,现在很多客户进 BI 报表,一开始都是把几十个图表放在一个页面上,分析起来也很不方便。像微软在 PowerBI 上已经有 Demo 出来了,用户提一个问题,Demo 直接把关键问题的答案反馈给你,所以如何帮助大家更好地访问和使用数据,把数据的价值充分挖掘出来并创造出更大的价值,这不仅是 GPT 要解决的问题,也是整个数据库或者数据分析这个产业和所有同行们一直在追求的终极目标。王一鹏:Alexey 怎么看 AI 热潮给数据库和 ClickHouse 带来的机会,咱们现在是否也在关注 AIGC 技术和 ClickHouse 的结合?Alexey:是的,我们看到了一些两者相结合的可能性,主要是偏前沿技术方面。现阶段,AI 可以协助设计查询语句、自动补全,目前可能还做不到像我们预期得那么强大,但看上去是可行的。AI 能够给出正确的查询,但如果我们需要做更加复杂的工作,它经常会出错。你必须重新调试并检查实际生成的 SQL 语句,但是确实现在已经证明了它是能做到的。如果我们能让 AI 变得更加强大同时降低成本,不需要再花几千万去训练,我觉得那个时候的可能性可能会更高一些。王一鹏:Alexey 所说的两者结合的可能性是服务于什么场景,是现在 ClickHouse 应用性更好了,还是本身在功能层面会出现一些创新?Alexey:有一些显而易见的方面,但不是用于核心数据库的,这些部件主要是用于用户界面,可以协助用户编写和纠正查询语句,可能自动执行数据探索。比如你有一个数据库,你只是想以某种方式把其中的数据呈现出来让数据结构更易于理解,也许可能对于内部的数据结构和算法应用 AI 会更难一些,特别是机器学习的数据结构。但这可能无关乎 ChatGPT 而是更加传统的机器学习。也许未来我们会找到更多的可能性。王一鹏:咱们现在内部有尝试用 ChatGPT 辅助我们写代码吗?Alexey:没有,因为现在这么做没有意义,而且太昂贵了,我们只是做一些小范围的实验性工作。展望 OLAP 数据库的未来趋势王一鹏:接下来,我想问一个关于趋势性问题,也想请两位聊一聊,在接下来十年间,行业内会需要什么样的 OLAP 的数据库?林亮:我觉得 OLAP 数据库会朝着三个方向发展。一个趋势是:数据库和云的结合。我们此前也提到过,原来是讲数据上云,现在是讲“数据 + 云”,就是怎么能让 OLAP 产品利用好云的技术,包括怎样做到更好的弹性、怎样更好地利用好云的资源、如何帮助客户更好地应对降本增效的要求,我觉得这会是一个方向。另外一个趋势是湖仓一体。我们每天所产生的数据量是相当大的,但我们现在能够管理和应用的数据还是很少的一部分,所以怎么能够做更深度的探索,把湖和仓更好地统一和管理起来,进一步挖掘数据价值,同时也基于平台更好地分享数据,是所有从业者当下要着重思考的问题。现在国家有数据局来做管理,我也认为后面整个数据会更规范化、标准化,会有更多的共享,所以数据的隐私保护,也是未来 OLAP 系统需要具备的能力。最后一个趋势是数据库与 AI 的结合。这要分方面看:一个是 AI 本身能够帮助数据库做到更好更优的调优和调整;另外一方面是 AI 到后边也会变成数据库的“一等公民”,就像 SQL 函数一样,可能会成为数据库的标准能力,怎么更好地把 AI 这些能力集成在一起使用也值得关注。王一鹏:林老师聊的还是挺全面的,Alexey 怎么看待数据库未来发展趋势的问题?Alexey:我觉得还有一些没有解决的问题有待解决。数据清理、数据准备、弄清楚数据结构等问题可能看起来很简单,对于非结构化数据或者半结构化数据,其实很难获得跟结构化数据相同的性能。所以首先需要定义数据的结构,有时候你必须编写脚本来清理数据。比如客户给你一个数据表,你要把它整合到数据库当中,这些问题上也许 AI 可以提供帮助。嘉宾简介Alexey Milovidov,ClickHouse 创始人及 CTO林亮,阿里云数据库事业部 OLAP 产品部负责人。曾就职 Google 十多年,在超大规模 SQL Engine 和规模存储引擎上经验丰富。目前负责阿里云 OLAP 产品部。云数据库 ClickHouse云数据库ClickHouse 是分布式实时分析型列式数据库服务。具有高性能、开箱即用、企业特性支持。广泛应用于流量分析、广告营销分析、行为分析、人群划分、客户画像、敏捷BI、数据集市、网络监控、分布式服务和链路监控等业务场景。点击此处查看ClickHouse详情
AnalyticDB PostgreSQL云上“升舱”活动数据仓库困境传统数据仓库,如Teradata, Oracle相对生态封闭,成本高昂、缓慢、难以运维云上自建数仓,如自建Greenplum,运维成本较高,底层架构管理复杂,对于企业来说需要大量的精力和成本的投入; AnalyticDB PostgreSQL产品介绍企业级云原生Serverless数据仓库,支持PB级数据分析,产品全面兼容PG/Greenplum开源生态,兼容Oracle/TD语法生态;自研云原生存算分离架构,具备秒级弹性和数据共享等国内领先的产品能力; 拥有完整的企业级分析能力,融合阿里云产品生态,可打造全场景覆盖的一站式数据平台;查看更多AnalyticDB PostgreSQL内容“升舱”方案若您当前的数仓是线下自建的Oracle/Teradata/DB2,或目前使用云上自建的开源数仓,如Greenplum,您可以参考以下的典型数仓迁移方案及主要优势; 保有数仓迁移方案优势自建Greenplum数仓数据迁移https://help.aliyun.com/document_detail/157271.html 10~20%的成本下降提供完善的托管体验白屏的运维和诊断能力秒级弹性和灵活扩缩容3X+性能提升自建Teradata数仓数据迁移https://help.aliyun.com/document_detail/128748.html最高可节省90%的TCO秒级弹性和灵活扩缩容全白屏化的运维和诊断能力多实例共享数据能力HTAP分析能力实时数据分析能力自建Oracle数仓数据迁移https://help.aliyun.com/document_detail/300115.html数据应用迁移https://help.aliyun.com/document_detail/124685.html更多数仓迁移方案Redshift迁移https://help.aliyun.com/document_detail/101215.html?BigQuery迁移https://help.aliyun.com/document_detail/609733.html?平均降低50%+的费用主流能力均可替换活动内容活动时间: 9月30日之前活动内容: 专业升舱支持:提供专业咨询支持,帮助评估当前的规格容量;POC支持:技术支持用户完成数据功能,性能POC;数据迁移支持:提供辅助迁移工具及技术支持端到端迁移;活动期间迁移优惠: 可以提供最高价值5W的的迁移测试补贴支持;参与方式 对于有“升舱”需求的客户,请提交咨询,我们会在5个工作日内联系您,进行评估和方案的沟通;点击 升舱活动链接报名
01什么是E-R图E-R图(Entity Relationship Diagram)也称实体关系图,是一种用来描述实体、属性和关系的模型。我们常用矩形来表示现实中客观存在且相互区别的实体,用椭圆来表示实体具有的某一特征,用菱形来表示实体和实体间一对一,一对多和多对多的关系。假如现在回到我们大学的数据库课堂上,那么你一定不会对下面这个图感到陌生。E-R图一般是用数据库外键来存储和维护这个关系。但是随着业务规模增大和数据量增长后外键性能的降低,越来越多的应用系统在设计时不再使用外键而通过业务代码来保障业务之间的依赖关系,从而导致不易通过外键信息查看到数据中的逻辑关系。02我们看到的E-R居然不一样现在有一个数据库叫DMS_META,打开一个我们常用的数据库管理软件可以查看一下对应的E-R图。如下图所示,表在渲染的同时展示出了表与表之间的外键引用关系。但当我们打开DMS查看对应E-R关系时,发现渲染出来的关系会更加丰富。跟之前的看到的E-R完全不一样。03DMS增强E-R做了什么DMS的E-R图为什么会不一样?DMS对DMS_META这个库都做了哪些操作?增强了哪些能力?3.1 传统E-R能力我们使用DMS的表结构设计创建了4个会员表huiyuan_t1(简称t1表),huiyuan_t2(简称t2表),huiyuan_t3(简称t3表),huiyuan_t4(简称t4表),同时创建一个外键表huiyuan_fk(简称fk表),该表和t1表有外键引用关系。同时使用DMS的测试数据构建能力为这些表插入对应的测试数据。待数据资产图谱构建完成后,回到DMS上查看对应的增强E-R图,可以查看到物理外键间的关联关系。同时也可以点击“节点”和“边”查看对应的表详情和关联关系详情。3.2 列算子血缘解析E-R能力列算子血缘解析E-R是基于DMS自研的列算子血缘解析器的能力构建,DMS每天将通过SQL窗口和数据库开发工单中的所有SQL进行列算子血缘解析,并将经过列算子血缘解析后的字段之间的关联、依赖及影响关系纳入增强E-R图谱。接下来我们在SQL窗口(也可以通过数据库开发中的变更工单)上模拟一些真实场景的数据库操作。分别使用t1表和t3表的user_id做一次关联生成一个宽表huiyuan_join(简称join表),使用t4表做一次数据过滤生成一个新的新表huiyuan_depend(简称depend表),使用t2表和t3表进行一定的过滤并关联起来生成一张新表huiyuan_influ(简称influ表)。通过以上3条SQL模拟了DMS上一般用户的常见查询操作。待数据资产图谱构建完成后,回到DMS上查看对应的增强E-R图,可以看到,除了传统的物理外键外,字段关联字段,字段依赖字段,字段影响字段的关联关系也体现到了增强E-R图中。3.3 任务编排E-R能力同样的,通过DMS的任务编排进功能行一个常见的ETL任务的开发,创建一个huiyuan_df(简称df表),使用任务编排功能每天0点定时清理df的表,并从t2表抽取数据写入到df表。通过上述操作模拟了一个数据ETL任务开发的场景,并使用任务编排的调度血缘来构建资产图谱。待数据资产图谱构建完成后,回到DMS上查看对应的增强E-R图,可以看到,除了传统的物理外键,列算子血缘关系外,任务编排的调度血缘的关系也体现到了增强E-R图中。3.4 智能探查E-R能力智能探查(SchemaMatching)是DMS自研的数据识别算法引擎,该引擎可在已有的数据资产中识别元数据和内容数据并自动挖掘数据内潜在的关联关系,并将挖掘到的关系将用于构建增强E-R图。比如可以发现t1表的user_name和t2表的user_name从元数据和数据内容识别上来看都是用户的会员名,接下来我们将ShcemaMatching引擎挖掘后的结果进行关联。待数据资产图谱构建完成后,回到DMS上查看对应的增强E-R图,可以看到,除了传统的物理外键,列算子血缘关系,调度血缘关系外,通过智能探查的关系也体现到了增强E-R图中。小彩蛋细心的读者可以看到DMS增强E-R图中表的右上角有一些小图标,标识了该数据资产在DMS数据资产图谱中的使用情况。增强E-R还隐藏了更多的图标和功能待您继续发掘。04DMS增强E-R的技术能力DMS的增强E-R与传统E-R的构建方案不同,除了具有传统外键展示能力,在DMS一站式多云多源数据纳管,统一Catalog采集,列算子血缘解析和数据资产图谱构建等能力支持下,可以帮助您挖掘出数据资产之间更多潜在的关联关系。4.1 多云多源的数据纳管能力在数据源纳管能力上DMS一直主打的是"多云多源"的能力,除了纳管在阿里云下TP/AP/NOSQL/大数据/文件日志等数据源形态,也支持用户在他云/自建下的各种主流数据源。可以很好的解决企业数据孤岛,一站式安全和稳定地管理企业的所有的数据资产。4.2 统一Catalog采集能力DMS自研的统一元数据采集系统已经稳定的支持了阿里集团内部10多年的元数据采集工作,并作为集团内统一的元数据标准为集团的数据管理和治理等业务提供数据支撑和服务,可以快速稳定地对“多云多源”的元数据进行采集,并将各种数据源的实例/库/表/列进行统一的构建和管理。4.3 列算子血缘解析能力列算子血缘解析器是DMS自研的集多引擎SQL解析,元数据自动获取,字段血缘解析,字段加工算子解析于一体的解析器,具有解析字段关联字段,字段依赖字段,字段影响字段,表关联表,表依赖表,表影响表,字段影响表,表影响字段等能力。基于它可以对用户全量SQL中的数据加工逻辑进行快速的解构并给出结构化的解析结果以及直观的可视化视图。4.4 数据资产知识图谱能力DMS基于元数据自动挖掘和阿里云Tair for Graph的能力构建了百亿级别的节点和关系的数据资产知识图谱,并结合多种数据资产业务应用场景,提供对应的查询和服务能力,比如,通过查看敏感数据的传递方式,可以避免敏感信息二次加工后泄露;通过查看数据之间的依赖关系,可尽早发现数据变更的风险;通过查看数据之间的关联关系,可辅助构建数仓宽表;通过查看数据之间的加工关系,可查看数据的加工链路;通过查看数据之间的引用关系,可识别数据库中的冷、热资产。在阿里云瑶池数据库峰会上,我们就看到了DMS列算子血缘解析和数据资产知识图谱在招商银行内数据治理场景的落地效果。招商银行总行信息技术部数据治理团队负责人杨鹏表示:“招商银行携手阿里云能有效洞察僵尸资产、冗余资产等数据质量问题,助力全量资产可视化智能管理,提升业务部门用数效率,帮助我行实现降本增效。”快使用DMS体验一下吧!点击「此处」即可开启体验之旅
01背景最近AI行业的发展真是日新月异,自年初以来ChatGPT的火爆,几乎每隔几天都被各种新产品发布刷屏,从GPT-4、文心一言到Microsoft 365 Copilot、Github Copilot X、ChatGPT Plugin等等。AI正在掀起一场新的生产力革命,以集成了AI能力的Office和Github为例,仅仅使用简单的语言进行描述就能在Word中轻松生成初稿和总结,在Excel中自动分析关键趋势并创建数据模型可视化等操作,在PPT中快速制作出漂亮的演示文稿。AI还可以通过分析注释,函数名,上下文,基于分析结果给出自动补全建议、函数和方法调用、甚至是完整的代码段。对于那种常年无人维护的项目,还能帮助你分析,生成文档,编写注释。从此程序员悖论——程序员最讨厌的两件事:“别人不写文档”以及“写文档”,今天终于被AI彻底解决了。因此,老板想我蹭一把热度——将Lindorm AI 引擎光速对AIGC相关模型适配,然后写个文章,一开始我是拒绝的,蹭热点不是我这种务实又进取的程序员的风格,但看我余额为0的钱包还是不得不开工。既然介绍AIGC ,那我把老板需求提给ChatGPT应该不过分吧。AIGC是AIGC是(AI-Generated Content)的简称,通常指的是使用人工智能技术生成的各种内容,包括文本、图像、音频和视频。这些内容是通过使用机器学习算法和神经网络等技术进行训练和生成的。...这不是写的比我还好!火速化身为CV工程师 (Ctrl+C 和 Ctrl+V) 把文档转发给老板不就完事了。老板说小伙子不错啊,让你调研AIGC不是让你当需求路由器呀。你得把最新最牛逼的产品让读者知道AIGC具体是个啥玩意,ChatGPT知识比较落后,还得靠你亲自调研。好吧让我看看最近营销号什么东东火,就是你了Midjourney v5。prompt:A pair of young Chinese lovers, wearing jackets and jeans, sitting on the roof, the background is Beijing in the 1990s, and the opposite building can be seen —v 5 —s 250 —q 2.*注:图片及文字部分来自Midjourney官方这幅作品是由Midjourney推出,由人工智能(AI)生成的“中国情侣”图片在国内外社交媒体上广为传播。这幅作品逼真的视觉效果让很多网友惊叹,认为“AI已经不逊于人类画师了”。该工具是继GPT-4之后又一个备受关注的AI产品。(聪明的你肯定猜到了,这句话又是ChatGPT生成。)只需要在Midjourney中输入上面这段英文prompt,就可以生成这张图片,是不是很酷炫!02AIGC与数据库AIGC这么好用,还不赶紧做个APP玩一玩,万一火了,搞个公司上市,走上人生巅峰,指日可待。不过,对于我这种小白程序员,只会写前端和SQL,对这些模型又不太了解,更别说还要部署复杂的服务架构。该咋办呢?来了来了,Lindorm AI 引擎它来了,使用Lindorm AI 引擎的In-DB Inference功能,仅仅需要写几句SQL,就能在数据库内完成模型部署和推理,省去一系列安装部署步骤,快速搭建起一个AIGC应用。那么什么是Lindorm AI引擎, 什么是In-DB Inference呢,具体的操作方法是什么呢?03Lindorm AI 引擎Lindorm是面向互联网、物联网中的海量非事务数据设计和优化的云原生多模数据库,支持结构化、半结构化、非结构化数据的统一存储和计算,提供宽表、时序、时空、对象、流等多种处理模型,并兼容多种开源标准接口和无缝集成三方生态工具,满足车联网、自动驾驶、监控、推荐、风控、账单、工业互联网等业务场景的需求。Lindorm AI 引擎是Lindorm最新推出的支持在数据库内集成 AI 能力对非结构化数据进行智能分析和处理的引擎,结合Lindorm已有的对结构化和半结构化数据的分析和处理能力,这使得多模数据的融合分析成为可能。伴随着 AI 模型生态的逐渐成熟,如框架、格式逐渐收敛统一,以及一些开源模型平台(如ModelScope、HuggingFace)的出现,让一些常用的模型唾手可得,可以预见到未来更多的需求是直接使用这些预训练模型对数据进行推理,或微调,而不是从头训练一个新的模型。为此,Lindorm AI 引擎即将推出BYOM(Bring Your Own Model)功能,支持导入预训练模型在数据库内直接进行推理的能力,就是In-DB Inference功能。Lindorm AI 引擎支持用户自己上传预训练模型到数据库中,也支持直接从开源模型平台(包括ModelScope、HuggingFace)导入模型的功能,用户无需下载模型就可以很方便地完成模型在 Lindorm 内的部署和推理。Lindorm AI 引擎会根据用户指定的模型平台上的模型路径,自动下载模型并针对Lindorm AI 引擎使用的推理节点硬件对其进行适当的优化,以达到最佳的运行效率。*ModelScope:https://modelscope.cn/home04Lindorm AI In-DB Inference使用介绍Lindorm AI In-DB Inference功能的使用非常简单,首先用户通过一个CREATE MODEL的SQL在数据库中导入模型,指定模型在数据库中或ModelScope/HuggingFace中的路径,以及对应的CV、NLP任务等信息。然后就可以使用一个SQL函数指定刚刚导入的模型使用数据库中的数据作为输入进行推理。05利用Lindorm AI 引擎进行AIGC应用开发Demo根据文本生成设计图▶︎ 模型背景这里我们以ModelScope上的中文StableDiffusion模型为例,演示如何在Lindorm AI 引擎内完成根据文本生成设计图。Stable Diffusion是一种AI文本生成图片的扩散模型,能够在给定文本输入的情况下生成逼真的图像。▶︎ 构建步骤1. 在Lindorm数据库中创建室内设计文本描述表,将用于生成图片的文本插入到表中,这里我们插入了3条关于室内设计的文字描述:lindorm:default> CREATE TABLE `room_desc` ( > `room_desc_id` INTEGER, > `room_desc` VARCHAR, > primary key(`room_desc_id`) > ); lindorm:default> INSERT INTO `room_desc` ( > `room_desc_id`, > `room_desc` > ) VALUES ( > 1, > '新中式风格的家居设计,在传统中式风格的基础上,融入了现代时尚的设计理念,打造出一个充满禅意的中式风格卧室空间。' > ), ( > 2, > '室内设计,开放式,厨房和起居室,模块化家具与棉织品,木地板,高天花板,大钢窗,可以看到一个城市。' > ), ( > 3, > '高分辨率摄影室内设计,梦幻般的下沉式客厅,木地板,通向花园的小窗户,包豪斯家具和装饰,高天花板,米色蓝色鲑鱼粉色调,室内设计杂志,舒适的气氛。' > ); 3 row affected (22 ms) lindorm:default> select * from room_desc; +--------------+----------------------------------------------------------------------------------------------------------------------------------------------+ | room_desc_id | room_desc | +--------------+----------------------------------------------------------------------------------------------------------------------------------------------+ | 1 | 新中式风格的家居设计,在传统中式风格的基础上,融入了现代时尚的设计理念,打造出一个充满禅意的中式风格卧室空间。| | 2 | 室内设计,开放式,厨房和起居室,模块化家具与棉织品,木地板,高天花板,大钢窗,可以看到一个城市。 | | 3 | 高分辨率摄影室内设计,梦幻般的下沉式客厅,木地板,通向花园的小窗户,包豪斯家具和装饰,高天花板,米色蓝色鲑鱼粉色调,室内设计杂志,舒适的气氛 | +--------------+----------------------------------------------------------------------------------------------------------------------------------------------+ 3 rows in set (30 ms)2. 接下来我们使用Lindorm AI 引擎扩展的CREATE MODEL SQL语法自动从 ModelScope平台导入中文Stable Diffusion模型:lindorm:default> CREATE MODEL `room_maker_model` > FROM 'modelscope://damo/multi-modal_chinese_stable_diffusion_v1.0' > TASK TEXT_TO_IMAGE > ALGORITHM STABLE_DIFFUSION; 0 row affected (63 ms)3. 最后通过SQL调用推理函数 AI_INFER在数据库中使用刚刚导入的模型进行推理,Lindorm会先使用模型根据文本生成图片,自动保存成Lindorm内的BLOB对象类型,并返回图片的下载链接:lindorm:default> SELECT > `room_desc`, > AI_INFER( > 'room_maker_model', > `room_desc` > ) as 'room_image' > FROM room_desc; +--------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+ | room_desc | room_image | +--------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+ | 新中式风格的家居设计,在传统中式风格的基础上,融入了现代时尚的设计理念,打造出一个充满禅意的中式风格卧室空间。 | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873258559.jpg | | 室内设计,开放式,厨房和起居室,模块化家具与棉织品,木地板,高天花板,大钢窗,可以看到一个城市。 | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873265155.jpg | | 高分辨率摄影室内设计,梦幻般的下沉式客厅,木地板,通向花园的小窗户,包豪斯家具和装饰,高天花板,米色蓝色鲑鱼粉色调,室内设计杂志,舒适的气氛。 | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873271757.jpg | +--------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+ 3 rows in set (7875 ms)4. 通过得到的链接(备注:上述案例中的链接为测试实例所属VPC内网链接,无法通过公网访问)可以看到生成了三张室内设计图片。设计文案👇新中式风格的家居设计,在传统中式风格的基础上,融入了现代时尚的设计理念,打造出一个充满禅意的中式风格卧室空间。设计图👇设计文案👇室内设计,开放式,厨房和起居室,模块化家具与棉织品,木地板,高天花板,大钢窗,可以看到一个城市。设计图👇设计文案👇高分辨率摄影室内设计,梦幻般的下沉式客厅,木地板,通向花园的小窗户,包豪斯家具和装饰,高天花板,米色蓝色鲑鱼粉色调,室内设计杂志,舒适的气氛。设计图👇对设计图进行风格变换▶︎ 模型背景ControlNet是前段时间比较火的能够对Stable Diffusion生成的图片进行各种条件控制的模型,这里我们用它来对刚刚生成的几张设计图进行风格切换。▶︎ 构建步骤1. 我们使用另外一个表来做演示,表结构设计为包含一个图片 URL 地址和一个 prompt 字段,用来维护想要对设计风格进行控制的提示词。我们为刚刚生成的 3 张图片各切换 3 种风格(分别是中式、地中海和工业风),因此一共得到 9 行数据(出于篇幅限制,这里省略了 INSERT 环节):lindorm:default> CREATE TABLE `control_room` ( > `control_room_id` INTEGER, > `img_url` VARCHAR, > `prompt` VARCHAR, > primary key(`control_room_id`) > ); lindorm:default> select * from control_room; +-----------------+--------------------------------------------------------------------------------------------------+-----------------------------+ | control_room_id | img_url | prompt | +-----------------+--------------------------------------------------------------------------------------------------+-----------------------------+ | 1 | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873258559.jpg | Chinese style, 1 room | | 2 | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873258559.jpg | Mediterranean style, 1 room | | 3 | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873258559.jpg | Industrial style, 1 room | | 4 | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873265155.jpg | Chinese style, 1 room | | 5 | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873265155.jpg | Mediterranean style, 1 room | | 6 | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873265155.jpg | Industrial style, 1 room | | 7 | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873271757.jpg | Chinese style, 1 room | | 8 | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873271757.jpg | Mediterranean style, 1 room | | 9 | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873271757.jpg | Industrial style, 1 room | +-----------------+--------------------------------------------------------------------------------------------------+-----------------------------+ 9 rows in set (25 ms)2. 接下来同样使用SQL从HuggingFace平台导入ControlNet模型:lindorm:default> CREATE MODEL `style_transfer_model` > FROM 'huggingface://lllyasviel/ControlNet' > TASK MULTIMODAL_TO_IMAGE > ALGORITHM CONTROL_NET; 0 row affected (68 ms)3. 同样,通过调用推理函数AI_INFER在数据库中使用刚刚导入的模型进行推理,Lindorm会使用img_url对应的图片以及prompt作为模型输入,通过模型生成新的图片,并返回图片的 URL:lindorm:default> SELECT > `img_url`, > `prompt`, > AI_INFER( > 'style_transfer_model', > `img_url`, > `prompt`, > 'control_type=seg' > ) as 'controlled_image' > FROM control_room; +--------------------------------------------------------------------------------------------------+-----------------------------+--------------------------------------------------------------------------------------------------+ | img_url | prompt | controlled_image | +--------------------------------------------------------------------------------------------------+-----------------------------+--------------------------------------------------------------------------------------------------+ | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873258559.jpg | Chinese style, 1 room | http://ld-xxx-blob.xxx.com:9000/images/cn_1678873429213.jpg | | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873258559.jpg | Mediterranean style, 1 room | http://ld-xxx-blob.xxx.com:9000/images/cn_1678873451405.jpg | | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873258559.jpg | Industrial style, 1 room | http://ld-xxx-blob.xxx.com:9000/images/cn_1678873472694.jpg | | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873265155.jpg | Chinese style, 1 room | http://ld-xxx-blob.xxx.com:9000/images/cn_1678873494592.jpg | | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873265155.jpg | Mediterranean style, 1 room | http://ld-xxx-blob.xxx.com:9000/images/cn_1678873516370.jpg | | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873265155.jpg | Industrial style, 1 room | http://ld-xxx-blob.xxx.com:9000/images/cn_1678873538218.jpg | | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873271757.jpg | Chinese style, 1 room | http://ld-xxx-blob.xxx.com:9000/images/cn_1678873560219.jpg | | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873271757.jpg | Mediterranean style, 1 room | http://ld-xxx-blob.xxx.com:9000/images/cn_1678873582595.jpg | | http://ld-xxx-blob.xxx.com:9000/images/sd_1678873271757.jpg | Industrial style, 1 room | http://ld-xxx-blob.xxx.com:9000/images/cn_1678873604486.jpg | +--------------------------------------------------------------------------------------------------+-----------------------------+--------------------------------------------------------------------------------------------------+ 9 rows in set (16219 ms)4. 通过链接,我们可以看到切换风格后的图片:是不是很Easy就在数据库中完成了AIGC?还有更多有趣的用法等待你去尝试!Lindorm AI 引擎目前处于邀测阶段,感兴趣可以加入钉钉群:20975001191 参与功能试用和讨论。06未来展望Lindorm AI 引擎实现了数据不出库,一站式智能处理,可以大大降低AIGC业务落地的使用门槛。未来我们还会进一步探索如何利用 AI 对非结构化数据的分析与处理能力实现多模数据的融合分析与处理。我们希望用户在采用Lindorm构建AIGC应用时,就像用MySQL构建库存订单管理一样简单!
前置知识过滤条件下推在我们的常规认知中,过滤条件肯定是推的越靠近底层越好,将尽可能多的过滤条件更贴近数据源,以使查询时能跳过无关的数据,在AnalyticDB MySQL中,由于存储计算分离架构,那么谓词下推就是把所有能推的谓词都推到存储节点上去做。比如下图,所有的过滤条件都推到存储节点上去做,这样减少了后续算子的计算量,也减少了中间网络传输的数据量。谓词下推带来了很多的好处,基本上所有数据库,都会把谓词下推作为他们重要的优化功能。全下推到存储弊端但是过滤条件下推到存储层一定会快吗?为了弄清这个问题,我们先来看一下AnalyticDB MySQL的存储节点的索引结构。ADB目前默认是全索引,即会为所有列创建索引,并且支持多个条件同时走索引,快速多路合并,能够在毫秒级别找出满足条件的结果集。下图展示了一个表上多个过滤条件的索引查找过程。可以看到是每一列都会查找索引,最后将RowIds做交并差集运算。不下推 VS 下推了解完索引结构后,我们构造一个简单的例子,来说明过滤条件下推到存储之后却变慢的情况。我们简单假设一个代价模型,每一行扫索引的代价是A,每一行取明细以及数据传输的代价是B,计算层每一行过滤的代价是C。并考虑如下sql。create table user (age int, id int); select count(*) from user; -- 结果10,000; select count(*) from user where age > 18; -- 结果9,000 select count(*) from user where id < 10; -- 结果 20 -- 考虑如下sql select * from user where age > 18 and id < 10 -- 结果 10● 常规计划代价 10,000A + 10,000A + 10B (两列分别查索引的代价 + 取明细以及数据传输的代价)● Id列不下推计划代价 10,000A + 20B + 20C (一列查索引代价 + 取明细以及数据传输的代价 +计算层代价)可以看出如果 10B + 20C < 10,000A 的话,Id列不下推计划是更优的计划。可优化场景默认情况下,优化器会将所有带索引的列下推存储,从而减少读取至计算引擎的数据。但是仍存在几种场景不建议使用索引过滤数据:● 谓词选择率高,且谓词条件多,数据经过过滤后返回的数据仍然很多,那么使用索引进行数据过滤然后取交集的效果不一定好。● 磁盘IO压力大。如果用户业务的查询特征是占用较多的IO资源,或者数据写入较多导致占用了较多IO资源,那么使用索引进行数据过滤时,存在磁盘IO资源的争抢,过滤效果也可能较差。● 过滤谓词中带有复杂操作,比如字符串比较,LIKE操作等,会对存储节点产生较大的资源消耗,如果其他条件过滤后数据不多,不下推会对整体性能更加友好。智能下推所以为了优化ADB上述场景的性能,同时也为了避免ADB研发人员和用户耗费精力使用不下推hint来进行sql调优,在ADB新版本推出了智能优化功能,优化器基于准确的统计信息,在ADB中智能控制过滤条件是否下推到存储节点,让用户不用再纠结于是否下推的sql调优,加速用户查询,把简单交给用户。术语定义▶︎ conjunction我们把过滤条件按照最外层的AND拆分之后的单元叫做conjunction,比如 ((A & B) | C) & D & E 就是由 ((A & B) | C), D,E 三个conjunction组成的。只所以这么定义是,conjunction是是否下推到存储的最小单元。一个conjunction里面的条件要么都下推,要么都不下推。▶︎ selectivity谓词的过滤度,如果有100行数据,满足A>10的数据是10行,那么A>10的selectivity是10%▶︎ connectorADB 优化器支持多个connector,既可以支持ADB本身存储引擎,也可以支持OSS外表。不同的connector需要不同的处理。实现▶︎ A series of rules这里是ADB优化器原有的一系列过滤条件下推的规则,会尽量把filter一路推到 table 上方,推到距离存储节点最近的地方,然后下面的工作便交给了智能下推模块。智能下推模块来决定什么谓词可以继续推给存储节点。▶︎ Pretreatment短路优化:在模块的开始会粗略判断整个表扫描的开销,比如是个很小的表,那就快速跳过,以减少后续流程处理的额外开销表达式转化:应用布尔代数定律,尽量将过滤条件转换为AND连接。拿一个简单的例子来说,( A & B ) | ( C & D ) 是无法做到部分下推,部分不下推的,但是将其转换为( A | C ) & ( A | D ) & ( B | C ) & ( B | D)之后。便可以做到部分下推。这一步进行了限制,不会盲目转化,因为转换之后的表达式变长,可能会导致codegen超限等影响。▶︎ CalcSelectivity在这里会根据直方图等精准的statistics,调用ADB优化器中的Cardinality Estimation模块去为每个conjunction计算selectivity和相应的reliability。这个模块依托ADB优化器中精准的统计信息以及完善的基数估计,提供高质量的选择率,为后续的代价的计算以及下推方案的选择,提供准确的输入。▶︎ Connector Cost Model存储层自定义的代价模型,定义了根据selectivity计算出来的cost满足一定条件的过滤条件不会下推。这种分离的模式使得接入ADB的别的存储层,有智能下推的需求,也可以简单实现connector cost model,便可以实现智能下推的功能。▶︎ FilterPushDownSelection这个模块负责将所有的conjunction以及其selectivity和reliability输入给相应的connector cost model,然后以conjunction为最小单元枚举下推组合,模型算出代价,最后根据代价去选择开销最低的下推方案。这样下来,ADB便有之前的全下推,演变为现在的智能下推。全下推 VS 智能下推效果下图展示了一些索引扫描耗时占比大的查询使用智能下推后的加速效果。数据来源于内部灰度客户在智能下推开启前后,线上sql的平均RT变化。可以看到有着十分明显的性能提升。结语在数据库和大数据等相关领域,查询优化十分重要。实际生产中的问题,远比本文提到的要复杂。篇幅有限,更多技术细节没有深究。AnalyticDB 作为国内领先的云原生数仓和 TPC-DS 世界记录保持者,在查询优化技术上不断投入和创新。对技术感兴趣的同学,欢迎加入 AnalyticDB 社区讨论。(云数据仓库ADB-开发者群:钉钉群号 23128105)AnalyticDB MySQL新推出的湖仓版已正式商用,对于低成本离线处理ETL有需求,同时又需要使用高性能在线分析支撑BI报表/交互式查询/APP应用的用户,欢迎购买和体验!另外对湖仓版感兴趣的客户也可以填写问卷来进行试用申请,点击「此处」填写问卷。
1. 概述数字化已经成为企业提升业务效率、市场竞争力、管理能力的关键,后疫情时代经济复苏和企业重新起航需要较长时间,大部分企业在这段时间的核心策略是“收缩战线,精兵简政”,企业在上云、用云过程中,面临增效降本的诉求,作为数字化的核心技术---数据库如何增效降本,和企业一起度过困难的阶段,是很多企业关注的话题。阿里云瑶池数据库一直在思考如何给企业提供高效稳定的数据库解决方案,同时帮企业节约IT成本,并持续建设和构思增效降本的方法和路径。2. 业务痛点和应对思考2.1 企业上云、用云面临的数据库增效痛点企业业务由小壮大过程中,业务逐步复杂、业务类型日趋多元化、数据量逐步变大、数据库实例数逐步增加,需要构建高性价比、低成本的数据库方案;数据库方案要具备高稳定性、高性能、健壮性好、架构简单易维护等特点;不同类型业务对数据库计算资源使用特点不同,需要具备灵活、高弹性、适配性好计算资源提供方式以满足不同类型业务个性化使用需求;随着数据量从较小逐步增大,数据存储如何更低成本、更便捷地存储和访问以及可持续支撑业务,也是数据库方案的重要关注点;随着研发团队的人员日趋增多和数据库实例的不断增长,如何给研发团队提供安全、高效、低使用成本的数据库方案的也成为企业负责人关注的重要话题。面对企业这些诉求,云数据库如何在产品、方案侧应对的呢?2.2 构建增效降本能力、策略和思考我们首先思考一个问题:将数据库定义为一种服务,对一个上云、用云企业,云数据库直观成本包括哪些?硬件成本:云厂商承载数据库实例的服务器、网络、存储以及IDC基础设施成本。软件成本:云厂商研发、迭代数据库软件的人力成本,部分服务有软件采购成本。使用和维护成本:企业使用数据库的人员花时间学习、掌握技能,数据库需要技术人员维护。时间成本:企业采用复杂方案、低效方案、不稳定方案方案,有较长的学习时间成本和试错成本。数据处理成本:为提高数据资产价值,企业探索数据使用方式和数据流转方式需要较大人力成本。对企业来说数据库成本包含两个维度,一个是云厂商提供可持续服务的成本,一个是企业使用和维护数据库的人力成本和时间投入成本;增效降本方案需要“降低”软硬件成本,并通过优势方案提高数据库使用人效、降低人力成本和时间成本。3. 构建云原生数据库增效降本方案3.1 数据库增效降本框架云数据库实现增效降本,提供几个层面手段和方案:1.数据库计算资源弹性,通过快速弹性升降配、自动弹性升降配、Serverless等方式提高弹性能力,充分利用云的弹性能力降本。2.数据库存储资源,提供数据透明冷热分层、数据平滑归档、存储高压缩比、新硬件增效降本等应对海量数据存储和访问的高性价比方案。3.数据库架构优化,提供数据库HTAP解决方案、多源汇聚库、低成本多级数仓等架构优化方案,降低使用成本、开发维护成本。4.建设运维、研发增效方案,基于DMS的数据库DevOPS方案,基于DAS的构建数据库“自动驾驶”方案。从下图可以看出云数据库提供的增效降本方案覆盖了数据计算、数据存储、数据流转、数据分析、数据管理维护等不同业务阶段供企业选择。3.2 计算弹性增效将本弹性是云原生数据库核心优势,能有效降低计算成本,阿里云数据库一直致力于提供弹性能力更强方案给企业客户,云数据库的弹性能力经历了三个阶段:第一阶段是高弹性能力,将天、小时级弹性提速到分钟级。第二阶段是自动弹升,支持基于预测的自动弹性伸缩和定时自动弹性伸缩提高弹性能力。第三阶段是建设和持续演进数据库Serverless能力,进一步提升资源利用率。传统主从复制架构数据库升降配和增加节点需要复制数据,耗费时间和数据物理大小有关。PolarDB借助RDMA高速网络和共享存储能力,升降配增加节点与数据库大小解耦,分钟级即可完成,可构建“流量突发型业务库”提效方案提升企业数据库弹性能力。部分企业业务复杂度高、多样化强、异常流量无法预测,对弹性方案提出了进化要求,数据库自治服务DAS的自动性能扩展结合PolarDB分钟级弹性提供分钟级自动弹升能力,很多企业客户借助该能力规避性能风险。云数据库RDS MySQL也支持性能自动扩容能力,云原生数仓AnalyticDB通过分时弹性支持定时自动弹升能力。Serverless技术给资源弹升和计费带来更灵活的能力,PolarDB攻坚了Serverless技术难点:资源解耦、自动弹性伸缩、按使用量计费、秒级弹性扩展等。支持无感BP Resize的本地Scale Up、跨机ScaleUp、跨机ScaleOut。云数据库RDS MySQL、云原生数据仓库AnalyticDB、云MongoDB也都具备了Serverless能力。3.3 存储透明冷热分层、压缩增效降本数据存储是数据库的核心能力,云数据库借助云基础设施构建和支持不同技术指标、不同成本、使用灵活的存储方案。企业的业务数据类型、业务数据量、数据物理大小随着业务发展到一定阶段和量级面临以下痛点:单实例存储量大、存储成本高、实时业务数据高性能访问、海量数据高性能访问诉求等。云数据库通过以下几种技术方案来实现数据存储方面的提效和降本:数据透明冷热分层存储读写数据存储压缩自研X-Engine引擎历史库硬件压缩盘(Smart-SSD)Tair PMEM持久内存3.3.1 透明冷热分层方案冷热数据分层存储是应对大量数据存储常见方案,根据数据使用频率、文件大小、文件类型等特征做数据冷热分层,采用适配的存储介质存储,满足存储海量数据、延长保存期限、降低存储成本、提高数据访问效率等诉求。数据冷热分层的关键是透明冷热分层存储策略、冷热数据透明读取以及无感数据过期迁移,通常以时间字段作为区分冷热数据依据。如在Lindorm上,在表上配置数据冷热时间分界点(COLD_BOUNDARY),Lindorm根据数据写入时间戳(毫秒)来判断数据冷热。数据写入时优先存储于热存储,写入时间超过冷热时间分界点,major_compact时归档冷数据到冷存储介质。数据读取时自动根据查询时间范围条件决定查询热区、冷区还是冷热都查。除了Lindorm,Clickhouse、PolarDB MySQL、AnalyticDB MySQL也支持数据冷热分层存储和读取。3.3.2 数据存储压缩方案除了将冷热数据分别存储到不同介质外,很多数据库支持引擎层面采用压缩算法来减少空间占用,如PolarDB X-Engine引擎,对比InnoDB引擎,最高可节省50%的存储空间;Lindorm内置深度优化的压缩算法,数据压缩率高达10:1以上。X-Engine引擎行存数据压缩业界根据MySQL可插拔存储引擎能力提供了RocksDB、Tokudb、Infobright等具备压缩能力的存储引擎应对关系型数据增长问题。阿里云X-Engine也是为解决海量关系型数据存储的数据引擎。X-Engine在LSM-Tree分层存储架构基础上进行了重新设计,根据数据访问频度(冷热)的不同将数据划分为多个层次,针对每个层次数据的访问特点设计对应存储结构,写入合适存储设备。使用Copy-on-write技术,避免原地更新数据页,对只读数据页面进行编码压缩,可以将存储空间降低至10%~50%。Lindorm高压缩能力Lindorm在数据压缩方面也提供了非常优秀的能力,提供超10倍数据压缩比。字典压缩:Lindorm宽表基于LSM-Tree引擎构建数据存储,通用压缩算法上结合ZSTD深度定制,推出字典压缩能力—自动提取数据样本采样分析,根据数据特质,智能选择合适的编码压缩参数,提取公共字典消除字典结构带来的额外开销,进一步提升了数据的压缩比率与压缩速度。时序数据专用压缩算法:Lindorm时序引擎借助TSM架构实现时序数据的高效写入,采用定制时序压缩算法提高压缩比,最高可达15:1的压缩率比。本地盘HDD与ESSD异构副本:Lindorm通过LindormDFS异构副本实现1副本ESSD+2HDD冗余,通过HDD盘低成本优势结合冷热分层显著降低存储成本。3.3.3 新硬件新技术方案硬件压缩盘(Smart-SSD)PSL4PolarDB引入阿里巴巴自研Aliflash Smart-SSD技术,在物理SSD磁盘层面压缩、解压缩存储的数据,实现性能零损耗下数据存储成本最高下降 60%。硬件压缩盘的压缩引擎集成在盘片内部,通过FPGA/ASIC提供专用算力在数据读写过程中实时压缩、解压缩数据,从而节省存储空间。Tair持久内存 Tair是阿里云自研云原生内存数据库,完全兼容开源Redis,除了纯内存的产品形态,Tair借助于新型存储介质——Intel 傲腾(AEP)持久内存技术,实现成本低于于内存(DRAM)30%以上。Tair持久内存实例中,每条记录都确保写入AEP并且持久化才返回,极大提升数据可靠性,可以做到RPO=0;读取路径上使用Dram缓存如索引、数据结构、元数信息等热点数据,加速数据访问。3.4 技术架构优化增效降本随着业务规模、用户量、业务复杂度的提升,企业使用数据库的场景日趋复杂,自建数据库服务面临着构建更多周边服务降低使用、学习成本,云数据库提供多种技术架构优化方案,本段介绍HTAP解决方案、多源汇聚库方案、基于湖仓一体的多级数仓方案。3.4.1 HTAP解决方案HTAP是数据库技术领域新概念,是在线事务(OLTP)和在线分析(OLAP)合称简写。HTAP的最大优点是可以在一个数据库中支持OLTP和OLAP业务,系统具备完整事务能力,支持实时插入、实时删除、单条更新、批量导入、按索引查询、海量数据实时分析等能力。阿里云PolarDB MySQL通过列存索引IMCI和弹性多机并行ePQ使得PolarDB具备HTAP能力,支持OLTP高并发读写的同时,大幅提升PolarDB在大数据量复杂查询性能。优化器支持基于代价的执行计划选择,从IMCI->ePQ->MySQL原生串行查询,保证SQL 100%可解析执行。IMCI(In-Memory Column Index)节点和行存只读节点基于物理复制保证延迟在毫秒至秒级,提高数据访问的实时性。适用于亿至百亿业务数据复杂查询提速、原生MySQL查询慢、业务混合负载业务查询提速。PolarDB HTAP方案在实际业务场景使用中最高可以达到百倍慢查询提速,畅捷通、金万维等客户都借助HTAP方案为业务提速。HTAP方案业务架构图如下:PolarDB IMCI通过列式存储高压缩存放、按需读取需要分析列、执行器算子并行执行、单个线程内算子数据交互以Batch为单位降低函数调用开销等技术结合配合弹性多机并行使得PolarDB成为一个真正的HTAP数据库系统。弹性多机并行ePQ可以利用多计算节点资源进行并行查询,提速TB级别甚至单表10TB以上多表关联复杂查询,突破单机CPU/IO瓶颈将多个节点计算资源打通,利用全局资源提速大量数据复杂查询。3.4.2 多源汇聚库多源汇聚库是泛互联网企业做微服务拆分、数据库垂直拆分后常见的跨实例数据访问、数据抽取、数据流转方案,为降低研发成本考虑采用汇聚库方式做拆分后跨库数据查询和数据流转。传统多源汇聚库方案通过开源或商业数据复制工具将多个业务库数据复制到汇聚库,汇聚库结合代理软件向不同业务侧提供数据库服务,支持跨库查询、数据抽取、数据下有复制等,常见架构如下:该方案满足跨库查询需求、数据向下游流转、慢查询导致业务库性能抖动问题,存在以下不足:数据复制延迟大影响数据访问质量、存储成本高、开源代理不稳定维护成本高、汇聚库以及数据流转任务恢复成本高DBA维护压力大。阿里云数据库提供基于PolarDB多主集群的多源汇聚库方案,多主集群支持一个集群多个主节点,任意主节点都可访问共享存储内所有数据,并可以在任意主节点读写。不同主节点可以承载不同数据库支持任意主节点之间秒级切换数据库,可以通过全局读节点结合智能代理替代汇聚库,支持流量自动转发读写和负载均衡,架构如下图:基于PolarDB多主集群构建的多源汇聚库方案具备以下业务收益:1.提高跨库聚合查询和数据向下游流转效率。2.降低存储成本:存储成本占比高(50%以上)相对自建数据库可降本10%以上,某交易属性客户迁移后降本20%。3.提高数据访问质量:复制延迟毫秒至秒。4.提高异常恢复速度:级扩容写节点、全局读节点高可用、分钟级新增几点。5.DBA工作量低:异常切换恢复操作便捷、数据流转方便、方便授权。3.4.3 基于湖仓一体的多级数仓方案 随着业务数据不断增长和多样化,可以把数据大致分为两类,一类是结构化数据,另一类是非结构化数据。结构化数据最具代表性的数据库有Oracle和Teradata,但面临维护成本+政策风险双重压力;半结构化或非结构化数据根据数据特征可以分为宽表、时序、图、key-value、文档等,这两类数据存储读取典型代表是Hadoop,但技术栈繁多、复杂依赖个人能力,维护成本过高。数据业务特性随着时间发展从传统商业业务数据,到互联网平台业务数据,再到万物互联的业务数据,数据规模也从GB级,到PB级,再到EB级。数据作为企业的核心资产,随着企业之间商业竞争日益激烈,数据流动越快产生价值越大企业竞争力越强。传统数仓面临挑战越加严峻,大数据发展也从传统数仓发展到离线大数据时代来满足大数据量和数据多样化的诉求,企业对数据实时性要求越来越高,需要通过实时数仓以及湖仓一体来解决所面临的痛点。下面介绍基于阿里云构建实时数仓和湖仓一体的多级数仓方案。如何构建实时数仓数仓一般分为ODS层、DWD层、DWS层和ADS层,数据分层越多,数据的实时性受影响越大。要构建实时数仓需要减少数据端到端的层数和并提高数据处理速度,数据分层结合数据业务需求,额外构建一套实时数仓,来满足实时业务场景。根据现有数仓体系演进的架构就变成标准数仓分层+流计算+批处理,具体架构变成如下:基于该设计理念衍生到阿里云实时数仓解决方案:选择数据传输服务DTS支持业务数据到实时数据的数流转,实时数仓选择云原生数据仓库AnalyticDB MySQL数仓版,湖仓一体方案选择AnalyticDB湖仓版支持,通过数据管理DMS支持任务编排、数仓开发、ETL等功能,同时DMS还支持流式ETL。为何选择DTS做数据实时流转数据传输服务DTS支持关系型数据库、NoSQL、大数据(OLAP)等数据源数据实时同步,提供功能丰富、操作便捷、数据实时复制、传输性能强、支持断点续传、易用性高、安全可靠的数据传输服务,简化数据流转工作,使数据开发人员可以专注数据业务开发。为何选择AnalyticDB?云原生数据仓库AnalyticDB MySQL版是新一代云原生数据仓库,AnalyticDB支持高吞吐数据实时增删改、低延时实时分析和复杂ETL,兼容上下游生态工具,可用于构建企业级报表系统、数据仓库和数据服务引擎。AnalyticDB具备以下优势:兼容MySQL:高度兼容MySQL协议以及SQL 92、SQL 99、SQL 2003标准。多租户:通过资源组实现计算资源隔离满足不同类型租户业务需求。分时弹性:支持定制弹性计划(每天定时、每周定时),业务高峰期来临前自动扩容满足业务流量增长需求,业务高峰过后缩容降低IT成本。AnalyticDB湖仓版基于AnalyticDB湖仓版构建湖仓一体方案,内部存储支持在线数据处理和查询,开放式存储支持离线数据处理,能够识别加载多种数据格式文件。具备云原生、自动数据冷热分层能、多租户、多种计算引擎等能力,支持PB级数据实时、离线分析,秒级到分钟级出结果,湖仓版架构图:3.5 运维、研发流程增效方案云数据库帮助企业解决了资源弹性、高可用、备份、监控等基础运维问题,随着业务发展、公司规模扩大,数据库运维团队面临着数据库集群规模化、研发流程化以及运维智能化建设需求。云数据库提供运维、研发流程增效方案:数据库DevOPS方案、数据库自治管理方案。3.5.1 数据库DevOps方案传统数据库研发模式通常会面临研发效率低、数据安全无保障、变更风险大等问题,比如新业务上线层次审批后因“还没到窗口发布期”不得不推迟几个小时;多项目共用库表发布顺序问题;新项目上线结构不合理慢SQL激增影响到生产环境。数据管理DMS提供了平台化、流程化数据库协同开发能力,使得构建、测试、发布数据库变更更快捷、安全和可靠。数据库开发设计阶段:表结构设计中,引入数据库设计规范。比如表名/列名带业务含义、必须有主键或UK等。DBA根据业务重要级别设置不同审批发布流程,比如非核心库研发TL审批、核心库必须DBA审批,一方面适当放权另一方面提升生产系统稳定性。SQL审核阶段:项目正式发布前,避免不符合数据库开发规范的SQL(比如建表语句不含主键、索引过多等)发布到线上影响生产服务,需要审核SQL语句、提出相关优化建议。发布阶段:结构设计及测试完成、SQL审核后,进入结构发布审批流程。由系统做风险识别,比如表数据量、索引数量、是否会锁表变更等,由审批人员(通常数据库owner或者DBA)审批确认,审批通过后由研发选择自动执行或者手动执行。变更执行阶段:在执行阶段,需要一些策略来降低变更风险,比如对添加唯一索引、变更主键等需要采用无锁表结构变更、限制DDL并发数降低对系统影响等。也需要根据业务类型级别设置不同变更窗口,比如交易相关数据库变更时间设定在凌晨执行。运维调优阶段:上线之后,要对变更内容进行持续关注,比如查询性能、会话并发数等等,需要从多个角度了解、并及时定位并解决数据库存在问题,保障服务安全性和稳定性。除了数据库DevOps相关功能外,DMS也提供了更加细粒度的安全策略:比如行级别访问权限控制、防泄露数字水印、敏感数据脱敏保护、操作审计等,对数据库进行全方位保护。3.5.2 数据库自动驾驶方案 DAS随着业务的发展,企业数据库集群不断增长,运维人员数量没有按比例增加,数据库运维平台化、自动化、智能化要求也是越来越高。人工智能、机器学习技术的发展,给数据库运维智能化带来新能力。如在SQL诊断与优化场景,数据库自治服务DAS便基于机器学习和专家经验,实现数据库“自感知、自修复、自优化、自运维及自安全”能力,企业可以“辅助驾驶”数据库,降低维护成本。DAS具备以下核心能力:异常事件:系统收集各种指标和事件,如QPS、TPS、CPU、IOPS等等,并对指标数据进行实时和离线分析,能秒级获取到异常事件。诊断发起:自动SQL优化服务从事件中心收异常事件,完成实例初步判断,向诊断引擎发起诊断请求并处理诊断结果,完成有效性评估,生成新的优化事件驱动下一步优化。建议推送或自动优化:根据用户设置的自治策略,事件中心推送SQL优化建议给DBA判断执行,或在用户授权下自动执行优化,并确认执行情况。效果跟踪和衡量:优化执行后,决策引擎启动跟踪任务,跟踪被优化SQL及相关SQL性能,如性能出现衰退,则自动回滚。DAS已具备“7 x 24实时异常检测、故障自愈、自动优化、智能调参、自动弹性、智能压测”等能力。并会持续发展自动化、智能化能力,数据库运维由目前的“辅助驾驶”升级为真正的“自动驾驶”。4. 增效降本方案展望除了持续优化迭代计算降本、存储降本、架构优化、流程增效等方案,帮企业增效降本之外,云数据库产品和解决方案,还好会依托云原生数据库和周边配套设施持续构建更丰富、更高效、更高性价比的数据库解决方案,助力企业持续发展。如需了解「数据库增效降本解决方案」,欢迎点击此处进行咨询
1.概览AnalyticDB MySQL高度兼容MySQL协议,支持毫秒级更新,亚秒级查询,可以对海量数据进行即时的多维分析透视和业务探索;而最新推出的AnalyticDB MySQL湖仓版(下文简称ADB湖仓版)支持低成本离线处理能力完成数据的清洗加工,同时提供高性能在线分析能力完成数据的洞察探索,真正做到数据湖的规模,数据库的体验。帮助企业降本增效,构建企业级数据分析平台。APS(ADB Pipeline Service)简介:ADB湖仓版在深化自身湖仓能力建设的同时,还推出了APS(ADB Pipeline Service)数据通道组件,为客户提供实时数据流服务实现数据低成本、低延迟入湖入仓。本文以数据源SLS如何通过APS实现高速精确一致性入湖为例,介绍相关的挑战和解决方法。在数据通道的构建上,我们选择Flink作为基础引擎。Flink作为业界熟知的大数据处理框架,其流批一体架构有助于我们处理多种场景。而ADB的湖则建设在Hudi之上,Hudi作为成熟的数据湖底座已经被多家大型企业实际应用,ADB在其上也已积累多年经验,如今ADB湖仓版把湖和仓进行深度融合提供更加一体化的解决方案。数据入湖的精确一致性挑战:在入湖通道中,有可能出现异常,升级,扩缩容等场景导致链路重启,触发部分已处理数据从源端重放,导致在目标端出现重复数据。为解决此问题一种做法是配置业务主键,并使用Hudi的Upsert能力来达到幂等写入目的。但SLS入湖的吞吐目标是每秒GB级别(某个业务的需求是4GB/s)且需要控制成本,Hudi Upsert难以满足需求,而SLS数据本身就具有Append特征,因此采用Hudi的Append Only模式写入实现高吞吐,并用其他机制保证数据不重不丢的精确一致性。2.端到端精确一致性的问题和解决方案流计算的一致性保障一般包含如下几种:精确一致的语义是所有一致性语义中要求最高的,但流计算中的Exactly-Once一般是指内部状态的精确一致性(Exactly-Once State Consistency),而业务需要的是端到端Exactly Once,即当出现异常Failover场景时,最终目标端的数据需要与源端保持一致,数据不重不丢。2.1 端到端精确一致性问题要实现精确一致性,就必然要考虑Failover场景,即当系统宕机任务重启时,如何恢复到某个一致性状态。Flink之所以称为Stateful Stream Processing是其可通过Checkpoint机制保存状态到后端存储,并在重启时从后端存储恢复到某个一致性状态。但在状态的恢复中,其仅仅保证了Flink自身的状态一致,而在包含源端、Flink、目的端这样的完整系统中,仍可能产生数据丢失或重复,导致端到端出现不一致。下面用一个字符连接的例子说明数据重复问题。下图是一个字符串连接的处理过程,处理逻辑是从源端读取一个个的字符,并对它们进行连接,每连接一个字符就向目标端输出一次,最终输出a, ab, abc ...多个不重复的字符串。本例的场景中,Flink的Checkpoint保存了已完成的字符连接ab,以及对应的源端位点(Checkpoint箭头指向的位点)。Current则指向当前正在处理的位点,此时已经向目标端输出了a, ab, abc。当发生异常重启时,Flink从Checkpoint恢复自身状态,回退位点并重新处理字符c,并再次向目标端输出abc,导致abc出现重复。在这个例子中,Filnk通过Checkpoint恢复状态,因此不会出现abb,或者abcc这种重复处理字符的情况,也不会出现ac种丢失字符的情况,保证了其自身的Exactly-Once。但是在目标端出现了两个重复的abc,因此没有保证端到端的Exactly-Once。2.2 端到端精确一致性方案Flink本身是一种复杂的分布式系统,其内部包含Source、Sink等算子,同时还存在Slot等并行关系,这样的系统要实现精确一致一般会想到两阶段提交,实际上Flink的Checkpoint就是一种两阶段提交的实现。而在端到端中,Flink和Hudi又组成了另一个分布式系统,这个分布式系统要实现精确一致性,就需要另一套两阶段提交的实现(我们这里不讨论SLS端,因为在本场景中Flink不会改变SLS的状态,只利用SLS的位点重放能力即可)。因此端到端中,是由Flink和Flink + Hudi两套两阶段提交来保证精确一致性(见下图)。Flink的Checkpoint两阶段实现不再赘述,后文会重点介绍Flink + Hudi两阶段提交的实现,定义出哪些是Precommit阶段,哪些是Commit阶段,同时发生异常时如何从故障中恢复保证Flink和Hudi的状态一致。例如Flink已经完成Checkpoint,而Hudi尚未完成Commit,如何恢复到一致性状态,这些在后续章节介绍。3.SLS入湖链路端到端精确一致实现下面介绍SLS入湖链路精确一致性的实现。整体架构如下,Hudi的组件是部署在Flink JobManager和TaskManager上的。SLS作为数据源,由Flink读取处理后,写出到Hudi表。因为SLS是多shard存储,因此会由Flink的多个Source算子并行读取。数据读取后通过Sink算子调用Hudi Worker写出到Hudi表。当然实际的链路中还会有Repartition,热点打散等逻辑,这些在图中做了简化。Flink Checkpoint的后端存储,以及Hudi数据的存储都是放在OSS上。3.1 SLS Source算子如何实现Source算子消费SLS数据已有大量介绍,此处不在赘述。这里介绍SLS的两种消费模式:消费组模式和普通消费模式以及他们的区别。▷ 消费组模式顾名思义,多个消费者可注册到同一个消费组,SLS会自动把Shard分配给这些消费者来读取。其优点是由SLS的消费组来管理负载均衡。如下图左,消费组中首先注册了两个消费者,因此SLS把6个Shard均匀分配给这2个消费者。当有新的消费者注册(如下图右),则SLS会自动均衡,把部分Shard从旧消费者迁移到新消费者,称为shard transfer。这种模式的优点是自动均衡,且在SLS Shard分裂/合并时会自动分配消费者。但该模式在我们的场景中却会引起问题。为保证精确一致,我们把SLS各Shard的当前位点保存在Flink Checkpoint中,运行中也是由各Slot上的Source算子持有当前消费位点。如果发生shard transfer,如何保证旧Slot上的算子不再消费,同时把位点转移给新Slot,这引入了新的一致性问题。尤其是大规模系统有数百个SLS Shard和数百个Flink Slot的情况下,很可能出现部分Source比其他Source先注册到SLS导致shard transfer不可避免。▷ 普通消费模式这种模式就是调用SLS的SDK直接指定shard、offset来消费数据,而不是由SLS消费组进行分配,因此不会出现shard transfer。如下,因为Flink的Slot为3,因此可提前计算出每个消费者消费2个Shard并据此分配,即使Source 3尚未ready,也不会把Shard 5和6分配给Source 1和2。可以想象,为了负载均衡(例如某些TaskManager的负载过高时),仍然需要迁移shard,但此时迁移是我们主动触发的,状态更加可控,从而避免一致性问题。3.2 Hudi Sink算子下面介绍下Hudi提交的相关概念,以及如何与Flink配合实现两阶段提交和容错达到精确一致。3.2.1 Hudi提交相关概念时间轴和InstantHudi维护着一条Timeline,Instant是指某个时间点(Time)发起的对表的操作(Action)及表所处的状态(State)的集合。一个Instant可以理解为一个数据版本,Action可能是对表的Commit,Rollback或者Clean等操作,这些操作由Hudi保证了其原子性,因此Hudi的Instant实际类似于数据库中的事务和版本的概念。在图中我们用Start Transaction,Write Data,Commit这种类似数据库事务的方式来表达某个Instant的执行过程。Instant中,部分Action的含义如下:Commit:将记录原子写入数据集Rollback :当Commit不成功时进行回滚,其会删除在写入中产生的脏文件Clean :删除数据集中不再需要的旧版本和文件Instant State一共有三种状态:Requested:操作已被计划但未被执行,可以理解为Start TransactionInflight:操作正在进行,可理解为Write DataCompleted:操作完成,可理解为CommitInstant的Time、Action和State都在元数据文件中描述,下图表示了时间轴上两个先后的Instant。Instant 1的.hoodie目录下的元数据文件描述了Instant的开始时间是2022-10-17 16:05:00,Action是Commit,State可以看到已完成提交(有20221017160500.commit文件),在表的分区目录下则是该Instant对应的parquet数据文件。而Instant 2则可以看到发生在第二天,且Action正在执行尚未提交。Hudi提交过程Hudi提交过程可以用下图理解。Hudi中存在两种角色,Coordinator负责发起Instant和完成提交,Worker负责写入数据。当开启一个事务时,Coordinator会分配一个Instant并传递给所有worker;Worker开始写入数据;开始提交时,Coordinator发送commit给各Worker。各Worker收到提交命令,flush data到持久化存储,并反馈自己的状态给Coordinator。Coordinator确认各Worker commit完成,然后在.hoodie目录中写commit文件完成全局提交。3.2.2 Flink + Hudi的两阶段提交了解了Hudi的写入和提交过程,它如何与Flink配合完成数据的写入和提交就可以用下图表达了。开启一个Hudi Instant;由Filnk Sink发送数据给Hudi Worker写出;发生Flink Checkpoint时,则通过Sink算子通知Worker flush数据,同时持久化operator-state(operator-state属于Flink checkpoint框架的一部分,持久化Hudi Worker所处的Instant等信息);当Flink完成Checkpoint的持久化,则通过notifyCheckpointComplete机制通知Hudi Coordinator提交该Instant。Hudi Coordinator此时完成最终提交,写commit文件,数据对外可见;结束Instant后,会立即开启一个新的Instant,重启上述循环。3.2.3 Flink + Hudi两阶段提交的容错处理实际的提交可简化为如上的流程。从图中可见,1到3是Flink的Checkpoint逻辑,如果异常在这些步骤上发生,则认为Checkpoint失败,触发Job重启,从上一次Checkpoint恢复,相当于两阶段提交的Precommit阶段失败,事务回滚。当3到4之间发生异常,则会出现Flink和Hudi状态不一致。此时Flink认为Checkpoint已结束,而Hudi实际尚未提交。如果对此情况不做处理,则发生了数据丢失,因为Flink Checkpoint完毕后,SLS位点已经前移,而这部分数据在Hudi上并未完成提交,因此容错的重点是如何处理此阶段引起的一致性问题。解决方法是Flink Job重启并从Checkpoint恢复时,发现Hudi最新的Instant有未提交的写入,需要保证执行Recommit。Recommit的流程如下图所示。之前已提到Hudi Worker在Checkpoint时除了flush data,还持久化了一个operator-state,在这里记录了Worker当时所处的Instant信息。Job从Checkpoint恢复时,Sink算子会读取operator-state,Hudi Worker从中恢复持久化的Instant信息;Hudi worker汇报给自己的Instant给Coordinator;Hudi Coordinator会从Instant Timeline中获取最新的Instant信息,并接收所有Worker的汇报;如果Worker汇报的Instant与Timeline中最新的一样,且该Instant尚未提交,则触发Recommit。如果Worker汇报的Instant与最新的不同,则认为上一次Instant执行失败,这份数据对用户不可见,回滚掉即可。可以想像下是否会存在重启时,部分Hudi worker在最新的Instant,而部分worker在旧的Instant的情况?答案是不会,因为Flink的Checkpoint就是相当于两阶段提交的Precommit阶段,如果Checkpoint完成则说明Hudi Precommit完成,所有Worker都处于最新Instant。如果Checkpoint失败,则重启时会回到上一个Checkpoint,此时Hudi worker所处的状态也是一致的,全部都回退到旧Instant。4.总结在数据入湖异常时的Failover处理中,Source通过Checkpoint中持久化的SLS位点,不会重放已处理的数据,保证数据不重,Sink通过Flink和Hudi配合实现的两阶段提交和Recommit机制,保证数据不丢,最终实现Exactly-Once。经过实测这套机制对性能的影响约在3% ~ 5%,以极小的代价保证精确一致性的情况下,实现了高吞吐实时入湖。在某个海量日志入湖项目中,日常吞吐达到3GB/s,峰值吞吐达到5GB/s,数据通道稳定运行,并配合ADB湖仓版的离在线一体化引擎,实现了用户的数据实时入湖,离在线一体化分析需求。除了精确一致性外,为实现高吞吐写和查,数据通道中还有自动热点打散,小文件合并等诸多挑战,将在后续文章中进行介绍。AnalyticDB MySQL湖仓版已正式上线商用,对于低成本离线处理ETL有需求,同时又需要使用高性能在线分析支撑BI报表/交互式查询/APP应用的用户,欢迎购买和体验!另外对湖仓版感兴趣的客户也依然可以填写问卷来进行试用,点击此处填写AnalyticDB MySQL 3.0湖仓版试用申请
1.背景1、在大数据时代,数据量呈指数级增长,预计到2025年,全球的数据总量将达175ZB,非结构化和半结构化数据已占据主导地位。对海量非结构化和半结构化数据进行高效存储,KV存储系统提供了很好的解决方案:● KV存储系统具有灵活的数据模型,数据表示为KV对形式,为任意数据类型,且长度不定;● KV存储的访存接口非常简单,向外提供Put、Get、Scan等简单的接口进行数据读写;● KV存储还具备高可扩展性,数据基于Key进行划分和索引,无需维护额外的元数据。由于KV存储系统具有上述诸多优点,因此被广泛应用在了NewSQL和NoSQL产品中。比如目前常见的KV存储系统:LevelDB、RocksDB、Cassandra、TiKV等。2、目前主流的持久化KV存储系统都采用LSM-tree(log-structured merge tree)架构作为存储引擎,其具有高效的写入效率,但同时存在严重的读写放大问题。如图,KV数据首先缓存在内存并进行排序,然后以批量追加的方式将数据写入磁盘上,形成磁盘上的一个SSTable文件,SSTable文件中的数据是按Key有序的,这种写入方式可以将大量的随机写转换为顺序写,从而充分利用磁盘顺序写的带宽优势,获得高效的写入效率。为兼顾读性能,磁盘上的数据被组织成多层形式,且容量逐层递增,并且除第0层以外,其他每层的数据是完全有序的。通过维护这样一个多层有序的架构,LSM-tree可以获得高效的写入和范围查询性能,并且提供高可扩展性,当需要扩展存储容量时,可以通过简单的增加LSM-tree的层数来实现高效的扩展。然而,LSM-tree多层的数据组织结构导致查询操作需要逐层搜索,从第0层开始,直到找到查询的数据为止,并且写入期间需要执行频繁的Compaction操作,具体Compaction操作需要从LSM-tree中读取相邻两层的数据,然后执行合并排序操作,再将合并后的有效数据写回磁盘。因此,当我们将数据从第0层逐渐合并到较高层时,需要将数据频繁的读出并且写回,进而导致严重的读写放大问题,且严重消耗磁盘的IO带宽。3、分布式KV存储系统被广泛应用,以支持大规模的数据存储。对于Cassandra、TiKV这一类分布式KV存储系统,首先数据基于Key的一致性哈希或者Key的范围划分到各个存储节点上,然后每个节点内部使用一个LSM-tree来存储管理所有数据,下图以Cassandra为例做详细的介绍。如图,KV数据首先基于Key的一致性哈希进行分区,图中有五个物理节点,每个节点有两个虚拟节点,因此整个哈希环被划分成十个范围段。图中0到100的范围段被划分成0-10、11-20、21-30等十个范围段,并且每个范围段都与顺时针方向最近的虚拟节点和相对应的物理节点相关联。比如0-10、51-60这两个范围段被划分到节点0;11-20和61-70这两个范围段被划分到节点1。通过上述划分策略,每个节点会包含多个范围段,并且节点内部将所有范围段存储在一个LSM-tree中。4、为保证数据的高可靠,多副本容错机制被广泛应用在分布式KV存储系统中,即每份数据会复制成多份,并且存储在多个节点上,因此每个节点上的数据可分为主副本和冗余副本。● 主副本:指通过一致性哈希划分策略划分到节点上的数据;● 冗余副本:指通过复制策略发送到节点上的冗余数据;● 统一索引:对于节点上的主副本和冗余副本,现有KV存储系统都采用统一的多副本管理方案,也就是把主副本和冗余副本统一存储在一个LSM-tree中,如下图。考虑到LSM-tree架构本身存在严重的读写放大问题,而统一的索引方案又会极大的增加LSM-tree中存储的数据量,因此会进一步加剧LSM-tree的读写放大问题。5、通过实验进一步验证了统一的多副本管理方案会加剧KV系统的读写放大。如图,在五个节点构成的本地存储集群上进行实验,客户端首先写入300GB的KV数据,然后从集群中读出30GB的KV数据,KV大小为1KB,这里分别统计了分布式KV系统Cassandra和TiKV在不同副本数量下的读写放大系数,图(a)展示了写放大系数,图(b)展示了读放大系数。由实验结果可知,当副本数量越多时,KV存储系统的写放大和读放大越严重,且放大系数增加的倍数超过副本数量增加的倍数,这里主要原因是上述分析的统一多副本管理方案,会大大加剧写流程中执行的Compaction数据量,并且也会成倍增加读流程中需要搜索的数据量。2.设计为解决分布式KV系统中统一多副本管理导致的问题,接下来介绍解决方案。2.1 设计思想主要设计思想是在存储层对主副本和冗余副本进行解耦,以避免读写过程中主副本和冗余副本之间的相互干扰。副本解耦后,采用多个LSM-tree来对解耦的多副本进行独立管理。如图,当系统配置为三副本时,在每个存储节点上使用一个LSM-tree来存储主副本,另外两个LSM-tree来分别存储来自其他两个节点的冗余副本。这种方案的想法及实现都非常简单,但是存在着一些典型的问题。2.2 mLSM的两个主要限制● 多个LSM-tree会导致K倍的内存开销,因为每个LSM-tree都需要在内存中维护一个MemTable;● 多个LSM-tree的解耦方案对Compaction开销的减少是非常有限的,因为每个LSM-tree仍然需要执行频繁的Compaction操作,从而来维护每层数据的完全有序,导致LSM-tree的Compaction开销仍然非常严重。通过实验验证,当客户端写200GB数据,采用三副本时,多个LSM-tree的解耦方案相比于统一索引方案,也就是原始方案,只减少了21%的Compaction数据量。综合上述两个分析可以得出,多个LSM-tree的解耦方案并不是最佳选择,需要进一步优化设计。2.3 设计方案DEPART,分布式KV存储系统的副本解耦方案在存储层对主副本和冗余副本进行解耦,然后根据功能需求,对解耦出的主副本和冗余副本进行差异化的管理,如下图。对于主副本:仍然使用LSM-tree架构来存储,但LSM-tree架构更加轻量级,从而保证高效的读写和范围查询性能;对于冗余副本:设计了一个有序度可调的两层日志架构进行存储,可根据上层应用的性能需求在读写性能之间做权衡。2.4 方案挑战a. 挑战一:如何设计副本区分机制实现主副本和冗余副本的解耦,下图是一个轻量级的副本区分机制。如图,当一个节点收到KV数据后,采用和Coordinator相同的步骤,首先计算Key的哈希值,然后根据一致性哈希数据分布机制,可以映射得到该KV划分到的节点ID。如果计算得到的节点ID等于当前节点,那么就说明这个KV数据是通过一致性哈希机制映射到当前节点的,则该KV数据会被识别为主副本,并且存储在LSM-tree当中,否则这个KV数据就是通过复制策略从其他节点发送过来的冗余数据,则当前节点将其识别为冗余副本,并且存储在两层日志当中。该解耦方案仅仅基于简单的哈希计算,因此是低开销的。此外,它在每个存储节点上独立执行,因此不会影响上层的数据分布机制以及一致性协议。b. 挑战二:如何设计有序度可调的两层日志架构(1) 对于解耦出的冗余副本,应该如何进行高效的管理,使其满足不同场景下的性能需求?这里设计了一个有序度可调的两层日志架构。如上图,当节点收到冗余副本后,首先以批量追加的方式将冗余副本快速写入到全局日志中,形成一个segment文件,这里的segment文件类似于LSM-tree当中的SSTable文件,从而保证冗余副本可以高效的写入磁盘。(2) 然后使用一个后台线程,将全局日志中的数据分割到不同的本地日志中,如下图。需要注意的是,每个本地日志用来存储一类冗余副本,他们所对应的主副本存储在相同的节点,比如这里本地日志LOGi,就用来存储对应主副本在节点i的这类冗余副本。这样做的好处是可以实现细粒度的冗余副本管理,对于不同节点发送过来的冗余副本,使用不同的本地日志进行独立管理,从而可以保证高效的冗余副本读写性能,并且当恢复数据时,只需要读取相应的本地日志,避免了扫描所有的冗余副本,也可以提高数据恢复的效率。(3) 其次,对于本地日志内部的数据管理也需要详细设计。考虑到根据一致性哈希数据分布策略,每个节点会负责若干范围段的数据,基于该特征,进一步设计了基于范围的数据分组机制。根据定义的范围段,将本地日志进一步划分成不同的独立组,不同组之间的数据没有重叠。比如节点2中的本地日志LOG0专门用来存储对应主副本在节点0上的冗余副本,又考虑到节点0中的主副本包含0-10、51-60等范围段,因此节点2中的本地日志LOG0被划分为Group 0[0-10]和Group 1[51-60]等若干组。数据分组可以有效提高数据GC以及恢复性能,因为GC和数据恢复操作只需要读取相应的组即可,避免了扫描整个的本地日志。(4) 对于每个组内的数据组织进行详细的设计。每个组会包含若干个sorted run文件,当分割全局日志时,每次分割操作都会在第2层的本地日志的组内产生一个sorted run文件,这些sorted run文件内部的KV数据是完全有序的,但sorted run文件之间的KV数据并未排序。因此,可以通过调整组内sorted run文件的个数来决定两层日志的有序度,从而在读写性能之间做权衡。比如,当组内的sorted run文件个数越少,则两层日志的有序度越高,这时候读操作需要检查的sorted run的文件个数也就越少,因此读性能会越好,但需要执行更频繁的合并排序操作,从而导致写性能会越差;反之,两层日志的有序度越低,合并排序开销越少,则写性能会越好,但读操作需要检查的sorted run文件个数也就越多,导致读性能会越差。(5)如何设置两层日志的有序度。考虑到有序度会决定系统的读写性能,因此可根据上层应用的性能需求,来设置不同的有序度。比如对于读密集型应用,或者系统配置为高的读一致性等级,则可以通过减少组内sorted run文件的个数来将两层日志设置为高有序度,以保证好的读性能;否则可以通过增加组内sorted run文件的个数,来将两层日志设置为低有序度,从而保证好的写性能。c. 挑战三:副本解耦后如何加速数据恢复操作副本解耦后,通过一种并行的恢复机制,以利用数据解耦存储的特征来加速数据恢复操作。如图步骤①中,当为节点上的数据构建Merkle tree以检测丢失的数据时,使用两个线程,并行地从LSM-tree的主副本和两层日志的冗余副本中读数据。当修复多个范围段的丢失数据时,如图步骤③,同样使用两个线程,并行地从LSM-tree的主副本和两层日志的冗余副本中读写数据。3.实验3.1 实验设置实验服务器硬件配置● 在6个节点(5个存储节点,1个客户端节点)组成的本地集群中运行所有实验, 10 Gb/s以太网交换机;● 工作负载:使用YCSB 0.15.0来生成工作负载,KV对大小为1KB,生成的工作负载服从Zipf分布 (0.99);● 参数:默认采用三副本,并且将写一致性等级和读一致性等级默认设置为1(WCL=ONE, RCL=ONE)。3.2 比较● Cassandra v3.11.4 VS multiple LSM-trees (mLSM) VS DEPART● DEPART builds on Cassandra v3.11.4在开源的分布式KV存储系统Cassandra上实现了原型系统DEPART,同时也实现了多个LSM-tree的简单解耦方案。将DEPART与Cassandra、多个LSM-tree的解耦方案分别进行性能比较,以展示系统DEPART的设计优势。实验一:基准测试实验一分别测试了不同KV系统的写、读、范围查询和更新操作的吞吐量。由实验结果可知,相比于Cassandra,系统DEPART可以显著提升所有操作的吞吐量。而对于多个LSM-tree的解耦方案,其可以较好地提升Cassandra的读性能,但对Cassandra的写性能提升非常有限。主要原因是多个LSM-tree的解耦方案会导致解耦出的每个LSM-tree仍然需要执行频繁的Compaction操作,以维护每层数据的完全有有序,从而导致总的Compaction开销仍然非常严重。实验二:不同一致性配置实验评估了不同一致性配置下的系统性能。这里对于强一致性等级,考虑了三副本下不同的写一致性等级和读一致性等级配置。由实验结果可知,与Cassandra相比。系统DEPART可以在不同一致性配置下均可以提高所有操作的吞吐量,并且相比于多个LSM-tree的解耦方案,DEPART可以有效提高写入和更新操作的吞吐量。然而,当读一致性等级(RCL)配置为大于1时,与Cassandra相比,DEPART的读性能收益会变小,并且DEPART的读性能还要略差于多个LSM-tree的解耦方案。其主要原因是,在这种读一致性配置下,每个读请求需要成功访问至少两个副本,因此必须搜索两层日志当中的冗余副本;又由于两层日志中的冗余副本并未完全排序,因此读取两层日志的性能要低于读取完全排序的LSM-tree的主副本。注意,DEPART的读性能仍然要好于Cassandra,因为副本解耦后,DEPART搜索的数据量更少,但是DEPART的读性能要差于多个LSM-tree,因为多个LSM-tree保持冗余副本完全有序。实验三:数据恢复性能分别测试当恢复不同数据量时所需要的时间。与Cassandra相比,DEPART将恢复时间减少38%-54%,主要原因是并行修复机制可以并行地读写主副本和冗余副本。实验四:有序度参数S对系统读写性能的影响如表格所示,当S的值为1时,两层日志会变为两层LSM-tree,KV数据是完全有序的,因此它可以获得最高的读吞吐量。但由于频繁的合并排序操作,这时候写吞吐量是最低的。当S的值从1不断增大时,两层日志的有序度会不断降低,故合并排序开销逐渐减小,因此写性能会不断增加,而读性能会不断降低。因此,可以通过调整S的取值,在读写性能之间做合适的权衡。4.总结DEPART是一个基于副本解耦的高性能和高可靠的分布式KV存储系统,包括轻量级副本解耦方案、两层日志架构、有序度可调机制、并行恢复机制等关键模块设计。更多详细的结果和分析见论文,源码地址:https://github.com/ustcadsl/departKV研究热点总结与展望首先,目前KV领域的绝大部分工作都集中在优化KV存储引擎上,例如改进LSM-tree架构,以减轻读写放大问题,以及结合新型硬件来重新设计KV存储引擎等等。但在KV系统的数据容错层,相关研究极少,我们进行了初步探索,观察到当前统一的多副本管理会极大加剧KV系统的读写放大,因此研究设计了基于副本解耦的多副本差异化管理框架,极大提升了系统性能。这项工作基于Cassandra开源平台实现,并可以应用在TiKV等一系列基于LSM-tree的分布式KV存储系统中。对于KV系统未来的研究方向,可以结合应用层的需求和缓存特征来进行特定的KV系统设计。例如,研究设计一种属性感知的内存KV系统,使其在存储结构上能够支持对数据属性值的高效读写,最终部署到云存储平台,以高效支撑SQL数据库等应用。此外也可以结合上层应用的其他特征和需求来设计针对性的KV存储系统。详细内容请参阅论文《DEPART: Replica Decoupling for Distributed Key-Value Storage》(点解此处即可查阅论文)
前言Teradata(TD)是美国前十大上市软件公司之一,经过逾30 年的发展,Teradata发展为全球领先的大数据分析和数据仓库解决方案厂商,赢得了超过2,000家客户的信任,在多个行业表现卓越,多年来一直居于领导者地位。随着Teradata近期宣布退出中国市场,越来越多的企业着眼于长期规划,将目光转移到国产数据库产品进行整体的技术架构升级,寻找高度契合国家战略、技术领先的国产化数据库产品。AnalyticDB PostgreSQL(以下简称ADB PG)是阿里云自研的云原生数据仓库产品,提供基于阿里云生态的公共云和混合云服务,核心代码高度自主可控,提供PB级数据实时交互式分析,ETL/ELT,和BI报表展示功能,支持数据高吞吐实时写入与批量导入,提供ACID保证和标准事务隔离级别,采用MPP全并行架构。ADB PG已获得三方机构认证,包括:“分布式分析型数据库大规模性能认证”和 “分析型数据库Serverless分级能力”获增强级等能力认定。申万宏源证券的数仓升级项目为阿里云第一个证券行业 “去Teradata数仓”项目,阿里云与申万宏源证券历时1年的紧密合作,最终成功实现ADB PG替换Teradata数据仓库。项目总计完成100多套上游业务源系统、约30套下游系统、25000多个任务、800多个服务接口、百TB数据、日新增500~700GB数据的平稳迁移,保障现有业务平稳有序运转同时,最终实现自主可控、数据快速赋能业务。以下是我们从该项目中总结沉淀的关于“AnalyticDB PostgreSQL替换Teradata数仓”的最佳实践。01数据仓库的发展趋势及困境经过近30多年的发展,企业级数仓都有了不同程度的发展,积淀了大量的业务数据。同时随着多维度的业务发展转变,数仓应用将面临如下的发展趋势。● 数据层面:数据规模不断突破,非结构化信息持续增长;● 业务层面:离在线快速响应,实时交互成为常态;● 架构层面:数据库与大数据加速融合,云原生将成为必然;● 产品层面:目前产品面临硬件老化,升级维护成本过高,需要下一代产品进行升级。02数仓架构升级挑战▶︎ 技术方面功能兼容性:众多的OLAP产品,不确定那款可以替代当前的数仓环境。改造方案全面性:改造数仓环境,涉及的环节非常多,需要通盘考虑。迁移实施复杂度:历史沉淀数据太过庞大,当前数仓老旧,涉及多个团队合作,整个迁移过程非常复杂。▶︎ 成本方面评估改造成本:采用新型的分布式数据库技术,改造评估成本无法准确估算。评估应用改造周期:30多年的数据沉淀,数据迁移速度、应用改造难度等无法有效评估改造周期▶︎ 运维方面数据安全监管:数据监管会变得空前严格,多场景的运维需求也会日益突出。开发人员技能:企业人员能力是否能够胜任,也决定着数仓改造的成败。DB管理技能:分布式数仓环境的DB运维能力的提升,则是对当前运维人员的又一技能挑战。云资源管理能力:分布式数仓需要日常的运维工作具备相关技能。03数仓迁移规划我们将Teradata迁移至ADB PG的数仓迁移方法总结归纳为“五阶十步”法,迁移项目为保证平滑过渡、风险可控等目标,总体会倾向平迁策略,即不改架构,不动流程,尽力兼容。“五阶十步”内容如下图示:图1 - Teradata数仓迁移“五阶十步”业务调研业务调研阶段需对原系统上下游做详实调研,调研内容包括但不限于:● 原数仓系统架构● 原数仓数据交互流程● 原系统资源盘点● 原数仓库表统计最后迭代输出调研分析报告,并与业务方做深入讨论与修正。原数仓系统架构图2 - 原数仓系统架构示意图比较典型的证券企业数仓架构:上游数据依赖采集程序生成数据文件,通过Teradata的FSLoad加载入库;下游系统不直接访问Teradata数仓,通过前置环境来过渡;数仓内部分层建模,ETL任务通过Automation调度工具集成。这种架构主要好处是管控能力强,体现在安全可控、性能可控、并发可控。原数仓数据交互流程图3 - 原数仓数据交互流程图原系统资源盘点针对现有系统资源使用情况进行多维度盘点,确认初步迁移计划。以数仓表统计为例,根据表的数据量和类型等关键指标,有针对性的制定下一步的迁移计划。方案设计该阶段需多方参与共创,设计并编制可落地的执行方案,提请业务方审议。内容包括但不限于:图4 - 方案设计以下就几项核心内容进行描述:系统架构如下图所示图5 - 新系统架构示意图图6 - ADB PG组件部署逻辑示意图图7 - DBStack部署架构图DBStack是阿里云企业级交易、分析、传输、治理于一体的数据库管理平台;能够帮助企业构建稳定、安全、经济的全场景数据库解决方案,快速替换Oracle、Db2、Teradata等传统数据库。规划设计迁移方案组织保障实施计划项目里程碑计划如图:图8 - 里程碑计划示意图04Teradata系列产品替换核心数仓替换:ADB PG适配ADB PG与Teradata在数据类型、DDL/DML等语法、函数、特殊关键字等存在差异性,为此ADB PG系统性整理差异对照和语法兼容项。以创建表为例,转换语法对照如下表:举个例子,Teradata创建表DDL:这个Teradata的DDL有三处特殊地方:-- 1)CHARACTER SET LATIN CASESPECIFIC-- 2)DATE FORMAT 'YYYYMMDD'-- 3)INTEGER FORMAT '99:99:99'CREATE TABLE ON_BOARD_MATCH_EVT( Evt_Id VARCHAR(200) CHARACTER SET LATIN CASESPECIFIC TITLE '编号' NOT NULL, Match_Dt DATE FORMAT 'YYYYMMDD' TITLE '成交日期' NOT NULL, Match_Tm INTEGER FORMAT '99:99:99' TITLE '成交时间' NOT NULL, Order_Dt TIMESTAMP(6) TITLE '委托日期' NOT NULL, Cust_Cd VARCHAR(80) CHARACTER SET LATIN CASESPECIFIC TITLE 'A代码' NOT NULL, Cust_No VARCHAR(80) CHARACTER SET LATIN CASESPECIFIC TITLE 'A编号' NOT NULL)PRIMARY INDEX ( Evt_Id )PARTITION BY ( RANGE_N(Match_Dt BETWEEN DATE '2000-01-01' AND DATE '2013-12-31' EACH INTERVAL '1' YEAR , DATE '2014-01-01' AND DATE '2015-12-31' EACH INTERVAL '1' MONTH , DATE '2016-01-01' AND DATE '2030-12-31' EACH INTERVAL '1' DAY , NO RANGE OR UNKNOWN) );转换成ADB PG相关DDL(三处特殊地方无法兼容,需要评估对业务的影响):CREATE TABLE ON_BOARD_MATCH_EVT( Evt_Id VARCHAR(200) NOT NULL, Match_Dt DATE NOT NULL, Match_Tm INTEGER NOT NULL, Order_Dt TIMESTAMP(6) NOT NULL, Cust_Cd VARCHAR(80) NOT NULL, Cust_No VARCHAR(80) NOT NULL) DISTRIBUTED BY(Evt_Id)PARTITION BY RANGE(Match_Dt)( START(DATE '2000-01-01') END(DATE '2013-12-31') INCLUSIVE EVERY(INTERVAL '1' YEAR), START(DATE '2014-01-01') END(DATE '2015-12-31') INCLUSIVE EVERY(INTERVAL '1' MONTH), START(DATE '2016-01-01') END(DATE '2030-12-31') INCLUSIVE EVERY(INTERVAL '1' DAY), DEFAULT PARTITION def__par);COMMENT ON COLUMN ON_BOARD_MATCH_EVT.Evt_Id IS '编号';COMMENT ON COLUMN ON_BOARD_MATCH_EVT.Match_Dt IS '成交日期';COMMENT ON COLUMN ON_BOARD_MATCH_EVT.Match_Tm IS '成交时间';COMMENT ON COLUMN ON_BOARD_MATCH_EVT.Order_Dt IS '委托日期';COMMENT ON COLUMN ON_BOARD_MATCH_EVT.Cust_Cd IS 'A代码';COMMENT ON COLUMN ON_BOARD_MATCH_EVT.Cust_No IS 'A编号';数据迁移工具:ADAM + DTSADAM在Teradata 迁移中,通过ADAM(亚当)可以实现数据库自动采集、兼容性评估、自动结构迁移和智能订正,同时对应用Perl 脚本SQL 自动转换,大大降低Teradata 迁移的成本和难度,目前支持Teradata13-16 的版本。ADAM核心功能● 采集TD 数据库的DDL、SQL、系统信息● TD => ADB For PG 兼容性分析● 自动对TD 进行结构迁移,并支持人工订正● TD ETL Perl/DSQL 脚本里面SQL 自动转换DTS数据传输服务DTS(Data Transmission Service)支持将Teradata迁移至云原生数据仓库ADB PG版。迁移类型支持● 库表结构迁移DTS将源库中迁移对象的结构定义迁移到目标库。● 全量迁移DTS将源库中迁移对象的存量数据,全部迁移到目标库中。数据库账号的权限要求:统一开发与调度平台:DMS▶︎ 背景介绍对于大型证券公司,其业务复杂度极高,据统计客户累计需要开发和调度的任务达到了2W+。阿里云DMS提供了强大的任务编排功能,能够完全对齐Automation相关功能。以下提供一个高效的迁移方案,可将生产调度系统从Automation迁移到DMS中。▶︎ 任务迁移方案方案目标:迁移工作量小,迁移后业务无损,提升运维效率。1、确定业务场景任务编排的业务场景,对齐automation的核心系统。以下几个业务场景为例:FLD_ODS_xxx、ITF_xxx、EXP_xxx2、采集任务迁移采集任务主要为脚本任务,根据上面的业务场景划分,将不同系统的采集任务放入不同的任务流,按照“一个表对于一个任务流”原则,迁移采集任务。3、加载入库(FLD+ODS)的任务如何迁移入库任务为脚本任务,需要把入库任务划分进不同的任务流划分任务流● 一张表对应一个任务流:根任务是脚本任务,脚本任务的内容是对于数据的完备性检查,对于脚本任务配置失败重试。● 一个任务流对应一张表:一个任务流只能有一个数据检查的脚本任务,从这个根任务起,添加所有依赖这个表的FLD与ODS任务,如下:● 任务流不需要配置调度周期,调度由上游采集任务来通过openAPI触发。4、对于采集加载之后的任务这里包含了加载任务之后,所有的任务,如明细层、汇总层、集市层等等;任务流划分方式,还是按照“一张表由且仅由一个任务流产生”的基本原则,这里我们拿ITF/EXP层来举例。划分任务流ITF / EXP示例ITF与EXP类似,会交叉依赖上层的多个表,故这两个层的处理方式是类似的,所以放在一起说,但注意的是这两个层需要放到不同的业务场景里调度方式DMS任务支持基于时间调度和基于“事件”调度两种模式。DMS任务编排完美适配Automation各项能力和用户开发调度需求,运行ETL调度任务,实时性高,业务拓展性好,异常恢复成本低。同时,通过跨任务流依赖检查以及事件调度等功能,也实现了复杂依赖关系的调度场景。05总结过去几十年,国外数据仓库平台厂商包括Teradata、Exadata、Netezza 等一直是金融、运营商等重点行业的优先选择。但是,近年来传统数仓掣肘明显,存在软硬绑定、难以升级与维护、成本高昂,以及架构老化,难以赋能业务创新;体系封闭,受制于人,难以突破等问题,企业急需架构升级。阿里云自研的新一代云原生数据仓库AnalyticDB PostgreSQL体系化解决以上难题,在关键行业的核心应用中成果显著。帮助金融、电信行业客户将传统数仓全面升级至云原生数仓,构建数据平台全新架构,有效满足客户对于数据平台实时化、弹性扩展、高性价比及安全可控的诉求,突破传统数仓技术瓶颈,最终赋能企业数智化创新。点击此处填写问卷,即可下载《数据仓库升级交付标准化白皮书》
“云数据库已经成为数据库行业的事实标准。”3月24日,在北京召开的阿里云瑶池数据库峰会上,阿里云数据库产品事业部负责人李飞飞表示,云数据库是一个全新的赛道,在这条赛道上云厂商具备先发优势。以PolarDB为代表的瑶池数据库打造“云原生+一站式”的数据管理与服务,正在带领国产数据库实现换道超车。 过去40多年,数据库技术一直在迭代,而进入到数字化和云计算时代后,云数据库就以高可靠、高可用、高性能,高弹性、自动化智能部署与运维等压倒性优势,对传统数据库市场发起了冲击。云数据库不仅能平稳支撑数字时代的业务峰值,在弹性场景下,成本仅为传统商业数据库的十分之一。“单一数据库已无法满足客户多元化、差异化的应用场景需求,云原生+一站式才是数据库的未来。”李飞飞介绍,云计算为数据库的架构发展开辟了新技术路径,云原生数据库正在快速向一站式数据管理与服务演进,要不断为客户创造价值,就必须实现“云原生化、平台化、一体化、智能化”。以阿里云自研的云原生数据库PolarDB为例:● 开创性地采用了CPU、内存、存储三层解耦技术,在提供金融级高可用、高可靠能力的基础上,实现极致弹性和云上资源秒级扩容,能以50%的成本、实现6倍商业和开源数据库的性能;● 基于内存列存索引(IMCI)加持的处理分析一体化能力,实现分析百倍加速,一体化的实时事务处理和实时数据分析,极简运维;● 多节点可同时写,最大化资源利用率;● 支持分布式事务、全局二级索引等重要特性,提供一体化体验。01云数据库成市场中坚力量,引领“云原生 + 一站式”潮流“传统数据库厂商逐渐失去了原有的霸主地位,而生于云、长于云、基于云原生架构的数据库开始成为市场的中坚力量。”中国工程院院士孙家广出席大会并表示,以云厂商为代表的云原生数据库的崛起,如阿里云瑶池数据库进入Gartner全球数据库领导者象限,标志着云数据库在提升产业竞争力和推动商业模式创新上发挥了重要作用。阿里云瑶池数据库是国内唯一、连续3年跻身Gartner全球云数据库领导者象限的服务商,稳居全球第一阵营,连续多年位居中国关系型数据库市场份额第一位。在2020年中国电子学会颁布的科学技术奖中,PolarDB荣获科技进步一等奖。本次峰会上,瑶池立足客户业务场景,首次将云原生数据库PolarDB和云原生数据仓库AnalyticDB打通融合,形成“云原生一体化”的HTAP解决方案。该方案为用户提供统一入口,内置实时同步链路,通过PolarDB和AnalyticDB数据共享,性能优化的行列转换,兼具数据处理与分析能力,为用户带来一站式的数据库使用体验。基于某游戏行业客户的真实场景测算,相比其他方案,云原生一体化HTAP解决方案以50%的成本提供了2倍性能。此外,阿里云推出了全新云原生多模数据库Lindorm AI 引擎。该引擎支持多模数据类型和灵活模型导入,可在数据库内集成AI能力,对非结构化数据进行智能分析和处理,打造AIGC应用的数据基础设施。用户仅需写几段SQL语言,就能在数据库内完成模型部署和推理,省去一系列安装部署步骤,快速搭建起一个AIGC应用,大幅降低AI服务的使用门槛。02牵手客户和伙伴,加速发展云数据库产业生态来自招商银行、中国联通、掌阅科技、太平洋保险、阳光保险、渤海银行等行业领先企业的代表,在峰会现场分享了基于阿里云瑶池数据库的数字化转型最佳实践。招商银行总行信息技术部数据治理团队负责人杨鹏表示:“招商银行携手阿里云能有效洞察僵尸资产、冗余资产等数据质量问题,助力全量资产可视化智能管理,提升业务部门用数效率,帮助我行实现降本增效。”中国联通则使用阿里云数据库替换原有IT系统架构,支撑了超4.2亿用户、计费数量高达450亿/天、20万容器数量,打造了全球规模最大的电信业务系统之一。MongoDB是业界最受欢迎的数据平台之一,自2019年与MongoDB达成战略合作伙伴关系以来,阿里云已成为MongoDB在中国最大的云服务提供商,最新版的MongoDB 7.0也将在阿里云上首发。MongoDB中国区区域副总裁杨燕在会上表示:“MongoDB与阿里云在联合研发、定向支持、生态共建等上深度合作,三年来累计为数万名客户提供MongoDB云服务。我们期待未来继续携手阿里云,赋能企业借助MongoDB开启创新下一站。”此外,峰会上阿里云还与全球流行的开源分析型数据库ClickHouse正式签订战略合作协议,成为ClickHouse在中国独家的云服务提供商,并提供具备独有企业能力的ClickHouse版本。ClickHouse创始人及CEO Aaron Katz表示:“与阿里云的合作是ClickHouse发展的一个重要里程碑,欢迎亚太区域的企业选择阿里云官方ClickHouse,掌握面向未来的分析应用 !” 未来,阿里云瑶池将持续与生态合作伙伴紧密协同,赋能客户拓展数据价值,共同发展。阿里云智能首席技术官周靖人表示:“今天瑶池数据库体系已经全面云原生化,更有效利用云上的弹性和计算资源,发挥云的极致能力。未来阿里云将持续加码,以数据库智能化作为重要发展方向,引领数据库与AI深度融合,为开发者和客户提供更便捷的数据服务。”目前,瑶池数据库产品已广泛应用于政企市场,服务于自然人税收管理系统、全国60%的省级医保信息平台、中国邮政、上海证券交易所、中国太保、招商银行、南方基金、友邦保险等金融、政务领域的标杆客户。END
数据库限制和数据库配置自建Oracle为源数据库限制数据库版本、架构限制支持Oracle数据库版本有10G、11G、12C、18C和19C。支持单节点、rac实例架构。支持12C及以上版本的租户式和非租户式架构;数据库配置限制增量限制数据库已开启ARCHIVELOG(归档模式),并且必须保证归档日志保留3天以上。数据库已开启Supplemental Logging。数据库接入方式限制支持自建Oracle数据库的公、私网ip接入。支持RAC架构下ScanIP、单节点的VIP或者物理IP接入。支持专线的方式接入,其中不支持RAC节点ScanIP专线接入。支持ADG主、备库方式接入。支持AWS RDS4Oracle为源接入。迁移对象限制待迁移的表需具备主键或唯一约束,且字段具有唯一性,否则可能会导致同步链路延迟、甚至目标数据库中出现重复数据。如果您的自建Oracle版本为12c及以上,待迁移表的名称长度需不超过30个字节。其他限制执行数据迁移前需评估源库和目标库的性能,同时建议业务低峰期执行数据迁移。否则全量数据迁移时,DTS会占用源库一定读资源,可能导致数据库的负载上升。Oracle为源支持写入字符集与数据库字符集不一致的场景,需要额外设置参数source.column.encoding。数据库配置Oracle为源链路全量迁移无需在源库执行特殊配置。Oracle为源的增量链路,需要抓取、解析源端日志以获取增量变更,需要客户在Oracle数据库中完成如下配置。1)开启日志归档模式DTS增量运行过程中,需要抓取源库online redolog或者archived redolog(如果online redolog找不到需要的增量日志,会自动查找archived redolog),因此需要在源库开启日志归档模式,如下介绍了检查、开启归档日志的步骤。第一步:检查源库是否已经开启归档模式(如果已经开启跳过后续步骤)archive log list;第二步:mount方式重启数据库(此过程需要重启数据库,客户根据实际情况操作)shutdown immediate; startup mount;第三步:开启日志归档模式alter database archivelog; alter database open;第四步:检查日志归档配置是否生效archive log list;2)开启补充日志DTS在增量同步时,还需要开启源库补充日志。目前DTS支持开启库级别补充日志和仅开启表级别补充日志两种模式,开启库级别补充日志,DTS任务运行更为稳定;开启表级别补充日志,不支持整库迁移中新建未开启补充日志的表,则更节约源Oracle数据库的磁盘空间。模式一:检查、开启库级别补充日志:检查库级别补充日志是否开启 SELECT supplemental_log_data_min, supplemental_log_data_pk,supplemental_log_data_ui FROM v$database; 开启库级最小补充日志 alter database add supplemental log data; 开启库级主键、唯一键补充日志: alter database add supplemental log data (primary key,unique index) columns; 检查库级别补充日志是否开启 SELECT supplemental_log_data_min, supplemental_log_data_pk, supplemental_log_data_ui FROM v$database;模式二:开启表级别补偿日志:开启库级最小补充日志 alter database add supplemental log data; 开启库级主键、唯一键补充日志: alter database add supplemental log data (primary key,unique index) columns; 开启表级补充日志(两者选其一) : 1.alter table table_name add supplemental log data (primary key) columns; 2.alter table table_name add supplemental log data (all) columns;AWS RDS4Oracle为源AWS RDS4Oracle为源数据库限制与自建Oracle一致,目前仅支持10G、11G、12C、18C、19C版本(12C以上版本仅支持非租户式架构)。但是DTS增量迁移在数据库配置上有所区别,如下详细介绍配置操作。数据库配置1)开启日志归档模式第一步:查看并设置归档日志保留时间exec rdsadmin.rdsadmin_util.show_configuration; exec rdsadmin.rdsadmin_util.set_configuration('archivelog retention hours', 72)2)开启补充日志AWS RDS4Oracle为源链路同样支持两种模式:库级别和表级别补充日志。模式一:检查、开启库级别补充日志:检查库级别补充日志是否开启 SELECT supplemental_log_data_min, supplemental_log_data_pk,supplemental_log_data_ui FROM v$database; 打开强制日志模式。 exec rdsadmin.rdsadmin_util.force_logging(p_enable => true); 开启库级主键、唯一键补充日志 exec rdsadmin.rdsadmin_util.alter_supplemental_logging('ADD', 'PRIMARY KEY'); exec rdsadmin.rdsadmin_util.alter_supplemental_logging('ADD', 'UNIQUE');模式二:开启表级别补偿日志:开启表级别全字段补充日志 exec rdsadmin.rdsadmin_util.alter_supplemental_logging('ADD', 'ALL'); 开启表级别主键补充日志 exec rdsadmin.rdsadmin_util.alter_supplemental_logging('ADD', 'PRIMARY KEY');Oracle为目标链路限制数据库版本、架构限制1.支持Oracle数据库版本有10G、11G、12C、18C和19C。2.支持单节点、rac实例架构。3.支持12C及以上版本的租户式和非租户式架构;数据库接入方式限制1.支持自建Oracle数据库的公、私网ip接入。2.支持RAC架构下ScanIP、单节点的VIP或者物理IP接入。3.支持专线的方式接入,其中不支持RAC节点ScanIP专线接入。4.支持ADG主、备库方式接入。5.支持AWS RDS4Oracle为源接入。其他限制1.执行数据迁移前需评估目标库的性能,同时建议业务低峰期执行数据迁移。否则全量数据迁移时,DTS会占用目标库一定网络资源和写资源,可能导致数据库的负载上升。2.由于DTS全量数据迁移并发执行insert操作,会导致目标数据库表产生部分碎片,因此全量迁移完成后目标数据库存储空间会比源实例库大。数据库配置Oracle为目标库的链路,全量迁移、增量迁移无需在目标库执行特殊配置。数据库账号权限准备Oracle作为源DTS迁移过程中,需要创建数据采集账号并授权。结构和全量迁移,需要给数据采集账号授予DBA角色或者精细化授权,增量迁移需要抓取源端日志,需要授予DBA角色或者精细授权。下面介绍了这授权和验证命令。结构迁移全量迁移增量迁移DBA角色精细授权DBA角色精细授权非租户式架构授予DBA角色精细授权结构迁移、全量、增量授予DBA权限#创建数据库账号(以rdsdt_dtsacct为例)并进行授权 create user rdsdt_dtsacct identified by rdsdt_dtsacct; grant create session to rdsdt_dtsacct; grant connect to rdsdt_dtsacct; grant dba to rdsdt_dtsacct; #rdsdt_dtsacct账号登陆,检查是否授权完成 select * from user_tab_privs; --授予权限:create session select granted_role from user_role_privs; --授予角色:connect、dba结构迁移、全量精细授权#创建数据库账号(以rdsdt_dtsacct为例)并进行授权 -- 创建账号 create user rdsdt_dtsacct identified by rdsdt_dtsacct; grant create session to rdsdt_dtsacct; -- 授予角色 grant connect to rdsdt_dtsacct; grant select_catalog_role to rdsdt_dtsacct; 校验命令(使用新建账号登陆):select * from user_role_privs; -- 授予系统权限 grant select any table to rdsdt_dtsacct; 校验命令(使用新建账号登陆):select * from user_sys_privs; --增量迁移精细授权不同版本、架构、接入方式,授权方式存在差异,下面分别给出了增量精细化授权操作。Oracle 10G~11G#创建数据库账号(以rdsdt_dtsacct为例)并进行授权 -- 创建账号 create user rdsdt_dtsacct identified by rdsdt_dtsacct; grant create session to rdsdt_dtsacct; -- 授予角色 grant connect to rdsdt_dtsacct; grant select_catalog_role to rdsdt_dtsacct; 校验命令(使用新建账号登陆):select * from user_role_privs; -- 授予系统权限 grant select any table to rdsdt_dtsacct; grant select any transaction to rdsdt_dtsacct; 校验命令(使用新建账号登陆):select * from user_sys_privs; -- 授予对象权限 -- 普通对象 grant select on all_objects to rdsdt_dtsacct; grant select on all_tab_cols to rdsdt_dtsacct; grant select on dba_registry to rdsdt_dtsacct; grant execute on sys.dbms_logmnr to rdsdt_dtsacct; -- 系统视图 grant select on v_$log to rdsdt_dtsacct; grant select on v_$logfile to rdsdt_dtsacct; grant select on v_$standby_log to rdsdt_dtsacct; -- ADG备库接入,需要给予该视图权限;主库接入不需要 grant select on v_$archived_log to rdsdt_dtsacct; grant select on v_$parameter to rdsdt_dtsacct; grant select on v_$database to rdsdt_dtsacct; grant select on v_$active_instances to rdsdt_dtsacct; grant select on v_$instance to rdsdt_dtsacct; grant select on v_$logmnr_contents to rdsdt_dtsacct; -- 系统基表 grant select on sys.USER$ to rdsdt_dtsacct; grant select on sys.OBJ$ to rdsdt_dtsacct; grant select on sys.COL$ to rdsdt_dtsacct; grant select on sys.IND$ to rdsdt_dtsacct; grant select on sys.ICOL$ to rdsdt_dtsacct; grant select on sys.CDEF$ to rdsdt_dtsacct; grant select on sys.CCOL$ to rdsdt_dtsacct; grant select on sys.TABPART$ to rdsdt_dtsacct; grant select on sys.TABSUBPART$ to rdsdt_dtsacct; grant select on sys.TABCOMPART$ to rdsdt_dtsacct; 校验命令(使用新建账号登陆):select * from user_tab_privs;Oracle 12G~19G(非租户式)#创建数据库账号(以rdsdt_dtsacct为例)并进行授权 -- 创建账号 create user rdsdt_dtsacct IDENTIFIED BY rdsdt_dtsacct; grant create session to rdsdt_dtsacct; -- 授予角色 grant connect to rdsdt_dtsacct; grant select_catalog_role to rdsdt_dtsacct; grant logmining to rdsdt_dtsacct; grant execute_catalog_role to rdsdt_dtsacct; 校验命令(使用新建账号登陆):select * from user_role_privs; -- 授予系统权限 grant select any table to rdsdt_dtsacct; grant select any transaction to rdsdt_dtsacct; 校验命令(使用新建账号登陆):select * from user_sys_privs; -- 授予对象权限 -- 普通对象 grant select on all_objects to rdsdt_dtsacct; grant select on all_tab_cols to rdsdt_dtsacct; grant select on dba_registry to rdsdt_dtsacct; grant execute on sys.dbms_logmnr to rdsdt_dtsacct; -- 系统视图 grant select on v_$log to rdsdt_dtsacct; grant select on v_$logfile to rdsdt_dtsacct; grant select on v_$standby_log to rdsdt_dtsacct; -- ADG备库接入,需要给予该视图权限;主库接入不需要 grant select on v_$archived_log to rdsdt_dtsacct; grant select on v_$parameter to rdsdt_dtsacct; grant select on v_$database to rdsdt_dtsacct; grant select on v_$active_instances to rdsdt_dtsacct; grant select on v_$instance to rdsdt_dtsacct; grant select on v_$logmnr_contents to rdsdt_dtsacct; -- 系统基表 grant select on sys.USER$ to rdsdt_dtsacct; grant select on sys.OBJ$ to rdsdt_dtsacct; grant select on sys.COL$ to rdsdt_dtsacct; grant select on sys.IND$ to rdsdt_dtsacct; grant select on sys.ICOL$ to rdsdt_dtsacct; grant select on sys.CDEF$ to rdsdt_dtsacct; grant select on sys.CCOL$ to rdsdt_dtsacct; grant select on sys.TABPART$ to rdsdt_dtsacct; grant select on sys.TABSUBPART$ to rdsdt_dtsacct; grant select on sys.TABCOMPART$ to rdsdt_dtsacct; 校验命令(使用新建账号登陆):select * from user_tab_privs;Oracle 12G~19G(租户式)#切换至PDB,创建数据库账号(以rdsdt_dtsacct为例)并进行授权 alter session set container = <ORCLPDB1>; -- 创建账号 create user rdsdt_dtsacct identified by rdsdt_dtsacct; grant create session to rdsdt_dtsacct; -- 授予角色 grant connect to rdsdt_dtsacct; grant select_catalog_role to rdsdt_dtsacct; grant logmining TO rdsdt_dtsacct; grant execute_catalog_role to rdsdt_dtsacct; 校验命令(使用新建账号登陆):select * from user_role_privs; -- 授予系统权限 grant select any table to rdsdt_dtsacct; grant select any transaction to rdsdt_dtsacct; 校验命令(使用新建账号登陆):select * from user_sys_privs; -- 授予对象权限 -- 普通对象 grant select on all_objects to rdsdt_dtsacct; grant select on all_tab_cols to rdsdt_dtsacct; grant select on dba_registry to rdsdt_dtsacct; grant execute on sys.dbms_logmnr to rdsdt_dtsacct; -- 系统视图 grant select on v_$pdbs to rdsdt_dtsacct; grant select on v_$log to rdsdt_dtsacct; grant select on v_$logfile to rdsdt_dtsacct; grant select on v_$standby_log to rdsdt_dtsacct; -- ADG备库接入,需要给予该视图权限;主库接入不需要 grant select on v_$archived_log to rdsdt_dtsacct; grant select on v_$parameter to rdsdt_dtsacct; grant select on v_$database to rdsdt_dtsacct; grant select on v_$active_instances to rdsdt_dtsacct; grant select on v_$instance to rdsdt_dtsacct; grant select on v_$logmnr_contents to rdsdt_dtsacct; -- 系统基表 grant select on sys.USER$ to rdsdt_dtsacct; grant select on sys.OBJ$ to rdsdt_dtsacct; grant select on sys.COL$ to rdsdt_dtsacct; grant select on sys.IND$ to rdsdt_dtsacct; grant select on sys.ICOL$ to rdsdt_dtsacct; grant select on sys.CDEF$ to rdsdt_dtsacct; grant select on sys.CCOL$ to rdsdt_dtsacct; grant select on sys.TABPART$ to rdsdt_dtsacct; grant select on sys.TABSUBPART$ to rdsdt_dtsacct; grant select on sys.TABCOMPART$ to rdsdt_dtsacct; 校验命令(使用新建账号登陆):select * from user_tab_privs; #切换至CDB$ROOT,并在如下两种方式选其一,进行账号创建并授权 alter session set container = <CDB$ROOT>; 方式一:创建C##开头的全局账号(以C##rdsdt_dtsacct为例)并进行授权 create user c##rdsdt_dtsacct identified by rdsdt_dtsacct; grant create session to c##rdsdt_dtsacct; grant connect to c##rdsdt_dtsacct; grant logmining to c##rdsdt_dtsacct; grant execute_catalog_role to c##rdsdt_dtsacct; grant select on v_$logmnr_contents to c##rdsdt_dtsacct; grant execute on sys.dbms_logmnr to c##rdsdt_dtsacct; grant select on v$database to rdsdt_dtsacct; 方式二:创建数据库账号(以rdsdt_dtsacct为例)并进行授权(如使用方式二,则您需要修改Oracle数据库的默认参数) alter session set "_ORACLE_SCRIPT"=true; create user rdsdt_dtsacct identified by rdsdt_dtsacct; grant create session to rdsdt_dtsacct; grant connect to rdsdt_dtsacct; grant logmining to rdsdt_dtsacct; grant execute_catalog_role to rdsdt_dtsacct; grant select on v_$logmnr_contents to rdsdt_dtsacct; grant execute on sys.dbms_logmnr to rdsdt_dtsacct;AWS RDS4Oracle 10G、11G、12C、18C、19C(非租户)接入方式#创建数据库账号(以RDSDT_DTSACCT为例)并进行授权 create user rdsdt_dtsacct identified by rdsdt_dtsacct; grant create session to rdsdt_dtsacct; -- 授予角色 grant connect to rdsdt_dtsacct; grant logmining to rdsdt_dtsacct; grant execute_catalog_role to rdsdt_dtsacct; 校验命令(使用新建账号登陆):select * from user_role_privs; -- 授予系统权限 grant select any table to rdsdt_dtsacct; grant select any transaction to rdsdt_dtsacct; 校验命令(使用新建账号登陆):select * from user_sys_privs; -- 授予对象权限 -- 系统视图 exec rdsadmin.rdsadmin_util.grant_sys_object('V_$LOGMNR_LOGS','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('ALL_OBJECTS','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('ALL_TAB_COLS','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('DBA_REGISTRY','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('V_$LOG','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('V_$LOGFILE','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('V_$ARCHIVED_LOG','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('V_$PARAMETER','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('V_$DATABASE','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('V_$ACTIVE_INSTANCES','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('V_$INSTANCE','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('V_$LOGMNR_CONTENTS','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('DBMS_LOGMNR','RDSDT_DTSACCT','EXECUTE'); -- 系统基表 exec rdsadmin.rdsadmin_util.grant_sys_object('USER$','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('OBJ$','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('COL$','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('IND$', 'RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('ICOL$','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('CDEF$','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('CCOL$','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('TABPART$','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('TABSUBPART$','RDSDT_DTSACCT','SELECT'); exec rdsadmin.rdsadmin_util.grant_sys_object('TABCOMPART$','RDSDT_DTSACCT','SELECT'); 校验命令(使用新建账号登陆):select * from user_tab_privs;Oracle作为目标DTS迁移过程中,需要创建数据复制账号并授权,结构迁移需要给数据采集账号授予DBA角色,全量迁移和增量迁移需要给数据采集账号授予resource角色。结构迁移全量迁移增量迁移DBA角色resource角色resource角色结构迁移授予DBA权限#创建数据库账号(以rdsdt_dtsacct为例)并进行授权 create user rdsdt_dtsacct identified by rdsdt_dtsacct; grant create session to rdsdt_dtsacct; grant connect to rdsdt_dtsacct; grant dba to rdsdt_dtsacct; #rdsdt_dtsacct账号登陆,检查是否授权完成 select * from user_tab_privs; --授予权限:create session select granted_role from user_role_privs; --授予角色:connect、dba全量迁移、增量迁移授予resoure权限#创建数据库账号(以rdsdt_dtsacct为例)并进行授权 create user rdsdt_dtsacct identified by rdsdt_dtsacct; grant create session to rdsdt_dtsacct; grant connect to rdsdt_dtsacct; grant resource to rdsdt_dtsacct; #rdsdt_dtsacct账号登陆,检查是否授权完成 select * from user_tab_privs; --授予权限:create session select granted_role from user_role_privs; --授予角色:connect、resource
2023年06月
2023年05月
2023年04月
2023年03月