2019 年 5 月 8 日 -10 日的 DTCC2019 年中国数据库大会上,腾讯云数据库专家工程师雷海林首受邀做了主题为《TDSQL 智能运维平台 - 扁鹊架构与实践》的技术分享,以下为大会现场演讲实录。
一、扁鹊的基本介绍
扁鹊系统是 TDSQL 面向云市场推出的一款针对数据库性能 / 故障等问题的自动化分析并为用户提供优化 / 解决方案的产品。
1. 扁鹊的需求背景
TDSQL 作为腾讯针对金融场景推出的高一致,分布式数据库集群的解决方案目前已覆盖了腾讯 90% 的支付业务场景,内部有大量团队使用;同时作为腾讯金融云的数据库产品,支持公有云和专有云两种云解决方案,目前拥有了大量的政府,银行、保险、物流、电商等客户,但随着客户和集群规模的不断扩大,在 TDSQL 运营过程中也带来了很大的挑战。
针对这些问题,我们认为需要一个自动化的故障 / 性能问题分析系统,减少 DBA 的重复劳动,沉淀我们的分析经验,快速定位问题,带给我们的客户最快速的响应同时也提升 DBA 的幸福指数。
之所以将这个模块命名为扁鹊,就是希望它能像古代的扁鹊神医为人诊断病因一样也可以为数据库“对症下药“,治疗 / 修复 / 预判数据库已知或潜在的风险。
2. 扁鹊的作用
在开发扁鹊系统的时候,随着 DBA 的专家知识库不断向扁鹊输入,目前我们大部分现网的性能 / 故障问题基本都可以通过我们扁鹊一键分析原因,大大解放了 DBA 的双手,极大提高了运营效率。下图是我们对扁鹊在设计阶段所设定的基本功能和目标,核心点就是希望扁鹊能做到风险事前预警,事中准确分析原因并解决问题,事后能对历史事件进行分析,发现问题点。
二、系统架构
扁鹊大体可以分为下图中的六个层次结构
1. 资源层主要包括 DB 实例和宿主机提供各种原始的信息
2. 采集层会从资源层采集一些性能指标,SQL 日志,表结构等必要的诊断信息并输送到存储层
3. 存储层负责将采集层提供的信息持久化,以供后续对历史数据进行分析
4. 索引层会从存储层提取数据再次进行分类并形成可编程的数据结构,也是分析层所需要的诊断单元
5. 分析层是扁鹊的核心逻辑,主要负责利用索引层的元数据信息结合 TDSQL 自身沉淀的知识库对数据库常见异常如主备切换,主备延迟,等问题进行根音分析,风险评估
6. 展示层最终会将分析层的结果可视化,大体可分为健康报表和具体的故障 / 性能 / 优化建议
下图展示了扁鹊更细化的结构,可以看到扁鹊具备了哪些功能,这些功能需要哪些元数据,元数据又从哪些层面获取,各模块之间如何交互等,如果大家要做类似的功能可以基于这个做一个很好的参考。
三、智能诊断原理与实践
我们将客户经常咨询的 DB 问题大体分为三类,可用性问题、性能问题、可靠性问题。
下面我们具体看一下扁鹊是怎样针对这三类问题进行分析并解决的。搜索关注腾讯云数据库官方微信,获取更多数据库技术干货分享,体验移动端一键管理数据库。
1. 可用性问题
可用性问题主要是指 DB 在一段时间内无法响应用户的请求
TDSQL 作为金融级数据库本身是做了高可用的,当主机出现异常无法继续提供服务时会自动选则新主切换。这里我们探测主是否存活的方法是利用一个 agent 模块定期的连接 DB 并向 TDSQL 自建的一个心跳表中写入数据,这样无论是磁盘坏块,磁盘满了还是 DB 重启导致 DB 不可用,agent 都能准确的判断出来,当 agent 连续一段时间写入心跳失败或超时就会触发切换的逻辑,在这期间 DB 会处于短暂的秒级不可用状态,从用户侧可能会收到 DB 只读,连接断开等异常。对于这种情况,业务往往需要清楚地知道切换的原因是什么,如何避免切换再次发生。
引起切换的原因有很多,这里我们列举了一些常见因素,如触发了内核某个 bug 导致 DB 重启 hung 住,磁盘故障导致 DB 无法写入。也有可能是由于用户的一些 SQL 过度的占用一些 CPU、IO 等资源导致的,如大事务,慢查询并发影响到用户或心跳线程写入等等。
要分析出切换问题的原因,我们首先要做的就是保留必要的现场信息,为我们后续的诊断提供线索。
这里我们实现了针对 top,iotop,iostat 等宿主机资源状态信息的秒级采集以及切换前 DB 内部 processlist,innodbstatus 等快照信息。我们上面列举的异常原因基本都可以在这些信息中反映出来,下面我们详细的解释一下如何利用这些信息分析切换原因,扁鹊针对这个问题的分析又达到了怎样的效果。
从我们自身的运维经验来看,由 DB 故障导致的切换并不常见,更多的情况是由于用户的 SQL 占用过多的系统资源引发的一些异常状况,主要可以分为慢查询并发和大事务两类,下面我们逐个分析两种行为触发切换的原因
由慢查询并发引起的主备切换
TDSQL 默认采用 innodb 存储引擎,在 innodb 中为了避免同时在 innodb 中同时运行的线程过多带来额外的性能开销,innodb 提供了一个 innodb_concurrency 的参数,用于限制同时在 innodb 中执行的线程数的最大值。搜索关注腾讯云数据库官方微信,获取更多数据库技术干货分享,体验移动端一键管理数据库。如果客户执行了用大量的并发连接执行慢查询,这些慢查询会不断地占用 innodb 的活跃线程,导致用户很多访问 innodb 相关的操作简单插入 / 更新等操作也容易被阻塞,等待 innodb 处理,同样也会引起 agent 心跳检测不断失败,从而触发主备切换。
当这种情况发生时,我们可以看到 innodb status 信息中有大量的线程处于等待队列,并且有很多慢查询在 processlist 中执行和很长时间,这样我们就可以分析事先保存的 innodb status 信息确认这一现象,再结合 processlist 中找出 TOP 慢 SQL 就可以知道是哪些慢查询并发导致了这个问题。
大事务引发的主备切换原因
TDSQL 为了保证主备数据的一致性默认采用 row 格式的 binlog,如果用户执行了一个 delete 大表的操作就可能产生一个非常大的 binlog 写入,由于 binlog 是顺序写入的,大事务的 binlog 没有完成写盘之前,后面一些小的写入操作如 TDSQL 心跳写入也会被阻塞在写入 binlog 的阶段等待大事务 binlog 写入完成,这个等待时间过程会导致心跳写入频繁出现超时。从而触发切换的逻辑,这种情况下我们会观察到 innodb status 中有大量事务已经完成的在 innodb 层的 prepared,等待写入 binlog,并且在 processlist 中有大量的心跳写入被阻塞。
目前针对这种情况 TDSQL 已经做了优化,比如默认限制 binlog 一次写入的大小不超过 1.5G 禁止大事务的产生。
扁鹊的自动化分析效果
结合上述分析流程,扁鹊会自动化的针对监控,切换前的 DB 快照等信息分析出切换的原因,并展示详细的分析过程。
1). 下图展示了扁鹊分析出由于 DB 发生不存活引发了主备切换
2). 这一例展示了扁鹊自动结合切换前 innodb status 的活跃线程已满和 processlist 慢查询过多两点判断出是由于慢查询并发触发了主备切换,并且扁鹊将 processlist 的 SQL 按照 SQL 指纹聚合起来,方便用户快速定位到是哪条 SQL 导致了这个问题
3). 这里我们看到扁鹊定位到了由于大事务引发的主备切换,并找到了引发大事务的具体 SQL
2. 性能问题
接下来我们介绍 DB 的性能,哪些原因会导致性能问题。
性能问题,从用户侧最直观的感受就是 SQL 的执行时耗过长,导致这个问题的常见原因有
- 网络因素,如延迟,丢包等
- SQL 自身执行较慢
- 资源饱和
- 锁等待
网络问题我们暂不在此深究,这里我们主要针对后三种情况展开分析一下:
SQL 自身执行较慢
对于 SQL 自身执行较慢通常是由于用户没有建立合适的索引,或者由于一些 SQL 写法上的原因导致没有利用到已有的索引,扁鹊针对这种 SQL 会自动的通过语法解析,SQL 访问的表结构,数据分布等信息进行分析,生成合适的索引优化建议反馈给用户。搜索关注腾讯云数据库官方微信,获取更多数据库技术干货分享,体验移动端一键管理数据库。
资源饱和
对于资源饱和引起的慢查询,如当前 CPU/IO 等资源飙升,扁鹊的会话分析功能会自动将当前会话按照 SQL 指纹进行聚合,从而快速找到导致消耗资源的 TOP SQL 再自动关联 SQL 优化模块得出优化建议。搜索关注腾讯云数据库官方微信,获取更多数据库技术干货分享,体验移动端一键管理数据库。这样不论是普通用户还是 DBA 都可以快速定位到资源消耗的罪魁祸首同时对优化的方案一目了然。
锁等待
引起 SQL 请求时耗高的另一大常见因素是锁等待问题比如事务 1 中一个会话更新了一行,但是事务还没有提交,这时另一个事务 2 的某个 SQL 去更新同一行就需要等待事务 1 提交完成才能执行,这其中等待的时耗也会导致整个请求的时耗增加。这种情况下用户的可能会发现部分简单的操作例如主键更新正常情况下都是 0ms 的,偶尔突然变成了数十秒,当客户反馈给我们后,发现 SQL 执行时耗可能又正常了,下面我们看一下扁鹊如何辅助客户 /DBA 分析这类问题。
在下图的例子中我们可以看到 session1 update t1 某一行后一直没有提交,该行锁始终不释放,导致 session2 update 同一行的操作出现锁超时现象。
对于这种情况只要客户的 session1 不提交事务并且不与 DB 断开连接,这个会话持有的锁就会一直保持。MySQLinformation_schema 下有三张表记录了事务之间的锁等待依赖关系,如下图中 session4 不被其他会话阻塞,但 session4 持有的锁阻塞了 session1,2,3,这里我们称 session4 为持有锁的领头会话。这种情况由于锁等待现场环境还在,扁鹊就通过分析这三张表的信息可以找到持有锁的领头会话并建议用户 kill session4 来解除锁等待。
下图是扁鹊诊断这种锁等待的效果图
除了事务未提交以外,用户的业务逻辑也有可能在执行完事务中所有 SQL 后没有立即提交事务,导致事务持有锁时间较长。在下图中可以看到 session1 执行完 update t1 后隔了 50s 才提交事务,导致 session2 的 update 同一行操作的时耗也在 50s 以上甚至出现锁超时错误,如果用户在 15 点反馈 12 点某个时刻出现了这样的问题,我们再去查看 information_schema 下的锁信息内容会发现已经没有这样的锁等待关系了。搜索关注腾讯云数据库官方微信,获取更多数据库技术干货分享,体验移动端一键管理数据库。针对这种情况,我们只能通过用户执行过的 SQL 日志,来找出 session1 这个历史会话信息,那么我们面临的问题是
- 从哪里提取 SQL 日志?
- 如何通过用户提供的慢查询高效的找出 session1 这个历史会话信息?
从哪里提取 SQL 日志?
TDSQL 的在用户和 DB 的连接之间有一个 proxy 层,所有的用户 SQL 执行都会先经过 proxy,在 proxy 中实现了高效的日志模块,可以将用户执行过的 SQL,执行时耗,客户端地址等信息脱敏后全量的保存下来,并且对性能没有任何影响。
如何通过用户提供的慢查询高效的找出 session1 这个历史会话信息?
虽然有了用户全量的历史 SQL 信息,但是我们仍然难以直接从日志中找到 session1 在某一时刻阻塞 session2 这种时间序列“交错”的会话信息,或者说是 session1 事务开始结束时间覆盖了某个时间点的事务信息。
这里扁鹊实现了一个事务模拟器,可以通过按客户端执行记录的 IP:PORT 分组并结合语法解析回放用户执行过的 SQL 来提取所有事务信息,如事务的开始,结束时间,事务中访问了哪些表,事务的影响行数,事务的总时耗等等,这样我们就可以通过设定过滤条件以事务为单位来找出某个事务具体的执行信息。
扁鹊诊断案例
接下来我们来看一个案例,用户反馈在 22:00:37 这个时刻 update T01_NOR_CUST_INFO 这张表出现了锁超时。
扁鹊通过设定 22:00:37,T01_NOR_CUST_INFO 这两个条件就可以自动找出事务执行时间包含 22:00:37 并且对 T01_NOR_CUST_INFO 有过 update/delete/insert/selectfor update 等可能产生行锁的事务,并自动的提示用户这个事务时耗过长,持有的锁时间过长可能影响其他会话这一异常信息。搜索关注腾讯云数据库官方微信,获取更多数据库技术干货分享,体验移动端一键管理数据库。有了这个功能,我们就可以根据用户提供的慢查询出现的时间点和 SQL 快速的找出影响的会话具体信息,用户就可以根据扁鹊提供的事务信息和时间来排查业务逻辑修复问题了。
3. 可靠性问题
DB 的可靠性问题主要表现为业务目前可能并未感觉数据库访问存在异常,但是想为 DB 做一次体检来确定 DB 是否有潜在的风险或隐患导致未来某一时刻 DB 出现异常的问题存在。
对于 DB 潜在风险的排查,我们针对性能监控,表结构,历史会话,慢查询等信息结合腾讯云海量数据 + 机器学习的能力系统的评估 DB 的健康状态,检测可能的异常并告知客户,尽可能将大部分异常在发生之前就发出预警,将风险降到最低。
四、总结
以上我们介绍了由 TDSQL 运营痛点催生扁鹊的需求背景,以及扁鹊的层次结构,组成元素,还有主备切换,锁等待分析等关键技术的诊断原理,实践经验。拥有扁鹊后在公有云性能类咨询工单已经基本降为 0,可以看出扁鹊目前的功能已经可以很好的服务于我们的客户也提升了我们 DBA 同学的生活品质,未来我们也会继续完善扁鹊的诊断、预测能力,整合我们 DBA 多年的运营经验和 AI、机器学习等技术,覆盖更多的异常场景,争取做到将所有异常在发生前就预测到,为客户提供更安心的运营环境。
本文转载自腾讯云数据库
原文链接: