梁长青,OceanBase 高级研发工程师,从事 SQL 执行引擎相关工作,目前主要负责 DBLink、单机引擎优化等方面工作。
沈大川,OceanBase 高级研发工程师,从事 SQL 执行引擎相关工作,曾参与 TPC-H 项目攻坚,目前主要负责并行执行、DBLink、数据类型等方面的工作。
我们发现,由于不同业务需求之间存在较大差异,不少用户会在实际业务中同时使用多种数据库产品。这些不同的数据库之间并不能直接进行数据访问,这为数据共享和流转带来了障碍。我们假设这样一个场景:某公司各部门的销售数据存储在各自的数据库中,当需要统计全公司的销售数据时,就得对所有数据库中的数据进行汇总。可以预想到,一种可行的方式是使用 ETL 工具,或自行编写脚本来实现数据的抽取和转换,进而将所有数据导入到同一数据库中再进行分析。很明显,这种方式需要编写更多的代码和脚本,开发和维护成本较高。进一步讲,如果用户频繁执行汇总操作,数据导出、导入的时间成本,以及数据存储成本也将变得非常高。
是否有方法能省去业务跨数据库时的繁琐步骤呢?数据库链接(Database Link,简称为 DBLink)可以为我们提供解决思路,这是一项在不同数据库之间进行连接和通信的功能。使用 DBLink,用户可以将一个数据库视为另一数据库的外部表,从而执行跨数据库的查询和数据操作。针对上述场景,我们便可以在一个数据库中建立到各个部门数据库的 DBLink,通过 DBLink 读取各个部门的销售数据并进行汇总分析。使用 DBLink 的优点是可以实时获取远端数据库的最新数据,同时,可以利用 DBLink 进行数据写入,将汇总数据同步给各个部门。
此前,OceanBase 已经支持了 OceanBase 到 Oracle 数据库的 DBLink 读功能。4.1 版本中,我们以 XA 事务能力为基础,进一步支持了跨 OceanBase 和 Oracle 的写事务能力,并支持了 OceanBase 到 OceanBase 的写事务能力。读写兼备的 DBLink 能力,可以让用户轻松实现跨数据库的数据共享与一体化,使得数据处理分析更便捷。本文将分享我们对 DBLink 功能的认识及使用方法。
OceanBase DBLink 功能对于用户来说,在跨库数据访问,数据迁移,数据一致性等方面具有实际意义。
数据迁移:在数据库需要迁移数据时,使用 DBLink 可以简化迁移过程。通过建立 DBLink,用户可以在原数据库中查询并获取需要迁移的数据,然后在目标数据库中插入这些数据,从而快速实现数据迁移;
跨库数据访问:有些应用需要将数据分散到不同的集群或同一集群的不同租户中,这时可以使用 DBLink 来实现跨集群、跨租户的数据共享和交互。如本文开头介绍的场景,某公司各部门的数据记录在各自的数据库中,在需要汇总分析全公司数据时,使用 DBLink 即可实时访问各部门数据;
数据一致性:基于 OceanBase 本身的 XA 事务能力,OceanBase 的 DBLink 不仅提供了读取远程数据的能力,还支持写事务。例如,一个应用程序需要在多个数据库中进行数据更新和插入,使用 DBLink 可以保证前述操作在一个事务中执行,从而保证数据的一致性和可靠性。
DBLink 功能主要分为读功能和写功能,下表是对读写功能的使用场景和版本支持情况的介绍。
为了验证 OceanBase 的 DBLink 能力,我们假设以下业务场景进行实验:A 客户需要将业务系统从 Oracle 迁移至 OceanBase:大部分业务场景完全迁移至 OceanBase 的多个 Oracle 模式租户,小部分业务场景仍保留在 Oracle,最终数据分散存放在 OceanBase 的 Oracle 租户 1、Oracle 租户 2 以及 Oracle 数据库上。
此时创建一个从 Oracle 租户 1 到 Oracle 租户 2 的 DBLink,命名为 OB_LINK;创建一个从 Oracle 租户 1 到 Oracle 数据库的 DBLink,命名为 ORCL_LINK。下文将具体展示 OceanBase DBLink 功能可以在实际业务中为用户带来的便利。
一、无需修改代码,正常使用 Oracle DBLink 功能
A 客户原本在业务系统上使用了 Oracle 的 DBLink 功能,将业务场景迁移至 OceanBase 之后,A 客户无需修改原有业务代码,在 Oceanbase 的 Oracle 租户下创建同名的 DBLink 即可无缝使用原有的业务代码。
二、平滑迁移 Oracle 表数据或 OceanBase 租户表数据
A 客户的大部分业务数据都已通过 OMS 从 Oracle 迁移至 OceanBase 的 Oracle 租户 1 上,临时发现还有名为 orders 的表被遗漏在 Oracle 数据库上未完成迁移。此时,可以使用 OceanBase DBLink 功能方便快捷地迁移数据,避免导出导入数据的繁琐操作。
obclient> create table orders as select * from orders@ORCL_LINK;
Query OK, 9999 rows affected (0.36 sec)
A 客户的业务数据分布在不同的 OceanBase 的 Oracle 租户上,如果需要将 Oracle 租户 1 的 lineitem 表数据迁移到 Oracle 租户 2,OceanBase DBLink 功能同样可以进行迁移操作。
obclient> create table lineitem as select * from lineitem@OB_LINK;
Query OK, 37641 rows affected (1.66 sec)
三、OceanBase 读异构的 Oracle 数据
A 客户的完成了业务数据的迁移过渡,有部分 sql 查询场景要同时访问位于 OceanBase 租户 1 上的 orders 表和 Oracle 上的 customer 表数据,OceanBase DBLink 支持从 Oracle 租户查询 Oracle 表数据的能力。
obclient> select a.O_CUSTKEY, b.C_NAME from orders a, customer@ORCL_LINK b where a.O_CUSTKEY = b.C_CUSTKEY;
+-----------+--------------------+
| O_CUSTKEY | C_NAME |
+-----------+--------------------+
| 665509 | Customer#000665509 |
| 1978019 | Customer#001978019 |
| 1855835 | Customer#001855835 |
| 525559 | Customer#000525559 |
| 103387 | Customer#000103387 |
| 28801 | Customer#000028801 |
+-----------+--------------------+
6 rows in set (0.01 sec)
四、OceanBase 跨租户读数据
A 客户的业务数据分布在不同的 OceanBase 的 Oracle 租户上, 有部分 sql 查询场景要同时访问位于 OceanBase 的 Oracle 租户 1 的 lineitem 表数据和 Oracle 租户 2 上的 partsupp 表数据,OceanBase DBLink 支持跨租户查询表数据的能力。
obclient> select a.L_ORDERKEY, b.PS_SUPPKEY from lineitem a, partsupp@OB_LINK b where a.L_PARTKEY = b.PS_PARTKEY;
+------------+------------+
| L_ORDERKEY | PS_SUPPKEY |
+------------+------------+
| 5010944 | 291423 |
| 5010944 | 41423 |
| 5010944 | 791423 |
| 5010944 | 541423 |
| 7808165 | 903434 |
| 7808165 | 653434 |
| 7808165 | 403434 |
+------------+------------+
7 rows in set (0.01 sec)
五、XA 事务保证下的写异构 Oracle 或写其他 OceanBase 租户
A 客户的业务数据分布在不同的 OceanBase 的 Oracle 租户上, 业务需要在 OceanBase 的 Oracle 租户 1 上向 Oracle 租户 2 和 Oracle 数据库写入数据并提交事务修改,三方将共同参与一个 XA 事务。XA 事务在使用 DBLink 写入数据前将自动开启,事务内有以下操作:
第一,向 Oracle 数据库的 customer 表的插入数据
obclient> insert into Customer@ORCL_LINK values(9989, 'Customer#01', 'abcdefg', 8, '123456789', -240.92, 'building', 'etc.');
Query OK, 1 row affected (0.32 sec)
obclient> select * from Customer@ORCL_LINK where C_CUSTKEY = 9989;
+-----------+-------------+-----------+-------------+-----------------+-----------+--------------+-----------+
| C_CUSTKEY | C_NAME | C_ADDRESS | C_NATIONKEY | C_PHONE | C_ACCTBAL | C_MKTSEGMENT | C_COMMENT |
+-----------+-------------+-----------+-------------+-----------------+-----------+--------------+-----------+
| 9989 | Customer#01 | abcdefg | 8 | 123456789 | -240.92 | building | etc. |
+-----------+-------------+-----------+-------------+-----------------+-----------+--------------+-----------+
1 row in set (0.00 sec)
第二,将 OceanBase 的 Oracle 1 租户的 lineitem 表的指定数据插入到 OceanBase 的 Oracle 2 租户的 lineitem 表上。
obclient> select * from lineitem@OB_LINK where L_ORDERKEY = 897;
Empty set (0.04 sec)
obclient> insert into lineitem@OB_LINK select * from lineitem where L_ORDERKEY = 897;
Query OK, 4 rows affected (0.03 sec)
obclient> select * from lineitem@OB_LINK where L_ORDERKEY = 897;
+------------+-----------+-----------+--------------+------------+-----------------+------------+-------+--------------+--------------+---------------------+---------------------+---------------------+---------------------------+------------+--------------------------------------+
| L_ORDERKEY | L_PARTKEY | L_SUPPKEY | L_LINENUMBER | L_QUANTITY | L_EXTENDEDPRICE | L_DISCOUNT | L_TAX | L_RETURNFLAG | L_LINESTATUS | L_SHIPDATE | L_COMMITDATE | L_RECEIPTDATE | L_SHIPINSTRUCT | L_SHIPMODE | L_COMMENT |
+------------+-----------+-----------+--------------+------------+-----------------+------------+-------+--------------+--------------+---------------------+---------------------+---------------------+---------------------------+------------+--------------------------------------+
| 897 | 9044941 | 544960 | 1 | 15 | 28282.35 | .07 | .04 | R | F | 1995-05-25 00:00:00 | 1995-05-09 00:00:00 | 1995-06-07 00:00:00 | COLLECT COD | REG AIR | r ideas. slyly spec |
| 897 | 18316926 | 66981 | 2 | 26 | 50492.26 | .05 | .08 | N | O | 1995-07-01 00:00:00 | 1995-06-10 00:00:00 | 1995-07-14 00:00:00 | COLLECT COD | MAIL | tions sleep according to the special |
| 897 | 12570365 | 820378 | 3 | 13 | 18651.62 | .07 | 0 | A | F | 1995-03-30 00:00:00 | 1995-05-17 00:00:00 | 1995-04-21 00:00:00 | TAKE BACK RETURN | MAIL | bold accounts mold carefully! braids |
| 897 | 10118182 | 618203 | 4 | 2 | 2399.36 | .08 | .08 | R | F | 1995-05-22 00:00:00 | 1995-05-07 00:00:00 | 1995-06-16 00:00:00 | COLLECT COD | RAIL | into beans. slyly special fox |
+------------+-----------+-----------+--------------+------------+-----------------+------------+-------+--------------+--------------+---------------------+---------------------+---------------------+---------------------------+------------+--------------------------------------+
4 rows in set (0.03 sec)
第三,将 Oracle 上更新后 customer 表和 Oracle 租户 2 上更新后的 lineitem 表做 join,并把 join 结果插入到 Oracle 租户 1 的 lineitem 表。
obclient> insert into lineitem select b.* from customer@ORCL_LINK a, lineitem@OB_LINK b where a.C_CUSTKEY = b.L_ORDERKEY;
Query OK, 9990 rows affected (1.12 sec)
Records: 9990 Duplicates: 0 Warnings: 0
第四,提交 XA 事务,OceanBase 的 Oracle 租户 1、OceanBase 的 Oracle 租户 2 和 Oracle 上对应的表更新一起提交事务内改动。
obclient> commit;
Query OK, 0 rows affected (0.04 sec)
通过以上场景的实际操作,我们验证了 OceanBase DBLink 功能的读能力和支持 XA 事务的写能力,在帮助用户降低从 Oracle 到 OceanBase 数据迁移成本的同时,提供跨租户迁移数据、查询 Oracle 或其他租户数据以及 XA 事务保证下的写数据能力。
本文介绍了 OceanBase 数据库目前 DBLink 功能的具体情况,未来我们将持续升级这些功能。
近期我们会从两方面对 DBLink 功能进行增强:一是支持访问更多的远程对象类型,例如近期将支持访问远程 PROCEDURE 和 SEQUENCE 对象;二是为了更好地支持 OLAP 场景,我们也将支持更多的数据源类型,支持连接 OceanBase 和 Oracle 以外的数据库。
在即将发布的 4.2 版本中,OceanBase 将会提供跨 MySQL 租户的 DBLink 读能力。我们相信 OceanBase DBLink 功能可以让用户的业务数据共享与流转更简单便捷,也欢迎大家向我们反馈使用感受。