Bug #121364 RESET PERSIST reports success after a disk-write failure and leaves stale configuration on disk
Submitted: 24 Sep 6:32
Reporter: Wwwwing Wwwwing Email Updates:
Status: Open Impact on me:
None 
Category:MySQL Server: Options Severity:S2 (Serious)
Version:MySQL 8.4 branch, commit `99960bf74fa919 OS:Linux
Assigned to: CPU Architecture:x86

[24 Sep 6:32] Wwwwing Wwwwing
Description:
A named `RESET PERSIST variable_name` removes the variable from the in-memory
persisted-variable maps and calls `flush_to_file()`, but ignores that function's
error return. If the backup file cannot be opened, written, synchronized, or
renamed, the SQL statement can report success even though `mysqld-auto.cnf`
still contains the supposedly removed setting.

This was reproduced in MySQL Community Server 8.4.11 by placing a directory at
the exact backup-file path before executing `RESET PERSIST max_connections`.
The statement returned exit status 0 with no warning, while the persistence
file remained byte-for-byte unchanged and retained `max_connections=222`.

How to repeat:
The following uses a disposable, digest-pinned container and a tmpfs data
directory. It does not modify an existing MySQL installation.

```bash
set -eu
IMG='mysql@sha256:85b9bf2e29cf836ecb8c2a15a935d4ba0c606631dff1dd79531a11983c638f2a'
C="mysql-my18-poc-$$"

docker run -d --name "$C" --label "edbf.owner=$C" \
  --network none --read-only --cap-drop ALL \
  --security-opt no-new-privileges=true --pids-limit 512 \
  --memory 2048m --cpus 2 --user 999:999 \
  --tmpfs /var/lib/mysql:rw,noexec,nosuid,nodev,size=1024m,uid=999,gid=999 \
  --tmpfs /var/run/mysqld:rw,noexec,nosuid,nodev,size=16m,uid=999,gid=999 \
  --tmpfs /tmp:rw,noexec,nosuid,nodev,size=128m,uid=999,gid=999 \
  -e MYSQL_ALLOW_EMPTY_PASSWORD=yes \
  "$IMG" --skip-name-resolve --log-error=/var/lib/mysql/error.log
trap 'docker rm -f "$C" >/dev/null 2>&1 || true' EXIT

for i in $(seq 1 120); do
  test "$(docker exec "$C" mysql -uroot \
    --socket=/var/run/mysqld/mysqld.sock -Nse 'SELECT @@port' 2>/dev/null)" = 3306 && break
  sleep 1
done
test "$(docker exec "$C" mysql -uroot \
  --socket=/var/run/mysqld/mysqld.sock -Nse 'SELECT @@port')" = 3306

docker exec "$C" mysql -uroot --socket=/var/run/mysqld/mysqld.sock \
  -e 'SET PERSIST max_connections=222;'
BEFORE=$(docker exec "$C" cat /var/lib/mysql/mysqld-auto.cnf)
printf 'before=%s\n' "$BEFORE"

# Force only the next backup-file open to fail: this path should be a file,
# but mkdir makes it an existing directory.
docker exec --user 0:0 "$C" mkdir /var/lib/mysql/mysqld-auto.cnf.backup

set +e
RESET_OUTPUT=$(docker exec "$C" mysql -uroot \
  --socket=/var/run/mysqld/mysqld.sock --batch --raw \
  -e 'RESET PERSIST max_connections; SHOW WARNINGS;' 2>&1)
RESET_RC=$?
set -e

AFTER=$(docker exec "$C" cat /var/lib/mysql/mysqld-auto.cnf)
printf 'reset_rc=%s\nreset_output=%s\n' "$RESET_RC" "$RESET_OUTPUT"
if [ "$BEFORE" = "$AFTER" ]; then echo 'file_unchanged=yes'; else echo 'file_unchanged=no'; fi
printf '%s\n' "$AFTER" | grep -o '"max_connections"[^}]*}'
```

## Actual result

The official 8.4.11 run returned:

```text
reset_rc=0
reset_output=
file_unchanged=yes
"max_connections": {"Value": "222", ...}
```

The original and final `mysqld-auto.cnf` contents were byte-identical. The
statement reported success and `SHOW WARNINGS` produced nothing, despite the
failed persistence update. The server remained healthy. The retained machine
record has SHA-256
`ec53368f441922236a6b2f5dac560ea466edcb8431f2aa20948c966d45ed1cf7`.

## Expected result

If the persisted configuration cannot be durably rewritten, `RESET PERSIST`
should return an error and must not report that the setting was removed.
Alternatively, the in-memory removal should be rolled back before returning an
error so memory and disk remain consistent.