一、安全规范

1.服务器

必须分离数据库的prod,test,dev环境,不允许在线上环境直接开发和做任何测试。

2.账户权限

一个账号对应一个数据库,应用账户只能允许访问对应的数据库。应用账号权限默认开启select/insert/update/delete/execute的权限。
每个应用建立一个账号,默认是可读写。 如果只读或只写,加_w,_r。
账户名长度不能超过16个字符

3.数据获取

有敏感信息的数据导出需要经理审批,防止数据泄露。

4.防止SQL注入

禁止对于SQL的传入参数。

二、命名规范

  1. 库名、表名、字段名必须使用小写字⺟,并采⽤下划线分割,不能超过32个字符。
  2. 禁止使用中文字符、系统保留字、特殊符号命名。
  3. 库名、表名、字段名必须⻅名知意。命名与业务、产品线等相关联:
    举例:遵循:{project名称} + “_” + 业务数据类型,比如“admin_user”、“student_order”,如果数据表为全局系统表,可以不包含{project}前缀,比如“user”。

三、基础规范

  1. 使⽤用INNODB存储引擎。
  2. 表字符集使用UTF8MB4,排序规则默认utf8mb4_general_ci,其他的表中排序规则根据业务来确定用相应的排序规则
  3. 所有表都需要添加注释;除主键外的其他字段都需要增加注释。推荐采⽤用英文标点,避免出现乱码。
  4. 禁止在数据库中存储图片、大文件等大数据。
  5. 每张表数据量建议控制在1000W以内。(TiDB除外)
  6. 禁止在线上做数据库压⼒力测试。
  7. 单个实例数据库数量不能超过50个(TiDB除外)
  8. 单个数据库容量不能超过300G(TiDB除外)

四、库表设计

  1. 禁止使⽤用分区表。

  2. 将大字段、访问频率低的字段拆分到单独的表中存储,分离冷热数据。

  3. 推荐使用HASH进行散表,表名后缀使⽤用十进制数,数字必须从0开始。(TiDB除外)

  4. 按日期时间分表需符合YYYY[MM][DD][HH]格式,例如2013071601。年份必须⽤用4位数字表⽰示。例如按日散表user_20110209、
    按月散表user_201102。(TiDB除外)

  5. 采⽤用合适的分库分表策略。例如千库十表、十库百表。(TiDB除外)

  6. 表名不使用复数名词。

  7. 库表名、字段名必须使用小写字母或数字,禁止出现数字开头禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。
    命名规范 :

    建库:
    项目简称_业务简称,例如:vysa_cme

    建表:
    业务简称_表的作用,例如 cme_phone_card

  8. 创建表时必须显式指定表存储引擎类型和字符集,存储引擎统一使用innodb。

  9. 表必须使用有序递增的整型字段做主键,字段类型用int或bigint,并且是无符号(unsigned)

  10. 单表字段不能超过30个

  11. 单表记录数不能超过5000W,否则分表
    建议表中添加三个字段:
    created_by: 记录创建人ID,字符串类型
    created_time: 记录创建时间,时间类型
    updated_time: 记录修改人ID,字符串类型
    updated_by: 记录修改时间,时间类型
    delflag: 逻辑删除表示,1 表示删除,0 表示未删除

五、字段设计

  1. 建议使用UNSIGNED存储⾮非负数值。
  2. 建议使用INT UNSIGNED存储IPV4
  3. 用DECIMAL代替FLOAT和DOUBLE存储精确浮点数。例如货币、金融相关的数据(待确认)
  4. INT类型固定占用4字节存储,例如INT(4)仅代表显⽰示字符宽度为4位,不代表存储长度。
  5. 强烈建议使用TINYINT来代替ENUM类型
  6. 不建议使用TEXT、BLOB类型,如有需要单独存储
  7. 禁止在数据库中存储明文密码
  8. 使用VARBINARY存储大小写敏感的变长字符串或二进制内容。
  9. 使用尽可能小的VARCHAR字段。VARCHAR(N)中的N表示字符数而非字节数,最大1024.
  10. 存储年使用YEAR类型。存储日期使用DATE类型。 时间日期使用datetime类型。
  11. 所有字段均定义为NOT NULL,定义其默认值,建议数字字段default 0,字符串字段default “”,不要default null
  12. 不使用on update current_timestamp, 请由程序去做DML

六、索引设计

  1. 单张表中索引数量不超过5个
  2. 单个索引中的字段数不超过5个
  3. 索引名必须全部使用小写
  4. 主键索引名为 pk_字段名;唯一索引名为 uk_字段名;普通索引名则为 idx_字段名。
  5. 非唯一索引按照“idx_字段名称[_字段名称]”进行命名。例如idx_age_name
  6. 唯一索引按照“uk_字段名称[_字段名称]”进行命名。例如uniq_age_name
  7. 组合索引建议包含所有字段名,过长的字段名可以采用缩写形式。例如idx_age_name_add
  8. 表必须有主键,推荐使用UNSIGNED⾃自增列作为主键,或者雪花算法生成id,注意控制主键长度,防止前端精度问题。
  9. 不使用更新频繁地列作为主键
  10. 尽量不选择字符串列作为主键
  11. 唯一键由3个以下字段组成,并且字段都是整形时,可使用唯一键作为主键。其他情况下,建议使用自增列 或发号器作主键
    1. 禁止冗余索引
    2. 禁止重复索引
    3. 不建议使用外键
    4. 联表查询时,JOIN列的数据类型必须相同,并且要建立索引
    5. 不在低基数列上建立索引,例如“性别”
    6. 选择区分度大的列建立索引。组合索引中,区分度大的字段放在前
    7. 对字符串使用前缀索引,前缀索引长度不超过10个字符;如果有一个CHAR(200)
      列,如果在前10个字符内,多数值是惟一的,那么就不要对整个列进行索引。对前10个字符进行索引能够节省大量索引空间,也可能会使查询更快。
    8. 不对过长的VARCHAR字段建立索引。建议优先考虑前缀索引,或添加CRC32或MD5伪列并建立索引。
    9. 合理创建联合索引,(a,b,c) 相当于 (a) 、(a,b) 、(a,b,c)。
    10. 合理使用覆盖索引减少IO,避免排序
    11. 不在索引列做计算,例如:where (id+1) < 200,不在索引列使用函数,比如date_format()

七、SQL规范

  1. 使用预编译语句prepared statement
  2. 只传参数,比传递SQL语句更高效一次解析,多次使用,降低SQL注入概率
  3. 用IN代替OR。SQL语句中IN包含的值不应过多,应少于1000个
  4. 禁止隐式转换。数值类型禁止加引号;字符串类型必须加引号
  5. 避免使用JOIN和子查询。必要时推荐用JOIN代替子查询。
  6. 避免在MySQL中进行数学运算和函数运算
  7. 减少与数据库交互次数,尽量采用批量SQL语句
  8. 拆分复杂SQL为多个小SQL,避免大事务
  9. 获取大量数据时,建议分批次获取数据,每次获取数据少于2000条,结果集应小于1M
  10. 用UNION ALL代替UNION
  11. 统计行数用COUNT(*)
  12. SELECT只获取必要的字段,禁止使用SELECT *。
  13. SQL中避免出现now()、rand()、sysdate()、current_user()等不确定结果的函数。
  14. INSERT语句必须指定字段列表,禁止使用 INSERT INTO TABLE()。
  15. 禁止单条SQL语句同时更新多个表。
  16. 避免使用存储过程、触发器、视图、自定义函数等
  17. 建议使用合理的分页方式以提高分页效率
    假如有类似下⾯面⾯面分页语句: SELECT * FROM table ORDER BY TIME DESC LIMIT 10000,10; 这种分页方式会导致大量的io,因
    为MySQL使用的是提前读取策略。
  18. 禁止在从库上执行后台管理和统计类功能的QUERY,必要时申请统计类从库。
  19. 程序应有捕获SQL异常的处理机制,必要时通过rollback显式回滚
  20. 重要SQL必须被索引:update、delete的where条件列、order by、group by、distinct字段、多表join 字段。
  21. 禁止使用%前导查询,例如:like “%abc”,无法利用到索引。
  22. 禁止使用负向查询,例如 not in、!=、not like
  23. 使用EXPLAIN判断SQL语句是否合理使用索引,尽量避免extra列出现:Using File Sort、Using Temporary
  24. 禁止使用order by rand()
  25. 不能在不同数据类型的字段上进行比较,避免字段类型转换损失性能
  26. SQL语句在程序中传入的参数值类型必须与字段在数据库中的类型相同
  27. INSERT语句必须写上具体的字段名称,写成:insert into table(字段1,字段2,…) values(值1,值2,…)。
    在做批量更新/插入操作时,建议操作的数据行数不要太多,也不要太少,一般100~200行提交一次,避免频繁io操作
    前端程序不允许使用set sql_mode和set tx_isolation(会话级事务隔离级别)语句
    不能使用SELECT … FOR UPDATE语法,它会扩大意向锁范围,影响数据库的并发效率
  28. 新数据架构业务尽量join表不能超过3个

八、行为规范

  1. 表结构变更必须通知DBA进⾏行审核
  2. 禁止有super权限的应用程序账号存在
  3. 禁止有DDL、DCL权限的应用程序账号存在。
  4. 重大项目的数据库方案选型和设计必须提前通知DBA参与
  5. 批量导入、导出数据必须通过DBA审核,并在执行过程中观察服务
  6. 批量更新数据,如UPDATE、DELETE操作,必须DBA进行审核,并在执行过程中观察服务
  7. 产品出现非数据库导致的故障时,如被攻击,必须及时通DBA,便于维护服务稳定
  8. 业务部门程序出现BUG等影响数据库服务的问题,必须及时通知DBA,便于维护服务稳定
  9. 业务部门推广活动或上线新功能,必须提前通知DBA进行服务和访问量评估,并留出必要时间以便DBA完成扩容
  10. 出现业务部门人为误操作导致数据丢失,需要恢复数据的,必须第一时间通知DBA,并提供准确时间点、 误操作语等重要线索。
  11. 提交线上建表改表需求,必须详细注明涉及到的所有SQL语句(包括INSERT、DELETE、UPDATE),便 于DBA进行审核和优化
  12. 对同一个表的多次alter操作必须合并为一次操作
  13. 不要在MySQL数据库中存放业务逻辑
  14. 对特别重要的库表,提前与DBA沟通确定维护和备份优先级,不在业务高峰期批量更新、查询数据库
  15. 在数据库中不能使用物理删除操作,要使用逻辑删除。