當您需要捕獲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版本開始支持)
實時計算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。
僅Hologres內部表支持開啟Binlog,外部表不支持開啟Binlog。
Binlog格式與原理
Binlog記錄由Binlog系統字段和用戶Table字段組成,具體字段定義如下表。
字段名稱 | 字段類型 | 說明 |
hg_binlog_lsn | BIGINT | Binlog的系統字段,表示Binlog序號。Shard內部單調遞增不保證連續,不同Shard之間不保證唯一和有序。 |
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;