MariaDB 基础教程:从安装到主从复制
MariaDB 是 MySQL 的社区分支,语法几乎完全兼容 MySQL。你在 MySQL 上学到的命令、配置、主从复制思路,绝大部分都能直接平移到 MariaDB 上,反之亦然。
本篇基于 CentOS 7 环境,从零带你走完一条完整的链路:
学完这一篇,你就拥有了搭建一个「能跑、安全、可扩展」的 MariaDB 服务的能力。
实验环境
| mariadb-server | 10.1.8.10/24 | 数据库服务端 |
| mariadb-client | 10.1.8.11/24 | 数据库客户端 |
在后面的「主从复制」章节,会换两台新机器:
| mariadb-server1 | 10.1.8.10/24 | 主库(Master) |
| mariadb-server2 | 10.1.8.11/24 | 从库(Slave) |
一、安装 MariaDB
1. 基础环境配置
装库之前,先给机器起个像样的主机名,并配置静态 IP——这是运维基本功,方便后续远程连接和主从通信。
服务端(mariadb-server):
hostnamectl set-hostname mariadb-server
nmcli connection modify ens33 ipv4.method manual \\
ipv4.addresses 10.1.8.10/24 \\
ipv4.gateway 10.1.8.2 \\
ipv4.dns 10.1.8.2 \\
autoconnect yes
nmcli connection up ens33
客户端(mariadb-client):
hostnamectl set-hostname mariadb-client
nmcli connection modify ens33 ipv4.method manual \\
ipv4.addresses 10.1.8.11/24 \\
ipv4.gateway 10.1.8.2 \\
ipv4.dns 10.1.8.2 \\
autoconnect yes
nmcli connection up ens33
小贴士:nmcli 是 CentOS 7 的网络管理命令。ipv4.method manual 表示手动配置静态 IP;autoconnect yes 表示开机自动连接。
2. yum 安装与启动
# CentOS 7 使用 yum 安装(服务端需要 mariadb + mariadb-server,客户端只需 mariadb)
[root@mariadb-server ~]# yum install -y mariadb mariadb-server
# 启动服务
[root@mariadb-server ~]# systemctl start mariadb
# 设置开机自启
[root@mariadb-server ~]# systemctl enable mariadb
# 查看运行状态
[root@mariadb-server ~]# systemctl status mariadb
说明:mariadb 是客户端命令工具,mariadb-server 是服务端。服务端机器才需要装 mariadb-server;客户端机器只装 mariadb 就能远程连接。
3. 安全初始化(必做!)
刚装好的 MariaDB 有三个隐患:root 密码为空、存在匿名用户、自带 test 测试库。这些在生产环境都是安全大坑,所以装完之后第一件事,就是运行安全脚本:
[root@mariadb-server ~]# mysql_secure_installation
脚本会通过一串交互式提问来加固数据库,逐条按下表选择:
| 1 | Enter current password for root (enter for none) | 直接回车 | 新装无 root 密码 |
| 2 | Set root password? | y | 设置 root 密码 |
| 3 | Remove anonymous users? | y | 删除匿名用户 |
| 4 | Disallow root login remotely? | y | 禁止 root 远程登录 |
| 5 | Remove test database and access to it? | y | 删除 test 测试库 |
| 6 | Reload privilege tables now? | y | 立即刷新权限 |
关键交互过程如下:
Enter current password for root (enter for none): # 回车,无 root 密码
Set root password? [Y/n] y # 设置 root 密码
New password:
Re-enter new password:
Password updated successfully!
Remove anonymous users? [Y/n] y # 删除匿名用户
Disallow root login remotely? [Y/n] y # 禁止 root 远程登录
Remove test database and access to it? [Y/n] y # 删除 test 库
Reload privilege tables now? [Y/n] y # 刷新权限
All done! …
为什么每一步都要做?
- 删匿名用户:否则任何人都能免密登录;
- 禁 root 远程登录:防止 root 密码被网络暴力破解;
- 删 test 库:它默认任何人都能访问。
4. 登录数据库
# 本地登录
[root@mariadb-server ~]# mysql -uroot -p
Enter password: # 输入刚才设置的密码(本教程后续统一用 huawei)
登录成功后,就进入了 MariaDB 的命令行交互界面:
Welcome to the MariaDB monitor. Commands end with ; or \\g.
MariaDB [(none)]>
二、基础 SQL 命令
铁律:每条 SQL 语句结尾必须以分号 ; 结束。不写分号,MariaDB 会以为你还没输完,一直等你继续输入。
1. 库操作(Database)
— 登录(带主机和端口)
mysql –uroot –p –h127.0.0.1 –P3306
— 查看所有数据库
show databases;
— 创建数据库
create database school;
— 创建数据库并指定字符集(推荐 utf8mb4,支持 emoji 表情)
create database school2 default character set utf8mb4 collate utf8mb4_general_ci;
— 使用(切换)数据库
use school;
— 查看当前所在库
select database();
— 删除数据库
drop database school2;
为什么要指定字符集?
默认字符集是老旧的 latin1,一旦存储中文或 emoji 就会乱码。建库时直接指定 utf8mb4 是最省心的做法——utf8mb4 是 utf8 的完整超集,支持所有 emoji 表情。
2. 表操作(Table)
— 查看当前库所有表
show tables;
— 创建表
create table student(
id int primary key auto_increment, — 主键,自增
name varchar(20), — 姓名
age int — 年龄
);
— 查看表结构
desc student;
— 查看建表语句
show create table student;
— 删除表
drop table student2;
desc student 的输出含义:
| Field | 字段名 |
| Type | 字段类型 |
| Null | 是否允许为空 |
| Key | 键类型(PRI = 主键) |
| Default | 默认值 |
| Extra | 附加属性(如 auto_increment 自增) |
3. DML 增删改查
DML(Data Manipulation Language,数据操纵语言)就是常说的「增删改查」:
— 插入数据(一次性插入多条)
insert into student(name, age) values
('zhangsan', 18),
('lisi', 20);
— 查询全部
select * from student;
— 条件查询(年龄大于 18 的)
select * from student where age > 18;
— 更新(把 id=1 的年龄改成 19)
update student set age = 19 where id = 1;
— 删除(删除 id=2 的记录)
delete from student where id = 2;
记忆口诀:增 INSERT、删 DELETE、改 UPDATE、查 SELECT。其中 SELECT 最常用也最灵活,WHERE 是它的灵魂——不会用 WHERE,等于开车不会踩刹车。
4. 用户与权限
— 创建用户(只允许本机登录)
create user 'admin'@'localhost' identified by '123456';
— 创建用户(允许任意地址远程登录)
create user 'admin'@'%' identified by '123456';
create user 'test'@'%' identified by '123456';
— 查看所有账号
select user, host from mysql.user;
— 授权:把 school 库的所有权限给 admin
grant all privileges on school.* to 'admin'@'%';
— 刷新权限
flush privileges;
— 查看某用户的权限
show grants for 'admin'@'%';
— 删除用户
drop user 'test'@'%';
权限粒度(重点):
- *.* —— 所有库的所有表;
- school.* —— school 库的全部表。
授权时要遵循「最小权限原则」:用多少给多少,别动不动就 *.*。
远程登录测试(在客户端机器上):
# 客户端安装 MariaDB 客户端
[root@mariadb-client ~]# yum install mariadb -y
# 用 admin 账号远程连接服务端
[root@mariadb-client ~]# mysql -uadmin -p123456 -h10.1.8.10 -P3306
三、配置文件
MariaDB 的配置集中在 /etc/my.cnf 及其子目录:
| /etc/my.cnf | 主配置文件 |
| /etc/my.cnf.d/*.cnf | 子配置目录(按模块拆分) |
| /etc/my.cnf.d/server.cnf | 服务端常用配置片段 |
常用的 [mysqld] 配置项:
[mysqld]
# 数据库 id:主从复制必须不一样,单机随便写
server-id=1
# 数据目录
datadir=/var/lib/mysql
# 监听地址:0.0.0.0 允许远程访问
bind-address=0.0.0.0
# 默认字符集
character-set-server=utf8mb4
# 开启 binlog(主从复制需要)
log_bin=mysql-bin
binlog_format=mixed
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
| server-id | 服务器唯一编号,主从复制时每个节点必须不同 |
| datadir | 数据文件存放目录 |
| bind-address | 监听地址,0.0.0.0 表示接受任意来源连接 |
| character-set-server | 服务端默认字符集 |
| log_bin | 开启二进制日志(主从复制、数据恢复的核心) |
| binlog_format | binlog 格式(statement / row / mixed) |
修改配置后,必须重启服务才能生效:
systemctl restart mariadb
防火墙别忘了! 否则外部机器根本连不上 3306 端口:
firewall-cmd –add-port=3306/tcp –permanent
firewall-cmd –reload
四、主从复制基础(一主一从)
1. 什么是主从复制?
主从复制是指:主库(Master)把数据变更以日志形式传输给从库(Slave),从库重放日志实现数据一致。
一句话理解:主库负责「写」,从库负责「读」,两者数据保持同步。它的价值在于:
- 读写分离:主库扛写、从库扛读,分担压力;
- 数据备份:从库天然是主库的一份实时备份;
- 高可用:主库挂了,从库能顶上。
2. 原理:三个日志 + 三个线程
先记住这 6 个名词,主从复制就懂了一半:
| 主库 | 二进制日志 binlog | 记录所有修改数据的 SQL,是同步的「数据源头」 |
| 主库 | binlog dump 线程 | 负责向从库传输 binlog |
| 从库 | 中继日志 relay log | 存放从主库拉来的 binlog,避免直接通过网络读主库 |
| 从库 | IO 线程 | 连接主库、拉取 binlog、写入本地 relay log |
| 从库 | SQL 线程 | 读取 relay log、执行 SQL、还原数据变更 |
类比:把主从复制想象成「抄作业」——
- 主库(学霸)把解题过程写进笔记本 binlog;
- 从库(同学)派 IO 线程 去把笔记本内容抄到自己的草稿纸 relay log 上;
- 再派 SQL 线程 照着草稿纸,自己一步步重新做一遍,最后得到一模一样的答案。
3. 完整同步流程
从库 Slave主库 Master从库 Slave主库 Master#mermaid-svg-LJgNQ6DtOJko0RON{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LJgNQ6DtOJko0RON .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LJgNQ6DtOJko0RON .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LJgNQ6DtOJko0RON .error-icon{fill:#552222;}#mermaid-svg-LJgNQ6DtOJko0RON .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LJgNQ6DtOJko0RON .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LJgNQ6DtOJko0RON .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LJgNQ6DtOJko0RON .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LJgNQ6DtOJko0RON .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LJgNQ6DtOJko0RON .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LJgNQ6DtOJko0RON .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LJgNQ6DtOJko0RON .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LJgNQ6DtOJko0RON .marker.cross{stroke:#333333;}#mermaid-svg-LJgNQ6DtOJko0RON svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LJgNQ6DtOJko0RON p{margin:0;}#mermaid-svg-LJgNQ6DtOJko0RON .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-LJgNQ6DtOJko0RON text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-LJgNQ6DtOJko0RON .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-LJgNQ6DtOJko0RON .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-LJgNQ6DtOJko0RON .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-LJgNQ6DtOJko0RON .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-LJgNQ6DtOJko0RON #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-LJgNQ6DtOJko0RON .sequenceNumber{fill:white;}#mermaid-svg-LJgNQ6DtOJko0RON #sequencenumber{fill:#333;}#mermaid-svg-LJgNQ6DtOJko0RON #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-LJgNQ6DtOJko0RON .messageText{fill:#333;stroke:none;}#mermaid-svg-LJgNQ6DtOJko0RON .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-LJgNQ6DtOJko0RON .labelText,#mermaid-svg-LJgNQ6DtOJko0RON .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-LJgNQ6DtOJko0RON .loopText,#mermaid-svg-LJgNQ6DtOJko0RON .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-LJgNQ6DtOJko0RON .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-LJgNQ6DtOJko0RON .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-LJgNQ6DtOJko0RON .noteText,#mermaid-svg-LJgNQ6DtOJko0RON .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-LJgNQ6DtOJko0RON .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-LJgNQ6DtOJko0RON .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-LJgNQ6DtOJko0RON .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-LJgNQ6DtOJko0RON .actorPopupMenu{position:absolute;}#mermaid-svg-LJgNQ6DtOJko0RON .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-LJgNQ6DtOJko0RON .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-LJgNQ6DtOJko0RON .actor-man circle,#mermaid-svg-LJgNQ6DtOJko0RON line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-LJgNQ6DtOJko0RON :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}① 写 binlog② IO线程请求 binlog(文件+位置)③ dump线程推送 binlog④ IO线程写入 relay log⑤ SQL线程重放 relay log
| ① | 主库执行增删改/建表时,先写事务日志(redo log)保证持久化,再按顺序写入 binlog |
| ② | 从库 IO 线程连接主库,告知要同步的 binlog 文件名和位置(position) |
| ③ | 主库 binlog dump 线程根据位置读取增量数据,通过网络发给从库 |
| ④ | 从库 IO 线程先写入本地 relay log,并更新状态文件(实现断点续传) |
| ⑤ | 从库 SQL 线程解析并执行 relay log 里的 SQL,还原主库数据变更 |
为什么要有 relay log? 如果从库直接通过网络读主库 binlog,网络一中断就容易丢数据。先落到本地 relay log,再慢慢执行,就安全多了,也支持断点续传、不重复/不遗漏。
4. 实战配置
实验拓扑(两台新机器):
| mariadb-server1 | 10.1.8.10/24 | 主库 Master |
| mariadb-server2 | 10.1.8.11/24 | 从库 Slave |
两台机器都要先完成:基础配置、安装、安全初始化(步骤同「一、安装」)。
主库配置(mariadb-server1)
# 1. 修改配置,添加 server-id 和 binlog
[root@mariadb-server1 ~]# vim /etc/my.cnf
[mysqld]
server-id=1 # 主从复制里每个节点必须唯一
log_bin=mysql-bin # 开启 binlog
# 2. 重启生效
[root@mariadb-server1 ~]# systemctl restart mariadb.service
# 3. 登录并创建复制专用账号
[root@mariadb-server1 ~]# mysql -uroot -phuawei
MariaDB [(none)]> create user 'repl'@'%' identified by 'Repl@123456';
MariaDB [(none)]> grant replication slave on *.* to 'repl'@'%';
MariaDB [(none)]> flush privileges;
— 4. 查看主库 binlog 位置(记下 File 和 Position 两个值!)
MariaDB [(none)]> show master status;
show master status 输出类似:
+——————+———-+————–+——————+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+——————+———-+————–+——————+
| mysql-bin.000001 | 548 | | |
+——————+———-+————–+——————+
重点记住 File(如 mysql-bin.000001)和 Position(如 548),待会儿从库配置要用。这个位置就表示「从库应该从哪个点开始同步」。
从库配置(mariadb-server2)
# 1. 修改配置,server-id 必须和主库不同
[root@mariadb-server2 ~]# vim /etc/my.cnf
[mysqld]
server-id=2 # 与主库不同
relay_log=mysql-relay-bin # 开启中继日志
# 2. 重启生效
[root@mariadb-server2 ~]# systemctl restart mariadb.service
# 3. 登录并指定主库信息
[root@mariadb-server2 ~]# mysql -uroot -phuawei
MariaDB [(none)]> change master to
master_host='10.1.8.10',
master_user='repl',
master_password='Repl@123456',
master_log_file='mysql-bin.000001', — 主库的 File
master_log_pos=548; — 主库的 Position
— 4. 启动从库复制
MariaDB [(none)]> start slave;
— 5. 查看从库状态
MariaDB [(none)]> show slave status\\G;
验证复制是否正常
关键看两个字段:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
只要这两个都是 Yes,复制就正常。 IO 线程管「拉日志」,SQL 线程管「执行日志」,缺一不可。
最终测试:在主库建库,看从库是否自动同步。
— 主库 server1 创建数据库
MariaDB [(none)]> create database qingqingcaoyuan;
MariaDB [(none)]> show databases;
— 能看到 qingqingcaoyuan
— 从库 server2 没手动创建,但也有了
MariaDB [(none)]> show databases;
— 同样能看到 qingqingcaoyuan ✅
总结
回顾本篇掌握的核心内容:
| 安装 | yum install mariadb mariadb-server + systemctl 启动 + mysql_secure_installation 安全初始化 |
| SQL | 库 / 表 / 增删改查(DML)/ 用户权限,每条语句以 ; 结尾 |
| 配置 | /etc/my.cnf,核心是 server-id、log_bin、bind-address、字符集 |
| 主从复制 | binlog → relay log,dump 线程 → IO 线程 → SQL 线程;Slave_IO_Running 和 Slave_SQL_Running 都为 Yes 即成功 |
MariaDB 作为 MySQL 的社区分支,学会了它,再上手 MySQL 基本是零成本迁移。这篇只是「基础」,进阶还可以继续学习主从复制的故障排查、读写分离,以及更复杂的集群方案。



