diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md index f20ffd37ecd..a9c3c4e4616 100644 --- a/changes/en-us/2.x.md +++ b/changes/en-us/2.x.md @@ -37,9 +37,11 @@ Add changes here for all PR submitted to the 2.x branch. - [[#6817](https://github.com/apache/incubator-seata/pull/6817)] bugfix: fix namingserver changVgroup failed - [[#6820](https://github.com/apache/incubator-seata/pull/6820)] Fix file path error in the Dockerfile - [[#6825](https://github.com/apache/incubator-seata/pull/6825)] Fix the issue of XA mode transaction timeout and inability to roll back in Postgres +- [[#6833](https://github.com/apache/incubator-seata/pull/6833)] SQLIntegrityConstraintViolationException capture incorrectly when inserting a globallock - [[#6835](https://github.com/apache/incubator-seata/pull/6835)] Fix the issue of missing request body of post method in HttpClientUtil + ### optimize: - [[#6499](https://github.com/apache/incubator-seata/pull/6499)] split the task thread pool for committing and rollbacking statuses - [[#6208](https://github.com/apache/incubator-seata/pull/6208)] optimize : load SeataSerializer by version diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md index 05d8cb958f4..222d513d1e0 100644 --- a/changes/zh-cn/2.x.md +++ b/changes/zh-cn/2.x.md @@ -38,8 +38,10 @@ - [[#6817](https://github.com/apache/incubator-seata/pull/6817)] 修复namingserver切换事务分组失效的问题 - [[#6820](https://github.com/apache/incubator-seata/pull/6820)] 修复Dockerfile得文件结构错误 - [[#6825](https://github.com/apache/incubator-seata/pull/6825)] 修复Postgres的XA模式事务超时无法回滚问题 +- [[#6833](https://github.com/apache/incubator-seata/pull/6833)] 插入全局锁时 SQLIntegrityConstraintViolationException 捕获不正确 - [[#6835](https://github.com/apache/incubator-seata/pull/6835)] 修复HttpClientUtil中post方法请求体缺失的问题 + ### optimize: - [[#6499](https://github.com/apache/incubator-seata/pull/6499)] 拆分 committing 和 rollbacking 状态的任务线程池 - [[#6208](https://github.com/apache/incubator-seata/pull/6208)] 支持多版本的Seata序列化 diff --git a/server/src/main/java/org/apache/seata/server/storage/db/lock/LockStoreDataBaseDAO.java b/server/src/main/java/org/apache/seata/server/storage/db/lock/LockStoreDataBaseDAO.java index 3bc6a4e3249..bb8bfd11168 100644 --- a/server/src/main/java/org/apache/seata/server/storage/db/lock/LockStoreDataBaseDAO.java +++ b/server/src/main/java/org/apache/seata/server/storage/db/lock/LockStoreDataBaseDAO.java @@ -16,6 +16,7 @@ */ package org.apache.seata.server.storage.db.lock; +import java.sql.BatchUpdateException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -372,10 +373,23 @@ protected boolean doAcquireLocks(Connection conn, List lockDOs) throws S return ps.executeBatch().length == lockDOs.size(); } catch (SQLIntegrityConstraintViolationException e) { LOGGER.error("Global lock batch acquire error: {}", e.getMessage(), e); - //return false,let the caller go to conn.rollabck() + //return false,let the caller go to conn.rollback() return false; - } catch (SQLException e) { - throw e; + } catch (BatchUpdateException e) { + Throwable cause = e.getCause(); + if (cause != null) { + if (cause instanceof SQLIntegrityConstraintViolationException) { + return false; + } + throw e; + } + SQLException nextException = e.getNextException(); + if (nextException == null) { + throw e; + } else if (nextException instanceof SQLIntegrityConstraintViolationException) { + return false; + } + throw nextException; } finally { IOUtil.close(ps); } diff --git a/server/src/test/java/org/apache/seata/server/lock/db/DataBaseLockStoreDAOTest.java b/server/src/test/java/org/apache/seata/server/lock/db/DataBaseLockStoreDAOTest.java index 1441f8e634d..efd44516d2f 100644 --- a/server/src/test/java/org/apache/seata/server/lock/db/DataBaseLockStoreDAOTest.java +++ b/server/src/test/java/org/apache/seata/server/lock/db/DataBaseLockStoreDAOTest.java @@ -23,7 +23,9 @@ import java.util.ArrayList; import java.util.List; +import org.apache.seata.common.ConfigurationKeys; import org.apache.seata.common.util.IOUtil; +import org.apache.seata.config.ConfigurationFactory; import org.apache.seata.core.store.LockDO; import org.apache.seata.server.storage.db.lock.LockStoreDataBaseDAO; import org.apache.commons.dbcp2.BasicDataSource; @@ -52,9 +54,9 @@ public static void start(ApplicationContext context){ dataSource.setUsername("sa"); dataSource.setPassword(""); + ConfigurationFactory.getInstance().putConfig(ConfigurationKeys.STORE_DB_TYPE, "h2"); + ConfigurationFactory.getInstance().putConfig(ConfigurationKeys.LOCK_DB_TABLE, "lock_table"); dataBaseLockStoreDAO = new LockStoreDataBaseDAO(dataSource); - dataBaseLockStoreDAO.setDbType("h2"); - dataBaseLockStoreDAO.setLockTable("lock_table"); prepareTable(dataSource); } @@ -88,7 +90,7 @@ public void test_acquireLocks() throws SQLException { lock.setXid("abc-123:123"); lock.setTransactionId(123L); lock.setBranchId((long) i); - lock.setRowKey("abc-"+i); + lock.setRowKey("test_acquireLocks-"+i); lock.setPk(String.valueOf(i)); lock.setTableName("t"); lockDOs.add(lock); @@ -97,7 +99,8 @@ public void test_acquireLocks() throws SQLException { boolean ret = dataBaseLockStoreDAO.acquireLock(lockDOs); Assertions.assertTrue(ret); - String sql = "select * from lock_table where xid = 'abc-123:123' and table_name = 't' and row_key in ('abc-0','abc-1','abc-2')" ; + String sql = "select * from lock_table where xid = 'abc-123:123' and table_name = 't' " + + "and row_key in ('test_acquireLocks-0','test_acquireLocks-1','test_acquireLocks-2')" ; Connection conn = null; ResultSet rs = null; try{ @@ -126,7 +129,7 @@ public void test_re_acquireLocks() throws SQLException { lock.setXid("abc-123:123"); lock.setTransactionId(123L); lock.setBranchId((long) i); - lock.setRowKey("abc-"+i); + lock.setRowKey("test_re_acquireLocks-"+i); lock.setPk(String.valueOf(i)); lock.setTableName("t"); lockDOs.add(lock); @@ -135,7 +138,8 @@ public void test_re_acquireLocks() throws SQLException { boolean ret = dataBaseLockStoreDAO.acquireLock(lockDOs); Assertions.assertTrue(ret); - String sql = "select * from lock_table where xid = 'abc-123:123' and table_name = 't' and row_key in ('abc-0','abc-1','abc-2')" ; + String sql = "select * from lock_table where xid = 'abc-123:123' and table_name = 't' " + + "and row_key in ('test_re_acquireLocks-0','test_re_acquireLocks-1','test_re_acquireLocks-2')" ; Connection conn = null; ResultSet rs = null; try{ @@ -166,7 +170,7 @@ public void tes_unLocks() throws SQLException { lock.setXid("abc-456:123"); lock.setTransactionId(123L); lock.setBranchId((long) i); - lock.setRowKey("abc-"+i); + lock.setRowKey("tes_unLocks-"+i); lock.setPk(String.valueOf(i)); lock.setTableName("t"); lockDOs.add(lock); @@ -175,7 +179,8 @@ public void tes_unLocks() throws SQLException { boolean ret = dataBaseLockStoreDAO.acquireLock(lockDOs); Assertions.assertTrue(ret); - String sql = "select * from lock_table where xid = 'abc-456:123' and table_name = 't' and row_key in ('abc-0','abc-1','abc-2')" ; + String sql = "select * from lock_table where xid = 'abc-456:123' and table_name = 't' " + + "and row_key in ('tes_unLocks-0','tes_unLocks-1','tes_unLocks-2')" ; Connection conn = null; ResultSet rs = null; try{ @@ -214,7 +219,7 @@ public void test_isLockable_can(){ lock.setXid("abc-678:123"); lock.setTransactionId(123L); lock.setBranchId((long) i); - lock.setRowKey("abc-"+i); + lock.setRowKey("test_isLockable_can-"+i); lock.setPk(String.valueOf(i)); lock.setTableName("t"); lockDOs.add(lock); @@ -236,7 +241,7 @@ public void test_isLockable_cannot() throws SQLException { lock.setXid("abc-123:222"); lock.setTransactionId(222L); lock.setBranchId((long) i); - lock.setRowKey("abc-"+i); + lock.setRowKey("test_isLockable_cannot-"+i); lock.setPk(String.valueOf(i)); lock.setTableName("t"); lockDOs.add(lock); @@ -245,7 +250,8 @@ public void test_isLockable_cannot() throws SQLException { boolean ret = dataBaseLockStoreDAO.acquireLock(lockDOs); Assertions.assertTrue(ret); - String sql = "select * from lock_table where xid = 'abc-123:222' and table_name = 't' and row_key in ('abc-0','abc-1','abc-2')" ; + String sql = "select * from lock_table where xid = 'abc-123:222' and table_name = 't' " + + "and row_key in ('test_isLockable_cannot-0','test_isLockable_cannot-1','test_isLockable_cannot-2')" ; Connection conn = null; ResultSet rs = null; try{ @@ -267,7 +273,7 @@ public void test_isLockable_cannot() throws SQLException { lock.setXid("abc-123:333"); lock.setTransactionId(333L); lock.setBranchId((long) i); - lock.setRowKey("abc-"+i); + lock.setRowKey("test_isLockable_cannot-"+i); lock.setPk(String.valueOf(i)); lock.setTableName("t"); lockDOs_2.add(lock); @@ -278,6 +284,58 @@ public void test_isLockable_cannot() throws SQLException { } + @Test + public void test_isLockable_cannot1() throws SQLException { + List lockDOs = new ArrayList<>(); + for(int i = 0; i < 3; i++) { + LockDO lock = new LockDO(); + lock.setResourceId("abc"); + lock.setXid("abc-123:222"); + lock.setTransactionId(222L); + lock.setBranchId(1L); + lock.setRowKey("test_isLockable_cannot1-"+i); + lock.setPk(String.valueOf(i)); + lock.setTableName("t"); + lockDOs.add(lock); + } + + boolean ret = dataBaseLockStoreDAO.acquireLock(lockDOs, true, true); + Assertions.assertTrue(ret); + + String sql = "select * from lock_table where xid = 'abc-123:222' and table_name = 't' " + + "and row_key in ('test_isLockable_cannot1-0','test_isLockable_cannot1-1','test_isLockable_cannot1-2')" ; + Connection conn = null; + ResultSet rs = null; + try{ + conn = dataSource.getConnection(); + rs = conn.createStatement().executeQuery(sql); + if (rs.next()) { + Assertions.assertTrue(true); + } else { + Assertions.fail(); + } + } finally { + IOUtil.close(rs, conn); + } + + List lockDOs_2 = new ArrayList<>(); + for(int i = 0; i < 3; i++) { + LockDO lock = new LockDO(); + lock.setResourceId("abc"); + lock.setXid("abc-123:333"); + lock.setTransactionId(333L); + lock.setBranchId(2L); + lock.setRowKey("test_isLockable_cannot1-"+i); + lock.setPk(String.valueOf(i)); + lock.setTableName("t"); + lockDOs_2.add(lock); + } + + boolean ret2 = dataBaseLockStoreDAO.acquireLock(lockDOs_2, true, true); + Assertions.assertFalse(ret2); + + } + @AfterAll public static void clearStoreDB(){ FileUtils.deleteRecursive("db_store", true);