tju-yxq opened a new issue, #6174:
URL: https://github.com/apache/rocketmq-dashboard/issues/6174
### Describe the bug
`ResourceOwnershipGuardTest.migrationConcurrentStartupIsIdempotentTest`
fails intermittently — and in practice very often — with an
`ExecutionException` wrapping an H2 `General error:
"java.util.ConcurrentModificationException"`. On this machine the single test
method fails **7 out of 10 consecutive runs**; on GitHub's CI runners today
alone, a dozen unrelated PR runs had their `Backend Tests (Java 21)` check go
red on this one test (it fails on pure-frontend PRs too, which is the clearest
sign it is the test environment racing, not the change under review).
### To reproduce
```
cd server
for i in 1..10: mvn test
-Dtest='ResourceOwnershipGuardTest#migrationConcurrentStartupIsIdempotentTest'
# observed: 7 of 10 runs fail
```
```
java.util.concurrent.ExecutionException:
org.h2.jdbc.JdbcSQLNonTransientException:
General error: "java.util.ConcurrentModificationException" [50000-240]
at
ResourceOwnershipSchemaMigration.afterPropertiesSet(ResourceOwnershipSchemaMigration.java:50)
Caused by: java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification
at org.h2.command.query.Select.getGroupSortedIndex(Select.java:365)
at org.h2.command.query.Select.preparePlan(Select.java:1297)
...
```
### Root cause
The test simulates two studio nodes starting at the same time by running
`ResourceOwnershipSchemaMigration.afterPropertiesSet()` on two threads against
one shared in-memory H2 database:
- thread A prepares the validation `SELECT name, COUNT(*) FROM
rmq_instance_topic GROUP BY name ...`; H2's planner picks a group-sorted index
and **iterates the table's index list** (`Select.getGroupSortedIndex`);
- thread B commits its `CREATE TABLE`/`CREATE INDEX` DDL, which **mutates
that same list**;
- H2 has no metadata locking, so the planner's iteration hits a
`ConcurrentModificationException`, which H2 rethrows as `General error`.
In production, two real nodes are serialized by MySQL's metadata locks (a
query plan blocks on the other node's DDL), so the migration logic itself is
not wrong across nodes — including the `CREATE ... IF NOT EXISTS` and the
catch-and-recheck in `ensureIndex`, which already tolerate a *completed*
concurrent DDL. The gap is that **nothing serializes two overlapping executions
inside a single process**: the regression test itself, or two Spring contexts
sharing one test database.
### Expected behavior
Overlapping in-process executions of the migration wait for each other (the
way Flyway serializes its migrations in-process) instead of racing the engine,
and the concurrent-startup regression test passes deterministically.
### Additional context
Same symptom previously reported in #5302 and re-filed as #6022 — this
report adds the 70% reproduction rate, the exact failing statement, and the H2
planner stack. Suggested fix: a process-wide mutex around the migration body,
submitted as a PR referencing this issue.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]