目标:统一理解「初始化」= 创建库、创建用户、授权、初始化表结构、基础种子数据;区分裸机 Linux、Windows、Docker、K8s、信创平台、云数据库,覆盖 MySQL / PostgreSQL / OpenGauss / Redis / MongoDB。 下面按平台分类,给可直接复制的脚本,同时区分一次性初始化(init)和持久化规则。
前置通用原则(所有平台都适用)
初始化脚本幂等:优先
IF NOT EXISTS,避免重复执行报错密码不要硬写在脚本,优先环境变量、secret、.env
区分:服务启动初始化(容器自带 init 机制) 和 手动离线初始化
生产环境:初始化脚本版本管理(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 工具
DBeaver:新建连接 → 打开 SQL 编辑器,执行初始化脚本
适合开发调试;生产 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 机制,两种方案:
自定义镜像:写 entrypoint 脚本,判断数据目录是否为空,为空则执行 gsql 初始化
外部脚本:容器启动后,单独调用
gsql -h 127.0.0.1 -U xxx -d postgres -f init.sql
重点:OpenGauss 默认不支持简单的 init 目录,这点和 MySQL/PG 不一样
四、Kubernetes 平台初始化
K8s 不依赖容器内置 init,主流 3 种方案:
InitContainer(推荐):独立初始化容器,等 DB 就绪后执行 SQL,跑完退出
Job 一次性初始化任务(可重跑,适合 Flyway/Liquibase)
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 目录 初始化方式:
云控制台:Web SQL 编辑器(阿里云 DMS、腾讯云 DMC)执行初始化 SQL
客户端远程连接:DBeaver / 脚本在 CI 服务器执行
云函数 / 流水线:CI 流程中调用 sql 脚本
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 / 达梦 / 人大金仓)
信创数据库重点差异:
达梦 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`
人大金仓:
ksql,语法贴近 PGOpenGauss:
gs_initdb(实例)、gsql(业务库 DDL)
信创容器:大多自研 iSulad,替代 docker;初始化逻辑:
iSulad 容器同样没有内置 /docker-entrypoint-initdb.d,必须外置脚本或 init 容器
七、不同平台初始化方案对比表
八、生产级最佳实践(跨平台统一规范)
不要手写一次性 DDL 上线,统一迁移工具:Flyway(SQL 优先) / Liquibase(支持多数据库方言)
所有密码:环境变量、K8s Secret、Vault,禁止写死 SQL
脚本幂等:
IF NOT EXISTS、先判断对象是否存在区分两层:
实例层初始化(
gs_initdb/dminit,只做一次)业务库层初始化(建库、用户、表、种子,迁移工具管理)
CI 流水线集成:提交代码自动跑迁移,开发、测试、生产流程一致
本文原创作者:易君召,详见:https://www.yijunzhao.cc/about,转载请注明出处。
原文链接
欢迎访问