在 Linux 上装好 MySQL、MariaDB 或 PostgreSQL 的软件包,只是拿到了一个”半成品”:数据目录还没建、系统表还不存在、root 账号要么没密码要么没法用。把这套空壳变成一台能安全提供服务的数据库,中间那一步就叫初始化。新手常卡在这里——报 Access denied、找不到临时密码、或服务直接启动失败。本文按 RHEL 系、Debian 系和 PostgreSQL 三条最常见路径,把初始化的每一步和排错方法讲清楚。
先弄清楚:初始化到底做了什么
不管你用哪个发行版,初始化的本质都是同一件事:创建数据目录,并在里面生成引擎运行所必需的系统表、权限表和时区表。软件包管理器只负责把二进制程序放到磁盘上,数据目录的内容必须由初始化程序生成——这就是为什么”装完就能连”在有些系统上成立、在另一些系统上完全不成立:有的发行版把初始化挂在了安装后脚本里自动执行,有的则留给你手动做。
开始之前确认三件事:数据目录位置(默认 /var/lib/mysql 或 /var/lib/pgsql/data,可在配置文件里改)、运行账户(几乎都是专用的 mysql/postgres 系统用户)、以及磁盘空间——建在快满的分区上会让后续启动直接失败。
RHEL/Rocky/CentOS 系:MariaDB 的手动初始化路径
在 RHEL 系上通过 dnf install mariadb-server 安装后,数据目录通常是空的,服务并不会自动可用。正确顺序是先启动一次服务触发初始化,再去日志里找临时 root 密码:
sudo dnf install mariadb-server
sudo systemctl enable --now mariadb
# 首次启动时生成的临时 root 密码写在这里
sudo grep 'temporary password' /var/log/mariadb/mariadb.log
拿到临时密码后立刻登录并做加固,这一步官方工具 mysql_secure_installation 已经替你串好了:设置 root 正式密码、删除匿名账号、禁止 root 从远程登录、删除默认的 test 库。四个问题全选 yes 是最省事的答法:
mysql -u root -p # 粘贴临时密码,登录后先改密码
sudo mysql_secure_installation
如果数据目录里有上一次失败留下的半套文件,服务会拒绝再次初始化,日志里常见 Do you really specify the right datadir 之类的报错。确认目录里没有任何要保留的数据后,清空 /var/lib/mysql 再重启服务即可重来。
Debian/Ubuntu 系:装完就能连,反而是个坑
Debian 系把初始化做进了包的 postinst 脚本,apt install mariadb-server 结束时数据目录已经建好,服务也起来了。看起来更友好,但它埋了一个新手最容易撞的坑:root 账号默认使用 unix_socket 认证,也就是说 root 能不能登录数据库,取决于你操作系统层面是不是 root,而不是密码对不对。
# 直接 sudo 进 mysql,不需要密码,这是正常现象
sudo mariadb -u root
# 想改回密码认证(确认业务脚本都改用独立账号后再做)
sudo mariadb -e "ALTER USER 'root'@'localhost' IDENTIFIED VIA mysql_native_password USING PASSWORD('强密码'); FLUSH PRIVILEGES;"
很多”我明明设了密码却还提示 Access denied”的帖子,根源就在这里:非 root 的普通用户用 root 加密码去连,socket 认证直接拒绝。建议的做法不是把 root 改回密码登录,而是像 RHEL 那节一样,为应用建立独立账号并只授予需要的库权限,root 只留给 sudo 环境下的维护操作。
PostgreSQL:initdb 要自己跑,或者交给封装脚本
PostgreSQL 的初始化程序叫 initdb,它创建数据目录、生成系统表并设置默认编码与locale。用发行版包管理器安装时,通常有封装好的命令代替手动执行:
# RHEL 系 postgresql-server 包
sudo postgresql-setup --initdb
sudo systemctl enable --now postgresql
# Debian 系则一般自动完成,用 pg_lsclusters 查看实例状态
pg_lsclusters
如果数据目录是空的或不存在,直接跑 initdb 时要以 postgres 用户身份执行,否则目录属主不对,服务起不来:
sudo -u postgres initdb -D /var/lib/pgsql/data --encoding=UTF8 --locale=C
初始化完成后,PostgreSQL 默认只监听本机 socket,且没有任何业务账号。日常入口是切到 postgres 系统用户进 psql,再建角色和库:
sudo -u postgres psql
CREATE ROLE app LOGIN PASSWORD '强密码';
CREATE DATABASE appdb OWNER app;
需要远程连接时再改两个文件:postgresql.conf 里的 listen_addresses,以及 pg_hba.conf 里按网段放行并选择 scram-sha-256 认证,改完 systemctl reload postgresql 生效。
初始化之后,立刻检查这四件事
- 字符集:MySQL/MariaDB 新装默认已是 utf8mb4,但老版本或自定义配置可能还是 latin1,用
SHOW VARIABLES LIKE 'character_set_server';确认,建库时显式写CHARACTER SET utf8mb4。 - 开机自启:初始化成功不等于重启后还在,
systemctl is-enabled逐个确认服务已 enable。 - SELinux:RHEL 系上如果把数据目录改到非默认路径,服务会因标签不对起不来,先看
sudo ausearch -m avc -ts recent再决定改标签还是改回默认路径,不要直接关掉 SELinux。 - 验证登录闭环:用一个刚建的业务账号从预期来源(本机 socket、127.0.0.1、或应用所在网段)实际连一次,能读能写才算初始化真正完成。
常见问题
问:找不到临时密码文件怎么办?
答:不同版本落点不同,依次找 /var/log/mariadb/mariadb.log、/var/log/mysqld.log,或用 journalctl -u mariadb -b 看首次启动的输出。都没有时,可以用跳认证方式重置:停止服务后以 --skip-grant-tables 启动,直接 UPDATE 用户表改密码,改完恢复正常启动。
问:初始化能不能指定别的数据目录?
答:可以。在配置文件的 datadir 指向新路径后,让初始化程序带着 --datadir 参数执行(PostgreSQL 是 initdb -D),并确保目录属主是数据库用户。RHEL 系记得处理 SELinux 上下文,这是自定义路径后服务起不来的头号原因。
问:容器里每次启动都要重新初始化吗?
答:不应该。官方镜像的启动脚本会先检查数据目录是否为空,为空才执行初始化,只要把数据目录挂成数据卷,重启和升级镜像都不会重复初始化;如果每次重启都重跑初始化,多半是忘了挂卷。
小结:初始化的核心动作永远是同一套——建数据目录、生成系统表、拿到第一个可用账号、然后立刻加固。RHEL 系要自己触发并去日志里找临时密码,Debian 系帮你做完了但要小心 socket 认证,PostgreSQL 则记住 initdb 和 pg_hba.conf 两件套。