Environment
- Percona Operator for MySQL based on PXC 1.20.0
- PXC 8.4.8-8.1, 3 nodes, HAProxy enabled
spec.users:
users:
- name: app
dbs: [app_db1, app_db2]
hosts: ["%"]
grants: [ALL]
passwordSecretRef: {name: app-users, key: app}
The user app@% already existed with an explicit privilege list (not ALL PRIVILEGES) and is the DEFINER of several views in both schemas (created by the application’s Liquibase migrations).
What happens
userChanged()returns true (“Grant not present in current grants”, grantALL), because the existing grant lines don’t contain the stringALL.upsertUserQuery()runsCREATE DATABASE IF NOT EXISTSfor each db, thenCREATE USER IF NOT EXISTS 'app'@'%' ....CREATE USER IF NOT EXISTSfails:
Error 4006 (HY000): Operation CREATE USER failed for 'app'@'%' as it is referenced as a definer account in a view.
This is MySQL bug #107139: theoperatoruser has neitherSET_ANY_DEFINERnorALLOW_NONEXISTENT_DEFINER.- The grant is never fixed, so the next reconcile repeats steps 1–3: about 300 times in 30 minutes, roughly every 6 seconds.
- Every pass runs
CREATE DATABASE IF NOT EXISTS. In Galera that statement is replicated as a total-order schema change even when the database already exists, and the operator sends it to whichever node<cluster>-pxc-unreadyresolves to. Application transactions in those schemas on the writer node get aborted and fail at COMMIT withDeadlock found when trying to get lock; try restarting transaction.wsrep_local_cert_failureson the writer reached 421 in a few hours, and unrelated application threads failed in the same millisecond. - Later passes ran into the operator’s 15 s read timeout while
CREATE DATABASEwaited behind open transactions (exec: invalid connection), and the loop continued.
Expected
- No
CREATE DATABASE IF NOT EXISTSwhen the database already exists, or at least not on every retry. - A failed user upsert should back off and/or be surfaced in the CR status, rather than retrying every few seconds against production schemas.
- The
operatoruser should haveSET_ANY_DEFINER(MySQL 8.2+), soCREATE USER IF NOT EXISTSworks for users that own views, triggers or routines. - The grant comparison (
strings.Contains(currGrant, "ALL")) should accept equivalent explicit privilege lists, or at least not loop on them.
Workaround
GRANT ALL ON app_db1.* TO 'app'@'%' (same for app_db2). The grant check then passes and the loop stops.
Code references (v1.20.0)
pkg/controller/pxc/users_custom.go:userChanged(),upsertUserQuery()pkg/controller/pxc/users.go:getUserManager()(connects via-pxc-unready)
Could this be turned into a K8SPXC ticket? I’m not able to create Jira tickets myself. Thanks!