clickhouse高级功能之MaterializeMySQL详解

clickhouse 20.8将新增 MaterializeMySQL引擎 ,可通过binlog日志实时物化mysql数据,极大提升了数仓的查询性能和数据同步的时效性;原有mysql中承担的数据分析工作 可交由clickhouse去做,这么做可显著降低线上mysql的负载,从此OLTP与OLAP业务实现完美融合

知识列表

介绍

目前 MaterializeMySQL database engine 还不支持表级别的同步操作,需要将整个mysql database映射到clickhouse,映射过来的库表会自动创建为ReplacingMergeTree表engine。

MaterializeMySQL 支持全量和增量同步,首次创建数据库引擎时进行一次全量复制,之后通过监控binlog变化进行增量数据同步;该引擎支持mysql 5.6/5.7/8.0版本数据库,兼容insert,update,delete,alter,create,drop,truncate等大部分DDL操作。

演示

  • 修改my.cnf开启mysql binlog模式
log-bin=/data/logs/mysql/mysql-bin.log  # 指定binlog日志存储位置
binlog_format=ROW  # 这里一定是row格式
server-id=1  

如果clickhouse使用的是20.8 prestable之后发布的版本,那么还需要配置开启GTID模式

gtid-mode=on
enforce-gtid-consistency=1    # 设置为主从强一致性
log-slave-updates=1   # 记录日志
  • 首先在mysql中先创建scene表
CREATE TABLE `scene` (
  `id` int NOT NULL AUTO_INCREMENT,
  `code` int NOT NULL,
  `title` text DEFAULT NULL,
  `updatetime` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),   ##主键要设置为not null,否则会报错
  KEY `idx_code` (`code`)   ##索引键也要设置为not null,否则会报错
) ENGINE=InnoDB default charset=Latin1;

  • 登陆clickhouse客户端,开启mysql物化引擎
SET allow_experimental_database_materialize_mysql = 1
# 因为该功能目前还处于实验阶段,在使用之前需要开启
  • 创建一个复制管道
CREATE DATABASE scene_mms
ENGINE = MaterializeMySQL('localhost:3306', 'db', 'root', 'xxx')

创建成果后可查看到clickhouse对应的表

VM_10_14_centos :) show tables

SHOW TABLES

┌─name───────────────────────┐
│ scene                      │ 
└────────────────────────────┘

25 rows in set. Elapsed: 0.002 sec. 

表结构如下:

ATTACH TABLE scene
(
    `id` Int32,
    `code` Int32,
    `title` Nullable(String),
    `updatetime` Nullable(DateTime),
    `_sign` Int8 MATERIALIZED 1,
    `_version` UInt64 MATERIALIZED 1
)
ENGINE = ReplacingMergeTree(_version)
PARTITION BY intDiv(id, 4294967)
ORDER BY tuple(id,code)
SETTINGS index_granularity = 8192

其中partition根据id,按照长度为4294967进行分段分区

  • 向表中插入数据
INSERT INTO scene(code, title, updatetime) VALUES(1000,'邀请函',NOW());
INSERT INTO scene(code, title, updatetime) VALUES(1001,'gyc',NOW());
INSERT INTO scene(code, title, updatetime) VALUES(1002,'易企秀',NOW());

目前20.8 testing版本使用的监听事件方式为UpdateRowsEventV2 ,而20.8 prestable只后的版本使用的gtid的binlog监听方式,这种方式在mysql主从模式下可以确保数据同步的一致性,但使用过程中可能会有一些意向不到问题,建议大家先使用testing版本进行测试,等20.8稳定版出来后再测试gtid的同步模式。

查询clickhouse对应的表,已可以实时看到数据变化

SELECT * FROM scene

┌─id─┬─code─┬─title─┬──────────updatetime─┐
│  2 │ 1001 │ gyc   │ 2020-09-03 10:00:02 │
└────┴──────┴───────┴─────────────────────┘

  • 更新mysql中id为2的数据
update scene set title="校园招聘" where id = 2

检查clickhouse中id为2的数据

select * from scene where id = 2
  • 尝试删除mysql中id为2的数据
DELETE FROM scene where id = 2

再次查询clickhouse中的数据已无数据

  • 在mysql执行删除表
drop table scene

此时在clickhouse处会同步删除对应表,如果查询会报错

 DB::Exception: Table scene_mms.scene doesn't exist.. 
  • 同理 ,如果在mysql客户端新增一张表,在clickhouse处也可实时生成对应的数据表
  • 修改表名
mysql> alter table scene rename test
  
Query OK, 0 rows affected (0.02 sec)

mysql> show tables
  
+----------------+
| Tables_in_test |
+----------------+
| test           |
+----------------+
1 row in set (0.00 sec)

修改表名称不会同步至clickhouse,且查询会报错

VM_10_14_centos :) show tables

SHOW TABLES

┌─name──┐
│ scene │
└───────┘
VM_10_14_centos :) select * from scene
 
Received exception from server (version 20.8.1):
Code: 60. DB::Exception: Received from localhost:9000. DB::Exception: Table test_mms.test doesn't exist.. 

# 通过报错信息可以看出 虽然查询的是scene表 ,但底层已重写为改名之后的test表,因为test表在clickhouse处没有执行成功,所以会报找不到对应表的错误;

同理, 在mysql处删除test表,clickhouse中的scene表依然存在,可见两边执行语句是根据表名进行对应的

  • 修改列名称也是不支持的,如果出现这种情况,删除通道重建就好了

  • 支持添加列与删除列,在mysql添加一列,随后再删除

mysql> alter table scene add column  title text;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table scene  drop column  title;
Query OK, 0 rows affected (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 0

观察clickhouse中前后表结构变化

DESCRIBE TABLE scene 

┌─name───────┬─type───────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ id         │ Int32              │              │                    │         │                  │                │
│ code       │ Int32              │              │                    │         │                  │                │
│ name       │ Nullable(String)   │              │                    │         │                  │                │
│ updatetime │ Nullable(DateTime) │              │                    │         │                  │                │
│ title      │ Nullable(String)   │              │                    │         │                  │                │
│ _sign      │ Int8               │ MATERIALIZED │ 1                  │         │                  │                │
│ _version   │ UInt64             │ MATERIALIZED │ 1                  │         │                  │                │
└────────────┴────────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘

7 rows in set. Elapsed: 0.001 sec. 

VM_10_14_centos :) desc scene 

DESCRIBE TABLE scene 

┌─name───────┬─type───────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ id         │ Int32              │              │                    │         │                  │                │
│ code       │ Int32              │              │                    │         │                  │                │
│ name       │ Nullable(String)   │              │                    │         │                  │                │
│ updatetime │ Nullable(DateTime) │              │                    │         │                  │                │
│ _sign      │ Int8               │ MATERIALIZED │ 1                  │         │                  │                │
│ _version   │ UInt64             │ MATERIALIZED │ 1                  │         │                  │                │
└────────────┴────────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘


总结

  • 通过上面的测试我们发现clickhouse的删除动作也是实时同步的,原因在于我们创建的MaterializeMySQL engine会默认为每一张表生成ReplacingMergeTree engine,当clickhouse遇到删除的binlog操作时,会将这条数据的_sign字段设为-1;
    目前ReplacingMergeTree还只是标记性删除,并非物理上的实际删除,索引随着删除日志的增多,查询过滤会有一定的负担。
  • MaterializeMySQL DataBase中的ReplacingMergeTree Engine表查询不再需要额外添加final修饰符了:
select * from scene
##等同于
select * from scene final
  • 需要注意的是20.8版本目前还不是稳定版,如果mysql中没有设置主键字段时,会在创建MaterializeMySQL数据库时报错:
DB::Exception: The db.scene cannot be materialized, because there is no primary keys.

主键字段和索引字段不允许为NULL

Rewritten MySQL DDL Query ... wasn't finished successfully: Code: 44, e.displayText() = DB::Exception: Sorting key cannot contain nullable columns

不过该ISSUES目前已被重视,20.7版本在create table 时解决了这个问题,可以通过设置allow_nullable_key=1来解决,但因为MaterializeMySQL是自动创建的数据表,所以该问题还是存在的,相信不久的版本在创建MaterializeMySQL DataBase时 也会解决这个问题

CREATE TABLE nullable_key 
      (k Nullable(int), v int) ENGINE MergeTree ORDER BY k SETTINGS allow_nullable_key = 1;
  • clickhouse单线程写入能力可以达到每秒几十万,在一般业务体系下增量更新的模式是完全没有问题的。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342