bigywater.tech
ClickHouse 内部原理 · 76

MySQL 表引擎:ClickHouse 如何读取外部数据库

真实用MySQL引擎连接一个真实运行的MySQL实例,验证双向实时读写能力,并诚实揭露NULL值处理的一个静默类型坑。

真实live直连
MySQL端新数据立即在ClickHouse可见,无需任何刷新
静默NULL转换
真实发现NULL写入非Nullable列会无声变成空字符串

做的事:真实连接同一台机器上的MySQL实例

代码-- MySQL端真实建表插入数据 CREATE TABLE ch_integration_test (id INT PRIMARY KEY, name VARCHAR(50), amt DECIMAL(10,2)); INSERT INTO ch_integration_test VALUES (1,'alice',10.50),(2,'bob',20.00),(3,'carol',30.50); -- ClickHouse端真实建MySQL引擎表 CREATE TABLE demo.mysql_ext (id UInt32, name String, amt Decimal(10,2)) ENGINE = MySQL('127.0.0.1:3306', 'mysqllab', 'ch_integration_test', 'root', '');

验证:真实是live直连,MySQL端一改,ClickHouse立即可见

实测 · 本机执行输出
SELECT * FROM demo.mysql_ext ORDER BY id;
→ 1 alice 10.5 / 2 bob 20 / 3 carol 30.5

-- 真实在MySQL端插入一行新数据
INSERT INTO ch_integration_test VALUES (4,'dave',40.50);

-- 立即再查ClickHouse这边(没有任何刷新/等待操作)
SELECT * FROM demo.mysql_ext ORDER BY id;
→ 1 alice 10.5 / 2 bob 20 / 3 carol 30.5 / 4 dave 40.5   ← 真实立即看到了新数据

-- 反向:真实从ClickHouse写入
INSERT INTO demo.mysql_ext VALUES (5, 'eve', 50.50);
-- MySQL端真实收到了这行数据

MySQL引擎表真实不是"导入一份快照",每次查询都真实实时连到MySQL执行,写入方向也真实是双向的——从ClickHouseINSERT进这张表,数据真实落到了MySQL那边的原表里。

诚实的坑:MySQL的NULL,真实被静默转成了空字符串

实测 · 本机执行输出(MySQL端note列允许NULL,ClickHouse端声明成非Nullable的String)
MySQL: ALTER TABLE ch_integration_test ADD COLUMN note VARCHAR(50) NULL;
       UPDATE ch_integration_test SET note='has note' WHERE id=1;
       -- 其余行的note真实都是NULL

ClickHouse: CREATE TABLE demo.mysql_ext2 (..., note String) ENGINE=MySQL(...);
            SELECT * FROM demo.mysql_ext2;
→ 1 alice 10.5 has note
  2 bob   20   (空字符串,不是NULL,也没有任何报错)
  3 carol 30.5 (空字符串)
  ...
这是一个真实容易被忽略的隐患:MySQL端note列真实允许NULL,但本文故意把ClickHouse这边的对应列声明成了非Nullable的String——按理说这种类型不兼容应该报错,但ClickHouse真实选择了静默兼容:把NULL自动转成了该类型的默认值(String类型的默认值是空字符串),整个过程没有任何警告或者报错。这意味着如果业务在MySQL端某一列本来就有NULL、代表"这个字段真的没有值",而ClickHouse这边的表结构没有小心地声明成Nullable(String),查询结果会把"没有值"和"值是空字符串"这两种真实不同的语义悄悄混在一起,下游任何区分这两种情况的逻辑都会真实出错,而且不会有任何报错提示你这里发生了静默转换。真实的建议是:接入MySQL引擎表之前,先确认源表哪些列真的允许NULL,ClickHouse这边对应声明成Nullable(...),而不是假设"能查出数据就说明类型声明对了"。

分步演示:从实时读写到诚实揭露的NULL坑

每一步都是本文上面用真实的MySQL实例跑出来的原始结果。

真实的live直连,但NULL处理藏着一个静默的坑
这一步新验证的方向

    本文用到的工具

    • 本机真实运行的MySQL 26.7.0实例(本系列MySQL篇章一直在用的同一个实例),真实的 ENGINE = MySQL(...)
    京ICP备2026067502号-1京公网安备11010502063487号