Current release: v1.0.1 — see the changelog before
assuming v1.0.0 is safe to use (it isn't; it crashes on enable).
Native audit plugin for MySQL 8.0.24+ that traces (logs) only queries
touching a configurable set of schemas/tables/connections, filtered by
command type — a low-overhead, partial alternative to general_log
(which is all-or-nothing).
This is the MySQL port of the selective_trace MariaDB
plugin, sharing its filtering logic
(core/filter_engine.{h,cc}, 194 unit-tested checks) but with a from-
scratch server-integration layer, because the MySQL 8.0 Audit API is a
different API from MariaDB's — not a dialect of it. See
CLAUDE.md for the full API comparison and
docs/DECISIONS.md for why each MySQL-specific
choice was made.
Etapa 5 in progress — live-validated on MySQL 8.0.40 and 8.4 LTS
(8.4.11), including a 1.2M-statement mixed load with no crash and no
memory growth after load stops. The filter engine (core/) is
ported, unit-tested and passing (194/194 checks; 234 across both suites,
including the TABLE writer recycling policy). MySQL 8.0.40, 8.4.11 and
9.7.2 source builds all compile clean and export the expected
dynamic-plugin symbols. Two real issues were found and fixed that a
compiler alone couldn't catch — a crash (the MariaDB-borrowed
per-connection state storage trick doesn't work on MySQL 8.0/9.x;
redesigned around a plugin-owned std::unordered_map, see
docs/DECISIONS.md §12) and a required one-time GRANT for TABLE
mode (the writer's internal connection authenticates as the
low-privilege mysql.session system account, not a superuser — see
docs/USAGE.md §1.1). After those fixes, a real mysqld 8.4.11 took
1.2M mixed INSERT/UPDATE/SELECT statements across 8 connections (856s)
with RSS flattening out and holding steady for 2 minutes post-load, plus
5000 connect/disconnect cycles with a 2 MB RSS delta — see
docs/RESEARCH_NOTES_MYSQL.md §5.5 for the full numbers. Filtering
variations, min_duration_ms, mask_passwords, graceful UNINSTALL
under load, Valgrind, the adversarial security suite, and any MySQL
9.7.2 runtime exercise are still open — see
docs/RESEARCH_NOTES_MYSQL.md "Etapa 5"
for the exact remaining scope. Still not recommended for production.
INSTALL PLUGIN selective_trace SONAME 'selective_trace.so';
SET GLOBAL selective_trace_schemas = 'vendas';
SET GLOBAL selective_trace_output = 'TABLE';
SET GLOBAL selective_trace_enabled = ON;
-- ... run traced queries ...
SELECT * FROM mysql.selective_trace_events ORDER BY ts DESC LIMIT 20;Full syntax, all system variables, and known limitations (most notably:
DDL statements cannot be table-filtered in MySQL — see why in
docs/DECISIONS.md §8) are in docs/USAGE.md.
docker build -t selective-trace-mysql-dev -f docker/Dockerfile docker/
docker run --rm -it -v "$PWD:/workspace" selective-trace-mysql-dev
# inside the container (MYSQL_VERSION picks the series — defaults to 8.0.40):
MYSQL_VERSION=9.7.2 ./scripts/build.sh full # clones MySQL source + full build
./scripts/build.sh --plugin # incremental: plugin only
./scripts/build.sh --package # copy the .so to build/plugin_output/This has been run successfully in this repo against mysql-8.0.40,
mysql-8.4.11 (LTS) and mysql-9.7.2 (source clone + configure + build +
incremental plugin rebuild + package, ~30-45 min the first time per series, seconds after
with the ccache/build volumes warm). See
docs/RESEARCH_NOTES_MYSQL.md for the
exact reproduction steps, volume setup, and what differs building against
9.x.
mysql-selective-trace-plugin/
├── CLAUDE.md # porting briefing / API comparison
├── core/ # shared filter engine (vendored, see DECISIONS.md #1)
│ ├── filter_engine.h / .cc
│ └── test_filter_logic.cc # 194 checks, g++ -std=c++17, no server headers
├── src/
│ ├── CMakeLists.txt
│ ├── selective_trace_mysql.cc # entrypoint: descriptor, sysvars, event capture
│ ├── log_writer_file_mysql.h/.cc
│ ├── log_writer_table_mysql.h/.cc
│ ├── writer_recycle_policy.h # TABLE writer connection recycling (DECISIONS.md #13)
│ └── test_writer_recycle.cc # 40 checks, no server headers
├── docker/Dockerfile # MySQL 8.0 source + C++17 toolchain (OL8)
├── scripts/build.sh
└── docs/
├── RESEARCH_NOTES_MYSQL.md # Etapa 0 — confirmed facts + open items
├── DECISIONS.md # design rationale
└── USAGE.md # operator guide
Two suites, 234 checks total. No server headers needed — pure C++17:
# filter engine (194 checks)
g++ -std=c++17 -Wall -Wextra -Werror -I core \
core/test_filter_logic.cc core/filter_engine.cc \
-o test_filter_logic && ./test_filter_logic
# TABLE writer connection-recycling policy (40 checks)
g++ -std=c++17 -Wall -Wextra -Werror -I src \
src/test_writer_recycle.cc \
-o test_writer_recycle && ./test_writer_recycleGPLv2, same as MySQL and the sibling MariaDB plugin.