写点什么

MySQL 中的哥哥表、妹妹字段,是什么鬼?

用户头像
云流
关注
发布于: 2021 年 01 月 08 日

晚上,我被叫进宽大的办公室,总监正在煮茶。高压锅煮着长嘴茶壶,水蒸气缭绕。领导举手之间,淡黄茶水奔涌而出,倒立而下浇上茶叶,漏出两杯茶水。


“喝茶?”领导推给我一杯,然后自己抿了一口。沉默良久,把显示器转到我这边:“最近数据库表出现了些有意思的东西,你来看看”。


我探着脑袋一瞧,心凉了半截。


时隔五年,又在项目里见到哥哥表和妹妹字段,着实让我坐立不安。所谓哥哥表,就是名称叫做 gg 的数据库表,意为公共;所谓妹妹字段,就是名称叫做 mm 的表子段,意为密码。比起 shit mountain 来,这些命名更让人浮想联翩,实为不规范之典范。



image


这么魔幻的事情,不止一次出现,任何领导都会坐不住。可惜的是,一次次的会议,专项讨论某一个 SQL 禁止条例,到最后还是大开方便之门,过往的规范承诺皆抛之脑外。


数据库命名规范是最基础的规范,连这个都没做好,证明监管工作确实出现了纰漏。我赶紧掏出自己的手机,翻到 xjjdog 的文章,打算把数据库要注意的地点,给领导汇报一下。


也顺便向大家汇报。


我把规范分成了统一的规范、索引规范、SQL 规范、命名规范、安全规范、性能小 Case 等 6 个部分。


请听我慢慢道来。


1. 统一的规范

首先,我们来一些通用的规范。这里有很多是经验值,如果你的数据库所在的宿主机硬件,并不是十分的牛 X,可以考虑再降低一下标准。


存储引擎: 请统一使用 innodb 存储引擎,特殊的数据库引擎必须通过 DBA 的评审。


字符集: 统一使用 utf8 字符集。这个要从应用程序、服务器、数据库的表、字段等全部统一起来。注意:MySQL 中的 utf8mb4 字符集,才是真正的 utf8,请用这个。


作用范围:不要在 MySQL 存储大对象,比如图片、音乐等;不要用 MySQL 做 Gis 运算、全文检索;不使用存储过程、触发器、函数、外键,避免破坏数据库的性能和扩展性。


使用上限:


  • 每个 MySQL 实例,数据库不要超过 50 个;

  • 单数据库容量,不要超过 500GB,否则分库;

  • 单表记录数量,不要超过 5000W,否则分表;

  • 单表子段数量,不要超过 30 个,否则拆表;

  • 单张表中索引数量不超过 5 个,单个索引中的字段数不超过 5 个;

  • varchar 字段最大值不超过 1024;注意:VARCHAR(N)中的 N 表示字符数而非字节数


2. 索引规范

索引是数据库中非常重要的结构,可以加速数据的检索。但索引是要占用大量空间的,如果你的数据表里面没几条记录,就不必创建索引。比如 2000 条以下。




image


选择性很小的字段(低基数列),不要加索引。比如一些 state,type,布尔判断等。因为加了也没用。


尽量让索引的内容尽量的短!比较长的子段,要使用前缀索引。比如:title varchar (64) ,可以创建前缀索引 idx_title (title(16)) 。


合理利用索引的最左原则,合并相似的索引。比如 (a) (ab) (abc)三种索引需求,我们只需要创建 abc 这一个索引就 ok 了。


避免在索引列做计算(这将造成索引失效),比如 data_format(created_date),substring(short_name,0,6) = 'xjjdog'。


不能使用 %前缀模糊查询,因为无法使用索引,例如:WHERE name LIKE '%味道'。


不能使用数据库端做全文检索操作。虽然它支持,也不要这么做。


索引的命名要有章可循:idx_前缀表明是普通索引,而 uk_前缀表明的是唯一索引。


3. SQL 规范

建议在每个表中,添加下面三个字段。其实,SpringBoot JPA,也建议你添加上这三个字段。根据时间字段,除了审计,还能够做一些非常 nice 的迁移操作;version 字段是高并发下的乐观锁实现,UPDATE 语句可以结合 version 字段,避免并发操作造成的不一致情况。


  • created:记录创建时间,时间类型

  • modified:记录修改时间,时间类型

  • version:“乐观锁”的版本标记,long 型,默认为 0


大多数字段应该定义成 not null 的,并分配默认值,但是不要 default null,因为数据库无法索引 null 值。


复杂的 SQL 查询语句,是绝对要避免的。我们所说的,就是慢查询。慢查询会占用大量资源,并阻塞线程,应该见谅将大 SQL 拆分成多条简单的 SQL,减少数据的锁定时间。


另外,不要在不同数据类型的字段上进行比较,避免字段类型转换造成性能损失,这就要求我们在 SQL 语句中传入的参数类型,和数据库中所定义的类型是相同的。




image


禁止使用 select *进行输出,应该选择具体的字段进行输出。除了避免无用的字段造成传输上的性能损耗,还能在一定程度上避免敏感信息的泄漏。


SQL 中避免出现 now()、rand()、sysdate()、current_user()等不确定结果的函数。


禁止使用 order by rand()。


插入语句,不要直接使用 nsert into table values(),而应该加入具体的字段,否则无法适应数据库变更情况。在做批量插入时,一次性操作 100-200 条就可以,没必要把 batch 数量设置成上千上万。


禁止非框架类业务代码,直接调用 set sql_mode 或者 set tx_isolation,禁止使用 SELECT … FOR UPDAT,优先采用乐观锁实现。


多表关联不要超过 3 个,尽量拆分成简单的 SQL 处理。


大多数开发人员会在需要时写 UNION,这往往会导致执行一个排序来消除重复。应该尽量使用 UNION ALL 来代替 UNION。


注意 OR 语句的一些改善情况。比如 WHERE id=1 OR id=2 可以 改写为 WHERE id IN(1,2)。在不同的字段,可以将 OR 改写为 UNION ALL。


4. 命名规范

数据库表和字段的命名,不要使用驼峰命名方式。比如,不能叫 saleOrder,而应该叫做 sale_order。因为大多数数据库,都不区分大小写,下划线命名会更安全。


这些命名,只能使用英文小写字母、数字和下划线,长度不超过 17 个字符。


命名应该有确切的含义。和代码规范一样,不允许使用 a,b 等无意义的字符串。不允许中文拼音缩写、中英文混用等。


严禁出现哥哥表和妹妹字段。


5. 安全安全安全



image


(1) 服务器隔离 如果你的公司有多个环境,比如 dev 环境,测试环境等,就要做好相应的隔离。比如,不允许在线上环境直接进行开发和测试、禁止在线上做数据库压⼒力测试。这是非常重要的,避免了无谓的数据错乱。如果条件允许,甚至可以做物理隔离,用不同的 IP 段进行区分。不长脑子的程序员有很多,你永远不知道他们连的是哪个环境的数据库。


(2)账户的权限 永远不要在生产上,让 root 账号远程可连。对不同的应用,应该分配不同的 database,并建立相互隔离的账号。


账号默认开启 select/insert/update/delete/execute 的权限就可以。create 都不能放开,用根本上杜绝程序员们删库跑路的机会。


针对安全级别高的应用,应分配读写账号。读账号去掉各种更新权限,只能做一些 sql 查询。账号命名方式上,可以加入_w 或者_r 后缀,表明它们的意图。


对于 SQL 的传入参数(数字,字符和混用)必须进行合法性检查,防止 SQL 注入。业务应该提前准备好风险 SQL 语句,进行集中审核,负责后果自负。


6. 性能小 case

如有自增字段,请使用无符号型(unsigned)int 或 bigint 。优先使用更小的数据类型,比如:


  • 数字用 tinyint、smallint、mediumint、int、bigint 类型;

  • 日期用 date、datetime 类型;

  • 时间用 timestamp、int 类型;

  • 不使用 char、varchar 存储日期和时间;

  • 使用更小的数据类型,能用 tinyint 的就不用 smallint,能用 timestamp 的就不用 datetime 类型;


不能使用 tinyblob、mediumblob、blob 和 longblob 类型字段,对于表存在大字段类型,应当考虑单独拆分。


OLTP 数据库绝对要避免大事务和数据库端运算,可以考虑使用 NoSQL 或者大数据计算平台。


End

可以看到,我们规范里,有些禁止的东西,其实最后还是用了。比如分区表、大字段存储、GIS 操作。但这是和规范不冲突的。


规范,只定义了一些常见的可能会引起严重后果的操作禁止,然后将风险的事情,交给专业的人去做,并评估、控制风险点的规模。


规范定了,要执行才行。不论是人工的 review,还是工具的检测。如此,系统才能健康成长,程序员才能不加班,领导才能开上保时捷。


这时候,我汇报完毕,抬头向领导望去。他的头倚在真皮座椅后背上,已经沉沉地的睡了过去。我把外套轻轻脱下来,披在他身上,这才捧过自己的茶杯,咕咚一口喝了下去。虽然茶已经凉了,但醇香一直在嘴中缭绕。


作者:小姐姐味道


链接:https://juejin.cn/post/6915275084047482894


用户头像

云流

关注

还未添加个人签名 2020.09.02 加入

还未添加个人简介

评论

发布
暂无评论
MySQL中的哥哥表、妹妹字段,是什么鬼?