已开启
MySQL 5.7.32 进行 CFGO 优化时,Sysbench 压测 在 CFGO + plan cache 场景下报错 2014 #91
liangwenjiao创建于  8月12日
liangwenjiao
liangwenjiao
8月12日 创建

问题概述

使用 openEuler GCC 12.3.1 2025.06 的 CFGO 编译 MySQL 5.7.32 时,prepared statement 工作负载出现:

mysql_stmt_store_result() returned error 2014
Commands out of sync

问题表现为 prepared statement 结果集处理异常。初步现象与 plan cache 相关,但CFGO前使能plan cache优化功能运行正常,进一步验证发现:

  1. 只对 sql/sql_executor.cc 使用 -fcfgo-profile-generate 即可复现;
  2. 其他 MySQL 翻译单元保持普通编译;
  3. 单线程即可稳定复现;
  4. 使用 --skip-plan-cache 仍然复现;
  5. 因此 plan cache 可能是触发场景,但不是问题成立的必要条件;
  6. 普通 GCC、标准 PGO 和 CFGO -O0/-O1 均正常,CFGO -O2/-O3 失败。

环境

操作系统和架构

AArch64
openEuler GCC toolchain

编译器

gcc-12.3.1-2025.06-aarch64-linux

CFGO 相关源码提交:

84635dc65ebe285457d0c16bbb5caf995f803436
[CFGO] Add cfgo-pgo optimization

9f8d7de855feb149e2ea58b72167b22908afacdc
[CFGO] Add more opts to cfgo

65b4c05ba79d7dc10ac9ed963ad17fd32c9f2fce
[CFGO] Update opts for CFGO-PGO

其中 2025.06 对应的 gcc/opts.cc::enable_cfgo_optimizations() 包含:

SET_OPTION_IF_UNSET (opts, opts_set, flag_modulo_sched, value);
SET_OPTION_IF_UNSET (opts, opts_set, flag_selective_scheduling, value);
SET_OPTION_IF_UNSET (opts, opts_set, flag_rename_registers, value);

MySQL

MySQL 5.7.32

复现条件

仅编译 sql/sql_executor.cc 时追加:

-fcfgo-profile-generate=<profile-dir>

在原始故障级别下:

-O2 -fcfgo-profile-generate=<profile-dir>

或:

-O3 -fcfgo-profile-generate=<profile-dir>

均可复现。

其他编译选项与正常 MySQL 构建保持一致。

结果对比

使用已修正 MySQL 源码 UB 的 sql/sql_executor.cc 进行测试:

编译配置 结果
普通 GCC -O3 PASS
UBSan -O3 PASS
标准 -fprofile-generate -O3 PASS
CFGO -O0 PASS
CFGO -O1 PASS
CFGO -O2 FAIL,error 2014
CFGO -O3 FAIL,error 2014
CFGO -O2 -fno-selective-scheduling PASS
CFGO -O3 -fno-selective-scheduling PASS

-fno-selective-scheduling 是目前验证出的最精确全局规避项。

关键二分结果

O2 新增优化

关闭所有 O2 相对 O1 新增优化:

PASS

但单独关闭以下优化均不能修复:

-fno-tree-tail-merge       FAIL
-fno-crossjumping          FAIL
-fno-ipa-icf               FAIL
-fno-optimize-sibling-calls FAIL

Scheduler

-fno-schedule-insns       PASS
-fno-schedule-insns2      FAIL

Scheduler heuristic 单独关闭均不能修复:

-fno-sched-interblock
-fno-sched-spec
-fno-sched-pressure
-fno-schedule-fusion

以上选项单独禁用均仍为:

FAIL

CFGO 特有默认选项

CFGO option bundle 中以下选项的单项验证结果:

-fno-rename-registers       FAIL
-fno-modulo-sched           FAIL
-fno-selective-scheduling   PASS

因此当前最明确的触发项是:

flag_selective_scheduling

函数级定位

对 sched1 进行函数级禁用:

函数 结果
do_select FAIL
end_send FAIL
sub_select FAIL
JOIN::exec() PASS

函数级规避:

-fdisable-rtl-sched1=_ZN4JOIN4execEv

这表明问题集中在 JOIN::exec() 的 sched1/selective scheduling 处理路径。

GCC 源码调用链

CFGO 选项处理:

gcc/opts.cc::enable_cfgo_optimizations()

无条件启用:

flag_selective_scheduling = true;

调度入口:

gcc/sched-rgn.cc::rest_of_handle_sched()

代码路径:

if (flag_selective_scheduling
    && ! maybe_skip_selective_scheduling ())
  run_selective_scheduling ();
else
  schedule_insns ();

Selective scheduler 实现:

gcc/sel-sched.cc::run_selective_scheduling()

生成代码证据

在失败对象 JOIN::exec() 的 CFGO 间接调用探针路径中,发现虚调用实际目标与已知候选目标的比较发生了错误的寄存器等价传播。

RTL 变化:

rtl-rnreg:
    cmp x26, x15

rtl-cprop_hardreg:
    cmp x26, x26

失败汇编中出现:

cmp x26, x26
b.ne ...

另一条路径中也观察到:

cmp x27, x27

这会使目标比较失去原本的判别意义。

禁用 cprop_hardreg 后,字面上的自比较可能消失,但候选寄存器仍由实际目标复制得到,例如:

mov x15, x1
cmp x26, x15

以下规避仍然失败:

-fno-cprop-registers
-fdisable-rtl-cprop_hardreg=_ZN4JOIN4execEv

因此 cprop_hardreg 更像是将前序错误状态显式折叠出来的后续 pass,而不是唯一根因。当前更准确的判断是:

selective scheduling 处理 CFGO speculative indirect-call 序列后,可能破坏了相关寄存器的值等价、依赖关系或 liveness 状态,后续寄存器传播 pass 将错误状态进一步折叠为恒真比较。

目前尚未进一步缩小到 gcc/sel-sched.cc 内的单个算法语句。

Plan cache 验证结果

以下场景均可以复现:

单线程
默认 plan cache
--skip-plan-cache

因此当前结论是:

  • plan cache/prepared statement 是最初暴露问题的业务场景;
  • 但问题不依赖 plan cache 才能成立;
  • 更底层的触发因素是 sql_executor.cc 在 CFGO O2/O3 下生成了错误机器代码。

最终规避验证

编译参数:

-fcfgo-profile-generate=/home/l30039266/expB-profile-O3-noselective
-O3
-fno-selective-scheduling

完整四阶段、单线程、每阶段 5 秒测试结果:

工作负载 事务数 ignored errors 结果
oltp_read_only 1817 0 PASS
oltp_read_only 1998 0 PASS
oltp_read_write 815 0 PASS
oltp_write_only 4267 0 PASS

期望结果

使用:

-fcfgo-profile-generate
-O2 或 -O3

编译 MySQL 5.7.32 的 sql/sql_executor.cc 后,prepared statement、结果集读取和 mysql_stmt_store_result() 应与普通 GCC 或标准 PGO 构建一致,不应出现:

error 2014
Commands out of sync

当前临时解决方案

在 CFGO 编译参数末尾添加:

-fno-selective-scheduling

或者仅对受影响函数禁用:

-fdisable-rtl-sched1=_ZN4JOIN4execEv

建议的编译器修复

对于 openEuler GCC 12.3.1 2025.06,建议从:

gcc/opts.cc::enable_cfgo_optimizations()

删除:

SET_OPTION_IF_UNSET (opts, opts_set, flag_selective_scheduling, value);

这样可以避免 CFGO 隐式开启存在兼容性风险的 selective scheduler,同时保留用户显式指定:

-fselective-scheduling

的能力。

另外,建议后续基于失败的 JOIN::exec() 代码序列构造一个独立 AArch64 GCC testcase,继续检查:

  • gcc/sel-sched.cc 对 CFGO 间接调用探针的指令移动;
  • REG_EQUAL / REG_EQUIV note 的维护;
  • speculative indirect-call 相关寄存器的 liveness;
  • selective scheduling 后 reload、register renaming 和 hard-register propagation 的数据流一致性。
likedislike
openeuler-ci-botopeneuler-ci-bot成员
8月12日 添加了label:sig/Compiler
openeuler-ci-bot
openeuler-ci-bot成员
8月12日 评论:

Welcome To openEuler Community

Hey @always_flipped_1 , thanks for your contribution to the community.

Bot Usage Manual

I'm the Bot here serving you. You can find the instructions on how to interact with me at Here . That means you can comment below every pull request or issue to trigger Bot Commands.

Contact Guide

If you have any questions, please contact the SIG: Compiler ,
and any of the maintainers: @SegFault, @alexanderbill, @cf-zhao, @chenzheng1030, @eastb233, @kuenking111_admin, @li-yancheng, @wangqiang95, @wd-gitcode ,
and any of the committers: @huang-xiaoquan, @huzife, @lin-4682, @xiongzhou4 .

likedislike
liangwenjiaoliangwenjiao
8月12日 修改标题为 “MySQL 5.7.32 sysbench压测 在 CFGO + plan cache 场景下报错 2014”,原标题为“MySQL 5.7.32 prepared statement 在 CFGO + plan cache 场景下报错 2014”
liangwenjiaoliangwenjiao
8月12日 修改标题为 “MySQL 5.7.32 Sysbench压测 在 CFGO + plan cache 场景下报错 2014”,原标题为“MySQL 5.7.32 sysbench压测 在 CFGO + plan cache 场景下报错 2014”
liangwenjiaoliangwenjiao
8月12日 修改标题为 “MySQL 5.7.32 进行CFGO优化时,Sysbench压测 在 CFGO + plan cache 场景下报错 2014”,原标题为“MySQL 5.7.32 Sysbench压测 在 CFGO + plan cache 场景下报错 2014”
liangwenjiaoliangwenjiao
8月12日 修改标题为 “MySQL 5.7.32 进行 CFGO 优化时,Sysbench 压测 在 CFGO + plan cache 场景下报错 2014”,原标题为“MySQL 5.7.32 进行CFGO优化时,Sysbench压测 在 CFGO + plan cache 场景下报错 2014”
rfwang07
rfwang07
8月19日 评论:
  1. 已从CFGO中移除-fselective-scheduling https://gitcode.com/openeuler/gcc/pull/386
  2. 问题根因为-fselective-scheduling在sched1 pass中将一条指令搬到了"建立其 REG_EQUAL 前提的那个分支"之前,却没有作废该注记(REG_DEAD 同样没有随之修正),最终导致指令被优化,调用丢失。该问题是上游版本缺陷,待提交上游修复
likedislike