當您需要捕獲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)等的全即時加工作業,滿足分層治理的前提下統一儲存,提升資料複用能力,並且縮短資料加工端到端延遲,為使用者提供一站式的即時資料倉庫解決方案。
使用限制
在Hologres中訂閱Hologres Binlog需要注意如下事項:
僅Hologres V0.9及以上版本支援訂閱Hologres Binlog,如果您的執行個體是V0.9以下版本,請您加入線上支援DingTalk群,詳情請參見如何擷取更多的線上支援?。
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版本開始支援)
Realtime ComputeBlink
支援
支援
支援
全託管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、Data Integration)等方式執行的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以下版本,請您使用自助升級或加入HologresDingTalk交流群反饋,詳情請參見如何擷取更多的線上支援?。
開啟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;