即日起在codingBlog上分享您的技术经验即可获得积分,积分可兑换现金哦。

再议数据库军规

微信 架构师之路 96℃ 0评论

上一篇《58到家数据库30条军规解读》引发了广泛的讨论,某些军规部分同学有疑惑,补充一文说明。

 

军规:必须使用UTF8字符集

DBA负责人确认后,纠正为“新库默认使用utf8mb4字符集”。

这点感谢网友的提醒,utf8mb4utf8的超集,emoji表情以及部分不常见汉字在utf8下会表现为乱码,故需要升级至utf8mb4

默认使用这个字符集的原因是:“标准,万国码,无需转码,无乱码风险”,并不“节省空间”。


一个潜在坑:阿里云上RDS服务如果要从utf8升级为utf8mb4,需要重启实例,所以58到家并没有把所有的数据库升级成这个字符集,而是“新库默认使用utf8mb4字符集”。


自搭的Mysql可以完成在线转换,而不需要重启数据库实例。

 

军规:数据表、数据字段必须加入中文注释

这一点应该没有疑问。

不过也有朋友提出,加入注释会方便黑客,建议“注释写在文档里,文档和数据库同步更新”。这个建议根据经验来说是不太靠谱的:

1)不能怕bug就不写代码,怕黑客就不写注释,对吧?

2)文档同步更新也不太现实,还是把注释写好,代码可读性做好更可行,互联网公司的文档管理?呆过互联网公司的同学估计都清楚。

 

军规:禁止使用存储过程、视图、触发器、Event

军规:禁止使用外键,如果有外键完整性约束,需要应用程序控制

军规:禁止大表使用JOIN查询,禁止大表使用子查询

很多网友提出,这些军规不合理,完全做到不可能。


如原文所述,58到家数据库30军规的背景是“并发量大、数据量大的互联网业务”,这类业务架构设计的重点往往是吞吐量,性能优先(和钱相关的少部分业务是一致性优先),对数据库性能影响较大的数据库特性较少使用。这类场景的架构方向是“解放数据库CPU,把复杂逻辑计算放到服务层”,服务层具备更好的扩展性,容易实现“增机器就扩充性能”,数据库擅长存储与索引,勿让数据库背负过重的任务。

 

关于这个点,再有较真的柳岩小编就不回复了哈,任何事情都没有百分之百,但58到家的数据库使用确实没有存储过程、视图、触发器、外键、用户自定义函数,针对业务特性设计架构,等单库吞吐量到了几千上万,就明白这些军规的重要性啦。

 

军规:只允许使用内网域名,而不是ip连接数据库

这一点应该也没有疑问。

不只是数据库,缓存(memcacheredis)的连接,服务(service)的连接都必须使用内网域名,机器迁移/平滑升级/运维管理太多太多的好处,如果朋友你还是采用ip直连的,赶紧升级到内网域名吧

 

军规:禁止使用小数存储国币

有朋友问存储前乘以100,取出后除以100是否可行,个人建议“尽量少的使用除法”。


曾经踩过这样的坑,100元分3天摊销,每天摊销100/3元,结果得到333.33。后来实施对账系统,始终有几分钱对不齐,郁闷了很久(不是几分钱的事,是业务方质疑的眼神让研发很不爽),最后发现是除法惹的祸。

解决方案:使用“”作为单位,这样数据库里就是整数了。

 

案例:SELECT uid FROM t_user WHERE phone=13812345678 会导致全表扫描,而不能命中phone索引

这个坑大家没踩过么?

phonevarchar类型,SQL语句带入的是整形,故不会命中索引,加个引号就好了

SELECT uid FROM t_user WHERE phone=’13812345678’

 

军规:禁止使用负向查询NOT!=<>!<!>NOT INNOT LIKE等,会导致全表扫描

此军规争议比较大,部分网友反馈不这么做很多业务实现不了,稍微解释一下:

一般来说,WHERE过滤条件不会只带这么一个“负向查询条件”,还会有其他过滤条件,举个例子:查询沈剑已完成订单之外的订单(好拗口):

SELECT oid FROM t_order WHERE uid=123 AND status != 1;


订单表5000w数据,但uid=123就会迅速的将数据量过滤到很少的级别(uid建立了索引),此时再接上一个负向的查询条件就无所谓了,扫描的行数本身就会很少。


但如果要查询所有已完成订单之外的订单:

SELECT oid FROM t_order WHERE status != 1;

这就挂了,立马CPU100%status索引会失效,负向查询导致全表扫描。

 

末了,除了《58到家数据库30条军规解读》中提到的基础规范、命名规范、表设计规范、字段设计规范、索引设计规范、SQL使用规范,还有一个行为规范的军规:

31)禁止使用应用程序配置文件内的帐号手工访问线上数据库

32禁止非DBA对线上数据库进行写操作,修改线上数据需要提交工单,由DBA执行,提交的SQL语句必须经过测试

33)分配非DBA以只读帐号,必须通过VPN+跳板机访问授权的从库

34)开发、测试、线上环境隔离

 

为什么要制定行为规范的军规呢,大伙的公司是不是有这样的情况:

任何研发、测试都有连接线上数据库的帐号?

是不是经常有这类误操作?

1)本来只想update一条记录,where条件搞错,update了全部的记录

2)本来只想delete几行记录,结果删多了,四下无人,再insert回去

3)以为drop的是测试库,结果把线上库drop掉了

4)以为操作的是分库x,结果SecureCRT开窗口太多,操作成了分库y

5)写错配置文件,压力测试压到线上库了,生成了N多脏数据

无数的事情,结果就是打电话给DBA,让他们帮忙擦屁股。

所谓的“业务灵活性”都是扯淡,为什么要有行为规范?不让你带刀,不是限制你,而是保护你的安全。要相信DBA是专业的,让专业的人干专业的事情。别把DBA看做你的对立面,多和他们沟通业务场景,沟通请求读写比,沟通访问模式,他们真的能帮助到你,这是我带DBA团队的一些感触。

 

谁都可能删除全库,能找回数据的,真的只有DBA

==【完】==

相关文章:58到家数据库30条军规解读


如果RD心怀内疚,如果DBA深有同感,帮转哟。

转载请注明:CodingBlog » 再议数据库军规

喜欢 (0)or分享 (0)
发表我的评论
取消评论

*

表情
(50)个小伙伴在吐槽
  1. 58到家招聘高级dba,高级运维,后端开发(java方向),前端fe,测试开发,产品经理。base北京,薪水不限,不加班,地点立水桥南,可以经常和楼主一起讨论技术,欢迎留言推荐自荐(留言后,楼主会主动联系)。
    58沈剑2017-02-17 00:31 回复
  2. 100元,即便以分为单位,那么除以3后,还是没法保证不缺那最后的一分钱的。上面这点描述,我没看懂。
    程序诗人2017-02-17 00:35 回复
  3. 很多公司把DBA划分到运维部,因为他们都是背锅侠/呲牙
    思醒2017-02-17 00:37 回复
  4. 不让你带刀,不是限制你,而是保护你的安全。/呲牙
    有点无聊2017-02-17 00:38 回复
  5. 然饿,小公司连dba都木有!
    colin2017-02-17 00:45 回复
  6. 强制使用powerdesigner,所有SQL来自powerdesigner生成,不许测试库往外手动拷SQL就解决文档问题了
    2017-02-17 00:46 回复
  7. mysql用decimal就可以避免金额精度的问题,实际计算比核算精度多一位。当然精度得所有系统统一,要不也会有尾差。
    yibo2017-02-17 00:51 回复
  8. 我们钱就是分单位的,没小数。比如500,就是5元。其实如果数字很大,可以用两个字段,一个整数,一个存小数位。但不能用double和flouat,会有精度丢失问题,正确的是decmail。貌似单词都拼错了,理解意思就行哈。
    Leon2017-02-17 00:52 回复
  9. 终于赶上了第一个座位,/调皮,行为规范真的很重要,不能用配置文件中的账号密码访问线上数据库实施类?
    to be or not to be2017-02-17 00:53 回复
  10. >再有较真的柳岩小编就不回复了哈 柳岩╮(‵▽′)╭
    赵安家2017-02-17 00:53 回复
  11. 域名和ip的绑定关系变更后,应用端无法即时感知,还是连的以前的ip。
    只要有你2017-02-17 00:55 回复
  12. 【解决方案:使用“分”作为单位,这样数据库里就是整数了。】这个并没有解决摊分3份的问题吧,改成分为单位依然除不尽啊,尾差需要用减法吧
    jason2017-02-17 01:00 回复
  13. dba辛苦了/憨笑
    hao2017-02-17 01:00 回复
  14. 确实没有dba所有都放云上了
    雪峰2017-02-17 01:09 回复
  15. "禁止使用小数存储国币" 关于这点举例的 100 分3天,即使使用了分为单位,平均下来也还是3333吧 是不是还是需要人为在程序上去处理,将某天的设为3334,才能保证财务对账呢? 这样其实跟decimal区别也不大吧? 请大牛解答下,谢谢
    月下子龙2017-02-17 01:10 回复
  16. 建议将数据库生命周日管理和单表的记录数纳入军规,我就强制规定,研发提交的表必须注明生命周日,比如保留N个月,定期备份清理,所有的表研发人员要对记录数有一定的评估!
    翔工2017-02-17 01:20 回复
  17. 有两个问题:1,我们的字段注释,测试库和开发库有。生产的没有。上生产可以清一下注释。2,关于钱,我们是电商平台,是存分的。关于100/3,还有好的解决方案没有
    王伟2017-02-17 01:28 回复
  18. 楼主,关于子查询的问题好像没有提及到,子查询使用不当,很是要命。很多时候会有一个误区,以为一个SQL语句能搞定的,就不要使用2个,其实,当数据量达到一定的级别后,就不见得了。
    Rex2017-02-17 01:30 回复
  19. 多年前踩过金额小数的坑,即使用了mysql的decimal也不行 java计算一旦有代码不用decimal来操作还是会悲剧,索性直接用分来存储,风险小很多
    姜春生2017-02-17 01:31 回复
  20. 很难控制rd不使用配置文件信息连接线上数据库,因为他就赤裸裸的放那了
    牛玉富2017-02-17 01:35 回复
  21. 表字段加上的注释能让黑客弄到手?
    andy2017-02-17 01:38 回复
  22. 非常赞成不使用存储过程,触发器等,去哪儿网也是这样的规范。
    月下无眠2017-02-17 01:41 回复
  23. 只允许使用内网域名, 这个怎么配置,我只是搞了个mysql+keepalived 双主的/难过
    路在何方2017-02-17 02:01 回复
  24. 中肯点说,大部分情况下是需要按照这些规则做更好,小部分情况例外也很正常,重点还是里面涉及到很多数据库原理,不懂原理胡乱操作就容易出事儿,说来说去开发还是得培训数据库,一些原理性的基础都不难,这才能写出高质量的sql,性能调优,高可用,灾备等就是dba专属的活了
    王建杰2017-02-17 02:12 回复
  25. 存储金额用 DECIMAL(M,D) 应该就可以了。 期末按照「倒挤」的方法计算,就可以平账了。
    TQ2017-02-17 04:08 回复
  26. 不明白为什么不能用视图。不是可以简化很多东西吗?
    时差2017-02-17 04:35 回复
  27. 曾经全裤被Drop,还好有DBA在恢复了大部分!
    FansLin2017-02-17 10:00 回复
  28. 无外键约束,那跟用nosql还有什么区别
    h2017-02-17 11:34 回复
  29. 楼主军规中没有提及分区表怎么规范使用,58到家有没使用到分区表啊?比如时间分区,存储日志数据。
    玟坚2017-02-17 13:45 回复
  30. (32)禁止非DBA对线上数据库进行写操作,修改线上数据需要提交工单,由DBA执行,提交的SQL语句必须经过测试 运维研发,连线上数据库从库的只读权限都没有,惭愧,惭愧。/撇嘴/撇嘴
    刘先森2017-02-18 00:46 回复
  31. 经历过实践优化后,军规都是很准确的。
    飞✈️2017-02-18 01:30 回复
  32. 大表不用join难度不小,高并发,数据大,但是业务特性决定数据库很难解耦,数据连接推到服务层处理又很难实现,查询条件也耦合,补充一条我们的军规,不允许写delete语句
    侯延涛2017-02-18 13:48 回复
  33. 写得很好,都是经验之谈/鼓掌
    星之七章2017-02-20 03:27 回复
  34. 有没有用什么数据库中间件?用技术来规范比用制度更好
    刘杨2017-02-20 10:21 回复
  35. 数据库默认使用utf8,对于需要使用emoji的字段特殊指定utf8mb4,这样是不是更节约存储空间?
    棉花糖2017-02-20 15:39 回复
  36. 表名加上t_有点疑问,应该不用t_吧
    Lorgine2017-02-20 15:49 回复
  37. 针对emjo确实经历过,不过在使用阿里云的时候,修改了,依然不起作用,最后还是程序做的手脚。一直不明所以。下次我把代码贴出来。沈大神 另外现在我们在用oracle,统一修改成al32utf8了了。以后utf8估计就没人用了/色/微笑
    王帅2017-02-21 00:25 回复
  38. 100块分三天那个例子不恰当,而且分三份,前两份用除法,最后一份用总量减去前两份比较好
    来杯可乐2017-02-21 00:41 回复
  39. 军规:禁止使用小数存储国币 使用“分”来存储货币,并不能解决文中100/3的案例吧
    wpf2017-02-21 03:34 回复
  40. 1.2,3这种虽然可以理解是什么含义,但是用另外一张表维护的时候同样会进行关联查询。数据量大的情况下依然有瓶颈,不知道理解对否
    楚天行2017-02-21 09:16 回复
  41. 负查询以前还真太没注意。另:柳岩是什么梗?/白眼
    赵伟2017-02-21 09:37 回复
  42. java也不加班嘛。。
    Yancey2017-02-22 03:42 回复
  43. (31)禁止使用应用程序配置文件内的帐号手工访问线上数据库 这条是指程序员不能用配置文件的帐号访问生产环境数据库,而dba 不受这条限制,是这样理解吗?
    土包子-Simit2017-02-22 22:13 回复
  44. 对于Java做后台用了什么技术框架,作者能讲一下吗?
    土包子-Simit2017-02-22 23:17 回复
  45. 我们的规约中, 表里面需要有固定两列,id自增主键,createtime当前时间戳 回溯问题,迁移数据时比较方便。建议录入。
    贺博@超星2017-02-23 01:05 回复
  46. 军规:禁止使用负向查询NOT、!=、<>、!<、!>、NOT IN、NOT LIKE等,会导致全表扫描 好多业务确实需要这一些呀! 不用 很麻烦的 虽然性能上 很不错 不过 互联网第一个一条 上线在说其他事/呲牙/呲牙/呲牙/呲牙
    阿里2017-02-24 01:55 回复
  47. 看到留言回复中说互联网公司一般不用分区表,可以甩个链接吗?谢谢
    2017-02-28 15:48 回复
  48. 货币那里可以这么搞,前面两个都靠除以出来的值,最后一个用总数减去前面两个的值完美解决,前老大说这是金融类系统的常识
    你的益达2017-03-01 00:27 回复
  49. 58沈剑你好!我看了你的文章受益匪浅,准备借鉴你的一些架构思想去学校做一些实践教学!请问,我需要得到你的授权吗?如果要,怎么操作?[呲牙]
    竹林清幽2017-03-01 00:31 回复
  50. 沈老师,我们是创业公司,现在要重构系统。网站的访问量现在不是很大,团队的技术力量相对薄弱,甚至没有dba,运维,但想用军规约束自己,为了以后打个相对好一点底子,不知道做是否合理?
    降生2017-03-16 01:53 回复