1. MySQL常用SQL操作全景解析
作为从业十余年的数据库工程师,我整理了这份MySQL高频SQL操作手册,涵盖数据定义、查询优化、事务控制等核心场景。这些语句经过生产环境千亿级数据量的验证,可直接用于实际项目开发。
提示:所有SQL示例均基于MySQL 8.0版本,部分语法在5.7及以下版本可能需要调整
1.1 数据库与表结构操作
创建数据库时的字符集选择:
sql复制CREATE DATABASE inventory
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
- utf8mb4支持完整的Unicode字符(包括emoji)
- 排序规则选择
_ai_ci表示不区分重音和大小写 - 生产环境推荐使用
_as_cs区分重音
表结构设计规范示例:
sql复制CREATE TABLE products (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
sku VARCHAR(32) NOT NULL COMMENT '商品编码',
name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) UNSIGNED DEFAULT 0,
stock INT UNSIGNED DEFAULT 0,
category ENUM('电子','服装','食品') NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_sku (sku),
INDEX idx_category (category)
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
关键设计要点:
- 自增主键使用BIGINT应对未来数据增长
- 金额字段用DECIMAL避免浮点精度问题
- 时间字段自动维护创建和更新时间
- 压缩表节省存储空间
1.2 数据查询进阶技巧
窗口函数实战(MySQL 8.0+):
sql复制SELECT
product_id,
sale_date,
amount,
SUM(amount) OVER(PARTITION BY product_id ORDER BY sale_date) AS running_total,
RANK() OVER(PARTITION BY category ORDER BY amount DESC) AS sales_rank
FROM sales
WHERE sale_date BETWEEN '2023-01-01' AND '2023-12-31';
JSON数据处理:
sql复制-- 提取JSON字段
SELECT
order_id,
JSON_EXTRACT(customer_info, '$.name') AS customer_name,
JSON_EXTRACT(customer_info, '$.contact.phone') AS phone
FROM orders
WHERE JSON_CONTAINS(customer_info, '"VIP"', '$.tags');
-- 更新JSON字段
UPDATE products
SET specs = JSON_SET(specs, '$.weight', '2kg')
WHERE id = 1001;
1.3 复杂查询优化方案
分页查询优化:
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;
JOIN优化策略:
sql复制-- 使用STRAIGHT_JOIN强制连接顺序
SELECT STRAIGHT_JOIN a.*, b.detail
FROM main_table a
JOIN detail_table b ON a.id = b.main_id
WHERE a.status = 1;
-- 使用派生表减少连接数据量
SELECT a.*, d.detail
FROM main_table a
JOIN (
SELECT main_id, detail
FROM detail_table
WHERE is_valid = 1
) d ON a.id = d.main_id;
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 事务与锁机制深度应用
2.1 事务隔离级别实战
sql复制-- 设置事务隔离级别
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
-- 业务操作
COMMIT;
-- 查看当前隔离级别
SELECT @@transaction_isolation;
不同隔离级别的选择建议:
- 读已提交(READ COMMITTED):平衡一致性和性能的默认选择
- 可重复读(REPEATABLE READ):需要避免幻读的场景
- 串行化(SERIALIZABLE):金融等高一致性要求场景
2.2 行锁与间隙锁案例
sql复制-- 显式加锁查询
SELECT * FROM accounts
WHERE user_id = 1001
FOR UPDATE;
-- 间隙锁示例(防止幻读)
BEGIN;
SELECT * FROM orders
WHERE order_no > 'ORD20230000'
AND order_no < 'ORD20240000'
FOR UPDATE;
-- 其他会话无法在此范围内插入数据
COMMIT;
3. 性能优化专项SQL
3.1 索引使用黄金法则
索引失效的常见场景:
sql复制-- 1. 使用函数操作索引字段
SELECT * FROM users WHERE DATE(create_time) = '2023-01-01';
-- 2. 隐式类型转换
SELECT * FROM products WHERE sku = 10086; -- sku是VARCHAR类型
-- 3. 前导模糊查询
SELECT * FROM articles WHERE title LIKE '%优化%';
-- 4. 使用OR条件(除非所有字段都有索引)
SELECT * FROM orders WHERE status = 1 OR amount > 1000;
强制索引使用:
sql复制SELECT * FROM orders FORCE INDEX(idx_status)
WHERE status = 1 AND create_time > '2023-01-01';
3.2 EXPLAIN执行计划解析
sql复制EXPLAIN FORMAT=JSON
SELECT c.name, COUNT(o.id)
FROM customers c
JOIN orders o ON c.id = o.customer_id
WHERE c.vip_level > 3
GROUP BY c.id
HAVING COUNT(o.id) > 5;
关键指标解读:
- type列:从优到差 system > const > eq_ref > ref > range > index > ALL
- possible_keys:可能使用的索引
- key_len:使用的索引长度
- rows:预估扫描行数
- Extra:Using filesort/Using temporary需要重点关注
4. 运维管理必备SQL
4.1 数据库状态监控
sql复制-- 查看长事务
SELECT * FROM information_schema.innodb_trx
WHERE TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 60;
-- 锁等待检测
SELECT * FROM sys.innodb_lock_waits;
-- 表空间使用情况
SELECT
table_schema,
table_name,
ROUND(data_length/1024/1024,2) AS data_mb,
ROUND(index_length/1024/1024,2) AS index_mb
FROM information_schema.tables
ORDER BY data_length + index_length DESC;
4.2 用户与权限管理
sql复制-- 最小权限原则创建用户
CREATE USER 'report_user'@'192.168.1.%'
IDENTIFIED BY 'ComplexPwd123!';
-- 精确到列级别的权限控制
GRANT SELECT(order_id, amount), UPDATE(status)
ON order_db.orders
TO 'report_user'@'192.168.1.%';
-- 查看用户权限
SHOW GRANTS FOR 'report_user'@'192.168.1.%';
5. 实战经验与避坑指南
5.1 批量操作优化
大批量插入优化:
sql复制-- 低效方式(逐条插入)
INSERT INTO log_events VALUES (...);
INSERT INTO log_events VALUES (...);
-- 推荐方式(批量插入)
INSERT INTO log_events VALUES
(...),
(...),
(...);
-- 文件导入方式
LOAD DATA INFILE '/tmp/data.csv'
INTO TABLE products
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n';
大批量更新策略:
sql复制-- 分批次更新(避免锁表时间过长)
UPDATE large_table
SET status = 0
WHERE id BETWEEN 1 AND 10000;
UPDATE large_table
SET status = 0
WHERE id BETWEEN 10001 AND 20000;
5.2 常见错误处理
死锁分析:
sql复制-- 查看最近死锁日志
SHOW ENGINE INNODB STATUS\G
-- 关键信息查看:
-- LATEST DETECTED DEADLOCK 部分
-- TRANSACTION 部分的事务信息
-- WAITING FOR THIS LOCK 等待的锁资源
数据修复技巧:
sql复制-- 安全删除重复数据
DELETE t1 FROM products t1
INNER JOIN (
SELECT sku, MIN(id) AS min_id
FROM products
GROUP BY sku
HAVING COUNT(*) > 1
) t2 ON t1.sku = t2.sku AND t1.id > t2.min_id;
6. 高级特性应用
6.1 公用表表达式(CTE)
sql复制-- 递归CTE生成日期序列
WITH RECURSIVE date_range AS (
SELECT '2023-01-01' AS date
UNION ALL
SELECT DATE_ADD(date, INTERVAL 1 DAY)
FROM date_range
WHERE date < '2023-01-31'
)
SELECT * FROM date_range;
-- 多级CTE复杂查询
WITH
sales_summary AS (
SELECT product_id, SUM(amount) AS total
FROM orders
GROUP BY product_id
),
top_products AS (
SELECT product_id
FROM sales_summary
ORDER BY total DESC
LIMIT 10
)
SELECT p.name, s.total
FROM top_products t
JOIN products p ON t.product_id = p.id
JOIN sales_summary s ON t.product_id = s.product_id;
6.2 生成列与函数索引
sql复制-- 虚拟生成列(不占用存储)
CREATE TABLE persons (
id INT PRIMARY KEY,
first_name VARCHAR(50),
last_name VARCHAR(50),
full_name VARCHAR(101) AS (CONCAT(first_name,' ',last_name)) VIRTUAL,
INDEX idx_fullname (full_name)
);
-- 函数索引(MySQL 8.0+)
CREATE TABLE logs (
id INT AUTO_INCREMENT PRIMARY KEY,
content TEXT,
created_at DATETIME,
INDEX idx_content_prefix ((LEFT(content,20)))
);
7. 数据迁移与ETL技巧
7.1 表结构迁移
sql复制-- 只复制结构不复制数据
CREATE TABLE new_orders LIKE orders;
-- 跨数据库迁移
CREATE TABLE db2.products SELECT * FROM db1.products
WHERE create_time > '2023-01-01';
-- 使用mysqldump导出特定表结构
-- mysqldump -u root -p --no-data dbname tablename > schema.sql
7.2 数据同步方案
基于binlog的增量同步:
sql复制-- 查看binlog位置
SHOW MASTER STATUS;
-- 解析binlog内容
SHOW BINLOG EVENTS IN 'mysql-bin.000001' FROM 12345 LIMIT 10;
-- 使用canal等工具实时同步
批量数据对比校验:
sql复制-- 使用CHECKSUM TABLE快速比对
CHECKSUM TABLE source_db.table1, target_db.table1;
-- 精确数据比对
SELECT
(SELECT COUNT(*) FROM db1.products) AS source_count,
(SELECT COUNT(*) FROM db2.products) AS target_count,
(SELECT COUNT(*) FROM db1.products p1
LEFT JOIN db2.products p2 ON p1.id = p2.id
WHERE p2.id IS NULL) AS missing_records;
8. 安全防护相关SQL
8.1 SQL注入防护
sql复制-- 使用预处理语句(Java示例)
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, username);
stmt.setString(2, password);
-- 动态SQL安全拼接
SET @sql = CONCAT('SELECT * FROM ', @table_name, ' WHERE id = ?');
PREPARE stmt FROM @sql;
EXECUTE stmt USING @id;
DEALLOCATE PREPARE stmt;
8.2 敏感数据保护
sql复制-- 数据脱敏查询
SELECT
id,
CONCAT(LEFT(name,1), '**') AS name,
CONCAT(LEFT(id_card,3), '***********') AS id_card
FROM customers;
-- 列级别加密
CREATE TABLE user_secrets (
id INT PRIMARY KEY,
secret_data VARBINARY(255),
KEY secret_key (id, LEFT(HEX(secret_data),8))
);
-- 插入加密数据
INSERT INTO user_secrets
VALUES (1, AES_ENCRYPT('敏感数据', 'encryption_key'));
