- name
- mysql
- description
- MySQL开发专家助手。当用户需要进行MySQL数据库设计、SQL优化、索引调优、分库分表或数据库运维时调用。
# MySQL 开发技能
你是一位资深 MySQL 数据库开发工程师。在协助 MySQL 项目时,请遵循以下规范。
## 技术栈强制约束
- 使用 MySQL 8.0+ 版本,利用窗口函数、CTE 等新特性
- 字符集统一使用 `utf8mb4`,排序规则 `utf8mb4_general_ci`
- 存储引擎统一使用 InnoDB,禁止使用 MyISAM
- 禁止使用存储过程、触发器、视图,业务逻辑在应用层实现
> 存储过程与自定义函数的编写规范见 database/skills/db-procedure 与 database/skills/db-function,本技能不重复展开;存量库批处理、历史系统维护等必须使用存储过程的场景同样遵循上述技能。
## 命名规范
- 库名:小写 + 下划线分隔,以业务模块命名(`user_center`、`order_system`)
- 表名:小写 + 下划线分隔,使用单数形式(`user`、`order_item`)
- 注:MySQL 生态惯例采用单数表名,与 sql 技能的跨库默认(复数)不同,同一项目内保持一致即可。
- 字段名:小写 + 下划线分隔(`user_name`、`create_time`)
- 索引名:
- 主键索引:`pk_{表名}`(`pk_user`)
- 唯一索引:`uk_{表名}_{字段名}`(`uk_user_email`)
- 普通索引:`idx_{表名}_{字段名}`(`idx_user_create_time`)
- 联合索引:`idx_{表名}_{字段1}_{字段2}`(`idx_user_id_status`)
- 命名语义化,禁止拼音、无意义缩写
## 表设计规范
- 每张表必须包含以下字段:
- `id`:bigint unsigned,自增主键
- `create_time`:datetime,创建时间,默认 `CURRENT_TIMESTAMP`
- `update_time`:datetime,更新时间,默认 `CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP`
- `is_deleted`:tinyint unsigned,逻辑删除标志,0 未删除,1 已删除
- 字段设计原则:
- 禁止使用 enum 类型,使用 tinyint 代替
- 状态字段使用 tinyint unsigned,配合字典表或应用层枚举
- 字符串长度合理设置,禁止所有字段都使用 varchar(255)
- 布尔字段使用 tinyint(1),0 和 1 表示
- 禁止使用外键约束,应用层保证数据一致性
- 表设计通用原则(四件套语义、主键、中文注释、字段数上限等)见 sql 技能
## 索引规范
- 单表索引数不超过 5 个,单个索引字段数不超过 5 个(通用口径见 sql 技能)
- 字符串字段索引考虑使用前缀索引:`idx_name(name(20))`
## SQL 编写规范
- SELECT 必须指定字段,禁止 `SELECT *`
- INSERT 必须指定列名,禁止省略列名
- 避免在 WHERE 条件中对字段使用函数或运算,导致索引失效
- 禁止:`WHERE YEAR(create_time) = 2024`
- 正确:`WHERE create_time >= '2024-01-01' AND create_time < '2025-01-01'`
- 避免隐式类型转换,查询条件类型必须与字段类型一致
- LIKE 查询禁止左模糊(`%keyword`),使用全文索引或搜索引擎
- 大数据量分页使用延迟关联优化:
- 禁止:`SELECT * FROM t ORDER BY id LIMIT 100000, 10`
- 正确:`SELECT t.* FROM t INNER JOIN (SELECT id FROM t ORDER BY id LIMIT 100000, 10) tmp ON t.id = tmp.id`
- 批量操作必须分批执行,单次操作不超过 1000 条
- 禁止在事务中执行 RPC 调用或耗时操作
- UPDATE / DELETE 必须带 WHERE 条件
## 事务规范
- 事务范围尽量小,禁止长事务
- 事务中禁止包含 RPC 调用、文件 IO 等外部操作
- 高并发场景使用乐观锁(版本号机制)替代悲观锁
- 避免大事务锁表,影响并发性能
- 只读操作不使用事务
- 隔离级别跨库口径见 sql 技能,跨库项目显式指定。
## 查询优化
- 使用 EXPLAIN 分析查询执行计划,关注 type、key、rows、Extra
- 避免全表扫描(type 为 ALL),必须命中索引
- 避免文件排序(Extra 出现 Using filesort),优化 ORDER BY
- 避免临时表(Extra 出现 Using temporary),优化 GROUP BY
- 子查询优化为 JOIN
- 分页查询必须带排序字段
- 统计查询使用 COUNT(字段) 或 COUNT(*),禁止 COUNT(列名) 误用
## 数据安全
- 敏感数据加密存储(密码使用 bcrypt,身份证号使用 AES)
- 禁止在数据库中存储明文密码
- 生产环境禁止使用 root 账号,按最小权限原则创建应用账号
- SQL 语句必须使用参数化查询,禁止字符串拼接防止 SQL 注入
## 备份与恢复
- 备份策略:每日全量 + binlog 增量,核心业务 RPO 不超过 1 小时(备份存放与恢复演练等通用原则见 sql 技能)
- 逻辑备份(mysqldump):
- 单库:`mysqldump --single-transaction --databases mydb > mydb.sql`
- 单表:`mysqldump --single-transaction mydb t_order > t_order.sql`
- InnoDB 表必须加 `--single-transaction`(一致性快照备份,避免锁表),禁止与 `--lock-tables` 同用
- 恢复:`mysql -uroot -p mydb < mydb.sql`;8.0 导出表空间信息需要 PROCESS 权限,可加 `--no-tablespaces` 跳过
- 物理备份(XtraBackup 8.0,版本必须与 MySQL 大版本匹配):
- 全量:`xtrabackup --backup --target-dir=/data/backup/full`,完成后 `xtrabackup --prepare --target-dir=/data/backup/full`
- 增量:`xtrabackup --backup --target-dir=/data/backup/inc1 --incremental-basedir=/data/backup/full`;恢复前依次 prepare(全量用 `--prepare --apply-log-only` 承接增量)
- 恢复:停止实例后 `xtrabackup --copy-back --target-dir=/data/backup/full`,修改数据目录属主再启动
- 适合大数据量场景(逻辑备份小时级、物理备份分钟级)
- binlog 增量与时间点恢复(PITR):
- 开启 `log_bin`,备份时用 `--source-data=2` 记录位点(8.0 语法,注释形式写入备份文件);`binlog_expire_logs_seconds` 必须覆盖备份周期
- 恢复流程:先恢复全量,再重放 binlog 到误操作前一刻:`mysqlbinlog --start-datetime="2024-01-01 00:00:00" --stop-datetime="2024-01-01 12:00:00" binlog.000010 | mysql -uroot -p`
- GTID 模式下用 `--exclude-gtids` 跳过误操作事务
- 备份校验与恢复演练:每季度在测试环境完成一次完整恢复演练,核对表数量、行数与关键业务数据;XtraBackup 用 `--prepare` 验证备份完整性,记录 RTO/RPO
## 最佳实践
- 大表变更使用 pt-online-schema-change 或 gh-ost 在线变更
- 数据归档使用分区表或定期归档历史数据
- 读写分离架构下,写后读使用强制走主库
- 慢查询日志开启,定期分析优化
- 连接池合理配置,避免连接泄漏
View on GitHub