本文介绍如何使用MaterializeMySQL引擎将MySQL(自建MySQL或RDS MySQL)数据同步到云数据库ClickHouse。这是一个不应在生产中使用的实验性功能。
参考链接:https://clickhouse.com/docs/zh/engines/database-engines/materialized-mysql/
1、背景信息
使用 MySQL 中存在的所有表以及这些表中的所有数据创建 ClickHouse 数据库。
ClickHouse 服务器用作 MySQL 副本。它读取 binlog 并执行 DDL 和 DML 查询。
2、创建数据库
CREATE DATABASE [IF NOT EXISTS] db_name [ON CLUSTER cluster]
ENGINE = MaterializeMySQL('host:port', ['database' | database], 'user', 'password') [SETTINGS ...]
引擎参数
host:port— MySQL服务地址
database— MySQL数据库名称
user— MySQL用户名
password — MySQL用户密码
3、配置属性
max_rows_in_buffer— 允许数据缓存到内存中的最大行数(对于单个表和无法查询的缓存数据)。当超过行数时,数据将被物化。默认值: 65505。
max_bytes_in_buffer— 允许在内存中缓存数据的最大字节数(对于单个表和无法查询的缓存数据)。当超过行数时,数据将被物化。默认值: 1048576.
max_rows_in_buffers— 允许数据缓存到内存中的最大行数(对于数据库和无法查询的缓存数据)。当超过行数时,数据将被物化。默认值: 65505.
max_bytes_in_buffers— 允许在内存中缓存数据的最大字节数(对于数据库和无法查询的缓存数据)。当超过行数时,数据将被物化。默认值: 1048576.
max_flush_data_time— 允许数据在内存中缓存的最大毫秒数(对于数据库和无法查询的缓存数据)。当超过这个时间时,数据将被物化。默认值: 1000.
max_wait_time_when_mysql_unavailable— 当MySQL不可用时重试间隔(毫秒)。负值禁止重试。默认值: 1000.
allows_query_when_mysql_lost — 当mysql丢失时,允许查询物化表。默认值: 0 (false).
CREATE DATABASE mysql ENGINE = MaterializeMySQL('localhost:3306', 'db', 'user', '***')
SETTINGS
allows_query_when_mysql_lost=true,
max_wait_time_when_mysql_unavailable=10000;
4、MySQL服务器端配置
为了MaterializeMySQL正确的工作,有一些强制性的MySQL侧配置设置应该设置:
default_authentication_plugin = mysql_native_password,因为MaterializeMySQL只能使用此方法授权。
gtid_mode = on,因为要提供正确的MaterializeMySQL复制,基于GTID的日志记录是必须的。注意,在打开这个模式On时,你还应该指定enforce_gtid_consistency = on。
5、虚拟列
当使用MaterializeMySQL数据库引擎时,ReplacingMergeTree表与虚拟的_sign和_version列一起使用。
_version— 同步版本。类型UInt64.
_sign— 删除标记。类型 Int8. Possible values:
1— 行不会删除,
-1 — 行被删除。
4、案例
首先在MySQL中配置 my.cnf
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
# 配置flink-mysql-cdc
server-id=1
log-bin=mysql-bin
binlog_format=row
binlog-do-db=wmy
binlog-do-db=db
# clickhouse
gtid-mode=on
enforce-gtid-consistency=1 # 设置为主从强一致性
log-slave-updates=1 # 记录日志systemctl restart mysqld
在MySQL中创建库和表
CREATE DATABASE db;
CREATE TABLE db.test (a INT PRIMARY KEY, b INT);在clickhouse中创建库
CREATE DATABASE mysql ENGINE = MaterializeMySQL('192.168.21.113:3306', 'db', 'root', '000000')
SETTINGS
allows_query_when_mysql_lost=true,
max_wait_time_when_mysql_unavailable=10000;
SET allow_experimental_database_materialize_mysql = 1
# 因为该功能目前还处于实验阶段,在使用之前需要开启可以查看是否有表
INSERT INTO db.test VALUES (1, 11), (2, 22);
DELETE FROM db.test WHERE a=1;
ALTER TABLE db.test ADD COLUMN c VARCHAR(16);
UPDATE db.test SET c='Wow!', b=222;
SELECT * FROM db.test;下面每执行一步操作的话就去clickhouse里面去查看
5、注意
目前20.8 testing版本使用的监听事件方式为UpdateRowsEventV2 ,而20.8 prestable只后的版本使用的gtid的binlog监听方式,这种方式在mysql主从模式下可以确保数据同步的一致性,但使用过程中可能会有一些意向不到问题,建议大家先使用testing版本进行测试,等20.8稳定版出来后再测试gtid的同步模式。
查询clickhouse对应的表,已可以实时看到数据变化
通过上面的测试我们发现clickhouse的删除动作也是实时同步的,原因在于我们创建的MaterializeMySQL engine会默认为每一张表生成ReplacingMergeTree engine,当clickhouse遇到删除的binlog操作时,会将这条数据的_sign字段设为-1;
目前ReplacingMergeTree还只是标记性删除,并非物理上的实际删除,索引随着删除日志的增多,查询过滤会有一定的负担。
MaterializeMySQL DataBase中的ReplacingMergeTree Engine表查询不再需要额外添加final修饰符了:
需要注意的是20.8版本目前还不是稳定版,如果mysql中没有设置主键字段时,会在创建MaterializeMySQL数据库时报错:
主键字段和索引字段不允许为NULL
不过该ISSUES目前已被重视,20.7版本在create table 时解决了这个问题,可以通过设置allow_nullable_key=1来解决,但因为MaterializeMySQL是自动创建的数据表,所以该问题还是存在的,相信不久的版本在创建MaterializeMySQL DataBase时 也会解决这个问题
clickhouse单线程写入能力可以达到每秒几十万,在一般业务体系下增量更新的模式是完全没有问题的。
CREATE DATABASE mysql ENGINE = MaterializeMySQL('192.168.21.113:3306', 'db', 'root', '000000')
SETTINGS
allows_query_when_mysql_lost=true,
max_wait_time_when_mysql_unavailable=10000,
SETTINGS allow_nullable_key = 1;目前这个只是一个实验阶段,相信在未来的时间里面这个会用得很多,在实时数仓的场景中




