Files
hzdyjs/docs/设计文档/database/mysql-database-standard.md

676 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MySQL 数据库建设规范(强制性)
## 📋 文档说明
**版本**: v1.0
**制定时间**: 2025-01-08
**适用范围**: 整个项目的所有数据库建表操作
**重要性**: ⚠️ **强制性规范** - 任何数据库相关开发都必须严格遵循本规范
---
## 🎯 总体原则
### 1. 一致性优先
- 所有业务表必须遵循统一的字段设计规范
- 统一使用标准的命名规范和数据类型
- 保持与现有数据库模型的高度一致性
### 2. 性能导向
- 优化查询性能,合理设计索引
- 控制表结构复杂度,避免过度冗余
- 考虑数据增长趋势,预留扩展空间
### 3. 安全可控
- 支持多租户数据隔离
- 统一的权限控制字段
- 完整的操作审计追踪
### 4. 可扩展性
- 预留扩展字段和机制
- 支持业务模块的独立发展
- 兼容未来功能需求
### 5. 可维护性
- 完整的中文注释说明
- 标准化的文档记录
- 便于理解和维护的结构设计
---
## 🔴 核心原则(强制执行)
### ⚠️ 强制性要求
1. **所有业务表**必须包含标准基础字段
2. **统一使用雪花 ID**作为主键
3. **强制使用逻辑删除**,禁止物理删除
4. **所有表必须支持多租户**
5. **完整的中文注释**是必须的
6. **禁止使用数据库外键约束**,关联关系通过应用层维护
---
## 🗄️ 数据库环境配置
### 基础配置要求
- **MySQL 版本**: 5.7.36+ (推荐 8.0+)
- **字符集**: utf8mb4
- **排序规则**: utf8mb4_general_ci
- **存储引擎**: InnoDB
- **时区**: Asia/Shanghai
### 数据库连接配置
```yaml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/hzdyjs_xg?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: ${DB_USERNAME:root}
password: ${DB_PASSWORD:password}
```
---
## 📊 表结构设计规范
### 🔴 强制性基础字段(所有业务表必须包含)
每个业务表都**必须**包含以下基础字段:
```sql
-- 主键字段(必须)
`id` bigint(20) NOT NULL COMMENT '主键ID',
-- 多租户字段(必须)
`tenant_id` varchar(20) NOT NULL DEFAULT '000000' COMMENT '租户编号',
-- 审计字段(必须)
`create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门',
`create_by` bigint(20) DEFAULT NULL COMMENT '创建者',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` bigint(20) DEFAULT NULL COMMENT '更新者',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
-- 逻辑删除字段(必须)
`deleted` tinyint(1) DEFAULT 0 COMMENT '删除标志(0代表存在 1代表删除)',
-- 主键定义(必须)
PRIMARY KEY (`id`) USING BTREE
```
### 字段设计细则
#### 主键字段 (id)
- **类型**: `bigint(20) NOT NULL`
- **策略**: 使用雪花 ID (ASSIGN_ID)
- **注释**: 主键 ID
- **强制要求**: 所有表必须使用此设计
#### 租户字段 (tenant_id)
- **类型**: `varchar(20) NOT NULL`
- **默认值**: '000000'
- **用途**: 多租户数据隔离
- **索引**: 必须创建索引
#### 审计字段
- **create_dept**: 创建部门 ID,记录数据创建的部门
- **create_by**: 创建人 ID,记录数据创建者
- **create_time**: 创建时间,自动记录数据创建时间
- **update_by**: 更新人 ID,记录最后更新者
- **update_time**: 更新时间,自动记录数据更新时间
#### 逻辑删除字段 (deleted)
- **类型**: `tinyint(1) DEFAULT 0`
- **含义**: 0-存在,1-已删除
- **强制要求**: 禁止物理删除,必须使用逻辑删除
---
## 📝 字段设计规范
### 数据类型选择
#### 字符串类型
- **varchar(n)**: 变长字符串,n≤255 时使用
- **text**: 长文本内容,如富文本、描述等
- **char(1)**: 固定长度字符,如状态标识
#### 数值类型
- **bigint(20)**: ID 类型字段(主键、外键)
- **int(11)**: 普通整数字段
- **decimal(m,n)**: 精确小数,如金额、评分
#### 时间类型
- **datetime**: 标准时间字段
- **timestamp**: 自动更新时间戳(特殊需求)
#### 布尔类型
- **tinyint(1)**: 布尔值,0-否,1-是
### 强制规则
#### 字段命名规范
- **使用小写字母**和下划线
- **见名知意**,避免缩写
- **统一后缀**:
- `_id`: ID 类型字段
- `_time`: 时间类型字段
- `_status`: 状态类型字段
- `_flag`: 标志类型字段
#### 字段长度规范
- **姓名字段**: varchar(50)
- **电话字段**: varchar(20)
- **邮箱字段**: varchar(100)
- **地址字段**: varchar(200)
- **标题字段**: varchar(200)
- **编码字段**: varchar(50)
#### NULL 值规范
- **主键**: NOT NULL
- **关联字段**: 根据业务需求确定
- **租户 ID**: NOT NULL
- **创建相关字段**: 可为 NULL
- **业务关键字段**: 建议 NOT NULL
---
## 🚫 外键约束规范(重要)
### 禁止使用数据库外键约束
#### 🔴 强制性原则
**项目中严格禁止使用数据库级别的外键约束(FOREIGN KEY),所有表关联关系通过应用层逻辑维护。**
#### 禁用外键约束的原因
1. **性能考虑**
- 外键约束会降低数据插入、更新、删除的性能
- 在高并发场景下会产生额外的锁开销
- 分库分表时外键约束会成为性能瓶颈
2. **灵活性要求**
- 支持数据库分库分表扩展
- 便于数据迁移和重构
- 避免循环依赖问题
3. **维护便利性**
- 简化数据库结构变更
- 减少约束冲突导致的部署问题
- 便于测试数据管理
#### 替代方案
1. **应用层数据一致性**
```java
// 在业务逻辑中维护关联关系
@Transactional
public void deleteUser(Long userId) {
// 检查关联数据
if (hasRelatedData(userId)) {
throw new BusinessException("用户存在关联数据,无法删除");
}
// 执行删除
userService.deleteById(userId);
}
```
2. **命名约定标识关联**
```sql
-- 通过字段命名明确标识关联关系
`user_id` bigint(20) COMMENT '用户ID,关联sys_user表',
`dept_id` bigint(20) COMMENT '部门ID,关联sys_dept表',
`role_id` bigint(20) COMMENT '角色ID,关联sys_role表'
```
3. **数据校验注解**
```java
// 使用注解进行数据校验
@Entity
public class User {
@NotNull
@ExistReference(table = "sys_dept", field = "id")
private Long deptId;
}
```
#### 关联字段设计规范
1. **命名规范**
- 关联字段必须以 `_id` 结尾
- 字段名能够明确表达关联关系
- 例如:`user_id`、`parent_id`、`dept_id`
2. **注释要求**
```sql
`user_id` bigint(20) NOT NULL COMMENT '用户ID,关联sys_user.id',
`parent_id` bigint(20) DEFAULT NULL COMMENT '父级ID,关联本表id,顶级为0',
```
3. **索引设计**
```sql
-- 关联字段必须创建索引,提升查询性能
KEY `idx_user_id` (`user_id`),
KEY `idx_dept_id` (`dept_id`),
```
#### 数据一致性保障
1. **业务层校验**
- 在 Service 层添加关联数据校验
- 删除操作前检查关联数据
- 使用事务确保操作原子性
2. **定期数据校验**
```sql
-- 定期执行数据一致性检查脚本
SELECT u.* FROM sys_user u
LEFT JOIN sys_dept d ON u.dept_id = d.id
WHERE u.dept_id IS NOT NULL AND d.id IS NULL;
```
3. **监控和报警**
- 建立数据一致性监控
- 发现数据不一致时及时报警
- 记录详细的操作审计日志
---
## 🔍 索引设计规范
### 基础索引(必须创建)
每个表都必须创建以下基础索引:
```sql
-- 租户索引(必须)
KEY `idx_tenant_id` (`tenant_id`),
-- 删除标志索引(必须)
KEY `idx_deleted` (`deleted`),
-- 创建时间索引(建议)
KEY `idx_create_time` (`create_time`),
-- 组合索引:租户+删除标志(高效查询)
KEY `idx_tenant_deleted` (`tenant_id`, `deleted`)
```
### 业务索引规范
#### 状态字段索引
```sql
KEY `idx_status` (`status`)
```
#### 时间范围索引
```sql
KEY `idx_time_range` (`start_time`, `end_time`)
```
#### 关联字段索引
```sql
-- 关联字段索引(注意:不使用外键约束)
KEY `idx_parent_id` (`parent_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_dept_id` (`dept_id`)
```
#### 组合索引
```sql
-- 常用查询组合
KEY `idx_user_type_status` (`user_id`, `type`, `status`)
```
### 索引命名规范
- **单列索引**: `idx_字段名`
- **组合索引**: `idx_字段1_字段2`
- **唯一索引**: `uk_字段名` 或 `uk_字段1_字段2`
---
## 🏗️ 建表 SQL 模板
### 标准业务表模板
```sql
-- ----------------------------
-- Table structure for 模块_表名
-- ----------------------------
DROP TABLE IF EXISTS `模块_表名`;
CREATE TABLE `模块_表名` (
-- 基础字段(必须)
`id` bigint(20) NOT NULL COMMENT '主键ID',
`tenant_id` varchar(20) NOT NULL DEFAULT '000000' COMMENT '租户编号',
`create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门',
`create_by` bigint(20) DEFAULT NULL COMMENT '创建者',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` bigint(20) DEFAULT NULL COMMENT '更新者',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`deleted` tinyint(1) DEFAULT 0 COMMENT '删除标志(0代表存在 1代表删除)',
-- 业务字段
`业务字段1` varchar(100) NOT NULL COMMENT '业务字段说明',
`业务字段2` text COMMENT '业务字段说明',
-- 关联字段(注意:不使用外键约束)
`user_id` bigint(20) DEFAULT NULL COMMENT '用户ID,关联sys_user.id',
`dept_id` bigint(20) DEFAULT NULL COMMENT '部门ID,关联sys_dept.id',
-- 状态和其他字段
`status` char(1) DEFAULT '0' COMMENT '状态(0正常 1停用)',
`sort_order` int(11) DEFAULT 0 COMMENT '排序',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
-- 主键和索引(注意:不创建外键约束)
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `uk_business_key` (`tenant_id`, `业务唯一字段`, `deleted`),
KEY `idx_tenant_id` (`tenant_id`),
KEY `idx_deleted` (`deleted`),
KEY `idx_status` (`status`),
KEY `idx_create_time` (`create_time`),
KEY `idx_user_id` (`user_id`),
KEY `idx_dept_id` (`dept_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='表的中文描述';
```
### 系统配置表模板
```sql
-- 系统配置类表(如字典、参数等)
CREATE TABLE `sys_配置表名` (
`id` bigint(20) NOT NULL COMMENT '主键ID',
`tenant_id` varchar(20) NOT NULL DEFAULT '000000' COMMENT '租户编号',
`create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门',
`create_by` bigint(20) DEFAULT NULL COMMENT '创建者',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` bigint(20) DEFAULT NULL COMMENT '更新者',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
-- 配置相关字段
`config_key` varchar(100) NOT NULL COMMENT '配置键',
`config_value` varchar(500) DEFAULT NULL COMMENT '配置值',
`config_type` char(1) DEFAULT 'N' COMMENT '系统内置(Y是 N否)',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `uk_config_key` (`config_key`, `tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统配置表';
```
### 关联关系表模板
```sql
-- 多对多关联表
CREATE TABLE `模块_关联表名` (
`id` bigint(20) NOT NULL COMMENT '主键ID',
`tenant_id` varchar(20) NOT NULL DEFAULT '000000' COMMENT '租户编号',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`create_by` bigint(20) DEFAULT NULL COMMENT '创建者',
-- 关联字段(注意:不使用外键约束)
`主表_id` bigint(20) NOT NULL COMMENT '主表ID,关联主表.id',
`从表_id` bigint(20) NOT NULL COMMENT '从表ID,关联从表.id',
-- 主键和索引(注意:不创建外键约束)
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `uk_relation` (`主表_id`, `从表_id`, `tenant_id`),
KEY `idx_主表_id` (`主表_id`),
KEY `idx_从表_id` (`从表_id`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='关联关系表';
```
---
## 🔄 数据迁移规范
### 迁移脚本命名
```
V{版本号}__{功能描述}.sql
例如:V1.0.1__add_user_table.sql
```
### 迁移脚本结构
```sql
-- ==========================================
-- 数据库变更脚本
-- 版本:V1.0.1
-- 功能:新增用户表
-- 作者:开发者姓名
-- 时间:2025-01-08
-- ==========================================
-- 新增表
CREATE TABLE IF NOT EXISTS `new_table` (
-- 表结构定义
);
-- 修改表(如果需要)
ALTER TABLE `existing_table`
ADD COLUMN `new_column` varchar(100) COMMENT '新字段说明';
-- 数据初始化(如果需要)
INSERT INTO `new_table` VALUES (...);
-- 创建索引(如果需要)
CREATE INDEX `idx_new_column` ON `existing_table` (`new_column`);
```
### 迁移注意事项
1. **向前兼容**:新增字段必须有默认值
2. **数据备份**:重要变更前必须备份
3. **灰度发布**:分步骤执行重大变更
4. **回滚方案**:准备对应的回滚脚本
---
## ⚡ 性能优化规范
### 查询优化
1. **避免 SELECT \***:明确指定需要的字段
2. **合理使用索引**:根据查询模式创建合适索引
3. **分页查询**:大数据量必须分页
4. **避免全表扫描**:WHERE 条件必须使用索引字段
### 表设计优化
1. **垂直分表**:字段过多时考虑分表
2. **水平分表**:数据量过大时考虑分表
3. **冗余设计**:适度冗余提升查询性能
4. **归档策略**:历史数据定期归档
### 索引优化
1. **组合索引**:多条件查询创建组合索引
2. **覆盖索引**:避免回表查询
3. **索引维护**:定期检查和优化索引
4. **避免冗余**:删除不必要的索引
---
## 🔒 安全规范
### 数据安全
1. **敏感数据加密**:密码、身份证等敏感信息
2. **数据脱敏**:测试环境使用脱敏数据
3. **访问控制**:基于角色的数据访问控制
4. **审计日志**:完整的数据变更日志
### 权限控制
1. **最小权限原则**:只授予必要的权限
2. **账号管理**:定期审查数据库账号
3. **密码策略**:强密码策略和定期更换
4. **网络安全**:限制数据库访问网络
### 备份策略
1. **定期备份**:每日全量备份
2. **增量备份**:实时或小时级增量备份
3. **异地备份**:关键数据异地存储
4. **恢复测试**:定期验证备份恢复
---
## ✅ 检查清单
### 新建表检查清单
- [ ] 包含所有强制基础字段
- [ ] 主键使用 bigint(20)类型
- [ ] 租户字段正确设置
- [ ] 逻辑删除字段存在
- [ ] 审计字段完整
- [ ] 表注释完整准确
- [ ] 字段注释完整
- [ ] **未使用外键约束**(重要)
- [ ] 关联字段命名规范(以\_id 结尾)
- [ ] 关联字段注释明确标识关联表
### 字段设计检查清单
- [ ] 字段命名符合规范
- [ ] 数据类型选择合理
- [ ] 字段长度设置适当
- [ ] NULL 值设置合理
- [ ] 默认值设置正确
- [ ] 字段注释明确
### 索引设计检查清单
- [ ] 基础索引已创建
- [ ] 业务索引设计合理
- [ ] 索引命名规范
- [ ] 唯一约束正确
- [ ] 组合索引顺序合理
---
## 🛠️ 工具和脚本
### 建表辅助脚本
```sql
-- 自动生成基础字段的存储过程
DELIMITER $$
CREATE PROCEDURE `add_base_fields`(IN table_name VARCHAR(64))
BEGIN
SET @sql = CONCAT('ALTER TABLE ', table_name, ' ADD COLUMN IF NOT EXISTS `tenant_id` varchar(20) NOT NULL DEFAULT ''000000'' COMMENT ''租户编号''');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 添加其他基础字段...
END$$
DELIMITER ;
```
### 表结构检查脚本
```sql
-- 检查缺失基础字段的表
SELECT
TABLE_NAME,
CASE
WHEN COLUMN_NAME IS NULL THEN CONCAT('缺少字段: ', required_field)
ELSE '字段存在'
END AS check_result
FROM (
SELECT 'tenant_id' AS required_field
UNION SELECT 'create_time'
UNION SELECT 'update_time'
UNION SELECT 'deleted'
) rf
CROSS JOIN INFORMATION_SCHEMA.TABLES t
LEFT JOIN INFORMATION_SCHEMA.COLUMNS c
ON t.TABLE_NAME = c.TABLE_NAME
AND c.COLUMN_NAME = rf.required_field
WHERE t.TABLE_SCHEMA = 'hzdyjs_xg'
AND t.TABLE_TYPE = 'BASE TABLE'
AND c.COLUMN_NAME IS NULL;
```
---
## 📚 参考示例
### 现有表结构参考
项目中已有的标准表结构可参考:
- `hq_hall_info` - 报告厅信息表
- `hq_hall_reservation` - 报告厅预约表
- `hq_sat_survey` - 问卷调查表
- `sys_user` - 用户表
- `sys_dict_data` - 字典数据表
### 命名示例
- **模块前缀**: `hq_`(后勤)、`sys_`(系统)、`gen_`(代码生成)
- **表名示例**: `hq_hall_info`、`sys_user_role`
- **字段示例**: `user_name`、`create_time`、`hall_status`
---
## ⚠️ 重要提醒
1. **强制性要求**:本规范所有标注为"必须"、"强制"的条目都是强制性的
2. **一致性保证**:新建表必须与现有表结构保持一致
3. **文档同步**:表结构变更必须同步更新文档
4. **Code Review**:所有数据库变更都需要进行代码审查
5. **测试验证**:新表结构必须经过充分测试验证
---
## 📞 技术支持
如有疑问或需要技术支持,请联系:
- **技术负责人**:项目技术负责人
- **文档维护**:定期更新和维护本规范
- **培训支持**:为团队成员提供规范培训
---
**最后更新**: 2025-01-08
**下次审查**: 2025-07-08