KomachiSion opened a new issue #2077: Saga transaction revert SQL error when 
keyGenerator is a union primary key
URL: https://github.com/apache/incubator-shardingsphere/issues/2077
 
 
   ## Bug Report
   
   When the ShardingSphere keyGenerator is part of table union primary key, 
Saga revert `INSERT` SQL will miss non-generated primary key parameters.
   
   ### Which version of ShardingSphere did you use?
   
   4.0.0-RC1-SNAPSHOT
   
   ### Which project did you use? Sharding-JDBC or Sharding-Proxy?
   
   Sharding-JDBC
   
   ### Expected behavior
   
   Revert SQL successfully.
   
   ### Actual behavior
   
   ```
   [ERROR] 2019-03-25 10:47:11,620 --main-- 
[org.apache.servicecomb.saga.core.FallbackPolicy] Failed to send compensation 
to demo_ds_1 
   org.apache.servicecomb.saga.core.TransportFailedException: Execute SQL 
`SagaBranchTransaction(dataSourceName=demo_ds_1, sql=DELETE FROM t_order_1 
WHERE order_id = ? AND user_id = ?, parameterSets=[[316889452515426305]])` 
occur exception.
        at 
io.shardingsphere.transaction.saga.servicecomb.transport.ShardingSQLTransport.executeSQL(ShardingSQLTransport.java:90)
        at 
io.shardingsphere.transaction.saga.servicecomb.transport.ShardingSQLTransport.with(ShardingSQLTransport.java:58)
        at 
org.apache.servicecomb.saga.format.JacksonSQLOperation.send(JacksonSQLOperation.java:47)
        at 
org.apache.servicecomb.saga.core.FallbackPolicy.apply(FallbackPolicy.java:36)
        at 
org.apache.servicecomb.saga.core.RequestProcessTask.compensate(RequestProcessTask.java:58)
        at 
org.apache.servicecomb.saga.core.CompensationTaskConsumer.consume(CompensationTaskConsumer.java:47)
        at org.apache.servicecomb.saga.core.TaskRunner.run(TaskRunner.java:57)
        at 
org.apache.servicecomb.saga.core.GraphBasedSaga.run(GraphBasedSaga.java:89)
        at 
org.apache.servicecomb.saga.core.application.SagaExecutionComponent.run(SagaExecutionComponent.java:63)
        at 
io.shardingsphere.transaction.saga.SagaShardingTransactionManager.submitToSagaEngine(SagaShardingTransactionManager.java:130)
        at 
io.shardingsphere.transaction.saga.SagaShardingTransactionManager.rollback(SagaShardingTransactionManager.java:115)
        at 
org.apache.shardingsphere.shardingjdbc.jdbc.adapter.AbstractConnectionAdapter.rollback(AbstractConnectionAdapter.java:237)
        at 
org.springframework.jdbc.datasource.DataSourceTransactionManager.doRollback(DataSourceTransactionManager.java:328)
        at 
org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:857)
        at 
org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:834)
        at 
org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.java:536)
        at 
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:286)
        at 
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
        at 
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at 
org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
        at 
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
        at 
org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:47)
        at 
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
        at 
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
        at 
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at 
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:671)
        at 
io.shardingsphere.example.transaction.saga.spring.namespace.SagaTransactionalService$$EnhancerBySpringCGLIB$$a3ffce67.processFailure(<generated>)
        at 
io.shardingsphere.example.transaction.saga.spring.namespace.SpringNamespaceExample.processSagaTransaction(SpringNamespaceExample.java:39)
        at 
io.shardingsphere.example.transaction.saga.spring.namespace.SpringNamespaceExample.main(SpringNamespaceExample.java:30)
   Caused by: java.sql.SQLException: No value specified for parameter 2
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:964)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:897)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:886)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:860)
        at 
com.mysql.jdbc.PreparedStatement.checkAllParametersSet(PreparedStatement.java:2211)
        at com.mysql.jdbc.PreparedStatement.addBatch(PreparedStatement.java:898)
        at 
com.zaxxer.hikari.pool.HikariProxyPreparedStatement.addBatch(HikariProxyPreparedStatement.java)
        at 
io.shardingsphere.transaction.saga.servicecomb.transport.ShardingSQLTransport.executeBatch(ShardingSQLTransport.java:112)
        at 
io.shardingsphere.transaction.saga.servicecomb.transport.ShardingSQLTransport.executeSQL(ShardingSQLTransport.java:87)
        ... 28 common frames omitted
   ```
   
   ### Reason analyze (If you can)
   
   RevertInsert operator use primary keys of `TableMetaData` to generate revert 
SQL, but only add parameter of keyGenerator so that the number of parameter is 
inconsistent.
   And the revertEngine has no information about the keyGenerator, including 
keyGenerator columnName and value, So it can't distinguish which key column is 
keyGenerator.
   
   ### Steps to reproduce the behavior, such as: SQL to execute, sharding rule 
configuration, when exception occur etc.
   
   sharding rule configuration:
   ```
   <?xml version="1.0" encoding="UTF-8"?>
   <beans xmlns="http://www.springframework.org/schema/beans";
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
       xmlns:context="http://www.springframework.org/schema/context"; 
       xmlns:tx="http://www.springframework.org/schema/tx"; 
       
xmlns:sharding="http://shardingsphere.apache.org/schema/shardingsphere/sharding";
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           
http://www.springframework.org/schema/beans/spring-beans.xsd 
                           http://www.springframework.org/schema/tx 
                           
http://www.springframework.org/schema/tx/spring-tx.xsd
                           http://www.springframework.org/schema/context 
                           
http://www.springframework.org/schema/context/spring-context.xsd
                           
http://shardingsphere.apache.org/schema/shardingsphere/sharding
                           
http://shardingsphere.apache.org/schema/shardingsphere/sharding/sharding.xsd";>
   
       <import resource="classpath:META-INF/shardingTransaction.xml"/>
   
       <context:component-scan base-package="io.shardingsphere.example" />
       
       <bean id="demo_ds_0" class="com.zaxxer.hikari.HikariDataSource" 
destroy-method="close">
           <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
           <property name="jdbcUrl" 
value="jdbc:mysql://localhost:3306/demo_ds_0?useSSL=false"/>
           <property name="username" value="root"/>
           <property name="password" value=""/>
       </bean>
       
       <bean id="demo_ds_1" class="com.zaxxer.hikari.HikariDataSource" 
destroy-method="close">
           <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
           <property name="jdbcUrl" 
value="jdbc:mysql://localhost:3306/demo_ds_1?useSSL=false"/>
           <property name="username" value="root"/>
           <property name="password" value=""/>
       </bean>
       
       <sharding:inline-strategy id="databaseStrategy" 
sharding-column="user_id" algorithm-expression="demo_ds_${user_id % 2}" />
       <sharding:inline-strategy id="orderTableStrategy" 
sharding-column="order_id" algorithm-expression="t_order_${order_id % 2}" />
       <sharding:inline-strategy id="orderItemTableStrategy" 
sharding-column="order_id" algorithm-expression="t_order_item_${order_id % 2}" 
/>
       
       <sharding:key-generator id="orderKeyGenerator" type="SNOWFLAKE" 
column="order_id" />
       <sharding:key-generator id="itemKeyGenerator" type="SNOWFLAKE" 
column="order_item_id" />
       
       <sharding:data-source id="shardingDataSource">
           <sharding:sharding-rule data-source-names="demo_ds_0, demo_ds_1">
               <sharding:table-rules>
                   <sharding:table-rule logic-table="t_order" 
actual-data-nodes="demo_ds_${0..1}.t_order_${0..1}" 
database-strategy-ref="databaseStrategy" 
table-strategy-ref="orderTableStrategy" key-generator-ref="orderKeyGenerator" />
                   <sharding:table-rule logic-table="t_order_item" 
actual-data-nodes="demo_ds_${0..1}.t_order_item_${0..1}" 
database-strategy-ref="databaseStrategy" 
table-strategy-ref="orderItemTableStrategy" 
key-generator-ref="itemKeyGenerator" />
               </sharding:table-rules>
           </sharding:sharding-rule>
           <sharding:props>
               <prop key="sql.show">false</prop>
           </sharding:props>
       </sharding:data-source>
       
       <bean id="transactionManager" 
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
           <property name="dataSource" ref="shardingDataSource" />
       </bean>
       <tx:annotation-driven />
       
       <bean id="sqlSessionFactory" 
class="org.mybatis.spring.SqlSessionFactoryBean">
           <property name="dataSource" ref="shardingDataSource"/>
           <property name="mapperLocations" 
value="classpath*:META-INF/mappers/*.xml"/>
       </bean>
       
       <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
           <property name="basePackage" 
value="io.shardingsphere.example.common.mybatis.repository"/>
           <property name="sqlSessionFactoryBeanName" 
value="sqlSessionFactory"/>
       </bean>
   </beans>
   ```
   
   SQLs:
   ```
       <update id="createTableIfNotExists">
           CREATE TABLE IF NOT EXISTS t_order (order_id BIGINT AUTO_INCREMENT, 
user_id INT NOT NULL, status VARCHAR(50), PRIMARY KEY (order_id, user_id));
       </update>
   
       <insert id="insert" useGeneratedKeys="true" keyProperty="orderId">
           INSERT INTO t_order (user_id, status) VALUES 
(#{userId,jdbcType=INTEGER}, #{status,jdbcType=VARCHAR});
       </insert>
   ```
   
   ### Example codes for reproduce this issue (such as a github link).
   
   
https://github.com/KomachiSion/sharding-sphere-example/tree/revert-insert-error
   
   ```
   
sharding-sphere-example/sharding-jdbc-example/transaction-example/transaction-base-saga-example/transaction-saga-spring-namespace-example/src/main/java/io/shardingsphere/example/transaction/saga/spring/namespace/SpringNamespaceExample.java
   ```
   

----------------------------------------------------------------
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.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to