From 97b1261a34e80fccf0370b192579b5fe67beb8f4 Mon Sep 17 00:00:00 2001 From: morningman Date: Wed, 9 Sep 2026 18:23:42 +0800 Subject: [PATCH] branch-4.1: [fix](regression) Deflake the sql cache regression suites #67734 Two regression-test-only changes. 1. test_sql_cache_over_arrow_flight, cherry-picked from #67734. The suite primes four sql cache entries on the MySQL control session, runs the same statements over Arrow Flight, and asserts the entries are still there. The FE sql cache is a single Caffeine map shared by every session and bounded by Config.sql_cache_manage_num (default 100); Caffeine admits a newcomer through a window sized at 1% of that bound, so at the default a just cached statement is dropped as soon as any other session caches anything, and enable_sql_cache defaults to true for the whole concurrently running p0 suite. Raise the bound while the suite runs and restore it afterwards, as the other five sql cache suites do. In p0 build 124525 the entry was gone 299ms after being primed. 2. sql_cache_object_type picks up the hunk that #67556 missed. The master fix in #67529 replaced the closing `assertTrue(hasSqlCache(objectSql))` with a re-prime for the same reason, but #67556 backported the original #67381 version of the file, so branch-4.1 kept the fragile assertion. It has failed 18 times here since 2026-09-02 and is currently muted; the three most recent failures were all on branch-4.1 PRs. With this the file is byte identical to master again. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01Njd8iDxdqc19QbLdNtZ7Pt --- .../test_sql_cache_over_arrow_flight.groovy | 15 +++++++++++++++ .../query_p0/cache/sql_cache_object_type.groovy | 7 ++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/regression-test/suites/arrow_flight_sql_p0/test_sql_cache_over_arrow_flight.groovy b/regression-test/suites/arrow_flight_sql_p0/test_sql_cache_over_arrow_flight.groovy index 577665b275b47d..a3fb39d38d9a60 100644 --- a/regression-test/suites/arrow_flight_sql_p0/test_sql_cache_over_arrow_flight.groovy +++ b/regression-test/suites/arrow_flight_sql_p0/test_sql_cache_over_arrow_flight.groovy @@ -84,6 +84,19 @@ suite("test_sql_cache_over_arrow_flight") { withGlobalLock("cache_last_version_interval_second") { runOnMysql "ADMIN SET ALL FRONTENDS CONFIG ('cache_last_version_interval_second' = '0')" + // The FE sql cache is a single Caffeine map shared by every session and bounded by + // Config.sql_cache_manage_num, which defaults to 100. Caffeine admits a newcomer through a + // window sized at 1% of that bound, so at the default a just cached statement is dropped + // again as soon as any other session caches anything -- and the whole p0 suite runs + // concurrently against this FE with enable_sql_cache on by default. The entries primed + // below would then be gone before the checks at the end of this suite, which is what made + // it flaky. Raise the bound while this suite runs, like the other sql cache suites do, and + // put it back afterwards so the rest of the run does not keep 10000 cached plans and their + // result rows alive in the FE heap. + def originalSqlCacheNum = + runOnMysql("ADMIN SHOW FRONTEND CONFIG LIKE 'sql_cache_manage_num'")[0][1].toString() + runOnMysql "ADMIN SET ALL FRONTENDS CONFIG ('sql_cache_manage_num' = '10000')" + def dbName = context.dbName runOnMysql "USE `${dbName}`" runOnFlight "USE `${dbName}`" @@ -164,5 +177,7 @@ suite("test_sql_cache_over_arrow_flight") { assertTrue(hasSqlCache(scalarSql)) assertTrue(hasSqlCache(rawStateSql)) assertTrue(hasSqlCache(convertedSql)) + + runOnMysql "ADMIN SET ALL FRONTENDS CONFIG ('sql_cache_manage_num' = '${originalSqlCacheNum}')" } } diff --git a/regression-test/suites/query_p0/cache/sql_cache_object_type.groovy b/regression-test/suites/query_p0/cache/sql_cache_object_type.groovy index 6300840d20ffdf..4e2520e70c516c 100644 --- a/regression-test/suites/query_p0/cache/sql_cache_object_type.groovy +++ b/regression-test/suites/query_p0/cache/sql_cache_object_type.groovy @@ -98,8 +98,13 @@ suite("sql_cache_object_type") { assertTrue(isNonEmpty(asBinaryCached[0][0])) assertTrue(isNonEmpty(asBinaryCached[0][1])) + // The sql cache is best-effort: the FE map holds soft values under a bounded size + // (Config.sql_cache_manage_num) and the rows themselves live in the BE result cache, so the + // entry created above may legitimately be gone by now. Re-prime it instead of asserting it + // survived; what must hold is that this setting is served its own NULLs and never the + // binary rows cached under the other one. run "set return_object_data_as_binary=false" - assertTrue(hasSqlCache(objectSql)) + primeSqlCache(objectSql) def asNullAgain = run(objectSql) assertNull(asNullAgain[0][0]) assertNull(asNullAgain[0][1])