GaussDB(DWS)采用MVCC(Multi-Version Concurrency Control) 多版本并发控制实现对数据库的并发访问,以及带来诸如锁冲突少、事务回滚代价低等好处,但同时给数据库空间管控带来极大挑战。
脏页率过高,也带来访问性能下降风险,本文未重点阐述此信息;。
本文主要从数据仓库的实践出发,结合数仓周期性的批量特征,制定数据表脏页空间回收实践,规避数据ETL过程带来空间几何膨胀问题,做到普通业务用户只关注业务实现,具体脏页空间运维对业务透明。
相信不久将来,GaussDB(DWS)会在脏页空间管理上更上一层楼,不再需要DBA关注与运维。
下文由DWS简称代替GaussDB(DWS)数据库产品全称,便于复述;
本文基于8.1.0版本数据库阐述;
1 实施设计
1.1 系统表
- 理念
- 避免脏页空间回收引入集群性能、业务连续性影响,即减少业务用户感知;
- 允许系统表存在一定膨胀空间(合理范围内的脏页率,并不影响集群性能);
- 业务高峰时段(业务重点保障时段)不实施脏页管控相关行为,最大化保障业务;
- 长期周期性vacuum(利用DWS行存vacuum打标脏页复用特性)与定期vacuum full(彻底回收脏页)相结合,有效控制空间膨胀;
- 过往实践,脏页率(脏页数据/总数据)超80%以上,有跟踪到性能下降风险;
- 思路
- 虽然DWS提供系统表auto vacuum(自动脏页空间管控),可较好管控系统表空间膨胀,但当前版本也存在无法完全适配客户实际场景(如高峰时段,业务影响系统表越频繁,业务和系统vacuum资源争抢越严重,进而影响集群整体性能);
- 系统表vacuum full属于重操作(八级锁),影响业务登录、DDL等操作,故当前不建议程序化定期操作(若业务存在明显空载时间窗口除外);
- 系统表vacuum操作,对业务影响有限,结合数仓周期性ETL特性,建议每日业务低峰时段自动化运行一次;由于每日业务ETL过程相当,故系统表每日一次vacuum,让系统表脏页重新复用,即系统表整体空间增长有限;
- 系统表对象有限,可一次性从pg_catalog模式中提取系统表清单,免去每次二次检索;
- 每次下发单张表vacuum操作前,需确认集群负载情况(本文当前采用pgxc_stat_activity查询活动非业务会话个数,各位可根据CPU、IO等负载管控阀值,但不建议太复杂),同时减少在业务DDL操作时段下发vacuum操作;
- 创建日志表,保存vacuum过程信息,即vacuum时间、当前表空间情况,用于后续分析;
1.2 用户表
- 理念
- 用户表影响范围有限,直接选择程序化vacuum full操作(列存也暂不支持vacuum效果);
- 限定业务低峰时段运行,避免资源争抢;
- 存在vacuum full最晚发起时间窗口管控,规避脏页回收清单过多,自动化程序超出限定时段运行;
- Vacuum full优先从可回收最大空间域值出发,保障回收结果,释放更多空间;
- Vacuum full兼顾脏页率,确保对应用户表性能保障;
- 固定周期(每周末,个人用户低峰期),对所有存在脏页的数据表,集群级遍历vacuum full,进一步管控好用户表脏页空间;
- 思路
- 收集过往集群资源使用相当稳定低峰时段,用于下发用户表vacuum full时间窗口;
- 收集用户表当前空间大小、脏页率信息,保存相关日志表;
- 根据日志表,筛选可回收空间大于阀值(如空间大小*脏页率>200MB)及脏页率大于阀值(如脏页率>30%)的常规用户表,用于每日vacuum full下发清单;
- Vacuum full用户表时,建议增加analyze操作,更新用户表统计信息,保持用户表最佳访问状态;
- 每周末(2天)除了常规vacuum full清单,增加一个队列,遍历本周以来,筛选存在脏页但又未被vacuum full的清单;
- 常规vacuum full清单,优先从可回收最大表空间的用户表开始下发,少量并发(如6个,主要根据集群负载资源出发,确保IO资源使用低于70%;当然也可以不敢调整并发,只要不影响业务用户使用,就可以增加并发),管控好下发时间窗口,一旦vacuum full超过时间窗口,不再发起新任务,并逐步停止调度;
- 周末遍历vacuum full清单,优先从表空间最小的表出发,适当提高并发度(如20个),这样较好解决小表脏页率高、但可回收空间低的矛盾点,也适量提高集群可用空间;
- 下发vacuum full前,主动通过pgxc_stat_activity的query字段,跟踪对应业务表是否正在被访问(active),减少vacuum full带来锁冲突、锁等待;
2 实现过程
2.1 关闭系统脏页空间管控
集群内下发相关参数,关闭当前版本auto vacuum特性。
gs_guc reload -Z coordinator -N all -I all -c "autovacuum=off" gs_guc reload -Z datanode -N all -I all -c "autovacuum=off" gs_guc reload -Z coordinator -N all -I all -c " autovacuum_max_workers=0" gs_guc reload -Z datanode -N all -I all -c " autovacuum_max_workers=0" |
2.2 创建相关日志表
- 表空间大小采集表
记录收集日期、模式名、表名、表大小、脏页率、(*表倾斜率)
- 表vacuum日志表
模式名、表名、回收前表大小、回收开始时间、回收后表大小、回收结束时间
*注,系统表、用户表复用该日志表
2.3 实现程序
- 主要使用python实现主线逻辑;
- Python封装gsql,实现数据库便捷交互连接(connect)、访问(sql_submit);
- 利用theading实现多线程并发(本文线程主要用于数据库交互并发);
- 将系统表、用户表vacuum拆分两个自动化程序;
- 利用文本配置交互,实现中途并发数增减操作;
2.4 调度程序
添加到crontab中每日低峰开始时间,发起程序自动化调度。
3 待改进
- 当前业务低峰周期是人为界定,遇到国家法定假日问题(工作日放假、周末补班)、源业务异常等业务高峰推迟、设备故障等问题,脏页空间回收程序,无法自动化适应变化;
- 当前每日用户表vacuum full时,在脏页率和可回收脏页空间之间没有做到平衡,对于部分场景(集群资源有限),可能导致小表脏页率居高,进而影响该用户表访问性能;