当您需要捕获Hologres数据库事件,用于数据之间的复制、同步或将这些事件作为消息流转发给不同的消费者处理时,Hologres支持Binlog功能,消费Hologres Binlog来提升数据复用能力,缩短数据加工端到端延迟。本文为您介绍在Hologres订阅Hologres Binlog及相关操作。
Binlog介绍
Hologres同传统MySQL数据库一样,支持通过Binlog记录数据库中所有数据的变化事件日志。通过Hologres Binlog,可以非常方便灵活的实现数据之间的复制、同步。但是Hologres Binlog一般只用于数据同步,而传统数据库Binlog还应用于主从实例同步和数据恢复等高可用场景。因此两者地实现存在一定差别,主要体现在以下方面:
Hologres Binlog不会记录DDL操作。
Hologres Binlog较为灵活,是表级别的,可以按需打开和关闭,且可以为不同的表设置不同的TTL。
Hologres作为分布式的实时数仓,Binlog同样也是分布式的。
Hologres Binlog可以非常方便地进行查询。
同时在大数据场景上,支持Flink直接消费Hologres Binlog,相较于传统数仓分层,Flink+Hologres Binlog可以实现完整的事件驱动,完成操作数据存储层(ODS)向数据仓库维度层(DWD)、DWD向数据服务层(DWS)等的全实时加工作业,满足分层治理的前提下统一存储,提升数据复用能力,并且缩短数据加工端到端延迟,为用户提供一站式的实时数据仓库解决方案。关于Binlog的更多介绍请参见技术揭秘文档。
使用限制
在Hologres中订阅Hologres Binlog需要注意如下事项:
仅Hologres V0.9及以上版本支持订阅Hologres Binlog,如果您的实例是V0.9以下版本,请您加入在线支持钉钉群,详情请参见如何获取更多的在线支持?。
Hologres V0.9以及V0.10版本,已存在的表无法修改表属性开启Binlog,需重新建表。从V1.1版本开始,可以按需开启Binlog。
Hologres V1.3.14和V1.1.82之前的版本仅支持Superuser消费Binlog,如果使用其他低权限账号消费Binlog会出现没有权限的报错:
permission denied for table hg_replication_slot_properties
。从Hologres V1.3.14和V1.1.82版本开始,若使用Flink消费Binlog,仅需账号具备查询表的权限即可。对于使用JDBC消费Hologres Binlog需要账号在Replication Role中。Hologres支持单表级别的Binlog功能,支持行存表和列存表。当前订阅Hologres Binlog支持的情况如下表。
Flink分类
Hologres行存表Binlog
Hologres列存表Binlog
Hologres行列共存表Binlog(从Hologres V1.1版本开始支持)
Flink分类
Hologres行存表Binlog
Hologres列存表Binlog
Hologres行列共存表Binlog(从Hologres V1.1版本开始支持)
实时计算Blink
支持
支持
支持
全托管Flink
支持
支持
支持
开源Flink
不支持
不支持
不支持
JDBC
Hologres V1.1版本开始支持
Hologres V1.1版本开始支持
Hologres V1.1版本开始支持
Blink消费Hologres Binlog暂不支持Hologres的TIMESTAMP类型,在Hologres建表时,请使用TIMESTAMPTZ类型。同时也不支持SMALLINT等特殊类型。
不支持消费分区表父表的Binlog,请使用分区子表或者普通表(非分区表)。Hologres从 V1.3.24版本开始,支持按需修改分区子表的Binlog TTL,若是没有显式指定分区子表的Binlog TTL,则与父表的Binlog TTL保持一致。同时需要注意Binlog TTL不是精准的时间,系统不会强保证Binlog到期后立马删除Binlog,将会在过期后的某个时间删除。
对于更新频繁的场景,理论上列存表开启Binlog的开销要大于行存表的开销,所以建议使用行存表开启Binlog。若该表同时涉及OLAP查询,则建议采用行列共存的存储方式,详情请参见表的存储格式。
仅Hologres内部表支持开启Binlog,外部表不支持开启Binlog。
Binlog格式与原理
Binlog记录由Binlog系统字段和用户Table字段组成,具体字段定义如下表。
字段名称 | 字段类型 | 说明 |
字段名称 | 字段类型 | 说明 |
hg_binlog_lsn | BIGINT | Binlog的系统字段,表示Binlog序号。Shard内部单调递增不保证连续,不同Shard之间不保证唯一和有序。 Binlog数据在Shard中的分布原理请参见分布键Distribution Key。 |
hg_binlog_event_type | BIGINT | Binlog的系统字段,表示当前Record所表示的修改类型。
|
hg_binlog_timestamp_us | BIGINT | Binlog的系统字段,系统时间戳,单位为us。 |
user_table_column_1 | 用户自定义 | 用户Table字段。 |
... | ... | ... |
user_table_column_n | 用户自定义 | 用户Table字段。 |
UPDATE操作会产生两条Binlog记录,分别为更新前和更新后的记录。订阅Binlog功能会保证这两条记录是连续的且更新前的Binlog记录在前,更新后的Binlog记录在后。
通过Hologres Connector(如Holo Client、Flink Connector、数据集成)等方式执行的UPDATE,Connector会将BEFORE_UPDATE翻译为DELETE,将AFTER_UPDATE翻译为INSERT,因此在
hg_binlog_event_type
字段中看到的是2,5,但Connector会保证数据的最终一致性。只有纯SQL方式执行UPDATE,
hg_binlog_event_type
字段的记录是BEFORE_UPDATE和AFTER_UPDATE。
Hologres的Binlog可以看作是一张特殊的行存表,为某张表打开Binlog,可以理解为是新创建了一张以hg_binlog_lsn
为Key, 业务表原有字段、hg_binlog_event_type
以及hg_binlog_timestamp_us
字段则组合起来作为Value的行存表。Binlog表的字段是固定的,也可以说是强Schema的,用户字段顺序与业务表DDL定义的顺序一致。因此建议开启Binlog的表使用行存表或者行列共存表,会使得读Binlog时会有更好的性能。
开启Binlog
Hologres中,Binlog功能默认关闭,您可以通过设置表属性binlog.level和binlog.ttl开启该功能。如下示例开启Binlog,更多关于创建表的参数说明,请参见CREATE TABLE。
理论上列存表开启Binlog功能的成本要大于行存表。如果您对表格的更新比较频繁,建议您使用行存表开启Binlog功能。
V2.1版本起支持的语法:
binlog.level
和binlog.ttl
表属性名更新为binlog_level
和binlog_ttl
。CREATE TABLE test_message_src ( id int PRIMARY KEY, title text NOT NULL, body text ) WITH ( orientation = 'row', clustering_key = 'id', binlog_level = 'replica', binlog_ttl = '86400' -- Binlog的TTL,单位为秒 );
所有版本支持的语法:
begin; create table test_message_src( id int primary key, title text not null, body text); call set_table_property('test_message_src', 'orientation', 'row');--创建行存表test_message_src call set_table_property('test_message_src', 'clustering_key', 'id');--在id列建立聚簇索引 call set_table_property('test_message_src', 'binlog.level', 'replica');--设置表属性开启Binlog功能 call set_table_property('test_message_src', 'binlog.ttl', '86400');--binlog.ttl,Binlog的TTL,单位为秒 commit;
参数说明如下。
参数 | 说明 |
参数 | 说明 |
| 是否开启Binlog,可选择:
|
| Binlog的TTL,单位秒。默认为30天,即默认值为2592000。 |
按需开启Binlog
从Hologres V1.1版本开始,可以根据业务需要选择开启/关闭Binlog能力,同时支持配置TTL满足不同业务场景对Binlog保留时间的诉求,已有表无需重新建表就能开启Binlog,操作方便快捷。
以下功能仅针对Hologres V1.1及以上版本,如果您的实例是V1.1以下版本,请您使用自助升级或加入Hologres钉钉交流群反馈,详情请参见如何获取更多的在线支持?。
开启Binlog
可以使用以下语句对已有表开启Binlog并设置Binlog TTL时间。
-- 设置表属性开启Binlog功能 begin; call set_table_property('<table_name>', 'binlog.level', 'replica'); commit; -- 设置表属性,配置Binlog TTL时间,单位秒 begin; call set_table_property('<table_name>', 'binlog.ttl', '2592000'); commit;
table_name为开启Binlog的表名称。
关闭Binlog
可以使用以下语句对已开启Binlog的表关闭Binlog。
-- 设置表属性关闭Binlog功能 begin; call set_table_property('<table_name>', 'binlog.level', 'none'); commit;
table_name为需要关闭Binlog的表名称。
修改Binlog的TTL
通过以下语句可以对已开启Binlog的表修改TTL,满足业务对Binlog不同保留时间的诉求。
Hologres从 V1.3.24版本开始,支持按需开启分区子表的Binlog TTL。如果没有显示修改子表的Binlog TTL,则默认与父表的Binlog TTL保持一致。
call set_table_property('<table_name>', 'binlog.ttl', '8640000'); --单位秒
table_name为修改Binlog TTL的表名称。
查询Binlog
Hologres表的Binlog数据采用强Schema格式。要查询特定表的Binlog,可通过将Binlog内置额外字段与表原有字段进行组合来实现。此外,Hologres还提供了一些函数,以便查询最新或最早的Binlog,或者通过已知的LSN和TIMESTAMP来查询相应的Binlog信息。
通过内置特殊字段直接查询Binlog
使用Binlog内置额外字段与表原有字段组合的方式查询Binlog,示例如下。
SELECT hg_binlog_lsn,hg_binlog_event_type,hg_binlog_timestamp_us,* FROM test_message_src;
查询结果示例如下。
查询表指定Shard上最早或最新的Binlog
使用hg_get_binlog_cursor
函数的方式查询Binlog,语法如下。
-- OLDEST,此shard上最早的Binlog
SELECT * FROM hg_get_binlog_cursor('<table_name>','OLDEST',<shard_id>);
-- LATEST,此shard上最新的Binlog
SELECT * FROM hg_get_binlog_cursor('<table_name>','LATEST',<shard_id>);
示例如下。
SELECT * FROM hg_get_binlog_cursor('test_message_src','OLDEST',0);
查询结果示例如下。
通过Binlog LSN查询相应Binlog的时间戳
使用hg_get_binlog_cursor_by_lsn
函数查询相应Binlog的时间戳,可返回大于等于所查询LSN(日志序列号)的第一条Binlog的信息,如果当前LSN不存在,返回结果中的hg_binlog_timestamp_us字段是当前时间。语法如下。
SELECT * FROM hg_get_binlog_cursor_by_lsn('<table_name>',<lsn>,<shard_id>);--LSN值(bigint类型)
示例如下。
SELECT * FROM hg_get_binlog_cursor_by_lsn('test_message_src',152,0);
查询结果示例如下。
通过Binlog TIMESTAMP查询相应Binlog的LSN
使用hg_get_binlog_cursor_by_timestamp
函数查询相应Binlog的LSN,可返回大于等于所查询时间的第一条Binlog的信息,如果已经是最新的,返回结果中的hg_binlog_timestamp_us
字段是当前时间,hg_binlog_lsn
字段是下一条数据插入时将会分配的LSN。语法如下。
如果传入的TIMESTAMP大于当前时间(now()函数返回的时间),SQL查询会抛出异常"get binlog cursor in future time"。
SELECT * FROM hg_get_binlog_cursor_by_timestamp('<table_name>',<timestamp>,<shard_id>);
示例如下。
SELECT *,to_timestamp(hg_binlog_timestamp_us/1000000.0) FROM hg_get_binlog_cursor_by_timestamp('test_message_src','2024-05-20 19:34:53.791+08',0);
查询结果示例如下。
实时消费Hologres Binlog
当前支持通过Flink、Blink以及JDBC(包括Holo Client)消费Hologres Binlog,详情请参见文档:
Flink和Blink实时消费Binlog,请参见Flink/Blink实时消费Hologres Binlog。
有关JDBC如何实时消费Binlog,请参见通过JDBC消费Hologres Binlog。
查看开启了Binlog的表
您可以使用如下SQL查看哪些表开启了Binlog。
SELECT
*
FROM
hologres.hg_table_properties
WHERE
property_key = 'binlog.level'
AND property_value = 'replica';
返回结果示例如下。
查看Binlog存储空间大小
关闭表DML过程中的Binlog
通过如下GUC可以使某个表在DML过程中不产生Binlog。Session级别开启,需添加在DML前一起执行。
--session级别开启
SET hg_experimental_generate_binlog=off;
- 本页导读 (1)
- Binlog介绍
- 使用限制
- Binlog格式与原理
- 开启Binlog
- 按需开启Binlog
- 查询Binlog
- 通过内置特殊字段直接查询Binlog
- 查询表指定Shard上最早或最新的Binlog
- 通过Binlog LSN查询相应Binlog的时间戳
- 通过Binlog TIMESTAMP查询相应Binlog的LSN
- 实时消费Hologres Binlog
- 查看开启了Binlog的表
- 查看Binlog存储空间大小
- 关闭表DML过程中的Binlog