記事のディレクトリ
MySQLとClickhouseは完全に異なる2つのデータベースであり、どちらにも長所と短所があり、それらが適しているビジネスシナリオも異なります。実際のビジネスでは、の特性と長所に応じて適切なデータベースを選択する必要があります。データベース自体。ビジネスシーン。従来のMySQLデータベースはOLTPビジネスを非常によくサポートしていますが、大量のデータの統計分析を必要とするOLAPなどのビジネスシナリオには、依然として大きな特定のパフォーマンスのボトルネックがあります。コアオンラインビジネスデータに対してより優れたBI統計分析とクエリを実行する場合は、オンラインデータを対応する統計分析データベースに同期する方法に直面する必要があります。Clickhouseは、2020年から、MySQLのスレーブデータベースとしてのClickhouseの使用、MySQLデータのリアルタイム同期、およびOLTPからOLAPへの飛躍を実現するMaterializeMySQLエンジンをリリースしました。
一、MaterializeMySQL
1.1MySQLとCKの簡単な比較
MySQLとClickhouseの主な類似点と相違点は次のとおりです。
MySQL | クリックハウス |
---|---|
リレーショナルデータベース、サポートするもの | 分散列データベース、トランザクションをサポートしていません |
できるだけ少ない行データを読み取るのに適した行ストレージモード | 列ストレージモードと高いデータ圧縮率は、大量のデータの読み取りに自然な利点があります |
シングルプロセスマルチスレッドサービス、単一のビジネスリクエストクエリは複数のCPUリソースを効果的に利用できません | マルチコアパラレル |
OLTPビジネスの場合 | オンライン分析処理を指向したOLAPビジネス |
1.2MaterializeMySQLの原則
2020年の後半に、Yandex CompanyはClickHouseコミュニティでMaterializeMySQLエンジンをリリースしました。これは、主にMySQLからの完全および増分のリアルタイムデータ同期をサポートするために使用されます。現在、MySQL 5.6 / 5.7 / 8.0バージョンをサポートしており、Delete / Updateステートメントと互換性があり、最も一般的に使用されるDDL操作です。
ご存知のとおり、MySQL自体のレプリケーションは主にbinlogトランザクションログに依存しており、MaterializeMySQLエンジンも例外ではありません。ただし、ネイティブMySQLのbinlogレプリケーションの違いは、2つの文法上の違いにより、MaterializeMySQLはイベント内のSQLステートメントを実行のためにCK内の特定のステートメントに変換せず、Binlogイベントを基になるステートメントに直接変換することです。ブロック構造。次に、物理レプリケーションに近い基盤となるストレージエンジンに直接書き込まれます。
MaterializeMySQL実装プロセス:
- MaterializeMySQLは、データベースレベルのレプリケーションをサポートします。
- Clickhouseでデータベースレベルのコピーを作成した後、clickhouseは指定されたデータベースアカウントを介してTCP / IP経由でデータに接続し、データベースに対して読み取りロックを使用してテーブルのフラッシュを実行し、関連するbinlogおよびテーブル構造のメタデータ情報を取得します。メタデータがコピーされた後グローバル読み取り専用ロックを解除し、select * fromtable_nameを使用してテーブルデータ情報のコピーを開始します。
- その後の増分データ同期では、MaterializeMySQLは、binlogイベント(MYSQL_QUERY_EVENT(DDL)、MYSQL_WRITE_ROWS_EVENT(挿入)、MYSQL_UPDATE_ROWS_EVENT(更新)、MYSQL_DELETE_ROWS_EVENT(削除))の分析を通じてリアルタイム同期を実現します。
- DDL操作の場合、MaterializeMySQLはデフォルトでMySQLテーブルデータの主キーをCKテーブルのソートキーとパーティションキーとして使用しますが、ClickhouseとMySQLのデータ定義の違いにより、DDLステートメントもそれに応じて変換されます
- 更新/削除操作の場合、MaterializeMySQLはバージョン管理に使用される_versionの非表示フィールドを導入し、_signフィールドを組み合わせてデータの有効性をマークします
MaterializeMySQLがレプリケーションチャネルを作成するとき、完全な初期化同期フェーズ中に、general_logを介してMySQLの特定の実行の詳細を表示できます。特定の実行ログは次のとおりです。
2021-03-14T15:40:02.016351+08:00 26 Connect [email protected] on ck_test using TCP/IP
2021-03-14T15:40:02.017402+08:00 26 Query SET NAMES utf8
2021-03-14T15:40:02.018822+08:00 26 Query SHOW VARIABLES WHERE (Variable_name = 'log_bin' AND upper(Value) = 'ON') OR (Variable_name = 'binlog_format' AND upper(Value) = 'ROW') OR (Variable_name = 'binlog_row_image' AND upper(Value) = 'FULL') OR (Variable_name = 'default_authentication_plugin' AND upper(Value) = 'MYSQL_NATIVE_PASSWORD')
2021-03-14T15:40:02.032549+08:00 26 Query SELECT version() AS version
2021-03-14T15:40:02.033620+08:00 26 Query FLUSH TABLES
2021-03-14T15:40:02.051444+08:00 26 Query FLUSH TABLES WITH READ LOCK
2021-03-14T15:40:02.052364+08:00 26 Query SHOW MASTER STATUS
2021-03-14T15:40:02.053295+08:00 26 Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
2021-03-14T15:40:02.054027+08:00 26 Query START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */
2021-03-14T15:40:02.055520+08:00 26 Query SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ck_test'
2021-03-14T15:40:02.057527+08:00 26 Query SHOW CREATE TABLE ck_test.t1
2021-03-14T15:40:02.060780+08:00 26 Query SHOW CREATE TABLE ck_test.t2
2021-03-14T15:40:02.062275+08:00 26 Query UNLOCK TABLES
2021-03-14T15:40:02.075348+08:00 26 Query SELECT * FROM ck_test.t2
2021-03-14T15:40:02.101797+08:00 26 Query SELECT * FROM ck_test.t1
2021-03-14T15:40:02.106329+08:00 26 Query COMMIT
2021-03-14T15:40:02.109026+08:00 27 Connect [email protected] on using TCP/IP
2021-03-14T15:40:02.109637+08:00 27 Query SET @master_binlog_checksum = 'CRC32'
2021-03-14T15:40:02.110123+08:00 27 Query SET @master_heartbeat_period = 1000000000
2021-03-14T15:40:02.111290+08:00 27 Binlog Dump GTID Log: '' Pos: 4 GTIDs: '4a2dfc1c-1f50-11eb-a38b-fa057042bc00:1-53,
a4ec8037-1a70-11eb-91ff-fa9f1ef63700:1-1741042'
2. MySQL-> CKのリアルタイムレプリケーション
1.1環境への準備
1、MySQL
- binlogログを有効にし、row_format = row
- gtidモードを使用してコピー
gtid_mode=ON
enforce_gtid_consistency=1
binlog_format=ROW
2、クリックハウス
1)環境パラメータ
-- 该参数默认关闭,若需要使用MaterializeMySQL引擎,必须打开该参数
mdw :) set allow_experimental_database_materialize_mysql=1;
2)レプリケーションチャネルを作成します
-- 语法
CREATE DATABASE ${dbname} ENGINE = MaterializeMySQL('${mysql_ip}:${mysql_port}', '${mysql_dbname}', '${mysql_user}', '${mysql_passoword}');
-- 执行SQL
mdw :) CREATE DATABASE ck_test ENGINE = MaterializeMySQL('172.16.104.13:3306', 'ck_test', 'root', '123');
3)情報をコピーする
MySQLリアルタイムレプリケーション情報の場合、datadirの下のメタデータディレクトリに保存されます。
-- MySQL的binlog位点信息
root@mysql 15:05: [ck_test]> show master status\G
*************************** 1. row ***************************
File: mysql-bin.000005
Position: 4048
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: 4a2dfc1c-1f50-11eb-a38b-fa057042bc00:1-37,
a4ec8037-1a70-11eb-91ff-fa9f1ef63700:1-1741042
1 row in set (0.00 sec)
-- Clickhouse复制位点信息
[root@mdw ck_test]# pwd
/data/clickhouse-server/data/metadata/ck_test
[root@mdw ck_test]# cat .metadata
Version: 2
Binlog File: mysql-bin.000005 //binlog文件
Executed GTID: 4a2dfc1c-1f50-11eb-a38b-fa057042bc00:1-37,a4ec8037-1a70-11eb-91ff-fa9f1ef63700:1-1741042 //GTID信息
Binlog Position: 4048 //binlog位点
Data Version: 9 //数据版本信息,全局递增
1.2基本機能テスト
1.データ書き込みの同期
すべてのMySQLデータについて、CKには対応する_signおよび_versionの非表示フィールドがあり、バージョン管理のマーク付けとクエリに使用されます。、
-- MySQL
root@mysql 14:44: [ck_test]> create table t2(id int primary key not null auto_increment,name varchar(2));
Query OK, 0 rows affected (0.03 sec)
root@mysql 14:45: [ck_test]> insert into t2 values(null,'aa'),(null,'bb');
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
root@mysql 14:45: [ck_test]> select * from t2;
+----+------+
| id | name |
+----+------+
| 1 | aa |
| 2 | bb |
+----+------+
2 rows in set (0.01 sec)
-- Clickhouse
mdw :) select * from ck_test.t2 order by id ;
SELECT *
FROM ck_test.t2
ORDER BY id ASC
┌─id─┬─name─┐
│ 1 │ aa │
└────┴──────┘
┌─id─┬─name─┐
│ 2 │ bb │
└────┴──────┘
2 rows in set. Elapsed: 0.009 sec.
-- Clickhouse隐藏字段查询
mdw :) select *,_sign,_version from ck_test.t2 order by id;
SELECT
*,
_sign,
_version
FROM ck_test.t2
ORDER BY id ASC
┌─id─┬─name─┬─_sign─┬─_version─┐
│ 1 │ aa │ 1 │ 7 │ //一次性写入的_version=7一致,由于是insert操作,_sign=1。
│ 2 │ bb │ 1 │ 7 │
└────┴──────┴───────┴──────────┘
2 rows in set. Elapsed: 0.003 sec.
2.データの更新
MySQLの更新操作では、CKテーブルデータを直接クエリすると、テーブルデータが正常に「更新」されていることがわかりますが、さらに_sign、_version情報をクエリすると、データが物理的に削除されていないことがわかります。更新前。したがって、Clickhouse Update操作の場合、変更されたレコードは実際に書き込まれ、_sign = 1、_version = $ {current version} + 1とマークされます。クエリを実行すると、CKは最終的に通常の結果セット情報として返すのに役立ちます。
-- MySQL
root@mysql 14:45: [ck_test]> select * from t2;
+----+------+
| id | name |
+----+------+
| 1 | aa |
| 2 | bb |
+----+------+
2 rows in set (0.01 sec)
root@mysql 14:47: [ck_test]> update t2 set name='aaa' where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
root@mysql 14:47: [ck_test]> select * from t2;
+----+------+
| id | name |
+----+------+
| 1 | aaa |
| 2 | bb |
+----+------+
2 rows in set (0.01 sec)
-- Clickhouse
mdw :) select * from ck_test.t2 order by id ; //可以看到,正常的查询,CK已经帮我们做了处理
SELECT *
FROM ck_test.t2
ORDER BY id ASC
┌─id─┬─name─┐
│ 1 │ aaa │
└────┴──────┘
┌─id─┬─name─┐
│ 2 │ bb │
└────┴──────┘
2 rows in set. Elapsed: 0.014 sec.
mdw :) select *,_sign,_version from ck_test.t2 order by id;
SELECT
*,
_sign,
_version
FROM ck_test.t2
ORDER BY id ASC
┌─id─┬─name─┬─_sign─┬─_version─┐
│ 1 │ aaa │ 1 │ 8 │ //update更新后的数据被写入ck表,_version+1
└────┴──────┴───────┴──────────┘
┌─id─┬─name─┬─_sign─┬─_version─┐
│ 1 │ aa │ 1 │ 7 │
│ 2 │ bb │ 1 │ 7 │
└────┴──────┴───────┴──────────┘
3 rows in set. Elapsed: 0.008 sec.
3.データの削除
削除操作の場合、CKテーブルデータを直接クエリすると、テーブルデータが正常に「削除」されていることがわかりますが、_sign、_version情報を追加でクエリすると、データが以前に物理的に削除されていないことがわかります。更新、および削除する必要のある行レコードデータの新しい行を追加し、_sign = -1、_version =現在のバージョン+1をマークするため、ckの削除操作では、レコードは物理的に削除されません。直接ですが、記号で削除されます。クエリクエリを実行すると、CKは、バージョン管理に従って最終的に通常の結果セット情報に戻るのに役立ちます。
-- MySQL
root@mysql 14:47: [ck_test]> select * from t2;
+----+------+
| id | name |
+----+------+
| 1 | aaa |
| 2 | bb |
+----+------+
2 rows in set (0.00 sec)
root@mysql 14:48: [ck_test]> delete from t2 where id=2;
Query OK, 1 row affected (0.01 sec)
root@mysql 14:48: [ck_test]> select * from t2;
+----+------+
| id | name |
+----+------+
| 1 | aaa |
+----+------+
1 row in set (0.01 sec)
-- Clickhouse
mdw :) select * from ck_test.t2 order by id ; //query操作正常显示结果集信息
SELECT *
FROM ck_test.t2
ORDER BY id ASC
┌─id─┬─name─┐
│ 1 │ aaa │
└────┴──────┘
1 rows in set. Elapsed: 0.009 sec.
mdw :) select *,_sign,_version from ck_test.t2 order by id;
SELECT
*,
_sign,
_version
FROM ck_test.t2
ORDER BY id ASC
┌─id─┬─name─┬─_sign─┬─_version─┐
│ 1 │ aaa │ 1 │ 8 │
└────┴──────┴───────┴──────────┘
┌─id─┬─name─┬─_sign─┬─_version─┐
│ 1 │ aa │ 1 │ 7 │
│ 2 │ bb │ -1 │ 9 │ //新增删除记录行,并标记_sign=-1表示删除操作
│ 2 │ bb │ 1 │ 7 │
└────┴──────┴───────┴──────────┘
4 rows in set. Elapsed: 0.008 sec.
4、DDL
1)CKテーブルのデータ構造情報については、MaterializeMySQLは当面show create xx構文をサポートしていないため、対応する物理ファイルを介してCKによって作成されたテーブル構造情報を表示できます。
[root@mdw metadata]# cat ck_test
cat: ck_test: 是一个目录
[root@mdw metadata]# cat ck_test.sql
ATTACH DATABASE ck_test
ENGINE = MaterializeMySQL('172.16.104.13:3306', 'ck_test', 'root', '123')
[root@mdw metadata]# cat ck_test/t2.sql
ATTACH TABLE t2
(
`id` Int32,
`name` Nullable(String),
`_sign` Int8 MATERIALIZED 1,
`_version` UInt64 MATERIALIZED 1
)
ENGINE = ReplacingMergeTree(_version)
PARTITION BY intDiv(id, 4294967) //分区键、排序键均由MySQL表数据主键继承
ORDER BY tuple(id)
SETTINGS index_granularity = 8192
2)新しいフィールドのDDL操作
-- MySQL新增表字段
root@mysql 14:48: [ck_test]> alter table t2 add age int;
Query OK, 0 rows affected (0.07 sec)
Records: 0 Duplicates: 0 Warnings: 0
root@mysql 14:52: [ck_test]> select * from t2;
+----+------+------+
| id | name | age |
+----+------+------+
| 1 | aaa | NULL |
+----+------+------+
1 row in set (0.00 sec)
-- Clickhouse表字段信息
[root@mdw metadata]# cat ck_test/t2.sql
ATTACH TABLE t2
(
`id` Int32,
`name` Nullable(String),
`age` Nullable(Int32), //CK表同步MySQL新增字段,对于ck这种列存储来讲,新增字段的操作还是比较简单的
`_sign` Int8 MATERIALIZED 1,
`_version` UInt64 MATERIALIZED 1
)
ENGINE = ReplacingMergeTree(_version)
PARTITION BY intDiv(id, 4294967)
ORDER BY tuple(id)
mdw :) select * from ck_test.t2 order by id ;
SELECT *
FROM ck_test.t2
ORDER BY id ASC
┌─id─┬─name─┬──age─┐
│ 1 │ aaa │ ᴺᵁᴸᴸ │
└────┴──────┴──────┘
1 rows in set. Elapsed: 0.010 sec.
mdw :) select *,_sign,_version from ck_test.t2 order by id;
SELECT
*,
_sign,
_version
FROM ck_test.t2
ORDER BY id ASC
┌─id─┬─name─┬──age─┬─_sign─┬─_version─┐
│ 1 │ aa │ ᴺᵁᴸᴸ │ 1 │ 7 │
│ 1 │ aaa │ ᴺᵁᴸᴸ │ 1 │ 8 │
│ 2 │ bb │ ᴺᵁᴸᴸ │ -1 │ 9 │
│ 2 │ bb │ ᴺᵁᴸᴸ │ 1 │ 7 │
└────┴──────┴──────┴───────┴──────────┘
4 rows in set. Elapsed: 0.023 sec.
3.フォローアップの質問と考え
- Clickhouseがレプリケーションを作成するには、グローバル読み取りロックを取得し、拡張テーブルの全表スキャンクエリを実行する必要があります。これは、リソースを大量に消費する操作です。したがって、ckレプリケーションのソースとしてbinlogとlog_slave_updatesを使用してライブラリからコピーすることをお勧めします。
- ckがレプリケーションチャネルを作成する場合、必要なデータベースユーザーの最小権限はSELECT、REPLICATION SLAVEONです。
- 通常のOLTPビジネスの場合、テーブルデータの変更には依然として頻繁な更新操作があり、すべてのckが冗長な挿入操作を実行します。私たちが懸念している最初のポイントはパフォーマンスです。頻繁なデータ更新によりckは多くのリソースを消費し、2番目のポイントはディスクスペースの消費です。ckはバックグラウンドでの一部のマージ操作で履歴の無効なデータをすばやく削除しますか?
記事の参照:
MySQLからClickHouseへの高速道路-MaterializeMySQLエンジン:
ClickHouseと彼の友人(9)MySQLリアルタイムレプリケーションと実装
CK公式ドキュメント
Clickhouse for Github