银行联机交易系统对服务质量有极高要求,通常要求单笔业务在数十毫秒内完成,这对整个联机交易系统的性能设计提出很大挑战,其中数据库SQL的执行效率是尤为关键的环节。不良的SQL语句会极大影响数据库处理响应时间,导致系统开销过大,整体处理响应变慢,无法满足业务服务质量要求,严重的SQL甚至会影响耗尽整个服务器资源,导致全网业务请求得不到及时处理,因此对应用系统的SQL治理非常重要。
过往银行应用系统严重依赖国外数据库产品,SQL治理手段有限,通常采用应用层拦截或者网络旁路方案,实施静态代码检查或网络请求截获进行SQL治理,准确度不高,实施复杂。随着国内自主创新步伐逐步加快,基于国产数据库的应用系统越来越多,通过应用方与厂商联合技术攻关,开拓出更广阔的技术实现途径。某头部大型国有银行联合GoldenDB分布式数据库,探索在数据库内核层实现SQL治理,达到了良好的治理效果。
全流程治理SQL治理涉及应用的开发阶段、生产阶段和事后优化等全流程环节,以保障生产系统稳健运行,并持续提升质量。在开发阶段进行SQL审核,提升SQL编写质量;生产过程中快速终止严重影响服务的SQL任务,并在事后对不良SQL进行迭代优化。
图 1: SQL全流程治理
应用开发阶段,使用模拟数据对应用SQL进行压测,收集设计不合理、性能差、影响系统运行的SQL,进行不良SQL改写和代码优化。通过这个阶段治理,可以快速提升应用处理性能,达到基本的投产性能要求。
系统上线初期,业务数据量相对较少,但随着业务的快速发展和数据量的持续激增,不良的SQL对系统和数据库的性能压力才会逐步表现出来,进而影响生产服务质量,需要快速干预,通过内核层识别出对生产系统过大开销的业务SQL并中止运行,避免整个生产系统受到影响,导致服务质量下降。
终止业务请求方式会影响到当前业务处理成功率,应设置足够阈值,且避免过度使用。更均衡的方式是收集生产上运行开销大的SQL,纳入到后续迭代版本中进行整改优化。
SQL治理框架SQL治理涉及系统管理员、运维人员和应用开发团队。管理员在GoldenDB管理台上设SQL治理规则(profile),管理台基于GoldenDB内核SQL治理能力和语法功能,下发规则到GoldenDB数据库引擎节点,数据库引擎实时收集SQL各环节执行信息,识别慢SQL请求,根据规则判断是否终止或者产生警告,并将该SQL语句以及采集的详细信息输出到运行日志中。
图 2: SQL治理框架
管理台对采集上来的慢SQL语句和日志进行分类统计,由管理员派发给开发团队进行版本优化或改进迭代。此外,GoldenDB管理台统计因治理规则而终止的SQL数量,达到一定数量时,产生告警上报到集中告警平台,由运维人员评估服务质量影响和系统干预。
GoldenDB数据库引擎通过以下数种手段识别慢SQL:一是基于实际执行的开销来判断慢SQL,包含执行时间过长、查询或者关联的结果集过大、扫描数据块数过多等情况;其次是基于静态SQL规则,设定对生产系统造成性能影响或者安全危害的SQL类型;三是采集用户占用的资源数据,包括CPU、连接数等系统和数据库资源。本项目中,也实现了一种试验性方案,即通过判断SQL执行计划中的开销估计进行过滤,对开销估计过高的SQL,在执行前进行终止,提前避免不良SQL对系统的影响。由于识别和干预位置在数据库不同的执行阶段,数据库内核关键模块均需要进行修改扩展,包括SQL解析器(基于静态SQL规则)、SQL优化(基于开销估计)和执行器(基于实际执行统计)。
图 3 :涉及SQL治理的主要模块
SQL扩展语法GoldenDB数据库引擎层扩展SQL治理规则语法(PROFILE):
CREATE PROFILE profile_name LIMIT profile_limit_list
其中,profile_limit_list 表示一组限制项集合,每个限制项包含三部分:
限制项名 状态[on|off] 策略[aborted|warning]。当为on的状态,则对该限制项生效,否则忽略该限制项;策略可以是aborted-终止执行,或者warning-警告,两者均会写入数据库运行日志。
创建治理规则后,可以将治理规则赋予特定用户:
CREATE USER ... PROFILE profile_name;
将治理规则指定到具体用户,以便区别联机交易场景和业务批量场景。联机交易场景特点为高并发、低时延的短平快SQL,批量场景则为大规模数据查询和更新,两者适用的策略不同。
当前已经实现的多种治理规则,举例如下:
1.基于实际开销的治理规则
(1) execution_time: DML和DQL语句允许的最大执行时间。
(2) select_result_set: 单次SQL执行允许返回的最大结果集行数。
(3) max_join_size: 多表关联查询中关联行数。
(4) logical_reads_per_call: 单次SQL执行所允许读的数据块的最大数目。
(5) logical_reads_per_session:单个会话允许读的数据块的最大数目,包括从内存和磁盘读的所有数据块。
...
2.高危SQL的治理规则:
(1) blacklist_unsafe_updates:SQL黑名单拦截(例如:没有where条件且没有limit,或者没使用索引,对DELETE和UPDATE语句生效等等)。
(2) blacklist_no_index: 不带索引黑名单拦截(全表扫描等场景)。
(3) blacklist_cross_join: 笛卡尔积黑名单拦截。
(4) blacklist_drop_database:DROP DATABASE黑名单拦截。
(5) blacklist_drop_table:DROP TABLE黑名单拦截。
(6) blacklist_truncate_table:TRUNCATE TABLE黑名单拦截。
...
3.基于资源统计的治理规则:
(1) sessions_per_user:该用户能够创建的最大会话数。
(2) cpu_per_session:单个会话允许的最大CPU时间。
(3) cpu_per_call:单次SQL执行允许的最大CPU时间。
...
4.基于代价估计的治理规则:
(1) sql_cost:SQL语句允许的最大代价。
实施效果目前该行多个应用系统使用该SQL治理平台进行开发阶段的SQL治理,治理效率明显提升,问题SQL得到快速收敛;并在试点生产应用中实施慢SQL采集和拦截,对过慢SQL进行快速干预,生产系统服务平稳性得到提高;将试点生产应用上采集的慢SQL列表,同步给应用团队定期整改,虽然业务数据量不断增加,但系统平均SQL执行时间维持在良好状态。
基于数据库内核层的SQL治理,相比较应用层治理和旁路治理具有诸多方面的优势:
undefined 准确度高。由于是在数据库内部实现,SQL质量评判来自真实数据,相比较静态代码检查、基于SQL文本规则检查的方式更加准确全面,不容易遗漏;随着实际生产数据量和处理负荷变化,该方案的持续治理优势更加凸显。
undefined 开销小。旁路治理需要采集大量数据进行中间分析,增加了系统负担,且需要部署专用生产设备;而该方案在数据库执行过程采集内部结构和少量统计数据,几乎不增加系统开销;基于SQL扩展语法,实施过程也非常简洁轻便。
undefined 定位精准。由于是深入到数据库内核层,直接访问数据库内部结构数据,可以快速做出规则判断,并输出关联的日志信息,包括执行SQL、执行开销、数据库当即状态等,事后分析和优化更加精准快速。
undefined 快速干预。质量差的SQL,影响到系统处理性能的请求,可以就地终止,保障整体服务质量不受影响。
实践总结基于数据库内核进行SQL治理在优化效率、轻量化部署和快速精准定位上具有诸多优势,在银行试点应用中已取得了良好的治理效果,后续进一步推广到更多新建系统中。目前数据库内核SQL治理功能仍较为基础,后续结合应用具体场景进一步完善,比如可以将多个治理规则进行条件组合,匹配更复杂的SQL治理要求;支持插件在线安装,让已投产数据库在线扩充SQL治理规则的能力。
以往银行系统依赖国外数据库技术,难以开展此类技术创新实践,得益于国产数据库应用的推进,国内数据库技术发展迅速,通过数据库底层技术的增强来解决应用痛点的开创性工作将会越来越多,同时也推动数据库技术继续向前发展。