1. MySQL 常用 SQL 语句全景指南
作为关系型数据库的标杆产品,MySQL 在日常开发中占据着不可替代的地位。无论是简单的数据查询还是复杂的业务逻辑处理,掌握核心 SQL 语句都是每位开发者的必修课。本文将系统梳理 MySQL 中最实用、最高频的 SQL 语句,涵盖数据定义、操作、查询、控制等全场景,并结合实际案例演示最佳实践。
提示:本文所有示例基于 MySQL 8.0 版本,部分语法在早期版本可能不兼容
1.1 数据库生命周期管理
创建数据库时推荐明确指定字符集和排序规则,避免后期出现乱码问题:
sql复制CREATE DATABASE inventory
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
查看数据库元信息时,SHOW CREATE DATABASE 比简单的 SHOW DATABASES 能获取更多配置细节:
sql复制SHOW CREATE DATABASE inventory;
删除数据库前务必先确认无业务连接,生产环境建议先重命名观察再删除:
sql复制RENAME DATABASE inventory TO inventory_backup;
DROP DATABASE inventory_backup;
1.2 表结构设计最佳实践
创建用户表时典型字段配置示例:
sql复制CREATE TABLE users (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL COMMENT '登录账号',
password_hash CHAR(60) NOT NULL COMMENT 'BCrypt加密密码',
email VARCHAR(100) UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
INDEX idx_username (username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
修改表结构时推荐使用 ALTER TABLE ... ALGORITHM=INPLACE 减少锁表时间:
sql复制ALTER TABLE users
ADD COLUMN mobile VARCHAR(20) AFTER email,
ALGORITHM=INPLACE;
1.3 数据操作黄金法则
批量插入时使用 VALUES 语法可提升 10 倍以上性能:
sql复制INSERT INTO products (name, price, stock) VALUES
('iPhone 15', 7999, 100),
('MacBook Pro', 12999, 50),
('AirPods Pro', 1999, 200);
UPDATE 操作必须带 WHERE 条件,生产环境建议先 SELECT 确认:
sql复制-- 先查询确认
SELECT * FROM orders WHERE status = 'pending' AND created_at < '2023-01-01';
-- 再执行更新
UPDATE orders SET status = 'expired'
WHERE status = 'pending' AND created_at < '2023-01-01'
LIMIT 1000; -- 大批量更新时分批执行
1.4 查询优化实战技巧
多表连接时明确指定连接方式可优化执行计划:
sql复制SELECT o.order_no, u.username, p.name
FROM orders o FORCE INDEX (PRIMARY)
INNER JOIN users u ON o.user_id = u.id
LEFT JOIN products p ON o.product_id = p.id
WHERE o.status = 'completed'
AND o.created_at BETWEEN '2023-01-01' AND '2023-12-31';
窗口函数实现复杂分析查询(MySQL 8.0+):
sql复制SELECT
product_id,
SUM(amount) AS total_sales,
RANK() OVER (ORDER BY SUM(amount) DESC) AS sales_rank,
SUM(SUM(amount)) OVER () AS grand_total,
SUM(amount)/SUM(SUM(amount)) OVER () AS sales_percentage
FROM order_items
GROUP BY product_id;
1.5 事务与锁机制深度解析
银行转账事务的完整实现:
sql复制START TRANSACTION;
-- 检查账户状态
SELECT balance INTO @balance FROM accounts WHERE user_id = 1001 FOR UPDATE;
-- 验证余额
IF @balance >= 5000 THEN
-- 扣款
UPDATE accounts SET balance = balance - 5000 WHERE user_id = 1001;
-- 入账
UPDATE accounts SET balance = balance + 5000 WHERE user_id = 1002;
-- 记录流水
INSERT INTO transactions VALUES(NULL, 1001, 1002, 5000, NOW());
COMMIT;
ELSE
ROLLBACK;
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Insufficient balance';
END IF;
1.6 索引优化全攻略
创建复合索引时遵循最左前缀原则:
sql复制-- 良好实践:将等值查询字段放前面,范围查询字段放后面
ALTER TABLE orders ADD INDEX idx_composite (user_id, status, created_at);
-- 以下查询能利用索引
SELECT * FROM orders
WHERE user_id = 1001 AND status = 'completed'
ORDER BY created_at DESC;
-- 以下查询只能部分利用索引
SELECT * FROM orders
WHERE status = 'completed' AND created_at > '2023-01-01';
使用 EXPLAIN ANALYZE 进行性能分析(MySQL 8.0.18+):
sql复制EXPLAIN ANALYZE
SELECT p.* FROM products p
JOIN product_tags pt ON p.id = pt.product_id
WHERE pt.tag_id IN (10, 20, 30)
GROUP BY p.id
HAVING COUNT(*) = 3;
1.7 存储过程与触发器
带错误处理的存储过程示例:
sql复制DELIMITER //
CREATE PROCEDURE process_order(IN order_id BIGINT)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
@sqlstate = RETURNED_SQLSTATE,
@errno = MYSQL_ERRNO,
@text = MESSAGE_TEXT;
INSERT INTO error_logs VALUES(NULL, 'process_order', @errno, @text, NOW());
ROLLBACK;
END;
START TRANSACTION;
-- 业务逻辑
UPDATE orders SET status = 'processing' WHERE id = order_id;
INSERT INTO order_processing_log VALUES(NULL, order_id, 'start', NOW());
COMMIT;
END //
DELIMITER ;
1.8 备份与恢复实战
使用 mysqldump 进行逻辑备份的关键参数:
bash复制mysqldump --single-transaction --routines --triggers \
--hex-blob --master-data=2 \
-u root -p inventory > inventory_backup.sql
时间点恢复操作流程:
sql复制-- 1. 恢复全量备份
mysql -u root -p inventory < inventory_backup.sql
-- 2. 应用binlog
mysqlbinlog --start-datetime="2023-12-01 00:00:00" \
--stop-datetime="2023-12-01 15:30:00" \
/var/lib/mysql/binlog.000123 | mysql -u root -p
1.9 性能监控与调优
关键性能指标查询语句:
sql复制-- 查看当前连接数
SHOW STATUS LIKE 'Threads_connected';
-- 查询缓存命中率
SHOW STATUS LIKE 'Qcache%';
-- InnoDB缓冲池状态
SHOW ENGINE INNODB STATUS;
-- 慢查询分析
SELECT * FROM mysql.slow_log
WHERE start_time > NOW() - INTERVAL 1 DAY
ORDER BY query_time DESC;
1.10 安全加固方案
创建最小权限用户的正确姿势:
sql复制CREATE USER 'app_user'@'192.168.1.%' IDENTIFIED BY 'ComplexP@ssw0rd';
GRANT SELECT, INSERT, UPDATE ON inventory.* TO 'app_user'@'192.168.1.%';
REVOKE ALTER, DROP ON *.* FROM 'app_user'@'192.168.1.%';
定期密码轮换策略:
sql复制ALTER USER 'app_user'@'192.168.1.%'
PASSWORD EXPIRE INTERVAL 90 DAY
FAILED_LOGIN_ATTEMPTS 5
PASSWORD_LOCK_TIME 1;
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 高频问题解决方案
2.1 死锁分析与处理
查看最近死锁记录:
sql复制SHOW ENGINE INNODB STATUS\G
典型死锁场景重现与解决:
sql复制-- 会话1
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1001;
UPDATE accounts SET balance = balance + 100 WHERE user_id = 1002;
-- 会话2 (同时执行)
START TRANSACTION;
UPDATE accounts SET balance = balance + 100 WHERE user_id = 1002;
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1001;
-- 解决方案:统一更新顺序
2.2 大数据量处理策略
分页查询优化方案:
sql复制-- 传统分页(性能差)
SELECT * FROM large_table LIMIT 1000000, 20;
-- 优化方案1:基于主键分页
SELECT * FROM large_table WHERE id > 1000000 ORDER BY id LIMIT 20;
-- 优化方案2:延迟关联
SELECT t.* FROM large_table t
JOIN (SELECT id FROM large_table ORDER BY create_time LIMIT 1000000, 20) tmp
ON t.id = tmp.id;
2.3 字符集问题排查
常见乱码问题诊断步骤:
sql复制-- 查看当前连接字符集
SHOW VARIABLES LIKE 'character_set%';
-- 检查表字段字符集
SELECT column_name, character_set_name, collation_name
FROM information_schema.columns
WHERE table_schema = 'inventory' AND table_name = 'products';
-- 转换字符集示例
ALTER TABLE products MODIFY COLUMN name VARCHAR(100)
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
3. 版本特性速览
3.1 MySQL 8.0 新特性应用
CTE (Common Table Expressions) 使用示例:
sql复制WITH regional_sales AS (
SELECT region, SUM(amount) AS total_sales
FROM orders
GROUP BY region
),
top_regions AS (
SELECT region
FROM regional_sales
WHERE total_sales > 1000000
)
SELECT r.region, p.name, SUM(o.amount) AS product_sales
FROM orders o
JOIN products p ON o.product_id = p.id
JOIN top_regions r ON o.region = r.region
GROUP BY r.region, p.name;
3.2 与 MariaDB 的语法差异
需要注意的主要区别:
sql复制-- MySQL 的 JSON 处理
SELECT JSON_EXTRACT('{"name":"John"}', '$.name');
-- MariaDB 的对应实现
SELECT JSON_VALUE('{"name":"John"}', '$.name');
-- MySQL 的窗口函数
SELECT RANK() OVER (PARTITION BY dept ORDER BY salary DESC);
-- MariaDB 10.2+ 也支持但实现细节可能有差异
4. 开发规范建议
4.1 SQL 编写禁忌清单
禁止使用的危险模式:
sql复制-- 1. 不带 WHERE 的 UPDATE/DELETE
UPDATE users SET status = 0; -- 灾难!
-- 2. 模糊查询前导通配符
SELECT * FROM products WHERE name LIKE '%apple%'; -- 无法用索引
-- 3. 隐式类型转换
SELECT * FROM orders WHERE order_no = 10001; -- order_no是varchar类型
-- 4. ORDER BY RAND()
SELECT * FROM products ORDER BY RAND() LIMIT 10; -- 全表扫描
4.2 数据库设计黄金法则
必须遵守的基本原则:
- 每个表必须有主键,且最好是自增整型
- 避免使用 ENUM 类型,用 tinyint 代替
- 文本字段必须明确字符集和排序规则
- 金额类数据使用 DECIMAL(20,4) 而非 FLOAT
- 大字段(如 TEXT/BLOB)单独建表存储
- 禁止在数据库中存储图片等二进制文件
5. 工具链集成
5.1 可视化工具配置技巧
MySQL Workbench 性能优化配置:
- 调整连接池大小:Edit → Preferences → SQL Editor → DBMS connection keep-alive interval
- 禁用自动提交:Session → Set Auto-Commit = OFF
- 优化结果显示:Query → Query Results → Limit Rows
5.2 命令行高效用法
mysql client 实用技巧:
bash复制# 执行外部SQL文件并记录输出
mysql -u root -p -vvv < script.sql > output.log 2>&1
# 批量执行多条语句
echo "SELECT NOW(); SELECT USER();" | mysql -u root -p
# 导出查询结果为CSV
mysql -u root -p -e "SELECT * FROM products" --batch | sed 's/\t/,/g' > products.csv
6. 生产环境checklist
上线前必须验证的项目:
- 所有SQL语句都有执行计划分析(EXPLAIN)
- 批量操作已测试锁表现象
- 事务隔离级别与业务需求匹配
- 备份恢复流程已验证
- 监控指标阈值已配置(连接数、QPS、慢查询等)
- 权限矩阵已按最小权限原则配置
