Metabase 连接 MySQL 数据库实战指南:配置详解、MySQL 8 认证兼容与 JSON 字段同步
【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase
本文以 Metabase 开源仓库(当前工作目录metabase/)中的 MySQL 连接官方文档 为主体,结合 MySQL 驱动源码 与相关测试、文档,系统讲解如何在 Metabase 管理界面中配置 MySQL 数据仓库连接、解决 MySQL 8+ 默认认证插件不兼容问题、处理 JSON 字段同步与展开、规避 Vitess 兼容性限制,并厘清模型动作、模型持久化、可编辑表等高级功能对数据库账号权限的要求。
读完本文,你将能够:独立完成一条 MySQL 连接的完整配置与排障;掌握 MariaDB 驱动连接 MySQL 8+ 时的认证插件切换方案;理解 JSON 展开与 500 行 schema 推断机制背后的实现原理;并为可写功能(Actions、模型持久化、表数据编辑)准备具备正确权限的数据库账号。
连接前的准备:版本支持与入口
Metabase 官方支持从 MySQL 社区仍维护的最老版本到最新稳定版本的所有 MySQL 版本(详见文档原话 "the oldest supported version through the latest stable version")。在驱动源码层面,src/metabase/driver/mysql.clj 定义了更精确的最低版本约束:
(def ^:private ^:const min-supported-mysql-version 5.7) (def ^:private ^:const min-supported-mariadb-version 10.2)也就是说,MySQL 5.7 以下、MariaDB 10.2 以下会在建立连接时被检测并打出红色警告日志(WARNING: Metabase only officially supports MySQL 5.7/MariaDB 10.2 and above.,见 warn-on-unsupported-versions)。MariaDB 与 MySQL 共用同一个驱动,因此连接 MariaDB 时同样选择MySQL驱动(见 MariaDB 文档)。
本页讨论的是把 MySQL 当作 Metabase 的数据仓库(data warehouse)来连接。若要把 MySQL 用作 Metabase 自身的应用数据库(application database),请参阅 配置 Metabase 应用数据库。
添加数据库连接的入口:点击右上角网格(grid)图标,依次进入Admin(管理员)>Databases(数据库)>Add a database(添加数据库),数据库类型选择MySQL。
编辑连接详细信息:每个字段的含义与建议
以下字段在建立连接后仍可随时修改,修改后记得保存。
Connection string(连接字符串)
可以粘贴一段连接字符串来预填下方其余字段,适合从已有配置迁移时使用。
Display name(显示名称)
该数据库在 Metabase 界面中的显示名称,建议使用团队可识别的业务名称。
Host(主机)
数据库的 IP 地址或域名,例如esc.mydatabase.com。
Port(端口)
数据库端口,MySQL 默认3306。这也是驱动连接属性表单中的默认占位值(见 connection-properties)。
Username(用户名)
用于连接数据库的账号。可以针对同一数据库使用不同账号建立多条连接,每条连接可拥有不同的 权限集合。
Password(密码)
对应账号的密码。
Use an authentication provider(使用认证提供方)
除了密码,还可以使用受支持的认证提供方进行认证,仅适用于自托管 Pro 与 Enterprise 套餐(文档以 plans-blockquote 标注)。
- IAM authentication(IAM 认证):如需使用 IAM 认证连接 Amazon RDS 实例,参见 AWS RDS 的 IAM 认证。
从驱动源码看,auth-provider为:aws-iam时,连接规格会被改写为 AWS 包装驱动:
(subprotocol "aws-wrapper:mysql" :classname "software.amazon.jdbc.ds.AwsWrapperDataSource" :sslMode "VERIFY_CA" :wrapperPlugins "iam")并强制要求:必须启用 SSL(否则抛异常 "You must enable SSL in order to use AWS IAM authentication"),且sslMode必须为VERIFY_CA(见 connection-details->spec)。
Use a secure connection (SSL)(使用安全连接)
可在此粘贴服务器 SSL 证书链(Server SSL certificate chain,PEM 格式)。源码中证书会被映射为 JDBC 参数serverSslCert(见 default-ssl-cert-details 与连接规格构造逻辑)。若使用 SSL 连接失败,可尝试在附加 JDBC 选项中追加trustServerCertificate=true(见下文排障章节)。
Use an SSH tunnel(使用 SSH 隧道)
通过 SSH 隧道访问数据库,参见 SSH 隧道指南。
Unfold JSON Columns(展开 JSON 列)
MySQL 的JSON类型列可以在 Metabase 中被"展开"为组件字段(component fields):每个 JSON key 变成一列。JSON 展开默认开启,如果性能不佳可以关闭。开启后,还可以在 表元数据 中针对单个列单独切换展开与否。
驱动源码佐证了这一点:database-supports? :nested-field-columns 的实现是(and (driver/common/json-unfolding-default db) (not (mariadb? db)))——即 JSON 展开默认开启,且MariaDB 不支持(MariaDB 没有真正的 JSON 类型,10.2.7 起JSON只是LONGTEXT的别名)。这与 MariaDB 文档 中 "JSON folding is not supported for MariaDB databases" 的表述一致。
在查询执行层面,展开的 JSON 字段通过json_unquote(json_extract(...))生成 SQL,并按目标类型做转换(时间戳走str_to_date、布尔直接返回、浮点用+ 0.0技巧兼容旧版 MySQL,见 json-query 实现)。类型映射上,MySQL 的JSON数据库类型被映射为:type/JSON(见 database-type->base-type)。
Additional JDBC connection string options(附加 JDBC 连接字符串选项)
可以追加 Metabase 连接数据库所用的 JDBC 连接字符串参数,例如占位符中给出的tinyInt1isBit=false——该参数控制tinyint(1)是否被当作布尔(BIT)处理,驱动在同步与查询执行两个阶段都会检查它(见 describe-fields-sql 与 db-type-name)。
驱动内置了一批默认连接参数(见 default-connection-args),供参考:
| JDBC 参数 | 值 | 作用 |
|---|---|---|
zeroDateTimeBehavior | convertToNull | MySQL 合法的0000-00-00日期在 Java 中非法,转换为null |
useUnicode/characterEncoding/characterSetResults | true/UTF8/UTF8 | 强制结果集使用 UTF-8 编码 |
useCompression | true | 在 Metabase 与 MySQL 之间对数据包做 GZIP 压缩 |
useLocalSessionState | true | 本地记录事务隔离级别与自动提交,避免每次查询命中数据库 |
nullCatalogMeansCurrent | true | 同步时仅枚举当前绑定的库,不扫描用户有权限的所有库 |
需要注意:附加选项存在安全过滤。驱动会拒绝allowLoadLocalInfile、allowLoadLocalInfileInPath、allowUrlInLocalInfile、autoDeserialize、serverRSAPublicKeyFile等危险键(见 validate-db-details!),一旦命中会抛出 "Potentially dangerous keys in additional options" 异常。
Re-run queries for simple explorations(简单探索时重跑查询)
默认情况下,只要在Summarize(汇总)菜单中选择分组选项、或在 钻取菜单 中选择过滤条件,Metabase 就会立即执行查询。如果你的数据库较慢,可以关闭此选项,改为让用户先点击Run(播放按钮)再应用 汇总 或过滤选择,避免每次点击都加载数据。
Choose when syncs and scans happen(选择同步与扫描时机)
具体选项说明参见 同步与扫描。开启后可配置:
- 数据库同步频率:每小时(默认)或每天;运行时刻以 Metabase 应用服务器所在时区为准。
- 字段值扫描(filter values):用于在仪表板/问题中启用复选框过滤。可选"按计划定期运行"、"仅在添加新过滤组件时"(按需扫描并缓存)、"从不,需要时手动执行"(配合 手动重扫字段值 按钮使用)。
Periodically refingerprint tables(定期为表重建指纹)
周期性重建指纹会增加数据库负载。
开启后,每次 Metabase 执行 同步 时都会抽样扫描列值。指纹查询会检查每列的前 10,000 行数据,据此估算每列的唯一值数量、数值与时间戳列的最小/最大值等。若关闭,Metabase 只会在初次设置时对列建立一次指纹。
连接 MySQL 8+ 服务器:认证插件兼容性
Metabase 使用MariaDB 驱动连接 MySQL 服务器,而该驱动不支持 MySQL 8 的默认认证插件caching_sha2_password。要连接 MySQL 8+,需要把 Metabase 所用账号的认证插件切换为mysql_native_password:
ALTER USER 'metabase'@'%' IDENTIFIED WITH mysql_native_password BY 'thepassword';如果密码中包含了 MySQL 无法以 UTF-8 直接理解的字符,可能需要在附加 JDBC 选项中追加passwordCharacterEncoding=<你的编码>(例如passwordCharacterEncoding=ISO-8859-1),确保认证时 MySQL 能正确解析密码中的特殊字符(见 Passwords with special characters)。
无法用正确的凭据登录(Unable to log in with correct credentials)
如何识别:Metabase 报错 "Looks like the username or password is incorrect",但你确信用户名和密码正确。原因可能是:你创建的 MySQL 用户所允许的主机(host)与你实际连接的主机不一致。
典型场景:MySQL 跑在 Docker 容器里,而metabase用户是用CREATE USER 'metabase'@'localhost' IDENTIFIED BY 'thepassword';创建的。此时localhost会被解析为 Docker 容器本身,而不是宿主机,导致访问被拒绝。
在 Metabase 服务日志中会出现类似错误:
Access denied for user 'metabase'@'172.17.0.1' (using password: YES).注意其中的主机名172.17.0.1(此处是 Docker 网络 IP),以及结尾的using password: YES。用命令行客户端也会得到相同错误:mysql -h 127.0.0.1 -u metabase -p。
如何修复:用正确的主机名重建 MySQL 用户:
CREATE USER 'metabase'@'172.17.0.1' IDENTIFIED BY 'thepassword';必要时也可用通配符%作为主机名:
CREATE USER 'metabase'@'%' IDENTIFIED BY 'thepassword';然后为该用户授权(以只读 SELECT 为例):
GRANT SELECT ON targetdb.* TO 'metabase'@'172.17.0.1'; FLUSH PRIVILEGES;记得删除旧用户:
DROP USER 'metabase'@'localhost';如果用户、主机、密码都正确仍然连不上,可以在附加 JDBC 选项中追加trustServerCertificate=true。该选项告诉驱动:即使服务器证书缺少根证书也信任它,从而建立安全连接。值得注意的是,驱动日志会在未显式配置该选项而启用 SSL 时打印提示:"You may need to add 'trustServerCertificate=true' to the additional connection options to connect with SSL."(见 connection-details->spec)。
另外,驱动会把常见的连接错误人性化为可读提示(见 humanize-connection-error-message):
| 原始错误 | 人性化提示 |
|---|---|
Communications link failure ... | 无法连接,请检查主机和端口 |
Unknown database ... | 数据库名称不正确 |
Access denied for user... | 用户名或密码不正确 |
Must specify port after ':' in connection string | 主机名不合法 |
启动 MySQL 8+ Docker 容器
如果你要新建一个 MySQL 容器,并且:
- 希望 Metabase 无需手动创建用户或切换认证机制即可连接;
- 或遇到了
RSA public key is not available client side (option serverRsaPublicKeyFile not set)错误;
可以在运行容器时追加--default-authentication-plugin=mysql_native_password启动参数。
简单的docker run方式:
docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=xxxxxx mysql:8.xx.xx --default-authentication-plugin=mysql_native_password或在 docker-compose 中:
mysql: image: mysql:8.xx.xx container_name: mysql hostname: mysql ports: - 3306:3306 environment: - "MYSQL_ROOT_PASSWORD=xxxxxx" - "MYSQL_USER=metabase" - "MYSQL_PASSWORD=xxxxxx" - "MYSQL_DATABASE=metabase" volumes: - $PWD/mysql:/var/lib/mysql command: ["--default-authentication-plugin=mysql_native_password"]注意:mysql_native_password在 MySQL 8.4 及以后版本默认被移除(deprecated → removed),生产环境更推荐按前文所述只对 Metabase 账号单独执行ALTER USER ... IDENTIFIED WITH mysql_native_password,或评估升级驱动的可行性。
同步包含 JSON 的记录:500 行 schema 推断机制
Metabase 会根据表的前五百行数据中出现的 JSON key 来推断 JSON 的"schema"。MySQL 的 JSON 字段本身没有 schema,Metabase 无法依靠表元数据来确定 JSON 字段包含哪些 key。作为变通,Metabase 会取前 500 条记录并解析其中的 JSON 来推断"schema"。之所以限制为 500 条,是为了避免同步元数据给数据库带来不必要的压力。
由此带来的问题是:如果 JSON 中的 key 逐条记录变化,前 500 行可能无法覆盖该 JSON 字段用到的全部 key。要让 Metabase 推断出所有 key,需要把缺失的 key 补充进前 500 行的 JSON 对象中(例如临时插入包含这些 key 的样例记录,完成同步后再删除)。
这与 MariaDB 形成对比:由于 MySQL 与 MariaDB 实现上的差异,JSON schema 推断在 MariaDB 上不生效(见 MariaDB 文档)。
Vitess 系数据库的已知限制
查询 Vitess 数据库(如 PlanetScale)时,应在每个子查询内添加
LIMIT子句。原因:Metabase 通常会对最终查询结果施加行数限制(如 2000 或 10000 行)。但由于 Vitess 的一个已知 bug,Vitess 可能把这些限制施加到子查询上,导致意外结果(例如 Metabase 内不能显示全部结果行)。变通办法就是在每个子查询中显式添加限制。还应与平台托管方确认:Vitess 在返回 information_schema 元数据时可能出问题。Metabase 需要这些元数据来填充其应用数据库;如果拿不到元数据,字段可能不显示或显示为空。
驱动源码同样体现了对 PlanetScale/Vitess 的关注:同步表清单时不能传入getCatalog()的结果,因为 Vitess 副本连接上getCatalog()会返回路由限定名<db>@replica,导致WHERE TABLE_SCHEMA = '<db>@replica'匹配不到任何行、同步到空库。因此驱动固定依赖nullCatalogMeansCurrent=true并传入nilcatalog(见 active-tables 与 default-connection-args)。
可写能力:Writable connection 与账号权限要求
Writable connection(可写连接)
可另外设置一条专用于写操作的连接,参见 可写连接。
Model features(模型相关功能)
选择是否启用与 Metabase 模型 相关的功能。这些功能通常要求用于连接的数据库账号同时具备读和写权限。
- Model actions(模型操作):开启后允许对基于该数据创建的模型执行 操作(Actions)。Actions 可以读取、写入和删除数据,因此数据库用户需要写权限。驱动层面,
actions、actions/custom、actions/data-editing三个特性仅在驱动为:mysql时启用(见 database-supports? 扩展),相关实现位于 mysql/actions.clj。 - Model persistence(模型持久化):Metabase 会创建存放模型数据的表,并按你定义的调度定期刷新。要启用 模型持久化,需要授予该连接凭据在 Metabase 提供的 schema 上的读写权限。驱动特性表中
:persist-models true表明该能力受支持(见 特性声明)。
Editable table data(可编辑表数据)
开启后,管理员可以直接在 Metabase 界面中创建、更新、删除表中的记录。这要求连接数据库的账号具备相应表的写权限。参见 权限。
驱动会通过SHOW GRANTS解析当前用户的表级权限(SELECT/UPDATE/INSERT/DELETE),用于判断表是否可写(见 current-user-table-privileges 与 parse-grant)。注意 MariaDB 因不允许普通用户查询角色权限而被跳过;此外,由于 MySQL 部分撤销(partial revokes)场景的解析错误(metabase#38499),表权限特性整体被禁用(见 database-supports? :table-privileges),可写性判定基于元数据表检查实现。
另外,uploads特性在 MySQL 上开启(见 特性声明),支持通过 CSV 上传建表;当 MySQL 全局变量local_infile为ON时,写入走LOAD DATA LOCAL INFILE批量导入,否则回退到普通INSERT INTO(见 insert-into!)。
进阶:Database routing(数据库路由)
启用数据库路由后,管理员可以用一个数据库构建问题(question),而该问题会根据查看者身份,针对具有相同 schema 的另一个数据库执行查询。参见 数据库路由。驱动特性表中:database-routing true(见 特性声明)确认 MySQL 驱动支持该能力。
Danger zone(危险区域)
涉及删除数据库等危险操作,参见 Danger zone。
驱动能力一览:理解 MySQL 连接的上限
结合 MySQL 驱动源码,以下是该驱动声明的关键特性能力(节选),有助于判断哪些功能可在此连接上使用:
| 特性 | 是否支持 | 说明 |
|---|---|---|
connection-impersonation | 是 | 支持连接模拟(需要角色,connection-impersonation-requires-role) |
convert-timezone/datetime-diff | 是 | 时区转换与日期差函数,基于convert_tz、timestampdiff实现 |
full-join | 否 | MySQL 不支持 FULL JOIN |
window-functions/offset | 否 | MySQL 不支持在含GROUP BY的查询中直接使用 lag/lead 实现 offset |
persist-models | 是 | 模型持久化 |
schemas | 否 | MySQL 无 schema 层(其 database 即其他引擎的 schema,驱动将:db槽位用于跨库路由) |
uploads | 是 | CSV 上传建表 |
case-sensitivity-string-filter-options | 否 | LIKE 大小写敏感度由服务器/列排序规则决定,不提供 UI 开关 |
nested-field-columns | 是(MySQL)/ 否(MariaDB) | JSON 展开 |
index/fetch、index/standalone-create | 是 | 索引管理(B-Tree 与 Full-text,见 supported-index-methods) |
database-routing | 是 | 数据库路由 |
同步相关实现也值得留意:驱动从information_schema.columns读取字段元数据(排除information_schema、performance_schema、sys、mysql等系统库及innodb_table_stats、innodb_index_stats表,见 describe-fields-sql);MySQL 的DATETIME被映射为:type/DateTime、TIMESTAMP被映射为:type/DateTimeWithLocalTZ(以 UTC 存储)、YEAR映射为整数、TINYINT默认按布尔处理(见 database-type->base-type)。若时区相关查询异常,可能需要把系统时区表导入 MySQL:mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql(见 set-timezone-sql 注释)。
进一步阅读
- MariaDB 连接指南(与 MySQL 共用驱动,注意其 JSON 展开与 schema 推断的差异)
- 管理数据库
- 元数据编辑(含单列 JSON 展开开关)
- JSON 展开详解
- 模型
- 设置数据访问权限
- 同步与扫描
- 驱动实现:src/metabase/driver/mysql.clj、src/metabase/driver/mysql/actions.clj、src/metabase/driver/mysql/ddl.clj;测试基座:test/metabase/test/data/mysql.clj
【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考