1. MySQL命令手册概述
作为一名长期与MySQL打交道的开发者,我深知在日常工作中快速查找和正确使用MySQL命令的重要性。这份手册是我多年使用MySQL的经验总结,涵盖了从基础操作到高级特性的完整命令集,特别针对MySQL 8.0及以上版本进行了优化和验证。
MySQL作为最流行的关系型数据库之一,其命令体系庞大而复杂。新手常常会陷入文档海洋中找不到方向,而有经验的开发者也需要不时查阅特定命令的精确用法。本手册的目的就是提供一个结构清晰、内容全面的参考指南,让你在开发、运维和故障排查时能够快速找到所需命令。
手册中的每个命令都经过生产环境验证,包含了实际使用中的注意事项和性能考量。不同于官方文档的全面但冗长,这里只精选最常用、最有价值的命令,并附上我在实际项目中积累的使用技巧和避坑指南。
2. MySQL服务管理
2.1 服务启停与状态管理
在Linux环境下管理MySQL服务是每个DBA和开发者的基本功。以下是经过验证的服务管理命令:
bash复制# 启动MySQL服务(适用于systemd系统)
systemctl start mysqld
# 优雅停止MySQL服务(等待当前操作完成)
systemctl stop mysqld
# 强制重启MySQL服务(生产环境慎用)
systemctl restart mysqld
# 查看服务详细状态(检查是否正常运行)
systemctl status mysqld
# 设置开机自启(生产服务器必配)
systemctl enable mysqld
# 验证MySQL进程是否运行
ps -ef | grep mysql
注意:不同Linux发行版的服务名称可能略有差异,CentOS/RHEL通常是mysqld,而Ubuntu/Debian可能是mysql。如果命令不工作,先用
systemctl list-units | grep mysql确认服务名称。
2.2 客户端连接技巧
连接MySQL客户端看似简单,但有些技巧能显著提高工作效率:
bash复制# 基础本地连接(会提示输入密码)
mysql -u root -p
# 指定socket文件连接(当默认socket位置不同时)
mysql -u root -p -S /var/lib/mysql/mysql.sock
# 带密码连接(脚本中使用,但注意安全风险)
mysql -u root -p'your_password'
# 远程连接指定主机和端口
mysql -h db.example.com -P 3306 -u app_user -p
# 连接后直接使用特定数据库
mysql -u root -p my_database
# 连接时执行SQL并退出(自动化脚本有用)
mysql -u root -p -e "SHOW DATABASES;"
安全提示:生产环境绝对不要使用-p后直接跟密码的写法(会在进程列表暴露密码),建议使用配置文件或交互式输入密码。
3. 数据库操作全指南
3.1 数据库创建最佳实践
创建数据库时,字符集和排序规则的选择直接影响数据存储和查询行为:
sql复制-- 安全创建数据库(避免已存在时报错)
CREATE DATABASE IF NOT EXISTS inventory_db
CHARACTER SET utf8mb4 -- 完全支持Unicode,包括emoji
COLLATE utf8mb4_0900_ai_ci; -- MySQL 8.0推荐排序规则
-- 查看数据库字符集配置
SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME = 'inventory_db';
关键选择说明:
- utf8mb4 vs utf8:MySQL中的"utf8"实际上是阉割版(最多3字节),真正的UTF-8需要utf8mb4
- 排序规则选择:_general_ci速度较快,_unicode_ci更准确,8.0+推荐_0900系列
- 生产环境务必指定字符集,避免默认值不一致导致的问题
3.2 数据库维护命令
日常维护中常用的数据库级操作:
sql复制-- 切换当前数据库
USE inventory_db;
-- 查看当前使用的数据库
SELECT DATABASE();
-- 修改数据库属性(如需要调整字符集)
ALTER DATABASE inventory_db
CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
-- 安全删除数据库(避免不存在时报错)
DROP DATABASE IF EXISTS temp_db;
-- 查看所有数据库(过滤显示)
SHOW DATABASES LIKE '%inventory%';
-- 查看数据库大小(单位MB)
SELECT
table_schema AS 'Database',
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'Size (MB)'
FROM information_schema.TABLES
GROUP BY table_schema;
4. 数据表设计与操作
4.1 创建生产级数据表
一个符合生产标准的表创建语句应该包含以下要素:
sql复制CREATE TABLE IF NOT EXISTS products (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
sku VARCHAR(32) NOT NULL COMMENT '库存单位编码',
name VARCHAR(100) NOT NULL COMMENT '商品名称',
description TEXT COMMENT '详细描述',
price DECIMAL(10,2) UNSIGNED NOT NULL COMMENT '销售价格',
cost DECIMAL(10,2) UNSIGNED COMMENT '成本价格',
stock INT UNSIGNED DEFAULT 0 COMMENT '库存数量',
status ENUM('active','inactive','discontinued') NOT NULL DEFAULT 'active',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY uk_sku (sku),
KEY idx_status (status),
KEY idx_price (price)
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COMMENT='商品信息表';
设计要点解析:
- 主键选择:自增BIGINT适合大多数场景,分布式系统可考虑雪花ID
- 字段约束:NOT NULL保证数据完整性,DEFAULT提供默认值
- 时间戳:自动维护创建和更新时间,减轻应用负担
- 索引策略:主键、唯一索引、普通索引合理搭配
- 注释:每个字段和表都应添加注释,方便维护
4.2 表结构修改实战
随着业务发展,表结构调整是常态,但需要谨慎操作:
sql复制-- 添加新字段(指定位置和注释)
ALTER TABLE products
ADD COLUMN weight DECIMAL(6,2) COMMENT '商品重量(kg)' AFTER price;
-- 修改字段定义(不重命名)
ALTER TABLE products
MODIFY COLUMN description VARCHAR(500) COMMENT '商品简短描述';
-- 重命名字段(同时可修改类型)
ALTER TABLE products
CHANGE COLUMN cost unit_cost DECIMAL(10,2) UNSIGNED COMMENT '单位成本';
-- 删除字段(先确认无依赖)
ALTER TABLE products
DROP COLUMN obsolete_flag;
-- 添加复合索引
ALTER TABLE products
ADD INDEX idx_status_stock (status, stock);
-- 修改表注释
ALTER TABLE products
COMMENT='商品基础信息表(含库存)';
大表修改警告:对于数据量大的表,直接ALTER可能导致锁表。建议使用pt-online-schema-change工具或先在从库修改再主从切换。
5. 数据操作语言(DML)精要
5.1 高效数据插入技巧
sql复制-- 基础插入(指定列名,避免依赖列顺序)
INSERT INTO products (sku, name, price)
VALUES ('PROD001', '无线耳机', 199.99);
-- 批量插入(显著提高性能)
INSERT INTO products (sku, name, price) VALUES
('PROD002', '蓝牙音箱', 299.99),
('PROD003', '智能手表', 599.99),
('PROD004', '平板电脑', 899.99);
-- 插入或更新(避免先查询)
INSERT INTO products (sku, name, price)
VALUES ('PROD001', '无线耳机(新款)', 219.99)
ON DUPLICATE KEY UPDATE
name = VALUES(name),
price = VALUES(price),
updated_at = CURRENT_TIMESTAMP;
-- 从查询结果插入
INSERT INTO product_archive (id, sku, name)
SELECT id, sku, name FROM products
WHERE status = 'inactive';
性能提示:批量插入时,适当增加每批的记录数(如1000条)能减少网络往返开销,但要注意不要超过max_allowed_packet限制。
5.2 复杂查询构建
sql复制-- 基础查询(总是明确指定列)
SELECT id, sku, name, price FROM products
WHERE status = 'active'
ORDER BY price DESC;
-- 分页查询(必须加ORDER BY)
SELECT id, sku, name FROM products
WHERE stock > 0
ORDER BY created_at DESC
LIMIT 20 OFFSET 40; -- 第三页,每页20条
-- 聚合查询(带分组过滤)
SELECT
status,
COUNT(*) AS product_count,
AVG(price) AS avg_price,
SUM(stock) AS total_stock
FROM products
GROUP BY status
HAVING product_count > 5;
-- 多表连接(明确指定JOIN类型)
SELECT
p.sku,
p.name,
c.name AS category_name,
i.quantity
FROM products p
INNER JOIN categories c ON p.category_id = c.id
LEFT JOIN inventory i ON p.id = i.product_id
WHERE p.status = 'active'
AND c.visible = 1;
查询优化建议:
- 避免SELECT *,只查询需要的列
- JOIN查询确保关联字段有索引
- 大数据集分页考虑使用"游标分页"(基于ID范围)
- 复杂查询先用EXPLAIN分析执行计划
6. 事务与锁机制深度解析
6.1 事务控制实战
sql复制-- 开始事务(两种方式等效)
START TRANSACTION;
-- 或
BEGIN;
-- 执行多个DML操作
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
INSERT INTO transaction_log (from_acc, to_acc, amount) VALUES (1, 2, 100);
-- 根据业务逻辑决定提交或回滚
IF everything_ok THEN
COMMIT; -- 确认永久保存
ELSE
ROLLBACK; -- 撤销所有更改
END IF;
-- 查看当前事务隔离级别
SELECT @@transaction_isolation;
-- 设置事务隔离级别(会话级)
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
事务设计原则:
- 事务范围应尽可能小,减少锁持有时间
- 避免在事务中进行耗时操作(如网络请求)
- 生产环境默认使用REPEATABLE READ(MySQL默认)
- 高并发场景可考虑READ COMMITTED减少锁冲突
6.2 锁等待与死锁处理
sql复制-- 查看当前锁情况
SELECT * FROM performance_schema.data_locks;
SELECT * FROM performance_schema.data_lock_waits;
-- 查看最近死锁信息
SHOW ENGINE INNODB STATUS\G -- 查看LATEST DETECTED DEADLOCK部分
-- 设置锁等待超时(秒)
SET SESSION innodb_lock_wait_timeout = 30;
-- 主动获取行锁(FOR UPDATE)
START TRANSACTION;
SELECT * FROM products WHERE sku = 'PROD001' FOR UPDATE;
-- 其他会话尝试修改此行会被阻塞
UPDATE products SET stock = stock - 1 WHERE sku = 'PROD001';
COMMIT;
死锁预防策略:
- 事务以固定顺序访问表和行
- 减少事务大小和持续时间
- 对热点数据考虑使用乐观锁
- 适当降低隔离级别(如READ COMMITTED)
7. 索引设计与优化
7.1 索引创建策略
sql复制-- 创建普通索引
CREATE INDEX idx_product_name ON products(name);
-- 创建唯一索引(防止重复)
CREATE UNIQUE INDEX uk_product_sku ON products(sku);
-- 创建复合索引(注意列顺序)
CREATE INDEX idx_category_status ON products(category_id, status);
-- 创建前缀索引(节约空间)
CREATE INDEX idx_product_desc ON products(description(100));
-- 删除索引
DROP INDEX idx_product_name ON products;
-- 查看表索引
SHOW INDEX FROM products;
-- 分析索引使用情况
SELECT * FROM sys.schema_index_statistics
WHERE table_schema = 'inventory_db';
索引设计黄金法则:
- 为WHERE、JOIN、ORDER BY子句中的列创建索引
- 遵循最左前缀原则设计复合索引
- 高选择性列更适合索引(区分度高)
- 避免过度索引,写操作会有维护开销
7.2 查询性能分析
sql复制-- 使用EXPLAIN分析查询
EXPLAIN SELECT * FROM products WHERE category_id = 5 AND status = 'active';
-- 更详细的EXPLAIN格式
EXPLAIN FORMAT=JSON
SELECT p.* FROM products p
JOIN categories c ON p.category_id = c.id
WHERE c.name = 'Electronics';
-- 查看实际执行统计(需先启用)
SET SESSION optimizer_trace="enabled=on";
SELECT * FROM products WHERE price > 100;
SELECT * FROM information_schema.optimizer_trace;
SET SESSION optimizer_trace="enabled=off";
EXPLAIN关键指标解读:
- type:从优到差 system > const > eq_ref > ref > range > index > ALL
- possible_keys:可能使用的索引
- key:实际使用的索引
- rows:预估检查的行数
- Extra:额外信息(如Using filesort需要优化)
8. 用户权限与安全管理
8.1 精细化权限控制
sql复制-- 创建应用用户(限制访问来源IP)
CREATE USER 'app_user'@'192.168.1.%' IDENTIFIED BY 'ComplexP@ssw0rd';
-- 授予特定数据库的读写权限
GRANT SELECT, INSERT, UPDATE, DELETE ON inventory_db.* TO 'app_user'@'192.168.1.%';
-- 授予存储过程执行权限
GRANT EXECUTE ON PROCEDURE inventory_db.update_stock TO 'app_user'@'192.168.1.%';
-- 授予特定表的只读权限
GRANT SELECT ON inventory_db.products TO 'report_user'@'%';
-- 查看用户权限
SHOW GRANTS FOR 'app_user'@'192.168.1.%';
-- 回收权限
REVOKE DELETE ON inventory_db.* FROM 'app_user'@'192.168.1.%';
-- 修改密码(MySQL 8.0+)
ALTER USER 'app_user'@'192.168.1.%' IDENTIFIED BY 'NewComplexP@ssw0rd';
-- 锁定/解锁账户
ALTER USER 'temp_user'@'%' ACCOUNT LOCK;
ALTER USER 'temp_user'@'%' ACCOUNT UNLOCK;
权限管理最佳实践:
- 遵循最小权限原则
- 避免使用'%'作为主机名(限制访问来源)
- 定期审计用户权限
- 使用角色管理权限组(MySQL 8.0+)
8.2 安全加固措施
sql复制-- 检查空密码账户
SELECT user, host FROM mysql.user WHERE authentication_string = '';
-- 检查匿名账户
SELECT user, host FROM mysql.user WHERE user = '';
-- 删除测试数据库
DROP DATABASE IF EXISTS test;
-- 设置密码复杂度要求(MySQL 8.0+)
SET GLOBAL validate_password.policy = MEDIUM;
-- 查看插件加载情况
SHOW PLUGINS;
-- 启用SSL连接
ALTER USER 'app_user'@'%' REQUIRE SSL;
-- 配置密码过期策略
ALTER USER 'app_user'@'%' PASSWORD EXPIRE INTERVAL 90 DAY;
安全加固建议:
- 删除匿名账户和测试数据库
- 启用密码复杂度策略
- 限制root账户远程登录
- 定期轮换数据库密码
- 启用SSL加密连接
- 配置数据库审计日志
9. 备份恢复与运维监控
9.1 可靠备份策略
bash复制# 完整数据库备份(适合小型数据库)
mysqldump -u root -p --single-transaction --routines --triggers --events inventory_db > inventory_full.sql
# 分表备份(大型数据库)
mysqldump -u root -p --single-transaction --tables products categories > inventory_tables.sql
# 只备份结构(无数据)
mysqldump -u root -p --no-data inventory_db > inventory_schema.sql
# 只备份数据(无结构)
mysqldump -u root -p --no-create-info inventory_db > inventory_data.sql
# 压缩备份(节省空间)
mysqldump -u root -p inventory_db | gzip > inventory_db_$(date +%F).sql.gz
# 从备份恢复
mysql -u root -p inventory_db < inventory_full.sql
备份进阶技巧:
- 使用--single-transaction确保一致性(InnoDB)
- 大数据库考虑使用mydumper并行备份工具
- 定期验证备份文件完整性
- 实施3-2-1备份策略(3份副本,2种介质,1份离线)
9.2 性能监控与调优
sql复制-- 查看服务器状态
SHOW STATUS LIKE 'Threads_%'; -- 连接数
SHOW STATUS LIKE 'Innodb_buffer_pool%'; -- 缓冲池使用
-- 查看运行中的查询
SHOW PROCESSLIST;
SHOW FULL PROCESSLIST; -- 显示完整查询
-- 查看打开的表
SHOW OPEN TABLES WHERE In_use > 0;
-- 检查慢查询(需先启用慢查询日志)
SELECT * FROM mysql.slow_log ORDER BY start_time DESC LIMIT 10;
-- 查看表统计信息
ANALYZE TABLE products;
SHOW TABLE STATUS LIKE 'products';
-- 优化表(碎片整理)
OPTIMIZE TABLE products;
性能关键指标:
- 连接数:Threads_connected vs max_connections
- 查询缓存命中率:Qcache_hits / (Qcache_hits + Com_select)
- 缓冲池命中率:Innodb_buffer_pool_read_requests / (Innodb_buffer_pool_read_requests + Innodb_buffer_pool_reads)
- 锁等待:Innodb_row_lock_waits
10. 高级特性与技巧
10.1 窗口函数应用
sql复制-- 计算销售额排名
SELECT
product_id,
SUM(amount) AS total_sales,
RANK() OVER (ORDER BY SUM(amount) DESC) AS sales_rank
FROM orders
GROUP BY product_id;
-- 计算移动平均
SELECT
date,
daily_sales,
AVG(daily_sales) OVER (ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM (
SELECT DATE(order_time) AS date, SUM(amount) AS daily_sales
FROM orders
GROUP BY DATE(order_time)
) sales_by_day;
-- 计算同比环比
SELECT
month,
revenue,
LAG(revenue, 1) OVER (ORDER BY month) AS prev_month,
revenue - LAG(revenue, 1) OVER (ORDER BY month) AS mom_growth,
LAG(revenue, 12) OVER (ORDER BY month) AS prev_year,
revenue - LAG(revenue, 12) OVER (ORDER BY month) AS yoy_growth
FROM monthly_revenue;
10.2 JSON数据处理
sql复制-- 创建包含JSON列的表
CREATE TABLE product_attributes (
product_id BIGINT PRIMARY KEY,
attributes JSON NOT NULL,
INDEX idx_attributes ((CAST(attributes->'$.color' AS CHAR(20))))
);
-- 插入JSON数据
INSERT INTO product_attributes VALUES
(1, '{"color": "red", "size": "XL", "weight": 1.5, "tags": ["new", "sale"]}');
-- 查询JSON字段
SELECT
product_id,
attributes->'$.color' AS color,
attributes->>'$.size' AS size -- 去除引号
FROM product_attributes
WHERE attributes->'$.color' = '"red"';
-- 更新JSON字段
UPDATE product_attributes
SET attributes = JSON_SET(attributes, '$.color', 'blue', '$.sale_price', 19.99)
WHERE product_id = 1;
-- 提取JSON数组元素
SELECT
product_id,
JSON_EXTRACT(attributes, '$.tags[0]') AS first_tag
FROM product_attributes;
10.3 通用表表达式(CTE)
sql复制-- 递归CTE生成日期序列
WITH RECURSIVE date_series AS (
SELECT CURDATE() AS date
UNION ALL
SELECT date + INTERVAL 1 DAY
FROM date_series
WHERE date < CURDATE() + INTERVAL 30 DAY
)
SELECT * FROM date_series;
-- 使用CTE简化复杂查询
WITH monthly_sales AS (
SELECT
product_id,
DATE_FORMAT(order_date, '%Y-%m') AS month,
SUM(amount) AS revenue
FROM orders
GROUP BY product_id, DATE_FORMAT(order_date, '%Y-%m')
),
top_products AS (
SELECT product_id, AVG(revenue) AS avg_revenue
FROM monthly_sales
GROUP BY product_id
ORDER BY avg_revenue DESC
LIMIT 10
)
SELECT
p.name,
ms.month,
ms.revenue
FROM monthly_sales ms
JOIN products p ON ms.product_id = p.id
WHERE ms.product_id IN (SELECT product_id FROM top_products)
ORDER BY ms.month, ms.revenue DESC;
11. 生产环境避坑指南
11.1 常见性能问题
-
索引失效场景:
- 使用函数操作索引列:
WHERE MONTH(create_time) = 3 - 隐式类型转换:
WHERE product_id = '1001'(product_id是整数) - 使用OR条件:
WHERE status = 'active' OR price > 100 - 前导模糊查询:
WHERE name LIKE '%手机%'
- 使用函数操作索引列:
-
连接池配置:
- 合理设置连接池大小(通常CPU核心数*2 + 磁盘数)
- 监控连接等待时间,避免连接泄漏
- 使用连接池健康检查
-
批量操作优化:
- 大批量INSERT使用LOAD DATA INFILE替代
- 大批量UPDATE分批次进行(如每次1000条)
- 避免在事务中进行大批量操作
11.2 架构设计建议
-
分库分表策略:
- 水平拆分:按ID范围、哈希或时间分片
- 垂直拆分:按业务模块分离
- 使用中间件(如ShardingSphere)或应用层路由
-
读写分离实现:
- 使用主从复制
- 应用层路由或中间件代理
- 注意主从延迟问题
-
缓存策略:
- 热点数据使用Redis缓存
- 注意缓存一致性(双写或失效策略)
- 考虑多级缓存(本地缓存+分布式缓存)
12. 版本特性速查
12.1 MySQL 8.0重要新特性
-
窗口函数:
- RANK(), DENSE_RANK(), ROW_NUMBER()
- 各种窗口帧定义方式
-
通用表表达式(CTE):
- 非递归CTE提高查询可读性
- 递归CTE处理层次结构数据
-
JSON增强:
- JSON_TABLE()转换JSON为关系表
- JSON聚合函数JSON_ARRAYAGG(), JSON_OBJECTAGG()
-
原子DDL:
- DDL操作支持原子性
- 崩溃后自动回滚未完成的DDL
-
不可见索引:
- 标记索引为不可见(测试删除影响)
ALTER TABLE t ALTER INDEX i INVISIBLE;
12.2 MySQL 5.7 vs 8.0性能对比
-
读性能:
- 8.0在复杂查询上快2-10倍(得益于优化器改进)
- 窗口函数减少多次查询和客户端处理
-
写性能:
- 8.0在高并发写入时表现更好(改进的InnoDB)
- 原子DDL减少元数据锁争用
-
高可用:
- 8.0改进组复制性能
- 新增克隆插件简化备份
13. 实用脚本集锦
13.1 数据库健康检查
sql复制-- 检查数据库大小
SELECT
table_schema AS 'Database',
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'Size (MB)'
FROM information_schema.TABLES
GROUP BY table_schema
ORDER BY SUM(data_length + index_length) DESC;
-- 检查未使用的索引
SELECT
object_schema,
object_name,
index_name
FROM sys.schema_unused_indexes
WHERE object_schema NOT IN ('mysql', 'information_schema', 'performance_schema');
-- 检查表碎片率
SELECT
table_schema,
table_name,
ROUND(data_free / (data_length + index_length) * 100, 2) AS 'Fragmentation %'
FROM information_schema.TABLES
WHERE data_free > 0
ORDER BY (data_free / (data_length + index_length)) DESC
LIMIT 10;
13.2 用户权限审计
sql复制-- 列出所有用户及其权限
SELECT
user,
host,
IF(plugin = 'mysql_native_password', 'Legacy', IF(plugin = 'caching_sha2_password', 'SHA2', plugin)) AS auth_method,
password_expired AS is_expired,
account_locked AS is_locked
FROM mysql.user
ORDER BY user, host;
-- 检查具有管理员权限的用户
SELECT
grantee,
privilege_type,
is_grantable
FROM information_schema.user_privileges
WHERE privilege_type = 'SUPER'
OR privilege_type = 'ALL PRIVILEGES';
-- 检查数据库级权限
SELECT
grantee,
table_schema,
group_concat(privilege_type) AS privileges
FROM information_schema.schema_privileges
GROUP BY grantee, table_schema
ORDER BY table_schema, grantee;
14. 性能优化实战案例
14.1 慢查询优化示例
问题查询:
sql复制SELECT * FROM orders
WHERE customer_id IN (
SELECT id FROM customers
WHERE registration_date > '2023-01-01'
)
AND order_date BETWEEN '2023-06-01' AND '2023-06-30'
ORDER BY total_amount DESC;
优化步骤:
-
使用EXPLAIN分析发现:
- customers表全表扫描
- orders表使用了低效的范围扫描
- 使用了filesort
-
优化方案:
sql复制-- 添加索引
ALTER TABLE customers ADD INDEX idx_reg_date (registration_date);
ALTER TABLE orders ADD INDEX idx_cust_order_date (customer_id, order_date);
-- 重写查询使用JOIN替代IN
SELECT o.*
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE c.registration_date > '2023-01-01'
AND o.order_date BETWEEN '2023-06-01' AND '2023-06-30'
ORDER BY o.total_amount DESC;
-- 进一步优化:使用覆盖索引
SELECT o.id, o.order_date, o.total_amount /* 只查询需要的列 */
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE c.registration_date > '2023-01-01'
AND o.order_date BETWEEN '2023-06-01' AND '2023-06-30'
ORDER BY o.total_amount DESC;
14.2 分页查询优化
低效分页:
sql复制SELECT * FROM large_table
ORDER BY create_time DESC
LIMIT 100000, 20; -- 越往后越慢
优化方案:
sql复制-- 方案1:使用索引覆盖+延迟关联
SELECT t.*
FROM large_table t
JOIN (
SELECT id
FROM large_table
ORDER BY create_time DESC
LIMIT 100000, 20
) tmp ON t.id = tmp.id;
-- 方案2:基于ID范围分页(假设ID和时间正相关)
SELECT * FROM large_table
WHERE id < last_seen_id -- 上一页最后一条记录的ID
ORDER BY create_time DESC
LIMIT 20;
15. 故障排查手册
15.1 常见错误处理
-
连接数耗尽:
sql复制-- 查看最大连接数 SHOW VARIABLES LIKE 'max_connections'; -- 临时增加连接数 SET GLOBAL max_connections = 500; -- 查看连接来源 SELECT user, host, db, command, time FROM information_schema.processlist ORDER BY time DESC; -
锁等待超时:
sql复制-- 查看当前锁等待 SELECT * FROM performance_schema.data_lock_waits; -- 设置更长的锁等待超时 SET SESSION innodb_lock_wait_timeout = 120; -- 终止阻塞的事务 KILL [process_id]; -
磁盘空间不足:
sql复制-- 查看数据库文件大小 SELECT table_schema, SUM(data_length + index_length) / 1024 / 1024 AS size_mb FROM information_schema.TABLES GROUP BY table_schema; -- 清理二进制日志 PURGE BINARY LOGS BEFORE '2023-06-01 00:00:00';
15.2 崩溃恢复流程
-
检查错误日志定位原因:
bash复制sudo tail -n 100 /var/log/mysql/error.log -
安全启动模式:
bash复制
mysqld_safe --skip-grant-tables --skip-networking & -
修复表:
sql复制REPAIR TABLE corrupted_table; -
InnoDB强制恢复(极端情况):
ini复制# 在my.cnf中添加 [mysqld] innodb_force_recovery = 4 # 1-6,数字越大恢复越激进 -
从备份恢复(最后手段):
bash复制
mysql -u root -p db_name < backup_file.sql
16. 监控与警报配置
16.1 关键监控指标
-
性能指标:
- 查询吞吐量:Com_select + Com_insert + Com_update + Com_delete
- 慢查询率:Slow_queries / Questions
- 缓存命中率:Innodb_buffer_pool_read_requests / (Innodb_buffer_pool_read_requests + Innodb_buffer_pool_reads)
-
资源指标:
- 连接数:Threads_connected / max_connections
- 线程缓存命中率:Threads_created / Connections
- 临时表:Created_tmp_tables / Created_tmp_disk_tables
-
复制指标(主从环境):
- 延迟:Seconds_Behind_Master
- IO/SQL线程状态:Slave_IO_Running, Slave_SQL_Running
16.2 Prometheus监控配置
yaml复制# mysqld_exporter配置示例
scrape_configs:
- job_name: 'mysql'
static_configs:
- targets: ['mysql-server:9104']
params:
collect[]:
- global_status
- info_schema.innodb_metrics
- info_schema.processlist
- info_schema.tables
- perf_schema.eventsstatements
- perf_schema.eventswaits
关键告警规则示例:
- 高连接数报警:
threads_connected / max_connections > 0.8 - 复制延迟报警:
mysql_slave_status_seconds_behind_master > 30 - 缓冲池命中率报警:
rate(mysql_global_status_innodb_buffer_pool_reads[1m]) / rate(mysql_global_status_innodb_buffer_pool_read_requests[1m]) > 0.1
17. 版本升级指南
17.1 升级前准备
-
兼容性检查:
sql复制-- 检查已弃用特性使用情况 SELECT * FROM sys.schema_deprecated; -- 检查可能受影响的SQL模式 SHOW VARIABLES LIKE 'sql_mode'; -
备份策略:
- 完整数据库备份
- 配置文件备份
- 用户权限导出
-
测试方案:
- 在测试环境验证升级过程
- 运行应用程序测试套件
- 性能基准测试对比
17.2 升级路径建议
-
5.7到8.0升级步骤:
bash复制# 1. 备份所有数据 mysqldump --all-databases --routines --events > full_backup.sql # 2. 停止MySQL服务 systemctl stop mysqld # 3. 安装新版本(使用官方repo) yum install mysql-community-server-8.0 # 4. 启动MySQL服务(自动升级) systemctl start mysqld # 5. 验证升级 mysql_upgrade -u root -p -
就地升级vs逻辑升级:
- 就地升级:速度快,但回滚困难
- 逻辑升级:导出/导入数据,更安全但耗时
-
升级后检查:
- 验证所有数据库和表
- 检查应用程序连接
- 监控性能指标
18. 云数据库特别注意事项
18.1 AWS RDS最佳实践
-
参数组配置:
- 创建自定义参数组
- 调整关键参数:
innodb_buffer_pool_size(建议为实例内存的75%)max_connections(根据实例规格调整)binlog_format=ROW
-
备份与恢复:
- 启用自动备份(保留期7-35天)
- 定期创建手动快照
- 测试从快照恢复流程
-
监控指标:
- CPUUtilization(<70%)
- FreeableMemory(>500MB)
- FreeStorageSpace(>20%)
- ReplicaLag(<30s)
18.2 阿里云RDS优化建议
-
只读实例使用:
- 报表查询路由到只读实例
- 设置读写分离权重
- 监控只读实例延迟
-
白名单配置:
- 仅允许应用服务器IP访问
- 区分生产/测试环境访问权限
- 定期审计IP列表