Metabase 应用数据库配置完全指南:从 PostgreSQL/MySQL 选型到 H2 迁移实战
【免费下载链接】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 的**应用数据库(Application Database)**是存放用户账号、问题(Question)、仪表盘(Dashboard)等全部 Metabase 内部数据的核心存储,它与存放业务数据的数据仓库是两个完全不同的概念。本文基于当前仓库 docs/installation-and-operation/configuring-application-database.md 展开,完整覆盖 PostgreSQL、MySQL/MariaDB、H2 三种应用数据库的配置方法、环境变量详解、SSL 连接注意事项,并结合仓库源码剖析 Metabase 底层如何解析连接信息、如何构建数据源,帮助你为生产环境选型并完成从默认 H2 到生产级数据库的迁移。
什么是应用数据库
Metabase 在运行过程中需要保存两类截然不同的数据:
- 应用数据库(App DB):Metabase 自身产生的内部数据,包括用户账号、问题、仪表盘、集合(Collection)、定时任务、权限设置等。
- 数据仓库(Data Warehouse):你通过 Metabase 连接和分析的业务数据库,连接方式见 Connecting to a supported database。
两者必须区分清楚:配置应用数据库是部署 Metabase 自身的第一步,而连接数据仓库则是后续分析业务的配置项。
Metabase 会在应用启动时读取应用数据库的连接配置,运行期间无法动态更换应用数据库——任何连接信息的修改都需要重启应用(或重新部署容器)才能生效。这是理解后续所有配置方式的前提。
支持的数据库选型
官方文档明确给出的选型建议是:
| 数据库 | 生产建议 | 最低版本要求 | 说明 |
|---|---|---|---|
| PostgreSQL | ✅ 推荐 | 官方支持"最老的仍受支持版本"至最新稳定版 | 生产首选 |
| MySQL / MariaDB | ⚠️ 可用 | MySQL 8.4.0 / MariaDB 10.6.0,必须使用utf8mb4字符集 | 也能支撑生产 |
| H2 | ❌ 仅限本地演示 | 无 | 默认内置,生产环境必须避免 |
另外注意:不支持阿里云 ApsaraDB MySQL,如使用阿里云可改用 ApsaraDB PostgreSQL。
使用 PostgreSQL 作为应用数据库
PostgreSQL 是生产环境的首选。Metabase 支持从"官方仍在支持的最老版本"一直到最新稳定版。
方式一:拆分环境变量
通过一组MB_DB_*环境变量指定连接信息:
export MB_DB_TYPE=postgres export MB_DB_DBNAME=metabase export MB_DB_PORT=5432 export MB_DB_USER=<username> export MB_DB_PASS=<password> export MB_DB_HOST=localhost java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jarMetabase不会帮你创建数据库,需要提前手动创建。使用createdb工具(注意显式指定 UTF-8 编码):
createdb --encoding=UTF8 -e metabase方式二:完整 JDBC 连接串
如果连接包含额外参数(如 SSL、连接超时等),可以直接使用MB_DB_CONNECTION_URI提供完整 JDBC 连接串:
export MB_DB_CONNECTION_URI="jdbc:postgresql://localhost:5432/metabase?user=<username>&password=<password>" java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar方式三:连接串 + 独立账号密码
当密码包含&、?、=等 JDBC 连接串中的特殊字符时,URL 编码容易出错。此时建议只把用户名和密码放入环境变量,与连接串分离。该组合方式自 Metabase 0.43.0 起支持(对应 issue #20122,源码注释见 src/metabase/app_db/env.clj):
export MB_DB_CONNECTION_URI="jdbc:postgresql://localhost:5432/metabase" export MB_DB_USER=<username> export MB_DB_PASS=<password> java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar源码视角:环境变量如何被解析
在 src/metabase/app_db/env.clj 中可以清楚看到连接信息的三种来源及优先级:
- 由
MB_DB_TYPE、MB_DB_HOST、MB_DB_PORT、MB_DB_DBNAME、MB_DB_USER、MB_DB_PASS拆分指定(对应broken-out-details函数); - 由
MB_DB_CONNECTION_URI单条 JDBC 连接串指定(raw-connection-string->DataSource); - 连接串 + 独立的
MB_DB_USER/MB_DB_PASS(0.43.0 起)。
当MB_DB_CONNECTION_URI与拆分变量同时存在时,连接串优先(env->db-type与env->DataSource都优先使用mb-db-connection-uri)。同时,env-defaults方法还内置了默认值::postgres默认localhost:5432,:mysql默认localhost:3306,这意味着即便你不显式设置MB_DB_HOST和MB_DB_PORT,Metabase 也会自动补齐(见 src/metabase/app_db/env.clj)。
在 src/metabase/app_db/data_source.clj 的raw-connection-string->DataSource中还有几处值得注意的兼容处理:
- 连接串以
postgres:开头会被自动改写为postgresql:,缺少jdbc:前缀会自动补齐(兼容 Heroku 等平台传入的裸协议串); - 兼容
jdbc:postgresql://user:password@host:port/db这种 URL 内嵌账号密码的旧写法(issue #14678、#20121); - 当连接串内嵌账号密码与
MB_DB_USER/MB_DB_PASS同时存在时,环境变量中的值优先,且会打印错误日志提示; - 每个新连接都会被显式设置为
READ_COMMITTED事务隔离级别,避免 MySQL/MariaDB 默认的REPEATABLE_READ引发频繁锁表导致性能问题。
使用 MySQL 或 MariaDB 作为应用数据库
虽然官方推荐 PostgreSQL,但 MySQL 与 MariaDB 也支持生产使用。最低推荐版本为MySQL 8.4.0 或 MariaDB 10.6.0,且必须使用utf8mb4字符集。
环境变量配置
export MB_DB_TYPE=mysql export MB_DB_DBNAME=metabase export MB_DB_PORT=3306 export MB_DB_USER=<username> export MB_DB_PASS=<password> export MB_DB_HOST=localhost java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar同样,Metabase 不会自动建库,需要手动执行 SQL(显式指定字符集与排序规则):
CREATE DATABASE metabase CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;JDBC 连接串方式
export MB_DB_CONNECTION_URI="jdbc:mysql://localhost:3306/metabase?user=<username>&password=<password>" java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar与 Postgres 一样,也可以把用户/密码拆出来独立设置(注意官方示例中端口写的是 5432,MySQL 实际应使用 3306):
export MB_DB_CONNECTION_URI="jdbc:mysql://localhost:3306/metabase" export MB_DB_USER=<username> export MB_DB_PASS=<password> java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar源码视角:驱动与默认参数
在 src/metabase/app_db/spec.clj 中可以看到,Metabase 底层实际使用MariaDB 的 JDBC 驱动(org.mariadb.jdbc.Driver)来连接 MySQL 应用数据库,并默认使用OpenSourceSubProtocolOverride避免与 Redshift 驱动冲突。make-subname函数会把 host/port/db 拼接成//host:port/db形式的 subname。
H2 应用数据库(默认,仅限本地演示)
Metabase 默认内置 H2 数据库 明确指出:如果持续使用 H2 且不定期备份,应用数据库可能损坏,导致所有问题、仪表盘、集合数据丢失。
默认行为:自动创建 H2 文件
如果不提供任何应用数据库连接环境变量,Metabase 会在JAR 文件所在目录自动创建 H2 数据库文件。可以通过ls命令查看:
ls metabase.*你会看到以下文件:
metabase.db.h2.db # 或者 metabase.db.mv.db(取决于首次启动 Metabase 的版本) metabase.db.trace.dbmetabase.db.h2.db对应旧的 PageStore 存储引擎,metabase.db.mv.db对应新版默认的 MVStore 引擎。
指定 H2 文件位置
使用MB_DB_TYPE=h2配合MB_DB_FILE指定数据库文件路径:
export MB_DB_TYPE=h2 export MB_DB_FILE=/the/path/to/my/h2.db java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar关键注意点:H2 会自动为路径追加.mv.db或.h2.db后缀,因此MB_DB_FILE不能包含扩展名。也就是说应写/path/to/metabase.db,而不是/path/to/metabase.db.mv.db(即使后者才是实际生成的文件名)。
源码视角:H2 连接细节
src/metabase/app_db/env.clj 揭示了 H2 连接的底层细节:
- 路径会被转换为
file:绝对路径形式(get-db-file函数); - 连接属性包含
DB_CLOSE_DELAY=-1(JVM 关闭前不关闭数据库)、MVCC=true(为 Quartz JDBC 后端启用行级锁支持,避免死锁)、DEFRAG_ALWAYS=true(关闭时碎片整理,可减少数 GB 空间)、LOCK_TIMEOUT=60000(锁等待时间从默认 1 秒延长到 1 分钟); - 当检测到
db-type为:h2时,启动阶段会打印醒目的红色 WARNING,明确提示 H2 不推荐用于生产部署(见 src/metabase/app_db/env.clj)。
从 H2 迁移到生产数据库
如果你已经用默认 H2 创建了内容,Metabase 提供有限的迁移支持:H2 → PostgreSQL。完整迁移步骤(含 JAR 与 Docker 两种方式的命令)见 Migrating to a production application database,核心命令如下:
export MB_DB_TYPE=postgres export MB_DB_CONNECTION_URI="jdbc:postgresql://<host>:5432/metabase?user=<username>&password=<password>" java --add-opens java.base/java.nio=ALL-UNNAMED -jar metabase.jar load-from-h2 /path/to/metabase.db # 不要包含 .mv.db迁移的要点:
- 迁移全程必须使用同一个 Metabase 版本:迁移命令所用的版本、最后写入 H2 文件的版本、以及生产环境的版本必须一致,迁移成功之后再考虑升级;
- 目标数据库必须是全新的空库,Metabase 会自动创建 schema 并搬移数据;
load-from-h2参数路径同样不能带.mv.db后缀;- 迁移前务必备份 H2 文件,参见 Backing up Metabase Application Data。
从源码看,load-from-h2命令实现在 src/metabase/cmd/load_from_h2.clj:它读取 H2 数据源后调用copy/copy!将数据按实体依赖顺序复制到目标库,随后检查加密状态——如果设置了MB_ENCRYPTION_SECRET_KEY而迁移的数据未加密,会立即对目标库执行加密;若 H2 用与当前密钥不同的密钥加密,则直接抛出异常。
从 0.38 之前版本升级的 SSL 注意事项
Metabase 0.38 起移除了 PostgreSQL 连接中NonValidatingFactory的默认使用。如果从旧版本升级,可能在启动时(PostgreSQL 应用数据库)或查询 PostgreSQL 数据仓库时遇到 SSL 校验失败。解决方式有两种:
- 为 PostgreSQL 连接配置 SSL 证书校验(推荐);
- 手动启用
NonValidatingFactory(不安全,仅用于排障或安全要求不高的场景)。
针对 PostgreSQL 应用数据库
使用MB_DB_CONNECTION_URI开启证书校验:
export MB_DB_CONNECTION_URI="postgres://localhost:5432/metabase?user=<username>&password=<password>&sslmode=verify-ca&sslrootcert=<path to CA root or intermediate root certificate>"无法启用证书校验时,可临时启用NonValidatingFactory:
export MB_DB_CONNECTION_URI="postgres://localhost:5432/metabase?user=<username>&password=<password>&ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory"针对 PostgreSQL 数据仓库数据库
在数据仓库的 JDBC 连接串末尾追加以下参数:
&sslmode=verify-ca&sslrootcert=<path to CA root or intermediate root certificate>若仍失败,追加(不安全方案):
&ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory更详细的 SSL 参数可参考 PostgreSQL JDBC 官方 SSL 客户端文档。
源码中的额外提示
Metabase 在 src/metabase/app_db/env.clj 中还会做一项善意检查:如果检测到 Postgres 连接串包含ssl=true但缺少sslmode=require,会打印警告,提示你可能需要在连接串中补充?sslmode=require,否则应用可能无法启动(对应 issue #8908)。
应用数据库环境变量速查
以下参数均在 Environment variables 中有完整定义(该文档由源码clojure -M:ee:doc environment-variables-documentation自动生成):
| 环境变量 | 类型 | 默认值 | 说明 |
|---|---|---|---|
MB_DB_TYPE | string | "h2" | 取值"h2"、"postgres"、"mysql"。为h2时使用MB_DB_FILE,否则使用MB_DB_HOST |
MB_DB_CONNECTION_URI | string | null | JDBC 风格连接串,可替代大部分MB_DB_*变量,优先级最高 |
MB_DB_HOST | string | null | 应用数据库主机名或 IP |
MB_DB_PORT | integer | null | 应用数据库端口(Postgres 默认 5432、MySQL 默认 3306 由源码补齐) |
MB_DB_DBNAME | string | null | 应用数据库名,配合MB_DB_HOST使用 |
MB_DB_USER | string | null | 连接用户名 |
MB_DB_PASS | string | null | 连接密码 |
MB_DB_FILE | string | "metabase.db" | H2 文件路径,不得包含.mv.db/.h2.db后缀;也可用于load-from-h2指定数据来源 |
MB_DB_AUTOMIGRATE | boolean | true | 为false时 Metabase 打印需要手工执行的迁移 SQL 并退出 |
MB_DB_AWS_IAM | boolean | false | (v0.58.0+)通过 AWS IAM 认证连接 AWS RDS/Aurora 上的 PostgreSQL/MySQL,需省略MB_DB_PASS |
MB_DB_AZURE_MANAGED_IDENTITY_CLIENT_ID | string | null | (v0.51.0+)用 Azure 托管身份认证连接 PostgreSQL/MySQL,需省略MB_DB_PASS,属于 Pro/Enterprise 功能 |
MB_DB_SSL_CERT | string | null | (v0.58.0+)MySQL/MariaDB 在 AWS IAM 认证下的 SSL 配置:"trust"或 PEM 证书文件路径 |
补充几个容易踩坑的细节:
MB_DB_CONNECTION_URI中的currentSchema参数无效,PostgreSQL 应用数据库的 schema 必须是public(见 environment-variables.md);- 环境变量的优先级高于Admin 面板中的设置,且环境变量不会写入应用数据库;
- 通过
MB_DB_AUTOMIGRATE=false可查看并手动执行数据库迁移:启动时会输出Database Upgrade Required提示与完整的 Liquibase SQL 脚本,执行完后再正常启动。注意它与 H2→生产库的迁移(load-from-h2)是两回事。
手工执行应用数据库迁移
正常情况下 Metabase 启动时会自动检测并执行应用数据库 schema 变更。如果你想先查看这些变更再手动执行,只需在启动前设置:
export MB_DB_AUTOMIGRATE=false启动后若检测到需要变更,Metabase 会输出类似下面的信息并停止启动:
2015-12-01 12:45:45,805 [INFO ] metabase.db :: Database Upgrade Required NOTICE: Your database requires updates to work with this version of Metabase. Please execute the following sql commands on your database before proceeding. -- ********************************************************************* -- Update Database Script -- ********************************************************************* -- Change Log: migrations/liquibase.yaml ...将输出的 SQL 脚本手动应用到数据库后重启 Metabase 即可。迁移过程遇到问题可参考 Loading from H2 troubleshooting guide。
总结
配置 Metabase 应用数据库的核心要点可以归纳为四条:
- 生产首选 PostgreSQL,通过
MB_DB_TYPE/MB_DB_HOST/MB_DB_PORT/MB_DB_DBNAME/MB_DB_USER/MB_DB_PASS拆分变量或MB_DB_CONNECTION_URI连接串配置,密码含特殊字符时建议将用户密码拆出独立设置; - MySQL/MariaDB 也可用于生产,但必须满足最低版本与
utf8mb4字符集要求; - H2 仅限本地演示,如果已经用了 H2 且内容需要保留,务必先备份再通过
load-from-h2迁移到 PostgreSQL,且全程保持同一版本; - 从 0.38 之前升级时留意 PostgreSQL SSL 校验策略变化,必要时按上文方案显式配置
sslmode或(不安全的)NonValidatingFactory。
更完整的参数列表可查阅 Environment variables,迁移细节见 Migrating to a production application database,生产环境部署建议参考 Running Metabase in production。
【免费下载链接】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),仅供参考