lhozy opened a new pull request, #8145:
URL: https://github.com/apache/incubator-seata/pull/8145
# PR: bugfix: fix global lock batch acquire false-failure on Dameng(DM)
## Ⅰ. Describe what this PR does
Fix `LockStoreDataBaseDAO#doAcquireLocks` so that batch global-lock
acquisition no longer produces a **false "lock acquire failed"** on databases
(e.g. **Dameng / DM**) whose JDBC driver returns an `executeBatch()` array
whose length differs from the number of batched statements.
Fixes #8144.
## Ⅱ. Why make this change
`doAcquireLocks` judged batch success with:
```java
return ps.executeBatch().length == lockDOs.size();
```
The JDBC spec does **not** guarantee `executeBatch()` returns exactly one
element per batched statement (elements may be counts, `SUCCESS_NO_INFO`, or
`EXECUTE_FAILED`, and some drivers aggregate). The DM driver aggregates the
per-row results (`DmdbPreparedStatement.executeBatchByRow` →
`ExecuteRetInfo.union`), so the returned array length ≠ statement count.
Consequence on DM: when a branch locks ≥ 2 rows, the lock rows are inserted
successfully but the `length == size` check returns `false`, so the caller
rolls back the inserted locks and the branch register is reported as a lock
conflict. Single-row branches (non-batch `doAcquireLock`) are unaffected, so
the bug only manifests for multi-row branches — making AT mode unusable on DM
for typical multi-row business transactions.
## Ⅲ. The change
`server/src/main/java/org/apache/seata/server/storage/db/lock/LockStoreDataBaseDAO.java`
```diff
for (LockDO lockDO : lockDOs) {
...
ps.addBatch();
}
- return ps.executeBatch().length == lockDOs.size();
+ // Do not rely on executeBatch().length == size: per the JDBC
spec the
+ // length is not guaranteed to equal the number of statements,
and some
+ // drivers (e.g. Dameng/DM) aggregate the per-statement
results, returning
+ // an array of a different length. Detect failure via
EXECUTE_FAILED instead;
+ // real conflicts (duplicate row_key) still throw
SQLIntegrityConstraintViolationException
+ // and are handled by the catch block below.
+ int[] result = ps.executeBatch();
+ for (int updated : result) {
+ if (updated == java.sql.Statement.EXECUTE_FAILED) {
+ return false;
+ }
+ }
+ return true;
} catch (SQLIntegrityConstraintViolationException e) {
LOGGER.error("Global lock batch acquire error: {}",
e.getMessage(), e);
// return false,let the caller go to conn.rollback()
return false;
```
## Ⅳ. How tested
- Existing behavior preserved on databases that return one element per
statement (MySQL, Oracle, PostgreSQL…): no `EXECUTE_FAILED` → returns `true`;
genuine duplicate-`row_key` conflicts still throw
`SQLIntegrityConstraintViolationException` → handled → `false`.
- On DM8 (store.mode=db): a branch acquiring multiple row locks now
succeeds; a cross-resource global transaction with multi-row branches both
commits and rolls back correctly, where before every multi-row branch register
failed with `Global lock batch acquire failed`.
## Ⅴ. Checklist
- [ ] Add/keep unit tests (consider a test asserting `doAcquireLocks`
returns true when `executeBatch()` returns an aggregated/short array).
- [ ] Changelog entry.
--
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]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]