mysql-database-standard.md 18 KB

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

数据库连接配置

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}

📊 表结构设计规范

🔴 强制性基础字段(所有业务表必须包含)

每个业务表都必须包含以下基础字段:

-- 主键字段(必须)
`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. 应用层数据一致性

    // 在业务逻辑中维护关联关系
    @Transactional
    public void deleteUser(Long userId) {
        // 检查关联数据
        if (hasRelatedData(userId)) {
            throw new BusinessException("用户存在关联数据,无法删除");
        }
        // 执行删除
        userService.deleteById(userId);
    }
    
    1. 命名约定标识关联
    -- 通过字段命名明确标识关联关系
    `user_id` bigint(20) COMMENT '用户ID,关联sys_user表',
    `dept_id` bigint(20) COMMENT '部门ID,关联sys_dept表',
    `role_id` bigint(20) COMMENT '角色ID,关联sys_role表'
    
  2. 数据校验注解

    // 使用注解进行数据校验
    @Entity
    public class User {
        @NotNull
        @ExistReference(table = "sys_dept", field = "id")
        private Long deptId;
    }
    

    关联字段设计规范

    1. 命名规范
    • 关联字段必须以 _id 结尾
    • 字段名能够明确表达关联关系
    • 例如:user_id、parent_id、dept_id
    1. 注释要求
    `user_id` bigint(20) NOT NULL COMMENT '用户ID,关联sys_user.id',
    `parent_id` bigint(20) DEFAULT NULL COMMENT '父级ID,关联本表id,顶级为0',
    
  3. 索引设计

    -- 关联字段必须创建索引,提升查询性能
    KEY `idx_user_id` (`user_id`),
    KEY `idx_dept_id` (`dept_id`),
    

    数据一致性保障

    1. 业务层校验
    • 在 Service 层添加关联数据校验
    • 删除操作前检查关联数据
    • 使用事务确保操作原子性
    1. 定期数据校验
    -- 定期执行数据一致性检查脚本
    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;
    
  4. 监控和报警

    • 建立数据一致性监控
    • 发现数据不一致时及时报警
    • 记录详细的操作审计日志

🔍 索引设计规范

基础索引(必须创建)

每个表都必须创建以下基础索引:

-- 租户索引(必须)
KEY `idx_tenant_id` (`tenant_id`),

-- 删除标志索引(必须)
KEY `idx_deleted` (`deleted`),

-- 创建时间索引(建议)
KEY `idx_create_time` (`create_time`),

-- 组合索引:租户+删除标志(高效查询)
KEY `idx_tenant_deleted` (`tenant_id`, `deleted`)

业务索引规范

状态字段索引

KEY `idx_status` (`status`)

时间范围索引

KEY `idx_time_range` (`start_time`, `end_time`)

关联字段索引

-- 关联字段索引(注意:不使用外键约束)
KEY `idx_parent_id` (`parent_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_dept_id` (`dept_id`)

组合索引

-- 常用查询组合
KEY `idx_user_type_status` (`user_id`, `type`, `status`)

索引命名规范

  • 单列索引: idx_字段名
  • 组合索引: idx_字段1_字段2
  • 唯一索引: uk_字段名 或 uk_字段1_字段2

🏗️ 建表 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='表的中文描述';

系统配置表模板

-- 系统配置类表(如字典、参数等)
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='系统配置表';

关联关系表模板

-- 多对多关联表
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

迁移脚本结构

-- ==========================================
-- 数据库变更脚本
-- 版本: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 值设置合理
  • 默认值设置正确
  • 字段注释明确

索引设计检查清单

  • 基础索引已创建
  • 业务索引设计合理
  • 索引命名规范
  • 唯一约束正确
  • 组合索引顺序合理

🛠️ 工具和脚本

建表辅助脚本

-- 自动生成基础字段的存储过程
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 ;

表结构检查脚本

-- 检查缺失基础字段的表
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