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]

Reply via email to