MySQL 命令速查
值班时最怕「知道该查什么,但想不起语法」。这一页把高频命令按场景分组,直接复制改参数就能用。
使用说明
- 示例默认在 MySQL 8.0 上执行,SQL 直接贴进客户端,
bash代码块的命令在 shell 里跑。 - 命令里的库名
shop、主机10.0.0.11、端口3306按实际替换。 - 8.0.23 起
CHANGE MASTER、START SLAVE等旧语法逐步废弃,新写法是REPLICATION SOURCE、REPLICA,两种都能用,建议统一用新的。
连接与信息
| 命令 | 说明 |
|---|---|
mysql -h 10.0.0.11 -P 3306 -u app -p shop | 连接指定库,-p 后不要直接跟密码 |
mysql --defaults-file=/etc/my.cnf -u root -p | 用指定配置文件连接,避免读到本机默认配置 |
SELECT VERSION(); | 服务器版本 |
SELECT USER(), CURRENT_USER(), CONNECTION_ID(); | 当前登录身份、实际匹配账号、连接 ID |
SHOW DATABASES; | 列出所有库 |
SHOW TABLES; / SHOW CREATE TABLE orders\G | 看表清单 / 看建表语句(含索引和引擎) |
SHOW VARIABLES LIKE 'datadir'; | 数据目录位置 |
SHOW VARIABLES LIKE '%character%'; | 字符集相关变量 |
SHOW GLOBAL STATUS LIKE 'Uptime'; | 已运行秒数,判断有没有偷偷重启过 |
SHOW PROCESSLIST; | 当前连接与执行状态(等价 SELECT * FROM information_schema.PROCESSLIST) |
SHOW FULL PROCESSLIST; | 带完整 SQL 文本,长语句不被截断 |
SHOW ENGINE INNODB STATUS\G | InnoDB 全景:死锁、事务、缓冲池、IO |
SELECT @@transaction_isolation; | 当前隔离级别 |
SHOW MASTER STATUS; | 主库 binlog 当前位点(8.2+ 也可 SHOW BINARY LOG STATUS) |
SHOW BINARY LOGS; | 列出所有 binlog 文件与大小 |
# 不进交互界面直接执行
mysql -h 10.0.0.11 -u app -p shop -e "SELECT COUNT(*) FROM orders;"
# 执行 SQL 文件
mysql -h 10.0.0.11 -u root -p shop < init.sql
# 导出表结构
mysql -h 10.0.0.11 -u root -p shop -e "SHOW CREATE TABLE orders\G"
用户权限
| 命令 | 说明 |
|---|---|
CREATE USER 'app'@'10.0.0.%' IDENTIFIED BY 'xxx'; | 建账号,host 支持 % 通配 |
ALTER USER 'app'@'10.0.0.%' IDENTIFIED BY 'new'; | 改密码 |
ALTER USER 'app'@'%' IDENTIFIED WITH mysql_native_password BY 'xxx'; | 换成老认证插件(仅兼容旧客户端时用) |
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.* TO 'app'@'10.0.0.%'; | 授权,按最小权限给 |
GRANT SELECT ON shop.* TO 'readonly'@'10.0.0.%'; | 只读账号 |
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'10.0.0.%'; | 复制账号必需权限 |
REVOKE DELETE ON shop.* FROM 'app'@'10.0.0.%'; | 回收权限 |
SHOW GRANTS FOR 'app'@'10.0.0.%'; | 看某账号的最终权限 |
DROP USER 'app'@'10.0.0.%'; | 删账号 |
SELECT User, Host, plugin FROM mysql.user; | 账号清单与认证插件 |
FLUSH PRIVILEGES; | 仅在直接改 mysql.user 表后需要 |
-- 排查「授权了却没权限」:看实际匹配到哪个账号
SELECT CURRENT_USER();
-- 查空密码账号(安全隐患)
SELECT User, Host, plugin FROM mysql.user WHERE authentication_string = '';
-- 锁定账号(离职交接时先锁不删)
ALTER USER 'app'@'10.0.0.%' ACCOUNT LOCK;
备份恢复
| 命令 | 说明 |
|---|---|
mysqldump -uroot -p --single-transaction --source-data=2 --all-databases > all.sql | 全库一致性备份并记录位点(8.0.26 之前参数叫 --master-data=2) |
mysqldump -uroot -p --single-transaction --databases shop > shop.sql | 单库备份(含 CREATE DATABASE) |
mysqldump -uroot -p --no-data shop orders > orders.sql | 只备份表结构 |
mysqldump -uroot -p --single-transaction --where="id<1000000" shop orders > part.sql | 按条件备份部分数据 |
mysqldump -uroot -p --routines --triggers --events --all-databases | 带上存储过程、触发器、事件 |
mysql -uroot -p < all.sql | 恢复全备 |
xtrabackup --backup --user=root --password=xxx --target-dir=/backup/full | 物理全备 |
xtrabackup --prepare --target-dir=/backup/full | 应用 redo,让备份可恢复 |
xtrabackup --copy-back --target-dir=/backup/full | 拷回数据目录(需先停库并清空 datadir) |
mysqlbinlog --start-datetime='2024-01-01 02:00:00' binlog.000001 | 从指定时间开始解析 binlog 内容 |
mysqlbinlog binlog.000001 > /tmp/inc.sql | 导出 binlog 为 SQL 文件,方便检查后再回放 |
mysql -uroot -p < /tmp/inc.sql | 回放 binlog 做时间点恢复 |
PURGE BINARY LOGS BEFORE '2024-01-01 00:00:00'; | 清理过期 binlog(别 rm) |
SHOW BINARY LOGS; | 确认清理结果 |
# 备份 + 压缩 + 记录时间,一条命令
mysqldump -uroot -p'xxx' --single-transaction --source-data=2 \
--routines --triggers --events --all-databases \
| gzip > /backup/full_$(date +%F_%H%M).sql.gz
# 恢复时先解压再导入
gunzip < /backup/full_2024-01-01_0200.sql.gz | mysql -uroot -p
恢复前确认三件事
- 目标实例的版本与字符集跟备份源一致;
gtid_purged不会和现有 GTID 冲突(用--set-gtid-purged=OFF或重置实例);- 备份文件校验过(
md5sum、行数抽查),别拿一个截断的文件往下恢复。
复制管理
| 命令 | 说明 |
|---|---|
CHANGE REPLICATION SOURCE TO SOURCE_HOST='10.0.0.11', SOURCE_USER='repl', SOURCE_PASSWORD='xxx', SOURCE_AUTO_POSITION=1; | 配置复制源(GTID 模式) |
CHANGE MASTER TO ... | 旧语法,8.0.23 前使用;新版本仍兼容 |
START REPLICA; / STOP REPLICA; | 启停复制(旧语法 START SLAVE) |
STOP REPLICA SQL_THREAD; / START REPLICA SQL_THREAD; | 只操作回放线程,IO 继续拉日志 |
SHOW REPLICA STATUS\G | 复制状态,重点看 Running 与延迟 |
SHOW REPLICA STATUS\G 中的 Retrieved_Gtid_Set / Executed_Gtid_Set | 已拉取 / 已执行的 GTID 集合 |
SHOW PROCESSLIST; | 主库上能看到每个从库的 dump 线程 |
RESET REPLICA ALL; | 清空复制配置(重建从库前用) |
SET GLOBAL rpl_semi_sync_source_enabled = ON; | 开半同步(主库,需先装插件) |
SELECT * FROM performance_schema.replication_applier_status_by_worker; | 并行复制各 worker 的回放状态 |
SELECT @@gtid_mode, @@enforce_gtid_consistency; | 确认 GTID 状态 |
-- 判断从库是否追平:两个集合相等就是追平
SHOW REPLICA STATUS\G
-- Retrieved_Gtid_Set: 3e11fa47-...:1-10523
-- Executed_Gtid_Set: 3e11fa47-...:1-10523
-- 从库看复制通道的连接状态(主库上查是空的)
SELECT CHANNEL_NAME, SERVICE_STATE, LAST_ERROR_MESSAGE
FROM performance_schema.replication_connection_status;
跳过一条报错事务
STOP REPLICA SQL_THREAD;
SET GTID_NEXT = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:100';
BEGIN; COMMIT;
SET GTID_NEXT = 'AUTOMATIC';
START REPLICA SQL_THREAD;
跳过之后主从数据就不一致了,务必记录跳过的 GTID 并安排校验修复。
诊断查询
| 命令 | 说明 |
|---|---|
SHOW GLOBAL STATUS LIKE 'Threads_connected'; | 当前连接数 |
SHOW GLOBAL STATUS LIKE 'Threads_running'; | 正在执行的线程数(比 connected 更能反映压力) |
SHOW GLOBAL STATUS LIKE 'Max_used_connections'; | 历史连接峰值 |
SHOW VARIABLES LIKE 'max_connections'; | 连接上限 |
SHOW GLOBAL STATUS LIKE 'Questions'; | 累计语句数,算 QPS 用 |
SHOW GLOBAL STATUS LIKE 'Com_commit'; | 累计提交数,算 TPS 用 |
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads'; | 物理读次数,算命中率用 |
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read_requests'; | 逻辑读次数 |
SHOW GLOBAL STATUS LIKE 'Slow_queries'; | 累计慢查询数 |
SHOW VARIABLES LIKE 'slow_query_log%'; | 慢日志开关与文件位置 |
SHOW VARIABLES LIKE 'long_query_time'; | 慢查询阈值 |
SHOW VARIABLES LIKE 'innodb_lock_wait_timeout'; | 锁等待超时秒数 |
SELECT * FROM information_schema.INNODB_TRX; | 当前所有事务(含长事务) |
SELECT * FROM performance_schema.data_locks; | 当前持有的锁(8.0 替代 INNODB_LOCKS) |
SELECT * FROM performance_schema.data_lock_waits; | 锁等待关系 |
SELECT * FROM sys.innodb_lock_waits; | 锁等待的人话版视图 |
SELECT * FROM sys.statement_analysis LIMIT 10; | 按耗时排 TOP SQL |
SELECT * FROM sys.schema_unused_indexes; | 从未被使用的索引 |
SELECT * FROM sys.schema_redundant_indexes; | 冗余索引 |
KILL CONNECTION 12345; | 断开连接(8.0 语法,KILL QUERY 只终止语句) |
EXPLAIN SELECT ...; | 看执行计划 |
EXPLAIN ANALYZE SELECT ...; | 实际执行并给出真实耗时(8.0.18+) |
ANALYZE TABLE orders; | 刷新统计信息,修执行计划跑偏 |
OPTIMIZE TABLE orders; | 重建表回收碎片(大表用 gh-ost) |
SHOW WARNINGS; | 上一条语句的警告,排查隐式转换很有用 |
-- 一条 SQL 看全实例健康度
SELECT
(SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME='Threads_connected') AS conn,
(SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME='Threads_running') AS running,
(SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME='Slow_queries') AS slow_total,
(SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME='Uptime') AS uptime_sec;
-- 找长事务(超过 60 秒)
SELECT trx_id, trx_state,
TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS seconds,
trx_rows_locked, trx_rows_modified, LEFT(trx_query, 80) AS sql_head
FROM information_schema.INNODB_TRX
WHERE TIMESTAMPDIFF(SECOND, trx_started, NOW()) > 60
ORDER BY seconds DESC;
别在生产随便跑这些
OPTIMIZE TABLE、ANALYZE TABLE、CHECK TABLE 在大表上都会带来真实的 IO 压力,OPTIMIZE 还会锁表。诊断类命令里,EXPLAIN ANALYZE 会真正执行 SQL,SELECT COUNT(*) 在大表上也是全扫。执行前先想清楚代价。