[ 
https://issues.apache.org/jira/browse/IGNITE-19247?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Pavel Pereslegin reassigned IGNITE-19247:
-----------------------------------------

    Assignee: Pavel Pereslegin

> BatchUpdateException: Replication is timed out" upon inserting rows in 
> batches via JDBC
> ---------------------------------------------------------------------------------------
>
>                 Key: IGNITE-19247
>                 URL: https://issues.apache.org/jira/browse/IGNITE-19247
>             Project: Ignite
>          Issue Type: Bug
>          Components: general
>    Affects Versions: 3.0
>            Reporter: Alexander Belyak
>            Assignee: Pavel Pereslegin
>            Priority: Critical
>              Labels: ignite-3
>             Fix For: 3.0
>
>         Attachments: ReplicationTimeoutReproducerClientLog.zip, 
> node_0.log.zip, node_1.log.zip, serverLog.zip, test.log
>
>
> Start single node cluster:
> {noformat}
> git commit 78946d4c
> https://github.com/apache/ignite-3.git branch mainbuild by:
>     ./gradlew clean allDistZip -x test -x integrationTest -x check -x 
> modernizer 
> start by:  
>     /tmp/ignite3-3.0.0-SNAPSHOT/ignite3-db-3.0.0-SNAPSHOT$ export 
> IGNITE_HOME=$(pwd)
>     /tmp/ignite3-3.0.0-SNAPSHOT/ignite3-db-3.0.0-SNAPSHOT$ bin/ignite3db start
>         Starting Ignite 3...
>         Node named defaultNode started successfully. REST addresses are 
> [http://127.0.1.1:10300]
>     /tmp/ignite3-3.0.0-SNAPSHOT/ignite3-cli-3.0.0-SNAPSHOT$ bin/ignite3 
> cluster init --cluster-endpoint-url=http://localhost:10300 --cluster-name=c1 
> --meta-storage-node=defaultNode
>         Cluster was initialized successfully{noformat}
> Code below just create <TABLES> tables with <COLUMNS+1> columns (int key and 
> varchar cols) and insert <ROWS> rows into each table (with SLEEP ms interval 
> between operations, with <RETRY> attemps.
>  
> {noformat}
> import java.sql.Connection;
> import java.sql.DriverManager;
> import java.sql.PreparedStatement;
> import java.sql.ResultSet;
> import java.sql.SQLException;
> import java.sql.Statement;
> public class TimeoutExceptionReproducer {
>     private static final String DB_URL = "jdbc:ignite:thin://127.0.0.1:10800";
>     private static final int COLUMNS = 10;
>     private static final String TABLE_NAME = "K";
>     private static final int ROWS = 100000;
>     private static final int TABLES = 3;
>     private static final int BATCH_SIZE = 100;
>     private static final int SLEEP = 0;
>     private static final int RETRY = 1;
>     private static String getCreateSql(String tableName) {
>         StringBuilder sql = new StringBuilder("create table 
> ").append(tableName).append(" (id int primary key");
>         for (int i = 0; i < COLUMNS; i++) {
>             sql.append(", col").append(i).append(" varchar NOT NULL");
>         }
>         sql.append(")");
>         return sql.toString();
>     }
>     private static final void s() {
>         if (SLEEP > 0) {
>             try {
>                 Thread.sleep(SLEEP);
>             } catch (InterruptedException e) {
>                 // NoOp
>             }
>         }
>     }
>     private static void createTables(Connection connection, String tableName) 
> throws SQLException {
>         try (Statement stmt = connection.createStatement()) {
>             System.out.println("Creating " + tableName);
>             stmt.executeUpdate("drop table if exists " + tableName );
>             s();
>             stmt.executeUpdate(getCreateSql(tableName));
>             s();
>         }
>     }
>     private static String getInsertSql(String tableName) {
>         StringBuilder sql = new StringBuilder("insert into 
> ").append(tableName).append(" values(?");
>         for (int i = 0; i < COLUMNS; i++) {
>             sql.append(", ?");
>         }
>         sql.append(")");
>         return sql.toString();
>     }
>     private static void insertBatch(PreparedStatement ps) {
>         int retryCounter = 0;
>         while(retryCounter <= RETRY) {
>             try {
>                 ps.executeBatch();
>                 return;
>             } catch (SQLException e) {
>                 System.err.println(retryCounter + " error while executing " + 
> ps + ":" + e);
>                 retryCounter++;
>             }
>         }
>     }
>     private static void insertData(Connection connection, String tableName) 
> throws SQLException {
>         long ts = System.currentTimeMillis();
>         try (PreparedStatement ps = 
> connection.prepareStatement(getInsertSql(tableName))) {
>             int batch = 0;
>             for (int i = 0; i < ROWS; i++) {
>                 ps.setInt(1, i);
>                 for (int j = 2; j < COLUMNS + 2; j++) {
>                     ps.setString(j, "value" + i + "_" + j);
>                 }
>                 ps.addBatch();
>                 batch++;
>                 if (batch == BATCH_SIZE) {
>                     batch = 0;
>                     insertBatch(ps);
>                     ps.clearBatch();
>                     System.out.println("Batch " + BATCH_SIZE + " took " + 
> (System.currentTimeMillis() - ts) + " to get " + i + " rows");
>                     s();
>                     ts = System.currentTimeMillis();
>                 }
>             }
>             if (batch > 0) {
>                 insertBatch(ps);
>                 ps.clearBatch();
>                 s();
>             }
>         }
>     }
>     private static int testData(Connection connection, String tableName) 
> throws SQLException {
>         try (Statement stmt = connection.createStatement();
>             ResultSet rs = stmt.executeQuery("select count(*) from " + 
> tableName);) {
>             rs.next();
>             int count = rs.getInt(1);
>             int result = ROWS - count;
>             if (result == 0) {
>                 System.out.println("Found " + count + " rows in " + 
> tableName);
>             } else {
>                 System.err.println("Found " + count + " rows in " + tableName 
> + " instead of " + ROWS);
>             }
>             s();
>             return result;
>         }
>     }
>     public static void main(String[] args) throws SQLException {
>         int lostRows = 0;
>         try (Connection connection = DriverManager.getConnection(DB_URL)) {
>             for (int i = 0; i < TABLES; i++) {
>                 String tableName = TABLE_NAME + i;
>                 createTables(connection, tableName);
>                 insertData(connection, tableName);
>                 lostRows += testData(connection, tableName);
>             }
>         }
>         System.exit(lostRows);
>     }
> }
>  {noformat}
>  Leads to 
> 1) Replication timeout exceptions like:
> {noformat}
> 0 error while executing 
> org.apache.ignite.internal.jdbc.JdbcPreparedStatement@68999068:java.sql.BatchUpdateException:
>  IGN-CMN-65535 TraceId:335d779d-bee2-41be-a723-8a34a3b40347 Remote query 
> execution
> 0 error while executing 
> org.apache.ignite.internal.jdbc.JdbcPreparedStatement@6973b51b:java.sql.BatchUpdateException:
>  IGN-REP-3 TraceId:b2d7a459-f3bf-497b-9bfb-bc7126813cd5 Replication is timed 
> out [replicaGrpId=d3c988c3-0c7f-483e-bbc3-b9b124df144c_part_20]{noformat}
> 2) Data loss. Queries:
> {noformat}
>  Count(*) from  K1{noformat}
> Found 99877 rows in K1 instead of 100000.
> See server logs in the attachment (serverLog.zip), TimeoutExceptionReproducer 
> (ReplicationTimeoutReproducerClientLog.zip).
>  



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to