本来我只是想写一篇关于数据备份和慢查询的文章。但随着学习的深入,我发现更多更有趣的MySQL知识,导致最后写了一个小系列。下面分享下我这次学习MySQL的一些感想。
MySQL各种关键设计的启发:
-
事务设计启发:
在没有深入学习MySQL之前,事务对我来说就只是几个简单的特性(ACID)。深入学习之后,才知道了redo log
、binlog
和二阶段提交
这些为了实现事务的具体技术。了解这些技术不单单使我对MySQL的理解提升一个层次,还有更多实际的帮助。比如:知道怎么调优(binlog要存什么格式、存多少天、redo log刷盘策略要怎么设定等等);知道磁盘写入瓶颈可能在什么地方,然后知道某些云厂商把用户当水鱼;知道数据要回滚可以有什么方式,并且知道这些方式都是些什么原理等等。
游戏服务端有大量在分布式环境实现原子性的功能,而这些功能实现的原理和MySQL的事务实现方式有很多共通的地方。比如如何保证玩家的一次购买行为只要付款成功,就一定会在游戏中发货。注意对于大多数游戏来说,支付和游戏都是分开实现、部署的,它们之间可能存在一条长长的链路。
又比如如何保证玩家A送给玩家B的礼物,玩家B一定会收到。注意这个过程中玩家B可能在线或不在线,甚至可能出现玩家A和玩家B同时操作同一份数据的可能,如果想通过无锁操作那么借鉴MySQL的事务设计也是一个很好的选择。
-
锁设计的启发:
MySQL的锁知识体系非常复杂(这里讨论的主要是InnoDB),光是隔离级别(Read Uncommitted
、Read Committed
、Repeatable Read
、Serializable
)就把我弄的一愣一愣的。还有不同类型的锁(意向锁、排它锁、共享锁、意向排它锁、行数、间隙、Next-Key锁等等),这些锁组合起来的运用更是让人头大。不过在认真学习完之后,你会发现这些锁的设计十分精巧地实现了不同的隔离级别。可能很多人不会喜欢如此复杂的锁设计,但是为了更好的并发和隔离的实现这是没办法的折中方案。
如果各位在MySQL学习上犯难,我建议通过实际的SQL(insert、update、delete)一条一条地去执行,看看这些SQL都持有了什么锁。
-
性能优化启发:
因为各种客观因素的限制(比如内存不可能无限大、事务需要各种隔离),MySQL充满了各种折中的设计。考虑各种要求,没办法做到所有情况最优,只能做到综合的最优。比如Cache的使用(里面甚至还有像JVM内存模型那样的young和old区)、磁盘回写策略(这里指批量延时回写)、临时表的设计。
MySQL面临的性能优化上的问题,在大多数项目中都会存在。要求就摆在你面前,但是机器预算是有限;JVM内存就这么多,Y区要多少、O区要多少;前后端数据要不要加密,加密的话两边都有影响、不加密不安全;A技术更全、B技术更快等等。这些问题总是会要我们不断抉择,这个时候就要根据自己实际的情况做分析,找到平衡和折中。
-
慢查询日志的启发:
我刚开始工作的时候甚至不知道慢查询这个东西,当时的项目也没有慢查询的治理这个理念。后面知道慢查询之后,就逐渐尝试优化项目中不健康的SQL。虽然这个动作对整个项目的运行来看并没有直接优化的作用,但是这种不断让项目更健康的尝试极大程度上影响了我之后的工作习惯。
关于慢查询我最直观的感受就是:知道问题比解决问题重要。在项目设计的时候,性能、异常情况的记录都是要认真考虑的。
-
MySQL对大量数据的操作:
进行大量数据操作是一件很痛苦的事,比如超大规模的数据排序、比如搜索索引树、比如返回大量数据给客户端、比如两个表的连表查询等等。对于这些操作数据库不可能把数据全部加载到内存里面再进行处理。如何通过磁盘和其他技术来做到,这个和我们习惯使用内存处理少量数据思路上有很大的不一样(比如外排的实现、比如分段传输)。各位不妨尝试了解一下。
上云的感想:
可能和其他公司不一样,我之前的项目组首先上云的是数据库而不是普通的云服务器(阿里的ECS、亚马逊的EC2)。这里说一下上云的感想:
经历过从本地部署MySQL到云MySQL的转变(云实例也是一样)。深深感觉到云服务带来的生产力的解放。在没有使用云服务之前,即使通过脚本的帮助我们部署一台线上MySQL服务器是一个很繁琐的事情(当时我们对容器技术的使用经验并不足矣在线上使用)。比如部署主从机器、对数据进行冷备等等诸如此类的操作。即使搭建完成,后续的维护、监控对经验不丰富的运维和开发同学来说还是充满各种困难和陡峭的学习曲线(比如查看数据库各项指标就要操作很多命令、死锁分析又是一大堆专业文档等着)。
后面在新项目组首次尝试了云服务器,部署服务器分分钟的事。要看监控打开链接就行,甚至死锁分析和压测都帮忙弄好。极大提高生产力,想要的给钱就行。云服务它是资源也是服务,让开发者用的舒心的还是他的服务。对云服务来说服务比资源更重要。不要只把云服务器当成是一个部署在远端的机器,不然无法充分挖掘他的宝藏。里面包含的各种附加服务(比如监控),都是业界先进和成熟的方案。企业只有充分利用这些资源才能切实节约宝贵资金。不能有效运用资源本身就是一种巨大的浪费。
监控系统的启发:
MySQL的各类监控做的十分完善的,sys
库中的metrics
视图就包含了大量数据库运行中的统计数据;sys
库中的processlist
视图会有各个线程的详细信息等等。只要用户愿意(或者说用户了解这些知识),MySQL的这些监控和统计可以让用户全方位掌握当前MySQL服务器的各种运行状态。我们的游戏服务器监控就大量借鉴了MySQL的经验(很多地方就是照抄),比如我们改造了锁组件的代码以支持统计评价锁持有时间(avg、95%、99%这几个方面)、锁等待时间;缓存组件统计了缓存命中率、单个玩家缓存大小(avg、95%、99%)、缓存寿命等等。如果你苦恼于不知道怎么优化自己的数据库(只知道数据库很卡)、不知道数据库当前还有多少性能可以压榨那么就应该好好看看数据库监控这一部分。又或者你现在想设计一个服务器的监控体系,但是不知道自己埋点是否充足,我就建议你看看MySQL的监控体系。
这里推荐一个数据库的监控工具:MySQL Exporter
总结:
- 关系型数据库经过了几十年的发展,一次小小的insert操作背后是无数人的努力和智慧的结晶,如果不探究一下这背后的东西将是巨大的遗憾和浪费;
- 知识不是单点存在的,如果想把单一知识点弄懂就需要其他大量的知识做支持。知道前因后果才算明白了这个知识点;
- 当探索出事物背后的实现原理的时候,知识增长给人带来的豁然开朗是非常快乐的。如果说有什么比这更快乐,那我认为是自己还想办法证明了这个实现原理;
- 当我们从电视、网络了解一个人,而没有实际接触一个人的时候,这个人对你来说是概念和抽象的。只有实际和ta接触、了解之后,才能更细致感受到这个人的特质,这个时候ta对你来说才是一个具体的、生灵活现的人而不是抽象和概念化的。这个情况放在技术上也是如此;
- 在数据库领域,如果没有足够底层知识的支撑,更高阶的技术操作将无法进行。只是知道CRUD,就没办法进行MySQL压测和调优。只是知道锁的概念,就没办法弄清楚MySQL锁是怎么回事更别谈如何彻底解决和避免。使用一个自己完全不了解的东西不是不可以,但是如果它一旦出现问题,那么解决这些问题往往会付出更高的代价。
网友评论