MySQL数据库规范
规范背景和目的
MySQL数据库与 Oracle、SQL Server 等数据库相比,有其内核上的优势与劣势,我们在使用MySQL数据库的时候需要遵循一定规范,扬长避短。本规范旨在帮助或指导开发人员做出适合线上业务的数据库设计,在数据库变更、数据库表设计、SQL编写等方面予以规范,从而为公司业务系统稳定、健康地运行提供保障。
适用范围及监管
本规范暂时仅适用于新、旧系统中新建立的数据库、表、SQL语句等,对于已经在使用的,不做强制要求,可以在后续的变更中逐步按照规范进行调整。
数据库设计规范
建表规范
- MySQL表必须包含主键,且必须为自增列,类型根据数据量规划选择int或bigint。
- 所有表必须包含updated_at且必须添加索引,该字段属性为 datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP (数据库自动更新,无需业务系统对其进行更新)。
- 表及表字段需添加注释。
- MySQL表字符集仅支持utf8和utf8mb4,存储引擎仅支持Innodb。
- 如业务要求对MySQL表中数据记录区分大小写,建表语句中需指定collate为utf8mb4_bin,否则忽略该属性使用默认值。
- 禁止使用外键。
- 禁止使用MySQL关键字作库、表或字段名。(https://dev.mysql.com/doc/refman/5.6/en/keywords.html)
- 对于库名、表名、字段名等使用有意义的英文词汇,词汇中间以下划线分割,禁止超过32个字符,禁止使用中文,禁止使用大写字母。
- 建表时,表格式使用默认Dynamic,禁止使用其它格式。
建表示例如下:
create table t_user(
id bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
user_id bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '用户id',
username varchar(45) NOT NULL DEFAULT '' COMMENT '真实姓名',
email varchar(30) NOT NULL DEFAULT '' COMMENT '用户邮箱',
nickname varchar(45) NOT NULL DEFAULT '' COMMENT '昵称',
avatar int(11) unsigned NOT NULL DEFAULT 0 COMMENT '头像',
birthday date NOT NULL DEFAULT '1000-01-01' COMMENT '生日',
sex tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT '性别',
short_introduce varchar(50) not null DEFAULT '' COMMENT '一句话介绍自己,最多 50个汉字',
user_resume varchar(200) NOT NULL DEFAULT '' COMMENT '用户提交的简历存放地址',
created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '用户记录创建的时间',
updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
user_review_status tinyint(4) unsigned NOT NULL DEFAULT 4 COMMENT '用户资料审核状态,1 为通过,2 为审核中,3 为未通过,4 为还未提交审核',
is_del tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否删除 0:未删除 1:已删除',
PRIMARY KEY (id),
UNIQUE KEY uk_user_id (user_id),
KEY idx_username(username),
KEY idx_createdat_userreviewstats(created_at,user_review_status),
KEY idx_updatedat(updated_at)
) CHARACTER SET=utf8mb4 COMMENT='用户基本信息' ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
字段规范
- 禁止在主表中使用TEXT或BLOB类型,VARCHAR字段性能比TEXT高,可用于替换TEXT类型;如有特殊需求必须使用TEXT,需将TEXT类型与主表分离,使用业务字段冗余进行关联,禁止使用无业务意义的数据库自增id对其进行关联。(也可以考虑将大对象内容存文件,在数据库表中存放这个文件的存储路径和文件名。)
- 对除TEXT、BLOB等大对象类型以外的字段均定义为NOT NULL并设置默认值。
- 禁止修改字段类型(可以修改长度),禁止修改已上线表字段名。
- 使用DECIMAL代替FLOAT和DOUBLE存储精确浮点数。
- 禁止使用MySQL关键字。(https://dev.mysql.com/doc/refman/5.6/en/keywords.html)
- 使用TINYINT代替ENUM类型。
- 使用TINYINT(1)代替BOOLEAN类型。
索引规范
- 二级索引命名规范为:idx_xxxx.
- 唯一索引命名规范为:uk_xxxx.
- MySQL5.6/5.7版本中禁止在where条件字段上使用函数或表达式 (如 abs (column)) ,将无法使用索引。
- 重要的字段需建立索引,如order by、group by、distinct、where条件字段等,符合索引中字段的位置由过滤性从高到低排列。
- 时间戳字段需建立索引,例如:created_at,updated_at等。
- 禁止在TEXT、BLOB等大对象类型字段上建立索引。
SQL编写规范
- 禁止使用SELECT * 查询所有字段,仅查询需要的字段。
- join语句中join条件字段类型、长度、字符集必须保持一致,否则MySQL将无法使用索引。
- 禁止update主键字段值。
- 避免大事务,⼀次修改不得超过2000条数据,否则,易引起MySQL复制延迟,或失败回滚时间较长等问题。
- insert into…values(XX),(XX),(XX)… 这里XX的值禁止超过2000个,过多的值易引起主从同步延迟或失败回滚时间较长等问题。
- 程序端insert语句需指定具体字段名称,禁止写成insert into t1 values(…),避免在表结构变更后出现不必要的报错。
- where子句禁止使用以通配符开始的LIKE条件查询,否则,MySQL将无法使用索引。
- 禁止在OLTP类型系统中使用没有where条件的查询。
- 在MySQL5.7中,对同⼀张表的多次alter操作需合并为⼀次操作,避免重复锁表。
- 禁止在数据库中进行数学运算。
- 禁止在主库上执行sum,count 等复杂的统计分析语句,可以使用从库来执行。
- where条件中等号左右两边的字段类型必须保持⼀致,否则,MySQL将无法使用索引。
- 禁止单条SQL语句同时更新多个表。