一、 问题场景:被慢 SQL 和索引拖垮的研发与 DBA

在大宗商品销采运储系统运行初期,DBA 和架构师还能靠人工盯盘。但随着系统膨胀到几千张表、几万个接口,噩梦开始了:

  1. 人工救火效率极低:月底批量对账,慢查询日志动辄几百 MB。DBA 登录服务器、拉取日志、复制 SQL、跑 Explain、找研发沟通改代码,处理一条慢 SQL 至少半小时。

  2. 索引泛滥成灾:研发人员换得勤,为了赶进度,每遇到一个查询就加个单列索引。最后一张核心订单表挂了十几个索引,导致写入性能暴跌,开单严重卡顿。

  3. 隐式转换与索引失效频发:业务代码里一个小小的 WHERE order_no = 123(把字符串传成数字),就能让千万级大表的索引瞬间失效,CPU 直接打满。

传统的事后排查,根本治不了本。企业迫切需要把 DBA 从“看日志的机器”中解放出来。

二、 趋势与要求:AIOps 是智能运维的必答题

随着国务院《关于深入实施“人工智能+”行动的意见》及国资委“AI+”专项行动的推进,AI 与 IT 运维(AIOps)的融合已经从“可选项”变成了“必答题”。

行业数据显示,超过 60% 的企业已经在尝试利用大模型辅助 IT 运维。企业的核心诉求非常明确:

  • 降本增效:让 AI 承担 80% 的重复性日志分析工作,人工只做最终审核。

  • 防患于未然:在数据库被彻底打崩之前,提前发现索引缺失、死锁隐患。

三、 AI 在数据库治理方向的使用

在当前的数据持久层,AI 可以重点在三个方向发力:

  1. 慢 SQL 智能诊断与改写:输入 SQL、表结构和执行计划,让 AI 指出为什么慢,并给出改写方案。

  2. 索引智能推荐与冗余清理:分析高频查询和从未使用的废索引,给出最优的联合索引方案。

  3. 故障根因辅助排查:输入死锁日志和监控指标,快速输出故障复盘报告。

图片

四、 AI 赋能的核心好处(ps: 不能全依赖AI)

  • 效率提升 10 倍:以前排查一条慢 SQL 要 30 分钟,现在 AI 3 秒钟给出初步诊断和改写建议。

  • 降低人为漏判:AI 能不知疲倦地扫描全量慢日志,发现隐藏极深的隐式转换或低效 Join。

  • 提升系统整体吞吐:通过清理冗余索引,直接提升核心大表(如订单、库存)的写入 TPS。


五、 工程化落地:打通 AI DBA 的“任督二脉”

要把 AI 引入数据库治理,绝不能搞个对话框就完事。必须打通 “采集 → 脱敏 → 拼装 → 推理 → 校验 → 闭环” 的完整流水线。

图片

(一)采集:定时拉取慢日志

不要直接去读庞大的 slow.log 文件,我们在数据库层开启 slow_query_log,并利用调度服务(基础服务层组件)定时查询 mysql.slow_log 系统表。

@Service
@Slf4j
public class SlowLogCollector {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    // 每天凌晨 2 点拉取前一天的 Top 50 慢 SQL
    @Scheduled(cron = "0 0 2 * * ?")
    public void collectSlowLogs() {
        String sql = "SELECT sql_text, query_time, lock_time, rows_examined, db " +
                     "FROM mysql.slow_log " +
                     "WHERE start_time >= DATE_SUB(NOW(), INTERVAL 1 DAY) " +
                     "ORDER BY query_time DESC LIMIT 50";
        List<SlowLogDTO> logs = jdbcTemplate.query(sql, (rs, rowNum) -> { ... });
        logs.forEach(this::processLog);
    }
}
(二)脱敏:阻断敏感数据外泄

大宗商品的 SQL 里往往带着真实客户名和金额,直接发给大模型就是严重的泄露事故。必须进行正则预处理。

public class SqlMasker {
    public static String mask(String sql) {
        // 1. 屏蔽单引号内的中文字符串(如客户名、商品名)
        // 将 WHERE customer_name = '西安XX贸易' 替换为 '***'
        sql = sql.replaceAll("'[^']*[\\u4e00-\\u9fa5]+[^']*'", "'***'");
        // 2. 屏蔽具体的敏感金额数字
        sql = sql.replaceAll("=\\s*\\d{5,}", "= ?");
        return sql;
    }
}
(三)拼装与推理:结合元数据调用大模型

光给 AI 一句 SQL 是不够的,必须附上表结构(DDL)、当前索引情况以及执行计划(Explain),AI 才能精准诊断。

@Service
public class AiDbAnalyzer {
    @Autowired
    private OpenAiService openAiService;

    public AiDiagnoseResult analyze(String rawSql) {
        String maskedSql = SqlMasker.mask(rawSql);

        // 获取 DDL、现有索引、Explain 结果
        String ddl = metaDataService.getDDL("t_sale_order");
        String indexes = metaDataService.getIndexList("t_sale_order");
        String explain = metaDataService.getExplainResult(rawSql);

        String prompt = buildPrompt(maskedSql, ddl, indexes, explain);

        // 调用私有化部署的 Qwen2-7B,强制返回 JSON 格式
        String response = openAiService.createChatCompletion(prompt);
        return JSON.parseObject(extractJson(response), AiDiagnoseResult.class);
    }

    private String buildPrompt(String sql, String ddl, String indexes, String explain) {
        return "你是一个资深的 MySQL 专家。请分析以下慢 SQL。\n" +
               "【表结构】\n" + ddl + "\n【现有索引】\n" + indexes + 
               "\n【执行计划】\n" + explain + "\n【SQL语句】\n" + sql + "\n" +
               "请以 JSON 输出:rootCause(根因)、optimizedSql(改写SQL)、indexDdl(建议添加的索引)";
    }
}
(四)校验与闭环:防幻觉与工单流转

大模型会“胡说八道”,比如推荐一个已经存在的索引。AI 的推荐必须经过代码校验,并转入工单人工 Review。

public void createDbaTicket(AiDiagnoseResult result, String originalSql) {
    // 防幻觉校验:查库确认 AI 推荐的索引是否已存在
    if (metaDataService.indexExists("t_sale_order", "idx_status_time")) {
        log.warn("AI 推荐的索引已存在,忽略");
        return;
    }

    // 推送工单到钉钉或企微,等待人工确认
    String ticketContent = String.format(
        "【AI慢SQL诊断】\n根因:%s\n原SQL:%s\n改写建议:%s\n索引建议:%s",
        result.getRootCause(), originalSql, result.getOptimizedSql(), result.getIndexDdl()
    );
    dingTalkClient.sendMarkdown("DBA优化群", ticketContent);
}

六、 进阶实战:用 AI 清理“废索引”

除了慢 SQL,我们还可以利用 MySQL 自带的 sys.schema_unused_indexes 系统表,找出从未被使用过的废索引。
通过定时任务将这份“废索引清单”和业务高频 SQL 发给大模型,让 AI 判断哪些可以安全删除,哪些可能是日终跑批依赖不能删。

AI 会告诉你:“idx_customer_name 建议直接删除;idx_create_time 虽然单查没用到,但极可能是对账跑批依赖的,建议保留。”

通过这种机制,我们经常能清理掉 20%~30% 的历史遗留冗余索引,直接提升核心大表 10% 以上的写入性能。

图片

七、 本篇小结

把 AI 引入数据库治理,核心不在于“模型多聪明”,而在于工程链路是否闭环。

记住四句话:

  1. 安全第一:用私有化模型,SQL 必须脱敏,AI 绝不直连生产库。

  2. 数据要全:只给 SQL 没用,必须带上 DDL、现有索引和 Explain。

  3. 防幻觉兜底:AI 推荐的索引必须经过代码去重校验。

  4. 流程闭环:诊断结果推给研发工单,人工审核后执行,才是落地的终点。

至此,【数据持久层】 全部完结!

从底层中间件的高可用,到数据持久层的分布式与海量数据治理,我们已经把整个大宗商品系统的“操作系统”和“地基”彻底打牢。

接下来,我们将正式踏入六层架构中篇幅最大、最核心的区域——【业务服务层】。

下篇预告:业务域全景与 DDD 落地:如何避免把微服务写成“分布式单体”?

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐