小易说IT 小易说IT

多平台数据库初始化方案

目标:统一理解「初始化」= 创建库、创建用户、授权、初始化表结构、基础种子数据;区分裸机 Linux、Windows、Docker、K8s、信创平台、云数据库,覆盖 MySQL / PostgreSQL / OpenGauss / Redis / MongoDB。 下面按平台分类,给可直接复制的脚本,同时区分一次性初始化(init)和持久化规则。

前置通用原则(所有平台都适用)

  1. 初始化脚本幂等:优先 IF NOT EXISTS,避免重复执行报错

  2. 密码不要硬写在脚本,优先环境变量、secret、.env

  3. 区分:服务启动初始化(容器自带 init 机制) 和 手动离线初始化

  4. 生产环境:初始化脚本版本管理(Flyway / Liquibase),不裸写大量 DDL

一、Linux 裸机(CentOS /openEuler/ Debian / Ubuntu)

适用:rpm/deb 安装的数据库,systemd 托管

MySQL 8 示例

# 1. 连接mysql(root)
mysql -uroot -p"$MYSQL_ROOT_PASSWORD"

-- 初始化SQL
CREATE DATABASE IF NOT EXISTS demo DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS 'demo_user'@'%' IDENTIFIED BY '${DEMO_PASS}';
GRANT ALL PRIVILEGES ON demo.* TO 'demo_user'@'%';
FLUSH PRIVILEGES;
USE demo;
SOURCE /opt/sql/init_table.sql;
SOURCE /opt/sql/seed_data.sql;

自动化脚本 init_mysql.sh

#!/bin/bash
set -e
MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
mysql -uroot -p"${MYSQL_ROOT_PASSWORD}" <<EOF
CREATE DATABASE IF NOT EXISTS demo DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS 'demo_user'@'%' IDENTIFIED BY '${DEMO_PASS}';
GRANT ALL ON demo.* TO 'demo_user'@'%';
FLUSH PRIVILEGES;
EOF
# 导入表和种子数据
mysql -udemo_user -p"${DEMO_PASS}" demo < /opt/sql/init_table.sql

PostgreSQL / OpenGauss

# 切换到postgres用户
su - postgres
psql

CREATE DATABASE demo;
CREATE USER demo_user WITH PASSWORD '${DEMO_PASS}';
GRANT ALL PRIVILEGES ON DATABASE demo TO demo_user;
\c demo
\i /opt/sql/init_table.sql

OpenGauss 注意:权限模型更严格,需要 gsql 代替 psql,gs_initdb 是实例初始化命令(底层库初始化,业务库不是这个)

二、Windows 平台(本地开发,MySQL/PG/OpenGauss)

两种方式:命令行 + GUI(DBeaver/Navicat)

方式 1:cmd/powershell 直接执行

$rootPass="xxx"
mysql -uroot -p$rootPass -e "CREATE DATABASE IF NOT EXISTS demo DEFAULT CHARACTER SET utf8mb4;"
mysql -udemo_user -p$demoPass demo < D:\sql\init_table.sql

Windows MySQL 注意:默认 mysql.exe 不在 PATH,要写全路径 C:\Program Files\MySQL\MySQL Server 8.0\bin\mysql.exe

方式 2:GUI 工具

  1. DBeaver:新建连接 → 打开 SQL 编辑器,执行初始化脚本

  2. 适合开发调试;生产 Windows Server 不推荐 GUI 初始化

国产 OpenGauss Windows 版本较少,一般 Windows 只做客户端,数据库跑 Linux

三、Docker 初始化(最常用!MySQL/PG/Mongo)

✅ 核心机制:容器启动时,自动执行 /docker-entrypoint-initdb.d/ 下的 .sql / .sql.gz / .sh

只在第一次启动、数据卷为空的时候执行!已有数据卷不会重复跑(非常关键)

MySQL docker-compose.yml 示例

version: '3.8'
services:
  mysql:
    image: mysql:8.0
    container_name: mysql-demo
    environment:
      MYSQL_ROOT_PASSWORD: ${ROOT_PASS}
      MYSQL_DATABASE: demo
      MYSQL_USER: demo_user
      MYSQL_PASSWORD: ${DEMO_PASS}
    volumes:
      - ./mysql-data:/var/lib/mysql
      - ./init:/docker-entrypoint-initdb.d
    ports:
      - "3306:3306"

目录结构

./init/
  01_create_user.sql
  02_table.sql
  03_seed.sql

命名带序号,保证执行顺序;卷清空才会重跑初始化

PostgreSQL Docker

PG 同样支持 /docker-entrypoint-initdb.d/

services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: demo
      POSTGRES_USER: demo_user
      POSTGRES_PASSWORD: ${DEMO_PASS}
    volumes:
      - ./pgdata:/var/lib/postgresql/data
      - ./init:/docker-entrypoint-initdb.d

OpenGauss Docker(自研镜像)

官方镜像不自带 initdb.d 机制,两种方案:

  1. 自定义镜像:写 entrypoint 脚本,判断数据目录是否为空,为空则执行 gsql 初始化

  2. 外部脚本:容器启动后,单独调用 gsql -h 127.0.0.1 -U xxx -d postgres -f init.sql

重点:OpenGauss 默认不支持简单的 init 目录,这点和 MySQL/PG 不一样

四、Kubernetes 平台初始化

K8s 不依赖容器内置 init,主流 3 种方案:

  1. InitContainer(推荐):独立初始化容器,等 DB 就绪后执行 SQL,跑完退出

  2. Job 一次性初始化任务(可重跑,适合 Flyway/Liquibase)

  3. Sidecar(不推荐)

InitContainer 示例思路

spec:
  containers:
  - name: mysql
    image: mysql:8
  initContainers:
  - name: init-db
    image: mysql:8
    command: ["/bin/sh","-c"]
    args:
    - |
      until mysql -h mysql -uroot -p${ROOT_PASS} -e "select 1"; do sleep 2; done
      mysql -h mysql -uroot -p${ROOT_PASS} < /sql/init.sql
    volumeMounts:
    - name: init-sql
      mountPath: /sql
  volumes:
  - name: init-sql
    configMap:
      name: db-init-sql

生产最佳实践:用 Liquibase/Flyway 做 K8s Job

把 DDL 版本化,Job 每次启动自动迁移,幂等,支持多次发布,是云原生标准方案,而不是裸脚本。

apiVersion: batch/v1
kind: Job
metadata:
  name: liquibase-migrate
spec:
  template:
    spec:
      containers:
      - name: liquibase
        image: liquibase/liquibase
        command: ["liquibase","--changelog-file=changelog.xml","update"]
      restartPolicy: OnFailure

五、云数据库(RDS、云 PG、云 OpenGauss)

云数据库底层实例由云厂商托管,不能登录宿主机、不能挂载 docker init 目录 初始化方式:

  1. 云控制台:Web SQL 编辑器(阿里云 DMS、腾讯云 DMC)执行初始化 SQL

  2. 客户端远程连接:DBeaver / 脚本在 CI 服务器执行

  3. 云函数 / 流水线:CI 流程中调用 sql 脚本

  4. Terraform / Pulumi:IaC 定义数据库、账号、权限(推荐基础设施即代码)

Terraform MySQL RDS 示例片段:

resource "aws_db_instance" "demo" {
  engine = "mysql"
}
resource "aws_db_query" "init" {
  depends_on = [aws_db_instance.demo]
  sql = <<SQL
CREATE DATABASE IF NOT EXISTS demo;
SQL
}

注意:云库默认有安全组、白名单;初始化机器 IP 必须放行

六、信创平台(银河麒麟、openEuler + OpenGauss / 达梦 / 人大金仓)

信创数据库重点差异:

  1. 达梦 DM:disql 客户端,实例初始化 dminit

# 达梦创建实例(底层初始化)
dminit PATH=/dmdata DB_NAME=demo INSTANCE_NAME=DMDemo PORT_NUM=5236
# 业务初始化
disql SYSDBA/SYSDBA@localhost:5236 `start /opt/sql/init.sql`
  1. 人大金仓:ksql,语法贴近 PG

  2. OpenGauss:gs_initdb(实例)、gsql(业务库 DDL)

信创容器:大多自研 iSulad,替代 docker;初始化逻辑:

  • iSulad 容器同样没有内置 /docker-entrypoint-initdb.d,必须外置脚本或 init 容器

七、不同平台初始化方案对比表

平台

载体

初始化机制

适合数据库

注意点

Linux 裸机

shell 脚本

手动 / 定时执行

MySQL/PG/OG/ 达梦

注意密码泄露,加 set -e

Windows

powershell/cmd

客户端执行

MySQL/PG

路径分隔符、PATH

Docker

容器

/docker-entrypoint-initdb.d(首次空卷执行)

MySQL/PG/Mongo

已有数据卷不会重复执行

K8s

InitContainer / Job

就绪探测 + 迁移工具

全部

优先 Flyway/Liquibase,不要裸脚本

云 RDS

DMS/CI 脚本 / IaC

远程 SQL 执行

云 MySQL/PG/OG

白名单、不要硬编码账号

信创 OS

iSulad / 裸机

自研客户端脚本

达梦、金仓、OpenGauss

无 docker-init 机制,命令行特殊

八、生产级最佳实践(跨平台统一规范)

  1. 不要手写一次性 DDL 上线,统一迁移工具:Flyway(SQL 优先) / Liquibase(支持多数据库方言)

  2. 所有密码:环境变量、K8s Secret、Vault,禁止写死 SQL

  3. 脚本幂等:IF NOT EXISTS、先判断对象是否存在

  4. 区分两层:

    • 实例层初始化(gs_initdb / dminit,只做一次)

    • 业务库层初始化(建库、用户、表、种子,迁移工具管理)

  5. CI 流水线集成:提交代码自动跑迁移,开发、测试、生产流程一致


本文原创作者:易君召,详见:https://www.yijunzhao.cc/about,转载请注明出处。

原文链接 https://www.yijunzhao.cc/archives/multi-platform-database-initialization-solution

欢迎访问 https://www.yijunzhao.cc/

https://www.yijunzhao.cc/