用户权限介绍
- 权限
INSERT,SELECT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE
- 每次设定只能有一个属主,没有属组或其他用户的概念
grant all privileges on *.* to user01@''192.168.226.%'' identified by ''123'';
权限 作用对象 归属 密码
作用对象分解
- . [当前
MySQL实例中所有库下的所有表] wordpress.* [当前MySQL实例中wordpress库中所有表(单库级别)]wordpress.user[当前MySQL实例中wordpress库中的user表(单表级别)]
企业中权限的设定
- 开发人员说:给我开一个用户
- 沟通
- 你需要对哪些库、表进行操作
- 你从哪里连接过来
- 用户名有没有要求
- 密码要求
- 发邮件
- 一般给开发创建用户权限
grant select,update,delete,insert on *.* to 'user01'@'192.168.226.%' identified by '123456';
实验思考问题
#创建wordpress数据库
create database wordpress;
#使用wordpress库
use wordpress;
#创建t1、t2表
create table t1 (id int);
create table t2 (id int);
#创建blog库
create database blog;
#使用blog库
use blog;
#创建t1表
create table tb1 (id int);
授权
1、grant select on *.* to wordpress@'192.168.226.%' identified by '123';
2、grant insert,delete,update on wordpress.* to wordpress@'192.168.226.%' identified by '123';
3、grant all on wordpress.t1 to wordpress@'192.168.226.%' identified by '123';
模拟企业真实场景下,DBA(数据库管理员)为开发人员创建专属数据库、建表,并精细化分配权限。
第一阶段:初始化环境与建库建表(准备“空房子”)
在给开发人员授权之前,DBA 需要先把基础设施搭好。
- 创建数据库
create database wordpress;create database blog;- 作用: 在
MySQL实例中创建两个独立的业务库(模拟企业里不同的项目)。这就好比建了两栋独立的办公楼。
- 切换并建表
use wordpress;create table t1 (id int);create table t2 (id int);use blog;create table tbl (id int);- 作用: 进入具体的库(办公楼),并在里面建好具体的表(房间)。
第二阶段:核心授权操作(给开发人员发“门禁卡”)
这是你实验的重点。企业里开发人员来了,DBA 不能直接给 root 账号,必须遵循最小权限原则。你通过 grant 语句逐步开放权限。
代码 1:
grant select on *.* to wordpress@'192.168.226.%' identified by '123';
-
作用拆解:
grant select:赋予查询权限。on *.*:作用于所有数据库的所有表(全局级别)。to wordpress@'192.168.226.%':创建/指定一个名为wordpress的用户,且限制只能从192.168.226.x这个网段连接(通过IP限制来源,比允许任何IP安全)。identified by '123':设置该用户的密码为123。
-
业务含义: 这一步给了开发人员查看全局数据的权限,通常用于排查问题时查阅基础数据,但还没有修改数据的权利。
代码 2:
grant insert,delete,update on wordpress.* to wordpress@'192.168.226.%' identified by '123';
- 作用拆解:
insert,delete,update:赋予增、删、改权限(CRUD 中的 CUD)。on wordpress.*:缩小范围,只针对wordpress这个库下的所有表。
- 业务含义: 开发人员开始在自己的业务库(
wordpress)里写代码了,他需要能修改自己业务库的数据。注意,他依然没有权限修改blog库的数据。
代码 3:
grant all on wordpress.t1 to wordpress@'192.168.226.%' identified by '123';
- 作用拆解:
grant all:赋予所有权限(包括建表、删表、增删改查等)。on wordpress.t1:精确到表级别,只对wordpress库里的t1这张表生效。
- 业务含义: 这就是最小权限原则的体现。可能
t1表是一个非常核心的配置表,开发人员需要最高权限去维护它,但同一个库里的t2表(可能涉及敏感数据)他依然只能用代码 2 里给的基础权限。
代码 4:刷新权限
flush privileges;
- 作用: 虽然用
grant语句授权通常会自动刷新内存,但在企业操作规范中,执行完一整套权限变更后,执行flush privileges;是一个好习惯,确保权限立即生效。
第三阶段:验证测试(以开发人员身份登录)
授权做完了,必须验证是否生效。终端截图展示了这个验证过程:
-
尝试登录:
mysql -uwordpress -p123(不带IP或带-h localhost)- 结果:
ERROR 1045 (28000): Access denied - 原因: 因为我们之前授权时,写的是
@'192.168.226.%'。当你直接本机登录(默认走localhost)时,MySQL认为你不在授权的网段内,所以拒绝。
- 结果:
-
按授权规则登录:
mysql -uwordpress -p123 -h 192.168.226.10- 结果: 成功进入
MySQL命令行。 - 原因:
-h指定了 192.168.226.10 这个IP,完全匹配了之前的网段授权。
- 结果: 成功进入
-
权限验证:
- 进去后执行
use wordpress;成功切换。 - 执行
show tables;成功看到了t1和t2(因为有select权限)。 - 执行
select * from t1;成功读取数据(因为没有写入测试,所以显示Empty set,但不报权限错误,说明查询权限正常)。

- 进去后执行

权限级别(全局、库级、表级)和具体操作权限
在企业级 MySQL权限管理中,这三条命令演示了基于角色的访问控制(RBAC)和最小权限原则的落地过程。
第一条:全局只读权限(Global Read-Only)
grant select on *.* to wordpress@'192.168.226.%' identified by '123';
- 权限范围:
*.*代表全局级别(Global Level),即当前MySQL实例中的所有数据库和所有表。 - 赋予的操作:
select。仅允许执行SELECT查询语句。 - 安全策略(Host 限制):
@'192.168.226.%'限制了该账号的登录来源IP网段,非该网段的客户端连接会被直接拒绝。 DBA视角的业务意义:为开发人员提供全局只读权限。这通常用于排查跨库的数据依赖问题,或进行全局数据抽取,但==严格禁止其对生产环境做任何数据变更(DML)或结构变更(DDL)==。
第二条:库级读写权限(Database-Level Read/Write)
grant insert,delete,update on wordpress.* to wordpress@'192.168.226.%' identified by '123';
- 权限范围:
wordpress.*代表库级别(Database Level),权限被精确收敛到wordpress这一个数据库下的所有表。 - 赋予的操作:
insert(插入)、delete(删除)、update(更新)。结合第一条命令,该用户在wordpress库中具备了完整的DML(数据操纵语言) 权限(CRUD)。 DBA视角的业务意义:满足开发人员对自身业务库进行日常数据维护的需求。同时,由于权限范围限制在wordpress.*,该用户依然无法修改其他业务库(如blog库)的数据,实现了==业务隔离==。
第三条:表级全权控制(Table-Level Full Control)
grant all on wordpress.t1 to wordpress@'192.168.226.%' identified by '123';
- 权限范围:
wordpress.t1代表表级别(Table Level),权限被进一步收敛到wordpress库中的t1这一张表。 - 赋予的操作:
all。代表该表上的所有可用权限,包括但不限于DROP(删表)、ALTER(修改表结构)、CREATE(建索引)等DDL(数据定义语言) 权限,以及所有DML权限。 DBA视角的业务意义:应对特殊业务场景。例如,t1可能是开发人员需要全权负责维护的临时表、日志表或核心配置表。==赋予all权限允许他们自主重建表结构或清空表数据==,而同一库中的其他表(如t2)依然受限于第二条命令的普通读写权限。
综合权限模型分析
这三条命令构成了一个漏斗式的权限收敛模型:
- 全局层(
*.*):授予基础的查询权限,保证跨库查阅能力。 - 数据库层(
wordpress.*):授予业务所需的读写权限,满足日常开发需求。 - 数据表层(
wordpress.t1):授予特定表的完全控制权限,应对特殊维护需求。
重点: MySQL的权限是叠加(Union)生效的。该用户最终的权限是这三条命令权限的并集。这种分层授权既保证了开发人员有足够的权限完成工作,又严格限制了误操作或恶意操作波及的范围。
客户端连接测试以及权限验证的过程

这一整套操作,就是标准的DBA 用户授权后的功能验证(Functional Testing),确保交给开发人员的账号是符合预期且安全的。
DBA 权限分配与验证 流程图
text
[阶段一:DBA 上帝视角]
│
▼
mysql -uroot -p123456
│
├─ 角色:数据库超级管理员(DBA)
├─ 权限:最高权限(建库、删库、建表、创建用户、分配权限等)
└─ 现实意义:绝对保密,仅限核心 DBA 团队掌握,绝不外借给开发人员。
│
▼
[阶段二:DBA 派发权限]
│
▼
grant ... to 'wordpress'@'192.168.226.%' identified by '123';
│
├─ 角色:DBA(执行者) <--> 开发人员(申请者)
├─ 操作:DBA 用 root 登录,执行 grant 命令
│ ├─ 网络层授权:放行 @'192.168.226.%'(限制来源 IP 网段)
│ └─ 数据层授权:分配特定库表的读写权限
└─ 原则:最小权限原则(只给工作必需的权限,绝不轻易 grant all)
│
▼
[阶段三:开发人员日常连接]
│
▼
Navicat (输入主机 IP、账号 wordpress、密码 123)
│
├─ 角色:开发人员
├─ 操作:使用图形化工具 Navicat 连接数据库
├─ 权限验证(连接成功即证明):
│ ├─ DBA 分配的网络权限(IP限制)生效了
│ └─ DBA 分配的库表权限生效了
└─ 后续限制(实验结论验证):
├─ 尝试删掉 wordpress 库里的 t1 表 → 会被拒绝(无 DROP 权限)
└─ 尝试修改 blog 库里的数据 → 会被拒绝(无跨库写权限)
逻辑架构视角(权限收敛漏斗)
如果你从系统架构的角度来看,这三步其实是一个权限逐级收敛、安全性逐级提高的过程:
text
===================== 权限边界 =====================
【最高层】 root 账号 (localhost)
└─> 拥有全部 DDL / DML / 授权 / 管理权限
│
│ (DBA 执行 grant 命令,向下派发)
▼
【中间层】 wordpress 账号 (192.168.226.% 网段)
├─> 全局层 (*.*) : 只有 SELECT (全局只读)
├─> 数据库层 (wordpress.*) : 拥有 INSERT, DELETE, UPDATE (库级读写)
└─> 数据表层 (wordpress.t1) : 拥有 ALL (表级全权)
│
│ (开发人员用 Navicat 连接)
▼
【最底层】 开发人员实际可操作范围
└─> 只能严格按照 DBA 分配的库表权限执行操作,多一步都做不了
核心总结(一句话牢记)
DBA用 root 手握全局,通过 grant 像做手术一样精细划分权限,最后开发人员只能用 wordpress 账号在划定的圈子里干活。 这就是企业级数据库安全管理的标准范式。


案件复盘:1142 报错背后的真相
线索一:操作者是谁?—— 身份决定权限
- 表面现象:
Navicat左侧连接名为wordpress连接和权限测试,报错INSERT command denied。 - 底层本质:你这次没有用
root越权操作,而是老老实实按规范使用了wordpress普通账号。MySQL服务器精准识别了你的身份,并执行了权限判定。 - 最终结论:系统“认号不认人”,你是普通用户,就只享有普通用户的待遇。
线索二:数据从哪来?—— 能看 ≠ 能改
- 表面现象:表格里还能看到
10和111111,但当你想插入888时却被拒绝。 - 底层本质:
- 那两条数据是你(
DBA)之前用 root 账号在 Linux 终端强行插入的。 - 现在你能看见它们,是因为你拥有
grant select on *.*的全局只读权限。 - 但你现在改不动,是因为你没有
blog库的写入权限。
- 那两条数据是你(
- 最终结论:允许跨库查数据辅助开发,严禁跨库篡改数据保证安全。
线索三:锅该谁背?—— 工具只是传话筒
- 表面现象:你曾怀疑“是不是
Navicat默认给了我权限?” - 底层本质:
Navicat只是将你的鼠标操作(点击保存)翻译成INSERTSQL语句发送给服务器。服务器核对权限后拒绝,Navicat只是把错误原封不动地弹出来给你看。 - 最终结论:
Navicat只是传话筒,MySQL才是铁面无私的判官。绝对不存在“工具绕过权限”一说。
MySQL连接管理
不建议使用的方法:
vim /etc/my.cnf
[client]
user = root
password = 123456
-
MySQL- -u:指定用户
- -p:指定密码
- -h:指定主机
- -P:指定端口
- -S:指定sock
- -e:指定
SQL
-
第三方连接工具
sqlyognavicat
1. 常见的几种登录方式
- 方式一:明文密码(极度不推荐)
- 命令:
mysql -uroot -p123456 - 特点:把密码直接写在命令里。虽然敲起来快,但极其危险。同一台服务器上的其他用户,只要执行
ps aux | grep mysql,就能直接看到你的密码明文。在生产环境绝对禁止。
- 命令:
- 方式二:交互式输入密码(最推荐 ✅)
- 命令:
mysql -uroot -p - 特点:敲完回车后,系统会提示
Enter password:,此时你输入密码,屏幕不会显示任何字符(不显示星号,也不显示数字)。这种方式既安全(密码不会留在历史命令或进程里),又通用(不需要依赖任何配置文件)。
- 命令:
- 方式三:依赖配置文件(图1里的写法,不推荐 ❌)
- 命令:直接敲
mysql - 特点:这就是你刚才在
/etc/my.cnf的[client]下面配置了user和password之后的效果。 - 缺点:极度不安全。任何能登上这台服务器的人,只要敲
mysql就能以 root 身份进去。生产环境严禁这么干。
- 命令:直接敲
- 方式四:使用
mysql_config_editor(企业级安全用法)- 命令:先执行
mysql_config_editor set --login-path=local --host=localhost --user=root --password,然后以后登录只需敲mysql --login-path=local。 - 特点:这是
MySQL官方提供的加密登录方式。密码会被加密存储在一个.mylogin.cnf文件里,比明文写在配置文件里安全得多。企业里用得多。
- 命令:先执行


企业级 MySQL 用户权限管理方案与实战命令
最小权限原则(Least Privilege)和职责分离(Separation of Duties)。
第一部分:创建受限超级管理员与权限回收
这部分演示了 DBA如何创建一个“受约束的超级管理员”,以及如何回收不再需要的权限。
1. 创建带资源限制的超级管理员
sql
CREATE USER 'super_admin'@'localhost' IDENTIFIED BY 'StrongAdminP@ssw0rd';
GRANT USAGE ON *.* TO 'super_admin'@'localhost'
WITH
MAX_QUERIES_PER_HOUR 0
MAX_UPDATES_PER_HOUR 0
MAX_CONNECTIONS_PER_HOUR 0
MAX_USER_CONNECTIONS 10;
CREATE USER ...:先创建一个账号,密码设置得比较强(符合安全规范)。GRANT USAGE ...:这里非常巧妙。USAGE本身代表“没有任何实际权限”,仅仅只允许该用户登录数据库。WITH ...:这是MySQL的资源限制子句。MAX_QUERIES_PER_HOUR 0:每小时查询次数无限制(0代表无限制)。MAX_UPDATES_PER_HOUR 0:每小时更新操作无限制。MAX_CONNECTIONS_PER_HOUR 0:每小时连接次数无限制。MAX_USER_CONNECTIONS 10:这是核心。限制该账号最多只能同时保持 10 个活跃连接。这可以防止因为程序 Bug 或恶意攻击导致数据库连接池被瞬间耗尽。
2. 授予管理员权限
sql
GRANT ALL PRIVILEGES ON *.* TO 'super_admin'@'localhost' WITH GRANT OPTION;
- 赋予了所有库和表的全部权限(ALL PRIVILEGES)。
WITH GRANT OPTION:这个子句非常关键,它允许该用户把自己拥有的权限再授权给其他用户。这才是真正意义上的“管理员”权限。- 注意:由于前面设置了资源限制,这个超级管理员的连接数依然受限于 10,所以它不是“无限膨胀”的。
3. 回收权限
sql
REVOKE SELECT ON *.* FROM root@'192.168.226.%';
- 这里演示了权限回收。假设之前因为某个特殊原因,给
192.168.226.%网段的 root 用户开了全局查询权限,现在任务完成了,出于安全考虑,必须用REVOKE收回。 - 如果是验证权限,可以使用
SHOW GRANTS FOR root@'192.168.226.%';来确认回收是否成功。
第二部分:不同角色的精细化权限分配方案
这部分是整个文档的精华,它针对企业里常见的 6 种角色,给出了详细的权限设计方案。
1. 开发人员 (Developer)
-
核心需求:日常写代码、调试,需要操作开发/测试库,通常不接触生产库。
-
基础权限:
SELECT,INSERT,UPDATE,DELETE(针对开发库业务表)。 -
结构权限:
CREATE TABLE,ALTER TABLE,CREATE INDEX(允许他们建表和修改表结构,方便开发)。 -
限制(红线):禁止
DROP(防止误删表)、禁止TRUNCATE(防止清空表)、禁止GRANT(防止开发人员私自授权,造成数据泄露)。 -
授权命令示例:
sqlGRANT SELECT, INSERT, UPDATE, DELETE, CREATE TABLE, ALTER TABLE ON dev_db.* TO 'developer'@'192.168.1.%';
2. 测试人员 (Tester)
- 核心需求:执行测试用例,写入测试数据,检查功能。
- 权限:只有数据操作权限(
SELECT, INSERT, UPDATE, DELETE)。 - 限制:禁止结构操作(不能改表结构、建表、删表)、禁止权限管理(不能 GRANT)。这是为了防止测试人员破坏测试环境的数据结构,导致测试数据失效。
3. 数据分析/报表人员 (Data Analyst)
-
核心需求:提取数据,制作报表。
-
权限:只读(
SELECT)。通常只针对特定的表或视图。 -
安全亮点:通过视图隐藏敏感列。
sqlCREATE VIEW safe_user AS SELECT id, name, register_date FROM user_info; GRANT SELECT ON safe_user TO 'analyst'@'%';把身份证、手机号等敏感信息隐藏起来,只授予视图的查询权限。这样分析人员看不到敏感数据,但依然能完成分析工作。
4. 运维、DevOps(Operations)
- 核心需求:监控数据库状态、备份、维护。
- 权限:
BACKUP DATABASE(备份)、SHUTDOWN(关库)、PROCESS(查看进程)。 - 限制:禁止
INSERT/UPDATE/DELETE业务数据(防止运维误改数据)、禁止DROP(防止破坏结构)。
5. 业务系统账号 (App Account)
- 核心需求:应用程序连接数据库,执行代码逻辑。
- 权限:根据业务需要,仅授予
SELECT/INSERT/UPDATE/DELETE(针对具体的业务表)。 - 限制:禁止
CREATE/ALTER/DROP。非常重要!因为程序 Bug 或SQL注入一旦发生,如果账号有DDL权限,整个表结构可能瞬间被毁。如果只有DML权限,最多被删几行数据,可以通过备份快速恢复。也禁止GRANT,防止权限扩散。 - 特殊:如果程序需要用临时表,可以单独授予
CREATE TEMPORARY TABLES权限。
6. DBA 自身 (DBA)
- 最高权限:
ALL PRIVILEGES(只用于紧急情况和核心管理)。 - 审计权限:
SELECT审计日志表,ALTER审计规则。 - 最佳实践:日常操作不建议使用 root 或高权限账号。强烈建议
DBA也通过堡垒机(Bastion Host,一种跳板机)来操作,这样所有操作都会被日志记录,防止内部人员作恶。
总结:权限分配的通用原则
文档最后总结的这三点,是所有运维人员和安全人员必须遵守的铁律:
- 环境隔离:生产、测试、开发环境必须用不同的账号体系,严格隔离,生产库的权限要给到最小。
- 动态调整:员工离职、转岗,必须立即回收权限(定期审计非常重要,比如每季度审一次)。
- 日志追溯:所有的权限变更(
GRANT/REVOKE),以及敏感的DELETE操作,都必须要有审计日志,做到“有迹可循”。
Mysql用户管理
MySQL用户与主机域核心知识
username@’主机域’
主机域:可以理解为是Mysql登录的白名单
主机域格式:
192.168.226.10
192.168.226.1%
192.168.226.1 192.168.226.10-19 192.168.226.100-199
192.168.226.%
192.168.%.%
%
`localhost`
192.168.226.0/255.255.255.0
一、 用户定义格式与作用
MySQL 用户的核心定义格式是:username@'主机域'(Host)。
- 主机域的作用:可以理解为
MySQL登录的白名单。它决定了特定的账号只能从哪些IP地址或网段连接到数据库,这是MySQL安全机制的重要一环。
二、 主机域(Host)的常见书写格式
在实际配置中,主机域可以使用具体的 IP、通配符(%)或网段形式,以应对不同的访问需求。结合当前环境(本机 IP 为 192.168.226.10),常见的格式如下:
192.168.226.10:精确匹配单个IP。只允许这一台机器(即本机)连接到数据库。192.168.226.%:C 类网段匹配。允许192.168.226.1到192.168.226.254这个网段内的所有机器连接。192.168.%.%:B 类网段匹配。允许192.168开头的所有网段(范围极大)。192.168.226.1%:前缀模糊匹配。匹配以192.168.226.1开头的所有IP地址(例如 192.168.226.10、192.168.226.100 等,不够精确,需慎用)。%:全匹配。允许从任何IP地址连接(生产环境极度危险,慎用)。localhost:本地 Socket 连接。仅允许从本机服务器发起连接,不经过 TCP/IP网络协议(这是默认 root 用户的常用配置)。192.168.226.0/255.255.255.0:子网掩码形式。精确指定192.168.226.0整个网段(与192.168.226.%效果类似)。
三、 实战用户表的操作与解析
1. 切换系统库
- 执行命令:
use mysql; - 作用:切换到
MySQL自带的系统数据库。MySQL所有的==用户账号、密码、权限信息==都存放在这个库中的user表里。
2. 查询所有列(重点疑问)
- 执行命令:
select * from user; - 为什么会有那么多列输出?
==因为
select *表示查询该表的所有字段== 。MySQL将用户的每一个具体权限(如增、删、改、查、建表、授权等)都设计成了独立的列字段。- 基本认证列:
Host(主机域)、User(用户名)、Password(加密后的密码哈希值)。 - 权限控制列:
Select_priv、Insert_priv、Update_priv、Grant_priv等等。这些列的值通常是Y或N,代表该用户是否具备全局级别的某项权限。 - 其他属性列:
plugin(密码加密插件,截图显示为mysql_native_password)、password_expired(密码是否过期)等。 - 注意:当把这张表的所有列全部在一行中打印出来时(如您截图中的长列表),终端会显示得非常长,同时很多列(如 N 或 0)是因为该用户为普通用户或受限用户,没有开启这些全局权限。

- 基本认证列:
3. 优化查询(查看核心信息)
-
执行命令:
select host,user from user; -
执行结果解析(结合您的环境): 这条命令==只提取最关键的两列==,输出会变得非常简洁清晰。在当前环境下,执行后会列出如下几行核心数据:
127.0.0.1|root192.168.226.%|wordpress::1|rootlocalhost|rootlocalhost.localdomain|rootlocalhost| (空)localhost.localdomain| (空)- 分析:这代表当前服务器默认配置了 root 账号用于本地访问(
localhost及几个本机回环IP别名),并为名为wordpress的网站程序配置了专用的连接账号(允许从 192.168.226 网段连接)。最后两行空用户名通常代表初始自带的无密码匿名用户,出于安全考虑通常建议将其删除。


用mysqladmin管理工具设置了root用户的密码
mysqladmin -uroot password '123456'
通过用户名和密码来登录数据库
mysql -uroot -p123456
1. 为什么它必须要在服务端(Linux终端)运行?
mysqladmin 是一个独立的可执行程序(通常存放在 MySQL的 bin 目录下,比如 /usr/bin/mysqladmin)。
它的运行机制是:
- 接收你输入的参数(比如
-uroot -p123456)。 - 通过网络或本地 Socket 连接去连上
MySQL服务端。 - 向服务端发送一条“修改密码”的指令。
- 服务端执行成功后,
mysqladmin程序就退出了。
因为它是一个独立的程序,所以必须要在操作系统的命令行(也就是您截图里的 [root@localhost ~]#)下运行。一旦您输入 exit 退出了 mysql> 交互环境,就回到了操作系统层面,这时候再敲 mysqladmin,系统才认识它。
2. 为什么在 mysql> 里面输入 mysqladmin 会报错?
因为 mysql> 是一个SQL 解析器。您在里面输入的所有东西,都会被当作SQL 语句来解析。
- 您输入
SELECT * FROM user;,它认识,去执行。 - 您输入
mysqladmin ...,它心里想:“这什么玩意儿?SQL语句哪有以mysqladmin开头的?”于是直接甩出ERROR 1064(语法错误)。
3. mysqladmin 和 SQL 命令改密码的区别
截图里展示了两种改密码的方式,它们其实是殊途同归,只是入口不同:
- 方法一(服务端外部工具,截图里做的):
在 Linux 终端:
mysqladmin -uroot -p123456 password '654321'特点: 不需要进入MySQL,直接在操作系统层面调用工具去连接并修改密码。 - 方法二(客户端内部
SQL语句): 先登录进mysql>,然后执行:ALTER USER 'root'@'localhost' IDENTIFIED BY '654321';特点: 利用SQL语句本身来修改权限表里的密码字段。

忘记 root 密码后的强制重置流程
它的核心思路是:让 MySQL 启动时暂时“忘记”检查密码(跳过权限表验证),从而让我们能免密登录进去,修改完密码后,再恢复正常启动。
# 如果mysql的密码忘记了,如何解决?
[root@server1 ~]# /etc/init.d/mysqld stop
[root@server1 ~]# mysqld_safe --skip-grant-tables --skip-networking
[root@server1 ~]# mysql
mysql> use mysql
mysql> update user set password=PASSWORD('123456') where user='root' and host='localhost';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> quit
Bye
[root@server1 ~]# pkill mysql
[root@server1 ~]# systemctl start mysqld.service
[root@server1 ~]# mysql -uroot -p123456
第一阶段:停止当前服务,进入“无密码”模式
1. [root@server1 ~]# /etc/init.d/mysqld stop
- 作用:停止正在运行的
MySQL服务。 - 原因:你要修改底层的认证方式,必须先让数据库停下来。
2. [root@server1 ~]# mysqld_safe --skip-grant-tables --skip-networking &
- 作用:这是整个流程的灵魂步骤。使用
mysqld_safe工具(一个守护进程启动脚本)来启动MySQL。 - 关键参数:
--skip-grant-tables:跳过权限表验证。==启动时,MySQL不会去加载mysql.user表里的密码和权限信息==。这意味着,任何人都可以免密登录,且拥有最高权限。--skip-networking:跳过网络连接。防止其他机器通过网络连上这个“不设防”的数据库,只允许本机(localhost)通过 Socket 连接,保证重置过程的安全性。
- 注:截图里的命令末尾虽然没有加
&(让程序在后台运行),但在实际操作中,敲下这行命令后,终端通常会卡住(因为它在运行),此时需要再开一个终端窗口来执行后面的步骤。
第二阶段:免密登录并修改密码
3. [root@server1 ~]# mysql
- 作用:由于上一步已经跳过了权限验证,此时输入
mysql命令,不需要-u和-p参数,直接就能进入MySQL交互界面。
4. mysql> use mysql
- 作用:切换到
mysql系统库,准备修改user表。
5. mysql> update user set password=PASSWORD('123456') where user='root' and host='localhost';
- 作用:这是核心的密码修改语句。
- 定位目标:找到
user表中,用户名为root且主机为localhost的那一行记录。 - 赋值操作:将
password字段的值,修改为PASSWORD('123456')。PASSWORD()是一个内置函数,用于生成加密后的哈希值。
- 定位目标:找到
- 结果提示解读:
Query OK, 0 rows affected:看起来好像没改(0行受影响),但在老版本MySQL(如5.6/5.7之前)里,如果设置的新密码和旧密码一样,MySQL可能认为不需要更新,所以显示 0。这并不代表密码没生效。Rows matched: 1 Changed: 0:说明找到了一条符合条件的数据(匹配了1行),但可能因为密码没有变化,所以没有实质性的修改(Changed 0)。- 如果你的目标是设置一个全新的密码,这里就会显示
Changed: 1。
6. mysql> flush privileges;
- 作用:刷新权限表。
- 原因:这是一个极其重要的习惯。在我们直接通过
update修改完系统表后,必须通知MySQL服务器重新加载权限表,这样新的密码才会立即生效。
7. mysql> quit
- 作用:退出当前的
MySQL客户端环境。
第三阶段:恢复正常状态并验证
8. [root@server1 ~]# pkill mysql
- 作用:强制杀掉所有与
MySQL相关的进程。 - 原因:刚刚启动的那个
MySQL是在“无权限验证”的畸形状态下运行的,不能一直这样开着。必须把它彻底停掉,才能正常启动。
9. [root@server1 ~]# systemctl start mysqld.service
- 作用:使用系统服务管理工具(
systemctl),正常启动MySQL。 - 结果:此时
MySQL会带着完整的权限表加载,正常启动,不再跳过验证。
10. [root@server1 ~]# mysql -uroot -p123456
- 作用:使用刚刚重置的新密码
123456尝试登录数据库。 - 如果成功,说明整个重置流程圆满完成。
/etc/init.d/mysqld为啥因为PID停止失败
1. 真正的数据库进程(/application/mysql/bin/mysqld)
- 定位:这是
MySQL的核心二进制可执行文件。 - 启动方式:执行该命令时,它启动数据库引擎,分配内存,监听 3306 端口,准备处理
SQL请求。 - 与配置文件的关系:它启动时依赖
--defaults-file=/etc/my.cnf参数。该参数指定了配置文件路径,mysqld会读取并严格按照该文件内的参数(如数据目录、端口、缓冲区大小等)运行。 - 特点:它不认识
start、stop等操作指令。如果在终端直接执行,它会在前台运行并占用终端。
2. 服务管理脚本(/etc/init.d/mysqld)
- 定位:这是一个 Shell 脚本,用于封装对
MySQL进程的启停管理。 - 工作方式:它接受
start、stop、restart、status等参数,并执行相应的逻辑。 - 执行
stop的逻辑:脚本会去指定路径(如/var/run或数据目录)查找mysqld.pid文件。读取里面的进程号(PID),然后调用kill命令终止该进程。如果找不到PID文件,脚本就会报错PID file could not be found!。 - 与配置文件的关系:脚本内部通常也会引用
/etc/my.cnf配置文件,但它的目的是为了获取PID文件路径等管理相关的信息,而不是像mysqld那样加载所有数据库运行参数。
3. 两者在本次操作中的关系(为什么会报错,以及如何处理)
- 正常情况下,脚本(
/etc/init.d/mysqld)负责管理核心进程(mysqld)。脚本启动mysqld时,会把进程号写入PID文件,以便后续通过stop命令读取并停止它。 - 当前报错
PID file could not be found!的原因:脚本无法找到PID文件,因此它不知道要终止哪个进程。 - 报错并不意味着
mysqld进程没有运行。通过ps -ef | grep mysql可以看到,mysqld进程(PID817)实际上正在运行。 - 因此,当前的操作逻辑是:由于管理脚本无法通过
PID文件正常停止该进程,我们手动获取其PID(817),直接使用kill -9 817命令终止它。停止后,再通过mysqld_safe --skip-grant-tables等参数手动启动,以进行后续的密码重置等操作。
一句话总结:
mysqld 是实际运行的服务进程,依赖 /etc/my.cnf 启动;/etc/init.d/mysqld 是管理该进程的脚本,依赖 PID 文件执行停止操作。PID 文件丢失导致脚本停止失败,所以需手动通过 PID强制终止进程。



MySQL 中 修改密码的三种核心途径
第一部分:修改密码的三种方式详解
这三种方式其实殊途同归,最终目的都是修改底层 mysql.user 表里的密码字段,但适用场景和生效机制不同。
# 1.直接修改,修改完直接生效
mysql> set password=PASSWORD('123456');
# 2.修改数据表user中的password字段,修改完需要flush privileges
mysql> update user set password=PASSWORD('321') where user='root' and host='localhost';
# 3.在授权的时候可以在最后通过identified by来指定密码,修改完需要flush lrivileges
mysql> grant all privileges on *.* to user01@'192.168.226.%' identified by '123456';
1. 直接修改(SET PASSWORD)
- 语法:
SET PASSWORD = PASSWORD('123456'); - 机制:这是
MySQL提供的专用SQL语句。它专门用来修改当前登录用户的密码。 - 生效:修改完立刻生效,不需要
flush privileges。因为MySQL内部会直接更新内存中的权限缓存。 - 适用场景:用户已经登录,且拥有修改自己密码的权限。
- 避坑:在
MySQL8.0 中,不再使用PASSWORD()函数,直接写SET PASSWORD = '123456';或者ALTER USER 'root'@'localhost' IDENTIFIED BY '123456';。


2. 修改数据表(UPDATE)
-
语法:
UPDATE user SET password=PASSWORD('321') WHERE user='root' AND host='localhost'; -
机制:这是一种“硬核”修改方式。绕过
SQL语法层,直接去修改mysql系统库中的user表。 -
生效:修改完必须执行
flush privileges;。因为直接修改表,MySQL的内存缓存(比如information_schema)不会自动更新,必须手动刷新。 -
适用场景:
- 忘记密码,处于
--skip-grant-tables免密模式时(此时SET PASSWORD等命令会报错,只能通过UPDATE表来修改)。 - 批量修改多个用户或特定主机域的用户密码。

- 忘记密码,处于

3. 授权时指定(GRANT ... IDENTIFIED BY)
- 语法:
GRANT ALL PRIVILEGES ON *.* TO username@'192.168.226.%' IDENTIFIED BY '123456'; - 机制:这是
MySQL5.7 及以前特有的语法。它把“创建用户”、“赋权”和“设置密码”三个动作合为一体。 - 生效:修改完必须执行
flush privileges;。 - 适用场景:新建用户并分配权限时,顺手设置好初始密码。
- 避坑(非常重要!):在
MySQL8.0 中,GRANT语句不能再用来创建用户或设置密码了。必须先CREATE USER,再GRANT。所以这个语法在 8.0 里已经废弃。


MySQL 三层启动调用链
核心启动链:
/etc/init.d/mysqld` ——(调用)——> `mysqld_safe` ——(拉起并监控)——> `mysqld
第一层:/etc/init.d/mysqld —— 标准化接口(面向操作系统)
1. 它是什么?
这是一个 Shell 脚本(在 CentOS 6及更早版本中是标准写法,CentOS 7+ 逐渐被 systemctl 取代)。它是 Linux 系统管理服务的“标准入口”。
2. 它的职责(为什么需要它?):
- 适配系统规范:Linux 管理服务有一套统一的标准(比如用
service mysqld start或systemctl start mysqld)。这个脚本的作用就是把系统的标准命令翻译成MySQL能听懂的话。 - 环境准备:在真正拉起数据库之前,它会做很多繁琐的准备工作:
- 读取配置文件(
/etc/my.cnf)。 - 检查数据目录的权限(确保
mysql用户有权限读写/var/lib/mysql)。 - 检查
PID文件是否残留、端口是否被占用。
- 读取配置文件(
- 结果反馈:当底层启动完毕后,它会向系统返回
OK或FAILED,让你能在屏幕上看到成功或失败的状态。
总结:它是面向操作系统的接口层,负责处理所有的系统对接和前置检查工作。
第二层:mysqld_safe —— 中间层守护(安全与监控)
1. 它是什么? 它是一个 守护进程(Daemon),本质上也是一个 Shell 脚本。它存在于第一层和核心数据库之间,是一个中间层。
2. 它的职责(为什么需要它?):
- 安全保障:它负责在启动核心数据库前,把一些不安全的因素排除掉。
- 故障恢复(最核心作用):
mysqld这个核心进程有时候会因为内存溢出、Bug 或异常SQL而崩溃。如果mysqld直接挂在系统上,服务就彻底死了。 而mysqld_safe会一直监控mysqld进程,如果发现它意外退出了,mysqld_safe会立刻把它重新启动,保证数据库的高可用性。 - 日志记录:负责记录启动过程中的错误日志(如
error.log),方便排查问题。 - 参数传递:像我们之前模拟忘记密码时用的
--skip-grant-tables和--skip-networking,通常就是通过mysqld_safe把这个参数传递给mysqld的。
总结:它是中间层的守护进程,负责监控核心进程并提供故障恢复机制。
第三层:mysqld —— 核心功能实现(数据库本体)
1. 它是什么?
这是 MySQL 真正的核心服务进程(二进制可执行文件,通常在 /usr/sbin/mysqld 或 /application/mysql/bin/mysqld)。它是实际执行数据库功能的核心程序。
2. 它的职责(为什么需要它?):
- 处理
SQL语句:解析客户端发来的SELECT、UPDATE等语句。 - 管理存储引擎:操作
InnoDB或MyISAM引擎去读写磁盘上的数据文件。 - 管理连接:监听 3306 端口,处理用户连接和权限验证。
- 维护内存结构:管理 Buffer Pool、日志缓冲区等。
3. 它的特点: 它极度专注,只做数据库该做的事。它不管防火墙,不管系统服务规范,不管崩溃后怎么重启(那是前两层的事)。它一旦启动,就会一直运行,直到被手动停止或崩溃。
总结:它是核心功能实现层,专注于数据库服务和数据处理本身。
为什么这种“分层设计”如此重要?(架构分析)
如果把这三层合并成一个大程序,会带来什么问题?
- 不兼容:不同 Linux 发行版(
Ubuntu、CentOS)管理服务的方式不同,合并会导致兼容性极差。 - 不稳定:核心数据库一旦崩溃,整个服务就全挂了,没有中间层去恢复它。
- 难维护:日志、权限检查、启动参数传递都和核心业务代码搅在一起,出错了很难排查。
三层分层的好处:
-
各司其职(单一职责):系统层管环境,守护层管生存,核心层管业务。
-
高可用:
mysqld_safe的存在,大大提高了数据库的健壮性。 -
可移植:只要针对不同的 Linux 系统写不同的
/etc/init.d/mysqld脚本,底层的mysqld_safe和mysqld几乎不需要改动。
补充:现代 MySQL 的变化(CentOS7+ 和 MySQL 8.0)
现在(CentOS 7 及以上),/etc/init.d/mysqld 已经被 systemd 取代(即 systemctl start mysqld)。
但是,分层的核心思想没有变。
- 现在的
systemd会直接接管mysqld,不再经过mysqld_safe(因为systemd本身就带有Restart=on-failure自动重启功能,替代了mysqld_safe的部分职责)。 - 但在一些手动编译安装的
MySQL5.6/5.7 环境中,这三层调用链依然经典且常见。
一句话总结:系统接口 -> 守护进程 -> 核心服务,层层递进,构建了稳定可靠的 MySQL 服务体系。
1. 从文件属性看:它是一个具有执行权限的文件
Linux 系统允许这个文件作为程序被运行
2. 从文件内容看:它是一个 Shell 脚本
看截图里的 cat /etc/init.d/mysqld 输出:
- 第一行:
#!/bin/sh这是最关键的标志。这行叫做 Shebang。它告诉 Linux 内核:“这个文件是个脚本,请用/bin/sh(也就是 Shell)来解释并执行它”。所以,它本质上就是一个 Shell 脚本。 - 后续的注释:
大段的
#开头的内容,都是在描述这个脚本的历史、用途(启动/停止MySQL守护进程)、以及在老版本 Linux(如RedHat)中的系统运行级别配置。这些是给管理员看的说明文档。
3. 脚本内部通常包含什么?
这个 mysqld 脚本的完整逻辑通常是这样的:
- 它接收系统传来的参数(如
start、stop、restart、status)。 - 它检查环境(检查配置、检查权限)。
- 最核心的:它调用真正的程序。当接收到
start参数时,它会去执行/application/mysql/bin/mysqld_safe或直接执行mysqld。

用户指令
1. 查看系统用户表
命令: mysql> select user,host from mysql.user;
- 作用:查询
mysql系统库中的user表,但只提取user(用户名)和host(允许登录的主机域)这两列。
2. 查看当前登录的用户
命令: mysql> select user();
- 作用:查看当前这个连接是以哪个用户的身份登录的。
- 结果解读(1 row in set):
输出
root@localhost。意思就是:您现在正以root用户的身份,从localhost(本机)登录着MySQL。
3. 查看当前数据库(成功但为空)
命令: mysql> select database();
- 作用:查看当前处于哪个数据库中。
- 结果解读(1 row in set):
输出
NULL。意思是:您现在虽然登录了MySQL,但并没有选中任何数据库(刚登录进来默认就是没有选中任何库)。
5. 切换数据库
命令: mysql> use mysql;
- 作用:切换到名为
mysql的系统数据库。 - 提示信息:
Reading table information for completion of table and column names:这是MySQL在读取表信息,为了给您提供自动补全提示(方便您敲表名、列名),不影响操作。Database changed:明确告诉您,已经成功切换到mysql库了。
6. 再次查看当前数据库(验证切换成功)
命令: mysql> select database();
- 作用:再次确认当前所在的数据库。
- 结果解读(1 row in set):
输出
mysql。这就证明您刚才的use mysql;生效了,您现在位于mysql系统库中。

MySQL多实例配置
多实例
- 多套后台进程+线程+内存结构
- 多个配置文件
- 多端口
- 多socket文件
- 多个日志文件
- 多个server_id
- 多套数据
实战配置
#创建数据目录
mkdir -p /data/330{7..9}
#创建配置文件
touch /data/330{7..9}/my.cnf
touch /data/330{7..9}/mysql.log
#编辑3307配置文件
vim /data/3307/my.cnf
[mysqld]
basedir=/application/mysql
datadir=/data/3307/data
socket=/data/3307/mysql.sock
log_error=/data/3307/mysql.log
log-bin=/data/3307/mysql-bin
server_id=7
port=3307
[client]
socket=/data/3307/mysql.sock
#编辑3308配置文件
vim /data/3308/my.cnf
[mysqld]
basedir=/application/mysql
datadir=/data/3308/data
socket=/data/3308/mysql.sock
log_error=/data/3308/mysql.log
log-bin=/data/3308/mysql-bin
server_id=8
port=3308
[client]
socket=/data/3308/mysql.sock
#编辑3309配置文件
vim /data/3309/my.cnf
[mysqld]
basedir=/application/mysql
datadir=/data/3309/data
socket=/data/3309/mysql.sock
log_error=/data/3309/mysql.log
log-bin=/data/3309/mysql-bin
server_id=9
port=3309
[client]
socket=/data/3309/mysql.sock
#修改目录权限
chown -R mysql.mysql /data/330*
#初始化3307数据,每条命令需要间隔若干秒,否则失败
/application/mysql/scripts/mysql_install_db
--user=mysql
--defaults-file=/data/3307/my.cnf
--basedir=/application/mysql --datadir=/data/3307/data
#初始化3308数据,每条命令需要间隔若干秒,否则失败
/application/mysql/scripts/mysql_install_db
--user=mysql
--defaults-file=/data/3308/my.cnf
--basedir=/application/mysql --datadir=/data/3308/data
#初始化3309数据,每条命令需要间隔若干秒,否则失败
/application/mysql/scripts/mysql_install_db
--user=mysql
--defaults-file=/data/3309/my.cnf
--basedir=/application/mysql --datadir=/data/3309/data
#启动多实例
mysqld_safe --defaults-file=/data/3307/my.cnf &
mysqld_safe --defaults-file=/data/3308/my.cnf &
mysqld_safe --defaults-file=/data/3309/my.cnf &
# 进入单独的mysql实例
mysql -S /data/3307/mysql.sock -uroot
#设置每个实例的密码
mysqladmin -S /data/3307/mysql.sock -uroot password '123456'
#查看server_id
mysql -S /data/3307/mysql.sock -e "show variables like 'server_id'" -p123456
mysql -S /data/3308/mysql.sock -e "show variables like 'server_id'" -p123456
mysql -S /data/3309/mysql.sock -e "show variables like 'server_id'" -p123456
# 关闭实例,如果设置了密码登录就需要密码了 用参数-p
mysqladmin -S /data/3307/mysql.sock -uroot -p123456 shutdown
mysqladmin -S /data/3308/mysql.sock -uroot -p123456 shutdown
mysqladmin -S /data/3309/mysql.sock -uroot -p123456 shutdown
准备工作
1. 编辑配置文件(核心部分)
使用 vim /data/3307/my.cnf 分别修改三个配置文件。这里面的参数是确保多实例互不干扰的关键:
basedir=/application/mysql:MySQL 的安装目录(三个实例共用同一个程序文件,节省空间)。datadir=/data/3307/data:数据目录。这是每个实例独立的,数据绝不能混在一起。socket=/data/3307/mysql.sock:套接字文件。本地连接(比如mysql -uroot)默认走 socket,如果不区分开,连接会串门。log_error=/data/3307/mysql.log:错误日志路径,独立存放方便排错。log-bin=/data/3307/mysql-bin:开启二进制日志(用于主从复制或数据恢复),前缀独立。server_id=7:服务器唯一 ID。在做主从复制时,每个节点的 ID 必须不同。port=3307:监听端口。必须不同(3307/3308/3309)。[client] socket=...:这个很重要。它告诉本机的MySQL客户端,连接这个实例时应该去哪个 socket 文件找它。

2. 修改目录权限
bash
chown -R mysql.mysql /data/330*
- 解释:将刚才创建的目录和文件的所有者改为
mysql用户。这一步极其重要! 因为后续启动MySQL时是用mysql用户的身份运行的。如果权限不对,MySQL无法写入数据或日志,直接启动失败。
3. 初始化数据
bash
/application/mysql/scripts/mysql_install_db
--user=mysql
--defaults-file=/data/3307/my.cnf
--basedir=/application/mysql --datadir=/data/3307/data
- 解释:这是数据库奠基仪式。
- 作用:它会去读取你写的
my.cnf,然后在datadir目录下生成MySQL的基础系统库(比如mysql库、performance_schema库等)。没有这一步,启动数据库会报错说找不到系统表。 - 教程特意标注:
#初始化3307数据,每条命令需要间隔若干秒,否则失败。 - 为什么必须间隔? 当你连续敲这三条命令时,系统资源(CPU、磁盘 IO)可能还没释放完,或者是前一个临时进程的锁还没释放。强行连续执行会导致后一个卡死或报错。必须等前一个
mysql_install_db命令完全执行完(回到命令提示符)之后,再执行下一个。 - 你的错误复盘:上一张图,是在 3307 的
mysqld已经启动(占用端口和资源)的情况下,又去执行mysql_install_db,这违背了“先初始化,再启动”的铁律,所以卡死了。
- 作用:它会去读取你写的
4.启动多实例
bash
mysqld_safe --defaults-file=/data/3307/my.cnf &
mysqld_safe --defaults-file=/data/3308/my.cnf &
mysqld_safe --defaults-file=/data/3309/my.cnf &
- 解释:初始化完成后,终于可以启动了。
- 使用
mysqld_safe启动(这是官方推荐的启动方式,它会监控mysqld进程,如果异常挂掉会自动重启)。 - 加上
&让它后台运行,否则你的终端会被第一个启动的实例卡住。
5. 登录并设置密码
bash
mysql -S /data/3307/mysql.sock -uroot
- 解释:初始化后,root 用户默认没有密码。
- 注意这里的
-S /data/3307/mysql.sock。因为你有三个实例,你直接敲mysql -uroot,系统不知道该连哪个。必须通过指定-S(socket) 参数,明确告诉客户端你要连 3307 这个实例。
bash
mysqladmin -S /data/3307/mysql.sock -uroot password '123456'
- 解释:给 3307 实例的 root 用户设置密码为
123456。

6. 验证实例(查看 server_id)
bash
mysql -S /data/3307/mysql.sock -e "show variables like 'server_id'" -p123456
mysql -S /data/3308/mysql.sock -e "show variables like 'server_id'" -p123456
mysql -S /data/3309/mysql.sock -e "show variables like 'server_id'" -p123456
- 解释:分别连接三个实例,查看它们各自的
server_id。 - 如果 3307 返回 7,3308 返回 8,3309 返回 9,说明你的多实例部署完全成功,它们各自独立工作了。

正确的梳理流程应是:
1. 创建目录和配置文件。
2. 赋予 mysql 用户权限。
3. 依次、逐个执行 `mysql_install_db` 初始化(务必等前一个结束)。
4. 分别使用 `mysqld_safe` 启动服务。
5. 通过 `-S` 指定 socket 进行单独管理。
mysqladmin
- “强制回应 (Ping)”服务器
- 关闭服务器
- 创建和删除数据库
- 显示服务器和版本信息
- 显示或重置服务器状态变量
- 设置口令
- 重新刷新授权表
- 刷新日志文件和高速缓存
- 启动和停止复制
[root@localhost ~]# mysqladmin -uroot -p123456 create hellodb
[root@localhost ~]# mysqladmin -uroot -p123456 drop hellodb
[root@localhost ~]# mysqladmin -uroot -p123456 ping 检查服务端状态的
[root@localhost ~]# mysqladmin -uroot -p123456 status 服务器运行状态
[root@localhost ~]# mysqladmin -uroot -p123456 status 服务器状态 --sleep 2 --count 10 每两秒钟显示
一次服务器实时状态一共显示10次
[root@localhost ~]# mysqladmin -uroot -p123456 extended-status 显示状态变量
[root@localhost ~]# mysqladmin -uroot -p123456 variables 显示服务器变量
[root@localhost ~]# mysqladmin -uroot -p123456 flush-privileges 数据库重读授权表,等同于reload
[root@localhost ~]# mysqladmin -uroot -p123456 flush-tables 关闭所有已经打开的表
[root@localhost ~]# mysqladmin -uroot -p123456 flush-threds 重置线程池缓存
[root@localhost ~]# mysqladmin -uroot -p123456 flush-status 重置大多数服务器状态变量
[root@localhost ~]# mysqladmin -uroot -p123456 flush-logs 日志滚动。主要实现二进制和中继日志滚动
[root@localhost ~]# mysqladmin -uroot -p123456 flush-hosts 清楚主机内部信息
[root@localhost ~]# mysqladmin -uroot -p123456 kill 杀死线程
[root@localhost ~]# mysqladmin -uroot -p123456 refresh 相当于同时执行flush-hosts flush-logs
[root@localhost ~]# mysqladmin -uroot -p123456 shutdown 关闭服务器进程
[root@localhost ~]# mysqladmin -uroot -p123456 version 服务器版本以及当前状态信息
[root@localhost ~]# mysqladmin -uroot -p123456 start-slave 启动复制,启动从服务器复制线程
[root@localhost ~]# mysqladmin -uroot -p123456 stop-slave 关闭复制线程
mysqldump
- 备份数据库和表的内容
# 备份所有数据库
mysqldump -uroot -p123456 --all-databases > /backup/mysqldump/all.db
-A > /backup/mysqldump/all.db
# 备份指定数据库
mysqldump -uroot -p123456 wordpress > /backup/mysqldump/wordpress.db
# 备份指定数据库指定表(多个表以空格间隔)
mysqldump -uroot -p123456 wordpress t1 > /backup/mysqldump/t1.db
# 备份指定数据库排除某些表
mysqldump -uroot -p123456 test --ignore-table=test.t1 --ignore-table=test.t2 > /backup/mysqldump/test2.db
- 还原的方法
# 注:在导入备份数据库前,db_name如果没有,是需要创建的; 而且与db_name.db中数据库名是一样的才可以导入
mysqladmin -uroot -p123456 create db_name
mysql -uroot -p123456 db_name < /backup/mysqldump/db_name.db
# source也可以还原数据库
mysql > use db_name
mysql > source /backup/mysqldump/db_name.db
第一部分:备份数据库和表的内容
核心工具是 mysqldump(MySQL 自带的逻辑备份工具)。它的基本公式是:
mysqldump [连接参数] [要备份的对象] > [导出的文件路径]
(注:> 是 Linux 的重定向符号,意思是不在屏幕上打印,而是把结果写入右边的文件里)。
1. 备份所有数据库
mysqldump -uroot -p123456 --all-databases > /backup/mysqldump/all.db
-A > /backup/mysqldump/all.db
--all-databases:关键参数,意思是把当前MySQL服务器里所有的数据库(包括系统库mysql、information_schema等)全部导出。> /backup/mysqldump/all.db:把导出的SQL语句保存到all.db这个文件中。- 适用场景:服务器整体迁移、全量冷备份。
2. 备份指定数据库
mysqldump -uroot -p123456 wordpress > /backup/mysqldump/wordpress.db
wordpress:写在连接参数后面,表示只备份名为wordpress的这个数据库.- 适用场景:只关心某一个业务库,不想备份其他无关的库。
3. 备份指定数据库指定表(多个表以空格间隔)
mysqldump -uroot -p123456 wordpress t1 > /backup/mysqldump/t1.db
- 这里的语法是:
mysqldump [连接参数] [数据库名] [表1] [表2] ... wordpress:这是数据库名。(注意:这里的wordpress是数据库名,不是用户名,指的是MySQL自带的系统数据库)。t1和t2:这是wordpress库里的两张表的名字。它们之间用空格隔开。- 作用:只备份
wordpress库里的t1表和t2表,其他表不管。 - 适用场景:误删了某几张核心表,只需要针对这几张表做单独备份。
4. 备份指定数据库排除某些表
bash
mysqldump -uroot -p123456 wordpress --ignore-table=wordpress.t1 --ignore-table=wordpress.t2 > /backup/mysqldump/wordpress_t.db
wordpress:备份wordpress数据库。--ignore-table=wordpress.t1:关键参数,意思是“忽略(不备份)wordpress库里的t1表”。--ignore-table=wordpress.t2:同上,忽略t2表。- 注意语法:写
--ignore-table时,必须带上数据库名.表名(如wordpress.t1)。 - 适用场景:数据库里有一张表特别大(比如几千万条日志数据),每次备份都很慢,就可以用这个命令把它排除掉,只备份其他重要的表。
第二部分:还原的方法
还原的本质就是把你之前备份出来的 .db(其实里面就是一堆SQL语句)重新执行一遍。图里给出了两种主流方式。
方式一:在 Linux 终端直接导入(不进入 MySQL 交互界面)
步骤 1:先创建目标数据库(如果不存在)
bash
mysqladmin -uroot -p123456 create db_name
mysqladmin:这是MySQL的管理工具。create db_name:创建一个名为db_name的空数据库。- 重点:备份文件里通常只包含“建表”和“插入数据”的语句,不包含“建库”语句(除非你全库备份时带了
--databases参数)。所以恢复前,你得先准备好一个空的“房子”。
步骤 2:导入数据
bash
mysql -uroot -p123456 db_name < /backup/mysqldump/db_name.db
- 这里的
<是输入重定向符号。意思是把右边的.db文件内容,作为输入喂给左边的mysql命令。 db_name:指定要导入到哪个数据库里。- 注意:这是一种“盲导”,如果过程中有报错,终端可能一闪而过,你很难察觉。
方式二:进入MySQL 交互界面导入
步骤 1:登录 MySQL 并选中数据库
sql
mysql -uroot -p123456 # 先登录进 MySQL
mysql> use db_name; # 选中你的目标数据库
步骤 2:使用 source 命令导入
sql
mysql> source /backup/mysqldump/db_name.db
source是MySQL客户端自带的一个命令。- 优点:当文件很大时,用
source导入,如果有SQL语法错误或者主键冲突,终端会明显地把报错信息打印出来,方便你排错。


- 备份指定库(
test.db):导出文件里通常没有CREATE DATABASE test;和USE test;。它仅仅是导出了一堆表和数据的SQL语句。

- 备份全库(
all.db):导出文件里包含CREATE DATABASE mysql;和USE mysql;等语句。

==总结==:
最稳妥的方式就是用同名数据库进行恢复。