Tuesday, March 24, 2026

Building and testing MySQL 9.7.0 early access build on macOS

Oracle released 9.7.0 community early access build, which is a part of their work towards fulfilling their new promises to the community. This is great news for community testing and I did my part in my usual way (previously: 8.0.45 / 8.4.8 / 9.6.0).

Build

No changes from 9.6.0: the current Xcode (26.3) builds the 9.7.0 early access build fine, LLVM 21 still fails (bug #119246).

Tests

Bad news

Good news

One-off issues

  • component_keyring_file.tablespace_encrypt_10 failed once under debug build
  • Likewise main.func_in_mrr
  • Likewise perfschema.idx_compare_metadata_locks
  • main.mysqltest failed testcase check one under debug build
  • rpl_gtid.rpl_semisync_gtid_tag crashed once under debug + sanitizers build
  • perfschema.system_events_component failed once under debug + sanitizers build
  • Likewise perfschema.stage_mdl_global
  • Likewise innodb_undo.truncate

Tuesday, February 10, 2026

Boring but useful: making large-scale changes on MySQL codebase with LLMs

I used Claude Code to do a simple mass refactoring on MySQL 9.6 over two weeks, resulting in a 25K line diff that passes the testsuite. That was something I wanted to experiment with for some time now: making boring but useful large-scale changes to MySQL while spending as little human effort as possible. Claude Code with Opus 4.5 (and 4.6 for the last few days) was used for everything.

Why boring but useful large-scale?

  • Pushing LLMs to the limit–like building a browser or a compiler, I guess I'd be building a database from scratch for a comparable project–is fun, it shows us what's possible and what needs one more frontier model release, but the result artifact itself is throwaway code, thus not usable in the general sense, nor do I have time (or money for tokens) for this.
  • Making algorithmically challenging changes is still firmly in the domain of humans. No "Add LSM tree to InnoDB. Be thorough. Do not make any mistakes." prompting here. Although, as I'm writing this, I just saw Zongzhi Chen doing exactly that and patching PostgreSQL with an InnoDB-like doublewrite buffer. Things move quickly.
  • Making too simple changes is a waste of LLM capabilities where sed would do the same faster and cheaper.

For a boring but useful large-scale change I picked replacing THD * with const THD & or THD & in method parameters and class fields. This might require some background. MySQL started in mid-90s, and its current source code, after 30 years, has features of three strata: modern C++ (C++11 to C++20), early standard C++ (C++98, C++03), and even earlier "C with classes" style. One thing still surviving from the earliest days is that pointers are used instead of references, including the contexts when the pointer can never be nullptr. I'll try not to digress on why it's not the right thing, C++ Core Guidelines has that (F.16, F.17, F.18, F.19, and finally F.60 for when the pointers are the right choice).

I settled on this after a few false starts, which made promising progress but eventually imploded. That was because of my mistake of not letting the agent make intermediate commits, resulting in unmanageable working directory diff every time. Now I believe I could have completed most of them too:

  • "Convert THD * to THD &": yep I tried it twice, the first time it broke the server and then couldn't debug its way out of the hole.
  • "Replace LEX_CSTRING with std::string_view" - the partial conversion was successful, but my mistake was not considering that lex strings are both owning and non-owning whereas string views are always strictly non-owning. The project failed in trying to replace the owning lex strings with something different altogether.
  • "Replace printf-style formatting with std::format" - this one imploded because of no intermediate commit rule, but not before scoring some strong wins, such as converting the MySQL error log and client error machinery and messages more or less correctly.

It was also my goal to spend as little of my time as possible on this, consciously ignoring some of the current best practices of this type of work, such as not setting up CLAUDE.md, not doing it in a dedicated container where the agent has full permissions, and not implementing any kind of Ralph Wiggum loop. All of these saved me some advance planning time, but then I had to go to a terminal and tell "continue" when it stopped mid-task or inexplicably started doing edits with some shell trickery instead of its standard tools. Thus by trying to save time I wasted some time, but definitely saved some thinking and could rubber-stamp agent questions while doing other, more useful, work.

I launched Claude Code and prompted

Convert pointers to THD to (optionally const) references to THD throughout the
codebase. The safe instances to convert are the ones where the pointer is dereferenced
unconditionally, there is an assert(thd != nullptr) check, or any thd == nullptr
branches are dead code (because e.g. the function is never called with pointer ==
nullptr). Not safe instances are the ones where null pointers are passed and C API.
In the touched code (and only in the touched code!) follow Almost Always Auto while
keeping references and pointers pulled out and const as much as possible (unless it
forces other code changes), except for trivial function parameters. Examples of AAA
and const: "const auto bar = ... ", "const auto *bar = ... ", "auto &baz = ...",
"const auto &x = ...", "const auto *const y = ...", "auto *const z = ..."

and letting it plan until we both were happy with the plan, and go. As I said above, every few tens of minutes to few hours it just stopped asking permission to continue, directly against original instructions. At those points I cleared its context and pointed to the plan file again.

Finally, some two weeks later (I did not orchestrate any parallelization, it sometimes parallelized itself a bit with subagents, also I needed room in the usage limits for other work on my account), it declared it's done. Then I ran debug + sanitizers testsuite, pasted any failures to the agent asking to fix, but, very importantly, always git bisect to the failing commit first. There were over a thousand commits. It debugged everything rather easily once it always had a relatively small regressing commit identified. Nice.

I succeeded in staying below usage limits of my Claude Max plan all the time. In the failed attempts above the agent parallelized much more aggressively and burned through the week's allowance in three days. I tried to preserve my sanity and did not go the route of stacked Max accounts.

With a clean testsuite run I asked it to create a second branch with all commits squashed. This produced a +25304, -25402 line diff. I looked at random points in the diff and everywhere I was satisfied with the result. The straightforward conversion bits went fine, but it also removed some provably-redundant nullptr checks, declared non-moveable classes as such, simplified constructors. The resulting release build binary is some 12K smaller on macOS, BTW. If this were real work, I'd still have to read the whole diff for any obvious issues, but in any case this is significantly faster than doing the work myself.

"If this were real work" - or is it? The nature of this patch is such that no tracking fork could take it, only Oracle MySQL. I have signed the contributor's agreement with them, then sent them some patches and have been waiting for years but they are still not merged, thus I will not submit this one unless asked to.

I pushed the code to GitHub:

To conclude, with LLMs, everyone has an opinion. A vocal part of the community does things like OpenClaw and Gas Town. I am way, way more conservative than that: so far I successfully avoided buying a Mac Mini for OpenClaw and giving my email and bank login details to it, and I also get uncomfortable quickly due to cognitive load if running too many coding agents in parallel. But, we live in exciting times, software engineering is changing and I am very optimistic.

Friday, January 23, 2026

Building and testing MySQL 8.0.45, 8.4.8, and 9.6.0 on macOS

Oracle has just released MySQL 8.0.45, 8.4.8, and 9.6.0 and here are the results of my usual testing of building them and running the testsuite on macOS, Apple Silicon hardware.

Build

All three versions compile with the current XCode (26.2) OK. With Homebrew-packaged LLVM, versions 14 to 17 inclusive are getting a strange CMake error that might have more to do with macOS than MySQL. LLVM 19 still fails to build 8.0.45 (bug #119238), but not 8.4.8, and so does LLVM 20 (bug #119239). Both these issues are pre-existing. But, 8.4.8 regressed in that it started being affected by bug #119246 too. LLVM 21 still fails to build 9.6.0 (preexisting bug #119246).

Test

Bad news:

  1. Bug #119735 Unhandled error log warning in main.initialize-sha256
  2. Bug #119738 global-buffer-overflow on INSTALL PLUGIN
  3. Bug #119739 Test rpl_gtid.rpl_gtids_table_disable_binlog_on_slave result difference
  4. Bug #119746 innodb.table_encrypt_4 failing with a result difference

No news aka old bad news:

  1. Bug #113189 ColumnStatisticsTest.StoreAndRestoreAttributesEquiHeight unit test fails
  2. Bug #113190 Several tests in routertest_integration_routing_sharing_constrained_pools fail
  3. Bug #113260 Client error in error log: MY-004031 - The client was disconnected …
  4. Bug #113665 perfschema.relaylog fails with a result difference
  5. Bug #113709 StrXfrmTest.ChineseUTF8MB4 failing with an AddressSanitizer error
  6. Bug #113722 Test main.index_merge_innodb failing with a result difference
  7. Bug #114892 Test XComControlTest.SuspectMemberFailedRemovalDueToMajorityLoss fails
  8. Bug #115480 Test innodb.log_first_rec_group failing
  9. Bug #116369 rpl.rpl_semi_sync_alias crashes under AddressSanitizer
  10. Bug #116373 auth_sec.acl_tables_row_locking failing with result diff
  11. Bug #116378 routertest_integration_routing_splitting crashing under AddressSanitizer
  12. Bug #116385 Test main.mysql_upgrade_grant timing out on debug build
  13. Bug #116394 Test binlog_gtid.binlog_gtid_binlog_recovery_errors crashes with an assert
  14. Bug #118171 Test main.mysqldump-tablespace-escape failing
  15. Bug #118185 Non-specific ASan error on TestLoaderGood/LoaderReadTest.load_wrong_version/0
  16. Bug #118213 Test perfschema.idx_compare_mutex_instances fails under debug + sanitizers
  17. Bug #119247 Test main.log_buffered-big failure
  18. Bug #119249 Router unit test setup failures
  19. Bug #119251 Test rpl.rpl_seconds_behind_master failure
  20. Bug #119252 Test router.response_cache failure
  21. Bug #119253 innodb.tablespace_encrypt_9 crashing the server with assertion failure
  22. Bug #119258 router integration tests failing to login

Good news:

  1. none! Every single bug I am tracking is present

Conclusion

With 4 new, 22 unchanged bugs, and not a single fix, the testsuite quality is continuing to slowly decay. I hope this will change for the better.

Addendum

A note for my future self. Issues I couldn't reliably reproduce:

  • main.mysqltest failing testcase check on 8.0.45, 8.0.45 debug build
  • innodb_zip.16k, main.mysqlpump_bugs failing with a result difference, 8.0.45 debug+sanitizers build
  • main.subquery_sj_firstmatch failing with a result difference, 8.0.45 release build
  • main.lowercase_table4 timeout, 8.0.45 debug+sanitizers build
  • x.mysqlxtest_mode_ssl test command failure, 8.4.8 release build
  • connection_control.performance_schema_processlist test result difference, 8.4.8 release build
  • merge_innodb_tests-t failed once, 8.4.8 debug+sanitizers build
  • routertest_harness_net_ts_timer failed once, 8.4.8 debug build
  • rpl_nogtid.rpl_semi_sync_optimize_for_static_plugin_config failing with global-buffer-overflow under 9.6.0 debug+sanitizers build, serious, but I couldn't reproduce.
  • routertest_integration_routing_direct, routertest_integration_routing_router_require, routertest_integration_routing_sharing, and routertest_integration_routing_sharing_constrained_pools failed once under 9.6.0 debug+sanitizers build and once under 9.6.0 debug build
  • perfschema.system_events_plugin, test_service_sql_api.test_sql_stmt, main.group_by, main.index_merge_innodb, perfschema.idx_compare_metadata_locks failed once, 9.6.0 debug build
  • router.authentication_mysql_accounts, router.app_specific_metadata_v_latest, and main.ps failed once, 9.6.0 release build

Monday, December 01, 2025

Look at me, I'm an (LLM-assisted) Emacs Lisp developer now

Claude Code came out in February and I was hooked immediately. Luckily for me Anthropic introduced flat rate pricing plans very soon afterwards, or I'd have been bankrupted by pay-per-token prices by summer. I tried to channel all that newly-developed addiction to something productive, and decided to write, greenfield, some Emacs Lisp packages. I think such projects are perfectly-sized for working with Claude Code: for smaller tasks the regular chat interface worked fine (although now Claude Code handles those for me too), and for larger tasks one needs to start paying more attention to context management.

So I wrote three Emacs Lisp packages, all related to LLMs (yeah there is some infinite recursion going on here. I guess it all stops at the singularity):

All three packages have been published on MELPA (which is like npm registry, but for Elisp), and the first package (the library one) is surprisingly popular, with about 1,700 installs as of today.

Obviously I learned a lot about LLM-assisted development too but so far I am not planning to blog about that specifically, as things move faster than my ability to draft and publish and there are some very good guides out there.

Tuesday, October 28, 2025

Building and testing MySQL 8.0.44 / 8.4.7 / 9.5.0 releases on macOS

Oracle MySQL 8.0.44 / 8.4.7 / 9.5.0 are out and it's time for me to build and run their tests on macOS, Apple Silicon hardware. I have skipped the review of the previous set of releases this summer due to personal reasons, so this covers the delta from 8.0.42 / 8.4.5 / 9.3.0, out in spring.

Build

No need to use any of the bundled 3rd party libraries, and the current XCode (26.0.1) compiles all the releases. As usual, things get more interesting with Homebrew-packaged LLVM. All releases fail to build with LLVM 17 and lower versions with a bizarre CMake error, which may have to do more with the newer macOS version 26 than MySQL. LLVM 18 and 19 build fine.

8.0.44: does not build with 20 & 21:

8.4.7: builds with LLVM 20, and 21 has a different error than 8.0.44: Bug #119242 8.4.7 fails to build with clang 21.

9.5.0: builds with LLVM 20, and 21 has a different error from both 8.0.44 and 8.4.7: Bug #119246 9.5.0 compilation error with LLVM 21

The newest compiler errors are, unfortunately, expected. So, all in all, things are looking good here.

Tests

A lot of churn here over the past two releases.

Bad news:

No news, aka previously reported bugs with no to little changes:

Good news:

One-off issues:

  • merge_innodb-t on 8.0.44 and 8.4.7, debug + sanitizers build
  • gcs_xcom_control_interface on 8.0.44 and 9.5.0 release builds
  • routertest_integration_routing_direct on 8.0.44 release build
  • binlog_gtid.binlog_check_gtid_persistor_compatibility crashed on 8.4.7 debug build
  • rpl_gtid.rpl_gtids_table_disable_binlog_on_slave result difference on 8.4.7 debug build
  • innodb.trigger_function_lock_compare timeout on 8.4.7 debug build
  • routertest_integration_routing_splitting on 8.4.7 debug w/ sanitizers builds, maybe Bug #116378 routertest_integration_routing_splitting crashing under AddressSanitizer, but was not able to confirm
  • perfschema.keyring_keys result difference on 8.4.7 release build
  • json.array_index result difference on 9.5.0 debug w/ sanitizers build
  • perfschema.error_log result difference on 9.5.0 debug w/ sanitizers build
  • main.slow_log result difference on 9.5.0 debug w/ sanitizers build
  • router.app_specific_metadata_v_latest result difference on 9.5.0 release build
  • innodb_undo.truncate test assertion failure on 9.5.0 debug build

Conclusion

Without the one-offs I have 9 new, 15 unchanged, and 12 fixed bugs. At last the fixed ones outnumber the new ones, hopefully this trend will continue.

Friday, May 16, 2025

Building and testing MySQL 8.0.42 / 8.4.5 / 9.3.0 on macOS

Previously: 8.0.41 / 8.4.4 / 9.2.0

MySQL 8.0.42 / 8.4.5 / 9.3.0 are out, and as usual, I have built and tested the new releases on macOS, due to its popularity as the server OS, of course.

Build

The 8.0 series don't build with the current XCode clang because of bug 118026 (Build failed with apple clang 17). That's inconvenient, but Homebrew-packaged LLVM clang versions 14 to 18 build it fine.

Another pre-existing build bug 117299 (ddl0bulk.h:236:15: error: parameter 'prebuilt' not found in the function declaration [-Werror,-Wdocumentation]) previously only affected 8.0, but now hits 8.4. Of course, the workarounds are simple enough.

I have also reported bug 118161 (Having Homebrew-installed googletest breaks build). I suspect this is not a 8.0.42 regression, thus will not be counting towards the running bug totals.

So, for build, we have one bug with no change, and one slightly worsened. Meh, but not too bad either.

Test

Here the things are not looking as good.

Bad news first. New bugs and existing bugs with substantial regressions. The number is substantial:

Bugs with no news:

Closed bugs or bugs that have improved in some ways:

Did not test:

One-off issues that I wasn't able to repeat properly for bug reporting.

  • rpl_gtid.rpl_gtids_table_disable_binlog_on_slave on 8.0.42
  • rpl_gtid.rpl_gtid_create_select on 8.0.42
  • test_services.test_table_access on 8.0.42
  • main.system_variable_source on 8.0.42
  • innodb.trigger_function_lock_compare on 8.0.42
  • gcs_xcom_control_interface-t on 8.0.42 and 9.3.0
  • router.authentication_mysql_accounts on 9.3.0
  • routertest_integration_routing_sharing on 9.3.0
  • routertest_integration_routing_sharing_constrained_pools on 9.3.0
  • rpl_nogtid.rpl_semi_sync_uninstall_plugin on 9.3.0
  • perfschema.idx_compare_events_waits_history on 9.3.0
  • sys_vars.log_slow_admin_statements_func on 9.3.0
  • main.subquery_mat_all on 9.3.0

Conclusion

Without the one-off issues I have 13 (!) new, 15 unchanged, 2 fixed, and 1 untested bug. The positive trend of the previous set of releases is no more, and the set of open issues almost doubles in size. I hope that the next quarterly release will look better.

Wednesday, January 29, 2025

Building and testing MySQL 8.0.41 / 8.4.4 / 9.2.0 on macOS

Previously: 8.0.40 / 8.4.3 / 9.1.0

Oracle released MySQL 8.0.41 / 8.4.4 / 9.2.0, and it's time for me to build and test it under macOS, of all things!

But first, a detour to the last set of releases Valgrind results, because its run took a few weeks on 9.1.0, and that's without --big-test. A big part of tests timed out, or failed randomly. There appear no errors that are diagnosed during server operation, and the shutdown logs are way too verbose for me to try to find any memory leaks. Perhaps 9.2.0 will fare better, and I will reduce --parallel further. Will it take two months to run? We will see!

Build

Mostly good news here, again. -DWITH_ZLIB=bundled is no longer required, that's probably due to newer XCode toolchain finally updating its zlib.

A new build bug:

A fixed build bug:

MySQL 8.0.41 does not build with LLVM 19. It could probably be fixed by backporting a fix for MySQL 8.4.4 which is documented as "Implemented the standards-compliant my_char_traits<unsigned char> for use as a drop-in replacement for std::char_traits<unsigned char>, which was deprecated in Clang 18 and removed in Clang 19. (Bug #37273525)"

Test

New bugs:

No changes:

Fixed bugs:

Did not test:

One-off issues:

  • main.join_cache_nojb failed once with query execution plan difference on 8.0.41 debug build.
  • rpl_gtid.rpl_gtids_table_disable_binlog_on_slave failed intermittently on 8.0.41 Debug with sanitizers, 8.4.4 Debug, & 8.4.4 Debug with sanitizers builds. The same happened in the previous set of releases too.
  • binlog_gtid.binlog_gtid_bgc_ticket_manager failed once on 8.4.4 Debug build.
  • routertest_integration_routing_sharing_constrained_pools failed once in a way that is not bug #113190 above.
  • rpl_gtid.rpl_heartbeat_log_pos_4gb timed out once on 8.4.4 Debug with sanitizers.
  • binlog_gtid.binlog_check_gtid_persistor_compatibility failed once on 9.2.0 Debug with sanitizers.
  • innodb.trigger_function_lock_compare timed out once on 9.2.0 Debug with sanitizers.

Conclusion

Without the one-off issues I have 2 new, 13 unchanged, 4 fixed, 1 untested bug. Much less churn than the last time, and finally the trend is positive.