POLARDB · 最佳实践 · POLARDB不得不知道的秘密(二)

前言mysql

POLARDB For MySQL(下文简称POLARDB)目前是阿里云数据库团队主推的关系型数据库。线上已经有不少企业用户在使用而且稳定运行了好久。固然,因为POLARDB是为云上环境专门打造的数据库,与原生的官方MySQL相比,有一些须要注意的事项。前几个月的月报介绍了一些,详见这篇[月报](http://mysql.taobao.org/monthly/2018/10/01/),结合笔者最近几个月一线的开发和运维经验,总结出如下几点新的注意事项并给出了建议。sql

 

空表/空实例空间问题数据库

因为POLARDB除了实例费用外,用户还须要支付实例占用的存储费用,而且是按照使用量来收费,即当前使用多少磁盘就付多少钱。这一点与RDS MySQL兼容版的预付费模式不太同样,因此不少用户对磁盘使用量很是敏感,除了上篇月报中提到的空间问题外,还有如下两类问题:空实例空间问题和空表空间问题。缓存

空实例空间问题。经常有用户会问,我刚买了一个POLARDB实例,可是才刚建立完,空间就占用了将近3GB(实际是2.8G左右),这是啥东西?个人磁盘被什么东西占用了?这里解释一下一个空实例大概有哪些文件以及他们占用的磁盘大小。安全

* 系统表ibdata1文件。能够查看系统变量`innodb_data_file_path`,ibdata默认大小就是200M,即在初始化后,ibdata就占用了200M空间,后续会按需自动扩展。
* MySQL系统库。目前权限信息,表的元信息等都放在MySQL库下,因为空表的空间占用问题(下一小节介绍),将近60个文件,占了230M左右的空间。
* Redolog文件。默认有两个,每一个1G(Redolog也是预分配空间),其中一个是当前正在用的日志文件,另一个是为了提升性能而提早分配的redolog,主要是为了减小Redolog切换时候的性能抖动。
* Undo文件。默认有8个,每一个10M。Undo空间能够放在ibdata里面,也能够挪出来(ibdata里面只留一个),POLARDB默认是把undo空间挪出来以独立文件的形式存在,主要是为了方便后续清理。
* Performance_schema表空间。虽然目前POLARDB 5.6兼容版本,不太建议使用Performance_schema,可是咱们仍是在编译的时候把相关的功能给加上了,这就致使在初始化时候就会把Performance_schema相关的表空间给初始化好,占用了一部分空间,因为空表的空间占用问题(下一小节介绍),50多个文件,占了210M左右的空间。
* auto.cnf文件,存放server uuid。因为空表的空间占用问题(下一小节介绍),占用4M。
* ib_checkpoint文件,存放checkpoint信息。由于Redolog是相似binlog顺序递增的,因此第一个ib_logfile可能被删掉,因此checkpoint信息不能放在那里。因为空表的空间占用问题(下一小节介绍),占用4M。
* innodb_repl.info,存放物理复制相关的信息。主要是POLARDB数据库内部使用,记录复制位点,切换信息等。因为空表的空间占用问题(下一小节介绍),占用4M。session

综上所述,空实例的主要空间是被Redolog给占用了,固然这个也是为了性能考虑。每一个日志文件大小1G,能在大多数场景下保证明例正常运行。随着DML的执行,Redolog会被使用,使用完后会上传OSS,以便恢复到时间点任务使用。多线程

空表空间问题。这个问题也经常被用户提起,我建立了不少表,可是数据还没导入,为啥空间增加那么快,差很少一千张空表就占用了40G的空间。这个问题的主要缘由是POLARDB底层使用了自研的文件系统PolarFS,为了提升性能,默认的文件块被设置为4M(Ext4文件系统这个值为4K),换句话说,因为一个文件至少占用一个块,因此文件大小最小为4M,而在InnoDB上,一张普通的表默认有两个文件,一个是FRM文件,一个是IBD文件,因此只要一张表成功建立,就会占用8M的空间。固然,这些空间能够理解为提早分配预留的空间,当后续数据被写入的时候,首先先使用这些预留的空间,只有被用完后,才会再分配空间。这个行为对大多数用户来讲影响不大,但对某些须要提早建立大量表可是数据量不大的用户来讲,影响比较大,会致使用户存储成本较高。不过幸运的是,针对这点,咱们的文件系统已经作了相应的优化,目前在内部测试阶段,达到预约的稳定性要求好,咱们会尽快发布到线上,目标是,在保证高性能和稳定性的状况下,尽量的减小磁盘空间使用量。架构


复制延迟问题
主备数据库的复制延迟是一个老生常谈的问题,在传统的主备架构下,只要主要压力稍微大一点或者作了一个DDL,备库有很大几率的发生延迟。发生延迟后,不只会影响应用从备库读取数据的正确性,也影响主备切换。因为POLARDB在架构上的优点(只有一份数据),所以大部分用户可能会误认为在POLARDB上理论上不该该发生延迟。由于主备都读取一份数据,固然都应该看到一致的数据啦。可是实际上,复制延迟也仍是有的,由于虽然磁盘上的状态一致了,可是内存上的状态不必定一致。在POLARDB上,主库和只读库经过物理复制来同步内存中的状态,因为同步的数据比较少,所以发生复制延迟的几率相比传统的MySQL复制仍是小不少的。接下来简单介绍一下复制的过程:运维

Primary节点会按期告诉Replica节点,可安全读取的日志位点上限,Replica在这个周期内,能够安全读取到这个位点如下的日志,若是超过这个位点,可能会读到Primary节点正在写的日志。Replica节点按期反馈应用日志的位点,表示本身应用到的日志位点,小于这个位点的必定已经应用完,大于这个的可能还没应用或者正在应用。Primary节点当前写到的日志位点和Replica节点应用到的位点之差即为复制延迟,若是复制延迟很大,就会致使Replica跟不上Primary。工具

另外,在POLARDB上,全部主库上执行完的DDL都要等全部Replica应用完相应日志后才能返回成功。换句话说,若是Replica有很大的复制延迟,可能会致使主库执行DDL不成功。这一点能够详见上一篇月报中的“DDL与大事务”小节。

由此可看,咱们要尽量的减少复制延迟。物理复制有两个阶段,一个是日志解析的阶段,另一个是日志应用的阶段。任何一个阶段慢了,均可能致使复制延迟。日志解析,目前是单线程解析,在咱们测试状况下,只有当写入量超过每秒20W(最大规格)的状况下,解析线程才会成为瓶颈。日志应用阶段,因为应用比较慢,目前是多线程应用,不过在POLARDB中,咱们只须要应用在内存中的数据页便可,换句话说,若是日志涉及的数据页不在内存中,咱们就不须要应用这些日志(目前的方案是把这些日志存在内存中),直到这些数据页被读入内存,咱们在IO线程中把这些拉下的日志都应用掉。

用户能够在只读节点上查询`Innodb_replication_delay`这个status变量来获取当前复制延迟。若是复制延迟比较大而且有不断增大的趋势,能够调大参数`loose_innodb_slave_recv_hash_cells_max`和`loose_innodb_slave_recv_hash_cells_min`来减小延迟。这个参数的主要做用就是增长日志hash桶的数量,从而减小日志查找时候的开销。另外,咱们的Proxy支持Session一致读,即同一个session内的读和写保证是逻辑相关的,在写以后当即读,必定会读到最新的数据(只有因为读写分离,会把读请求发到有延迟的只读节点,从而致使读取到历史版本的数据)。

 

内存问题
有部分用户发现,相比RDS MySQL兼容版,POLARDB的内存使用量会更多,这里须要说明一下,这里的主要缘由是咱们在不少地方使用了以空间换时间的方法,因此内存使用量上会有必定的上升。若是用户发现内存占用过多,能够从如下几个方面诊断:

* 调小`table_open_cache`,同时使用`flush tables`命令关闭全部表空间。这招对打开表数量不少且用户链接不少的用户来讲,效果比较明显。
* 关闭自适应哈希。`innodb_adaptive_hash_index`,这个功能可能会占用不少的内存,可是在如今的SSD磁盘下,性能提高有限。
* 适当的调小buffer pool。这点比较适用于链接数多,同时又不少复杂查询的用户。不过目前调整Buffer pool须要联系售后。

大部分用户的实例,在内存上涨到必定数量后,会中止上涨,这种状况下,即便内存占比比较高,也不用担忧,由于咱们是尽量的使用内存,把内存尽量的都用起来,缓存数据,提升效率。可是若是发现实例内存不断上涨,而后直到OOM,这种状况,请马上联系咱们,咱们会帮您在后台开启一个内存监控工具(依赖Jemalloc profiling工具,可是须要重启数据库),能够用来发现这些内存去哪儿了,究竟是您使用的问题,仍是内存泄露问题,若是是咱们的问题,咱们会尽快解决并给与必定的补偿,若是是您使用的问题,咱们也会给您指出,给出优化的建议等。

在后续的POLARDB版本上,咱们会增长更多的内存监控功能,方便用户自行进行排查。

 

IOPS问题

目前POLARDB的每种规格的实例,都有IOPS限制。同时,RDS MySQL的实例也有IOPS限制。每每有不少用户把这个两个IOPS作比较,其实意义不大。

在RDS中,这个IOPS是指数据文件(后台刷脏线程触发)的写盘次数,日志文件每秒的写盘次数(即主要是Redolog和Binlog加起来的写盘次数限制)是不统计在里面的。可是在POLARDB中,这个IOPS限制不但包括了日志文件的写盘次数限制,也包括了数据文件的写盘限制,即二者加起来每秒写盘的次数不能超过这个值。数据和日志一块儿限制,一块儿隔离,这样更加合理,也减小了由于磁盘压力而产生的性能抖动。

所以,咱们在设置同一类型的规格IOPS参数时,POLARDB上的IOPS通常都比RDS上大好几倍。多出来的IOPS主要是给日志文件刷盘预留的。

目前临时表的磁盘仍是普通的NVME本地磁盘,没有放在自研的磁盘上,所以临时表的IOPS暂时不计入总的IOPS,而RDS上这一部分是放在数据盘上,因此这部分IO会记录到IOPS限制上。同时,咱们在MySQL内核代码中,也有部分限制,主要是为了防止某些用户临时表使用过多从而影响了其余用户。

错误日志,审计日志,慢日志的写盘操做一样在本地盘,没有计入IOPS限制。

另外,咱们在IO带宽上,目前尚未硬的限制(目前POLARDB的实例达不到自研存储的带宽上线),可是很快,为了资源隔离的更加完全,咱们也会加上IO带宽的限制和隔离。

 

升级问题
因为POLARDB是阿里云自研的关系数据库产品,咱们在上面不但开发了数据库系统,还开发了一套对应的文件系统和块存储系统。很多用户对咱们的指望很高,也提出了许多优化建议,所以POLARDB的系统升级频率会比RDS家族的产品高。一方面,咱们须要修复一些极端状况下会被触发的BUG,另一方面,咱们须要知足用户形形色色的需求。固然,咱们的系统升级都是热升级,咱们竭尽所能尽量减小对用户的影响,例如在系统升级时期的性能抖动时间,数据库不可服务时间等等。若是系统要升级,咱们会提早给用户发短信/邮件以及大客户的电话通知,通常系统升级都在凌晨用户设定的可运维时间,正常的升级流程可能会形成秒级的服务中断,客户只须要在应用端保证能重连数据库便可。若是那天晚上,升级不太方便,请尽快提工单给咱们,咱们再约其余时间。咱们后台也在开发一套主动运维系统,有了这套系统以后,用户就能够在控制台上在指定的时间点内主动升级数据库,同时不一样版本的数据库也会有详尽的releasenote,便于用户按需升级。

 

总结
这篇文件简单解答了几个用户经常问到的问题。但愿对你们有所帮助。

最后,欢迎使用POLARDB。

相关文章
相关标签/搜索