makssent opened a new issue, #34973: URL: https://github.com/apache/shardingsphere/issues/34973
### Which version of ShardingSphere did you use? 5.5.2 ### Which project did you use? ShardingSphere-JDBC or ShardingSphere-Proxy? ShardingSphere-JDBC ------ **Hello everyone!** While working with XA transactions and the Firebird database, I encountered a problem that I don’t yet know how to solve. Perhaps someone has some ideas? This issue may not be directly related to ShardingSphere's code but rather to its interaction with Firebird. ### Problem Description When initializing a connection, ShardingSphere retrieves metadata for each table in the database. Example code: ```Java try { connection = dataSource.getConnection(); connection.setAutoCommit(false); Statement statement = null; try { statement = connection.createStatement(); ``` In Firebird, the `FBStandAloneConnectionManager` ([GitHub link](https://github.com/FirebirdSQL/jaybird/blob/master/src/main/org/firebirdsql/jaybird/xca/FBStandAloneConnectionManager.java)) is responsible for regular connections and transaction execution. In this class, there is a variable `mc.setManagedEnvironment(false);` that changes during operation. When we retrieve metadata, this variable is modified. Then, we execute the required query: ```Java String sql1 = "INSERT INTO T_ORDER (USER_ID, ORDER_TYPE, ADDRESS_ID, STATUS) VALUES (123, 1, 456, 'PENDING')"; String sql2 = "INSERT INTO T_ORDER (USER_ID, ORDER_TYPE, ADDRESS_ID, STATUS) VALUES (789, 2, 101, 'PROCESSING')"; Connection connection = null; try { connection = dataSource.getConnection(); connection.setAutoCommit(false); Statement statement = null; try { statement = connection.createStatement(); statement.executeUpdate(sql1); statement.executeUpdate(sql2); ``` Typically, for XA transactions in Firebird, the `XAConnectionManager` ([GitHub link](https://github.com/FirebirdSQL/jaybird/blob/master/src/main/org/firebirdsql/ds/FBXADataSource.java)) is used, where the `ManagedEnvironment` variable is set to true: ```Java @Override public FirebirdConnection allocateConnection(FBManagedConnectionFactory mcf, FBConnectionRequestInfo cxRequestInfo) throws SQLException { FBManagedConnection mc = mcf.createManagedConnection(cxRequestInfo); mc.setManagedEnvironment(true); mc.addConnectionEventListener(this); return mc.getConnection(); } ``` However, since we use transaction managers like `Atomikos or Narayana` in our configuration, we don’t go through the `XAConnectionManager` (in `Atomikos`, `UserTransactionManager` is used). As a result, the `ManagedEnvironment` variable is not updated to true and remains false. ### Resulting Error This leads to the following issue: when attempting to execute an XA transaction, we receive the error: `Connection enlisted in distributed transaction`. This occurs because the InternalTransactionCoordinator ([GitHub link](https://github.com/FirebirdSQL/jaybird/blob/master/src/main/org/firebirdsql/jdbc/InternalTransactionCoordinator.java)) performs a check: ```Java void setTransactionCoordinator(boolean managedConnection, boolean autoCommit) throws SQLException { FBManagedConnection mc = connection.getManagedConnection(); InternalTransactionCoordinator.AbstractTransactionCoordinator coordinator; if (managedConnection && mc.inDistributedTransaction()) { coordinator = new ManagedTransactionCoordinator(connection); } else if (autoCommit) { if (mc.inDistributedTransaction()) { throw new SQLException("Connection enlisted in distributed transaction", SQLStateConstants.SQL_STATE_INVALID_TX_STATE); } ``` Since we are using a DistributedTransaction, but managedConnection is false, the error is thrown. ---- **Perhaps someone will find a solution faster than I can. Maybe I missed something or have a misunderstanding — I would be grateful for any help.** Config.yaml: ```yaml # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # mode: type: Standalone repository: type: JDBC # props: # path: demo dataSources: # ds_1: # dataSourceClassName: com.zaxxer.hikari.HikariDataSource # driverClassName: com.mysql.cj.jdbc.Driver # jdbcUrl: jdbc:mysql://localhost:3306/SHARD5?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true&logger=com.mysql.cj.log.Slf4JLogger&profileSQL=true # username: root # password: password # maxPoolSize: 10 ds_0: dataSourceClassName: com.zaxxer.hikari.HikariDataSource driverClassName: org.firebirdsql.jdbc.FBDriver jdbcUrl: jdbc:firebirdsql://localhost:3050/D:/sharding/Databases/SHARD1.FDB?useManagedConnection=true&log_level=4&trace_file=D:/sharding/logs/shard1_trace.log username: sysdba password: masterkey maxPoolSize: 10 ds_1: dataSourceClassName: com.zaxxer.hikari.HikariDataSource driverClassName: org.firebirdsql.jdbc.FBDriver jdbcUrl: jdbc:firebirdsql://localhost:3050/D:/sharding/Databases/SHARD2.FDB?useManagedConnection=true&log_level=4&trace_file=D:/sharding/logs/shard2_trace.log username: sysdba password: masterkey maxPoolSize: 10 # ds_2: # dataSourceClassName: com.zaxxer.hikari.HikariDataSource # driverClassName: org.firebirdsql.jdbc.FBDriver # jdbcUrl: jdbc:firebirdsql://localhost:3050/D:/sharding/Databases/SHARD3.FDB # username: sysdba # password: masterkey # maxPoolSize: 10 # ds_3: # dataSourceClassName: com.zaxxer.hikari.HikariDataSource # driverClassName: org.firebirdsql.jdbc.FBDriver # jdbcUrl: jdbc:firebirdsql://localhost:3050/D:/sharding/Databases/SHARD4.FDB # username: sysdba # password: masterkey # maxPoolSize: 10 rules: - !SHARDING tables: T_ORDER: actualDataNodes: ds_$->{0..1}.T_ORDER_$->{0..1} tableStrategy: standard: shardingColumn: ORDER_ID shardingAlgorithmName: T_ORDER_inline keyGenerateStrategy: column: ORDER_ID keyGeneratorName: snowflake_generator defaultDatabaseStrategy: standard: shardingColumn: USER_ID shardingAlgorithmName: database_inline shardingAlgorithms: database_inline: type: INLINE props: algorithm-expression: ds_${USER_ID % 2} T_ORDER_inline: type: INLINE props: algorithm-expression: T_ORDER_$->{ORDER_ID % 2} keyGenerators: snowflake_generator: type: SNOWFLAKE transaction: # defaultType: LOCAL defaultType: XA providerType: Atomikos # props: # transactionTimeout: 10 props: sql-show: true ``` ### You can get the sample code from: https://github.com/apache/shardingsphere/tree/master/examples/shardingsphere-jdbc-example-generator, when using the command: ```./mvnw -B clean install -f examples/shardingsphere-jdbc-example-generator/pom.xml -Pexample-generator -Dmodes=standalone -Dtransactions=xa-atomikos -Dfeatures=sharding -Dframeworks=spring-boot-starter-jdbc``` The code for the test: ```Java public void DoubleInsertTestWithoutAutoCommit() throws SQLException { String sql1 = "INSERT INTO T_ORDER (USER_ID, ORDER_TYPE, ADDRESS_ID, STATUS) VALUES (123, 1, 456, 'PENDING')"; String sql2 = "INSERT INTO T_ORDER (USER_ID, ORDER_TYPE, ADDRESS_ID, STATUS) VALUES (789, 2, 101, 'PROCESSING')"; Connection connection = null; try { connection = dataSource.getConnection(); connection.setAutoCommit(false); Statement statement = null; try { statement = connection.createStatement(); statement.executeUpdate(sql1); statement.executeUpdate(sql2); } catch (SQLException e) { throw new RuntimeException(e); } connection.commit(); } catch (SQLException e) { if (connection != null) { connection.rollback(); } throw e; } finally { if (connection != null) { try { connection.setAutoCommit(true); connection.close(); } catch (SQLException e) { LOGGER.error("Failed to close connection", e); } } } } ``` -- 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: notifications-unsubscr...@shardingsphere.apache.org.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org