transactions that split GPB in transaction log are not handling a rollback correctly

Bug #626566 reported by Joe Daly
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Drizzle
Fix Released
Medium
David Shrewsbury
7.0
Fix Released
Medium
David Shrewsbury

Bug Description

I changed transaction_services.cc to have a small value for trx_msg_threshold= 512 to demonstrate this. Rollback seems to be causing the last segment to be omitted in the transaction log and no rollback message to be logged. This test case works fine if instead of ROLLBACK, COMMIT is called.

ran the following:

use test;
CREATE TABLE t1 (
id INT NOT NULL
, value INT NOT NULL
, PRIMARY KEY (id)
);
START TRANSACTION;
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (1,1);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (2,2);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (3,3);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (4,4);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (5,5);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (6,6);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (7,7);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (8,8);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (9,9);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (10,10);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (11,11);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (12,12);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (13,13);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (14,14);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (15,15);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (16,16);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (17,17);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (18,18);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (19,19);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (20,20);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (21,21);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (22,22);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (23,23);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (24,24);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (25,25);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (26,26);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (27,27);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (28,28);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (29,29);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (30,30);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (31,31);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (32,32);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (33,33);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (34,34);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (35,35);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (36,36);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (37,37);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (38,38);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (39,39);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (40,40);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (41,41);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (42,42);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (43,43);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (44,44);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (45,45);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (47,47);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (48,48);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (49,49);
INSERT INTO `test`.`t1` (`id`,`value`) VALUES (50,50);
ROLLBACK;

transaction log contents

drizzle> SELECT PRINT_TRANSACTION_MESSAGE('transaction.log', ENTRY_OFFSET) FROM DATA_DICTIONARY.TRANSACTION_LOG_TRANSACTIONS;
| transaction_context {
  server_id: 1
  transaction_id: 1
  start_timestamp: 1283135027866274
  end_timestamp: 1283135027866366
}
statement {
  type: CREATE_TABLE
  start_timestamp: 1283135027866287
  end_timestamp: 1283135027866365
  create_table_statement {
    table {
      name: "t1"
      engine {
        name: "InnoDB"
      }
      field {
        name: "id"
        type: INTEGER
        constraints {
          is_nullable: false
        }
      }
      field {
        name: "value"
        type: INTEGER
        constraints {
          is_nullable: false
        }
      }
      indexes {
        name: "PRIMARY"
        is_primary: true
        is_unique: true
        type: UNKNOWN_INDEX
        key_length: 4
        index_part {
          fieldnr: 0
          compare_length: 4
        }
        options {
        }
      }
      type: STANDARD
      schema: "test"
      options {
        has_user_set_auto_increment_value: false
        collation: "utf8_general_ci"
        collation_id: 45
      }
      creation_timestamp: 1283135027
      update_timestamp: 1283135027
    }
  }
}
 |
| transaction_context {
  server_id: 1
  transaction_id: 2
  start_timestamp: 1283135027923477
  end_timestamp: 1283135027938057
}
statement {
  type: INSERT
  start_timestamp: 1283135027923481
  end_timestamp: 1283135027938055
  insert_header {
    table_metadata {
      schema_name: "test"
      table_name: "t1"
    }
    field_metadata {
      type: INTEGER
      name: "id"
    }
    field_metadata {
      type: INTEGER
      name: "value"
    }
  }
  insert_data {
    segment_id: 1
    end_segment: false
    record {
      insert_value: "1"
      insert_value: "1"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "2"
      insert_value: "2"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "3"
      insert_value: "3"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "4"
      insert_value: "4"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "5"
      insert_value: "5"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "6"
      insert_value: "6"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "7"
      insert_value: "7"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "8"
      insert_value: "8"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "9"
      insert_value: "9"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "10"
      insert_value: "10"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "11"
      insert_value: "11"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "12"
      insert_value: "12"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "13"
      insert_value: "13"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "14"
      insert_value: "14"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "15"
      insert_value: "15"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "16"
      insert_value: "16"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "17"
      insert_value: "17"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "18"
      insert_value: "18"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "19"
      insert_value: "19"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "20"
      insert_value: "20"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "21"
      insert_value: "21"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "22"
      insert_value: "22"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "23"
      insert_value: "23"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "24"
      insert_value: "24"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "25"
      insert_value: "25"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "26"
      insert_value: "26"
      is_null: false
      is_null: false
    }
      insert_value: "27"
      insert_value: "27"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "28"
      insert_value: "28"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "29"
      insert_value: "29"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "30"
      insert_value: "30"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "31"
      insert_value: "31"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "32"
      insert_value: "32"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "33"
      insert_value: "33"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "34"
      insert_value: "34"
      is_null: false
      is_null: false
    }
    record {
      insert_value: "35"
      insert_value: "35"
      is_null: false
      is_null: false
    }
2 rows in set (0 sec)

drizzle>

Related branches

Revision history for this message
David Shrewsbury (dshrews) wrote :

I suspect that on a rollback, the current active Transaction is simply deleted. Any previous Transaction messages associated with the same transaction will have already been sent through the replication stream.

I think we are going to have to design a way to buffer bulk load transactions and only send them to the replication stream once the transaction is complete. We could handle rollbacks properly then. And that will also fix the possibility of Transactions being intermingled in the replication stream with multiple concurrent sessions.

Revision history for this message
David Shrewsbury (dshrews) wrote :

Hmm, this actually looks like a bug with setting segment_id.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.