作者:文韵涵
爱可生 DBLE 团队开发成员,主要负责 DBLE 需求开发,故障排查和社区问题解答。
问题背景
在使用某些 GUI 工具连接 DBLE 操作时,会因为某些 SQL 在 DBLE 中不兼容导致 GUI 工具出现异常不能正常使用。
通常排查方案:
- 步骤一:需要知道 GUI 工具操作时下发了哪些 SQL 至 DBLE ;一般用 tcpdump 、Wireshark 等抓包工具获取 SQLs
- 步骤二:将 SQLs 逐个在 Mysql Client 中执行,定位问题 SQL
排查案例1
登陆 phpMyAdmin 首个界面,未展示数据库列表
GUI 工具: phpMyAdmin 7.4.20 (这里用的是docker)
DBLE 版本:3.21.02.x
访问 http://ip:8080 ,使用 DBLE 的 8066 用户密码登陆;登入后的界面发现未展示数据库列表,如下图:
为什么没有展示数据库列表呢?
排查步骤一:
先下载 tcpdump(用于抓包)、Wireshark(查看包)工具;然后执行 tcpdump 命令采集操作(登入 phpmyadmin 后的界面)期间的 tcp 协议传输生成 cap 文件,然后将其文件放置 Wireshark 中转成 Mysql 协议然后过滤(如下图)方便阅读、排查以及提取下发的所有 SQLs ;(实际上需要逐个点开 Request Query 然后手动提取 SQL )
排查步骤二:
将收集的 SQLs 逐个在 Mysql Client 中执行,定位到问题 SQL (原因:phpMyAdmin 下发查询库列表时,DBLE 返回空结果集)
具体问题 SQL :
- SELECT
SCHEMA_NAME
FROM INFORMATION_SCHEMA
.SCHEMATA
, (SELECT DB_first_level FROM ( SELECT DISTINCT SUBSTRING_INDEX(SCHEMA_NAME, ‘’, 1) DB_first_level FROM INFORMATION_SCHEMA.SCHEMATA WHERE TRUE ) t ORDER BY DB_first_level ASC LIMIT 0, 100) t2 WHERE TRUE AND 1 = LOCATE(CONCAT(DB_first_level, '’), CONCAT(SCHEMA_NAME, ‘_’)) ORDER BY SCHEMA_NAME ASC; – 查询所有库 - 2021-08-06T15:33:28.350 9 Query SELECT COUNT(*) FROM ( SELECT DISTINCT SUBSTRING_INDEX(SCHEMA_NAME, ‘_’, 1) DB_first_level FROM INFORMATION_SCHEMA.SCHEMATA WHERE TRUE ) t; – 查询库的个数
在步骤一中,需要用到额外工具协助排查,可能需要储备一些知识(如:TCP 协议、抓包命令);于是,非开发人员排查此问题是比较苦恼的。
general log
开启 general log ,将所有到达 DBLE 的 SQL 语句记录下来。这样一来不再需要使用抓包工具就可以拿到所有 SQLs(直接进入步骤二)
具体见general日志:
https://actiontech.github.io/dble-docs-cn/2.Function/2.27_general_log.html
相关参数
- enableGeneralLog:general log 的开关标识,1-开启、0-关闭
- generalLogFile:general log 文件的存储路径
- generalLogFileSize:触发文件翻转的大小,当超过16MB则将 general.log 翻转为 yyy-MM/general-MM-dd-%d.log 的格式文件
- generalLogQueueSize:内部实现机制队列用到的大小,默认4096
以上参数在 bootstrap.cnf 中配置,在这个配置中的更变,需要充气后才能生效。
相关命令
- show @@general_log; – 查询 general log 的开关状态和文件路径
- enable @@general_log; – 开启 general log
- disable @@general_log; – 关闭 general log
- reload @@general_log_file=’/tmp/dble-general/general/general.log’; – 修改 general log 的文件路径
以上命令仅管理端支持执行,立即生效,不需要重启 DBLE 。另外下次重启 DBLE 的时候会保留当前设置,不会丢失。
版本
- 从 DBLE3.21.02 版本开始引入 general log ;(之前的版本不支持)
性能
- 开启 general log 后,DBLE 性能损耗在3~5%之间;建议在排查某些错误临时打开,等调试完后关闭
输出类型
- 与 Mysql 相比,DBLE 的 general log 的输出类型只有 File 模式
打印格式
- 开启后,记录格式(与 Mysql 的 general log 格式一致)
实现机制
DBLE 中 general log 的异步落盘机制具体的实现参考log4j
具体实现
- 同步处理
- 将 sql 包装为 Log ;Log 包含 Time、Id、Command、Argument 等信息
- 将 Log 放置 generalLog 队列中;(若队列已满时,会一直阻塞在此处,直到队列有空闲位置)
- sql 的后续流程处理
- 异步处理
- 监听队列且处理队列
- 当前 Log 的 byte 大小 <= Buffer 缓存剩余空间(默认4096),则先入 Buffer 缓存中;后续 Buffer 缓存满了会触发落盘
- 当前 Log 的 byte 大小 > Buffer 缓存剩余空间, 先将 Buffer 缓存中的 Log +当前 Log 直接落盘
- 因为采用了 Disruptor(generalLog 实际上是一个环形队列),入队计算会决定是否为批量处理的状态,如果为批量处理,也会触发将 Buffer 缓存中的 Log/ 当前 Log 的落盘
- 翻转条件:日期变动(每天) || general.log 的大小>generalLogFileSize 时