Bug #14007649 65111: INNODB SOMETIMES FAILS TO UPDATE ROWS INSERTED
BY A CONCURRENT TRANSACTIO The member function QUICK_RANGE_SELECT::init_ror_merged_scan() performs a table handler clone. Innodb does not provide a clone operation. The ha_innobase::clone() is not there. The handler::clone() does not take care of the ha_innobase->prebuilt->select_lock_type. Because of this what happens is that for one index we do a locking read, and for the other index we were doing a non-locking (consistent) read. The patch introduces ha_innobase::clone() member function. It is implemented similar to ha_myisam::clone(). It calls the base class handler::clone() and then does any additional operation required. I am setting the ha_innobase->prebuilt->select_lock_type correctly. rb://1060 approved by Marko
This commit is contained in:
parent
074ce71e90
commit
391ea219c2
56
mysql-test/suite/innodb/r/innodb_bug14007649.result
Normal file
56
mysql-test/suite/innodb/r/innodb_bug14007649.result
Normal file
@ -0,0 +1,56 @@
|
||||
create table t1 (
|
||||
rowid int,
|
||||
f1 int,
|
||||
f2 int,
|
||||
key i1 (f1, f2),
|
||||
key i2 (f2)) engine=innodb;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`rowid` int(11) DEFAULT NULL,
|
||||
`f1` int(11) DEFAULT NULL,
|
||||
`f2` int(11) DEFAULT NULL,
|
||||
KEY `i1` (`f1`,`f2`),
|
||||
KEY `i2` (`f2`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
insert into `t1` (rowid, f1, f2) values (1, 1, 10), (2, 1, NULL);
|
||||
start transaction with consistent snapshot;
|
||||
start transaction;
|
||||
update t1 set f2 = 4 where f1 = 1 and f2 is null;
|
||||
(b) Number of rows updated:
|
||||
select row_count();
|
||||
row_count()
|
||||
1
|
||||
insert into t1 values (3, 1, null);
|
||||
(b) After update and insert query.
|
||||
select rowid, f1, f2 from t1;
|
||||
rowid f1 f2
|
||||
1 1 10
|
||||
2 1 4
|
||||
3 1 NULL
|
||||
commit;
|
||||
(a) Before the update statement is executed.
|
||||
select rowid, f1, f2 from t1;
|
||||
rowid f1 f2
|
||||
1 1 10
|
||||
2 1 NULL
|
||||
SET SESSION debug="+d,bug14007649";
|
||||
update t1 set f2 = 6 where f1 = 1 and f2 is null;
|
||||
(a) Number of rows updated:
|
||||
select row_count();
|
||||
row_count()
|
||||
1
|
||||
(a) After the update statement is executed.
|
||||
select rowid, f1, f2 from t1;
|
||||
rowid f1 f2
|
||||
1 1 10
|
||||
2 1 NULL
|
||||
3 1 6
|
||||
commit;
|
||||
"The trx with consistent snapshot ended."
|
||||
select rowid, f1, f2 from t1;
|
||||
rowid f1 f2
|
||||
1 1 10
|
||||
2 1 4
|
||||
3 1 6
|
||||
drop table t1;
|
58
mysql-test/suite/innodb/t/innodb_bug14007649.test
Normal file
58
mysql-test/suite/innodb/t/innodb_bug14007649.test
Normal file
@ -0,0 +1,58 @@
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_debug.inc
|
||||
|
||||
create table t1 (
|
||||
rowid int,
|
||||
f1 int,
|
||||
f2 int,
|
||||
key i1 (f1, f2),
|
||||
key i2 (f2)) engine=innodb;
|
||||
|
||||
show create table t1;
|
||||
insert into `t1` (rowid, f1, f2) values (1, 1, 10), (2, 1, NULL);
|
||||
|
||||
connect (a,localhost,root,,);
|
||||
connect (b,localhost,root,,);
|
||||
|
||||
connection a;
|
||||
start transaction with consistent snapshot;
|
||||
|
||||
connection b;
|
||||
start transaction;
|
||||
update t1 set f2 = 4 where f1 = 1 and f2 is null;
|
||||
|
||||
-- echo (b) Number of rows updated:
|
||||
select row_count();
|
||||
|
||||
insert into t1 values (3, 1, null);
|
||||
|
||||
-- echo (b) After update and insert query.
|
||||
select rowid, f1, f2 from t1;
|
||||
|
||||
commit;
|
||||
|
||||
connection a;
|
||||
|
||||
-- echo (a) Before the update statement is executed.
|
||||
select rowid, f1, f2 from t1;
|
||||
|
||||
SET SESSION debug="+d,bug14007649";
|
||||
update t1 set f2 = 6 where f1 = 1 and f2 is null;
|
||||
|
||||
-- echo (a) Number of rows updated:
|
||||
select row_count();
|
||||
|
||||
-- echo (a) After the update statement is executed.
|
||||
select rowid, f1, f2 from t1;
|
||||
|
||||
commit;
|
||||
|
||||
--echo "The trx with consistent snapshot ended."
|
||||
|
||||
select rowid, f1, f2 from t1;
|
||||
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
|
||||
drop table t1;
|
56
mysql-test/suite/innodb_plugin/r/innodb_bug14007649.result
Normal file
56
mysql-test/suite/innodb_plugin/r/innodb_bug14007649.result
Normal file
@ -0,0 +1,56 @@
|
||||
create table t1 (
|
||||
rowid int,
|
||||
f1 int,
|
||||
f2 int,
|
||||
key i1 (f1, f2),
|
||||
key i2 (f2)) engine=innodb;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`rowid` int(11) DEFAULT NULL,
|
||||
`f1` int(11) DEFAULT NULL,
|
||||
`f2` int(11) DEFAULT NULL,
|
||||
KEY `i1` (`f1`,`f2`),
|
||||
KEY `i2` (`f2`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
insert into `t1` (rowid, f1, f2) values (1, 1, 10), (2, 1, NULL);
|
||||
start transaction with consistent snapshot;
|
||||
start transaction;
|
||||
update t1 set f2 = 4 where f1 = 1 and f2 is null;
|
||||
(b) Number of rows updated:
|
||||
select row_count();
|
||||
row_count()
|
||||
1
|
||||
insert into t1 values (3, 1, null);
|
||||
(b) After update and insert query.
|
||||
select rowid, f1, f2 from t1;
|
||||
rowid f1 f2
|
||||
1 1 10
|
||||
2 1 4
|
||||
3 1 NULL
|
||||
commit;
|
||||
(a) Before the update statement is executed.
|
||||
select rowid, f1, f2 from t1;
|
||||
rowid f1 f2
|
||||
1 1 10
|
||||
2 1 NULL
|
||||
SET SESSION debug="+d,bug14007649";
|
||||
update t1 set f2 = 6 where f1 = 1 and f2 is null;
|
||||
(a) Number of rows updated:
|
||||
select row_count();
|
||||
row_count()
|
||||
1
|
||||
(a) After the update statement is executed.
|
||||
select rowid, f1, f2 from t1;
|
||||
rowid f1 f2
|
||||
1 1 10
|
||||
2 1 NULL
|
||||
3 1 6
|
||||
commit;
|
||||
"The trx with consistent snapshot ended."
|
||||
select rowid, f1, f2 from t1;
|
||||
rowid f1 f2
|
||||
1 1 10
|
||||
2 1 4
|
||||
3 1 6
|
||||
drop table t1;
|
58
mysql-test/suite/innodb_plugin/t/innodb_bug14007649.test
Normal file
58
mysql-test/suite/innodb_plugin/t/innodb_bug14007649.test
Normal file
@ -0,0 +1,58 @@
|
||||
--source include/have_innodb_plugin.inc
|
||||
--source include/have_debug.inc
|
||||
|
||||
create table t1 (
|
||||
rowid int,
|
||||
f1 int,
|
||||
f2 int,
|
||||
key i1 (f1, f2),
|
||||
key i2 (f2)) engine=innodb;
|
||||
|
||||
show create table t1;
|
||||
insert into `t1` (rowid, f1, f2) values (1, 1, 10), (2, 1, NULL);
|
||||
|
||||
connect (a,localhost,root,,);
|
||||
connect (b,localhost,root,,);
|
||||
|
||||
connection a;
|
||||
start transaction with consistent snapshot;
|
||||
|
||||
connection b;
|
||||
start transaction;
|
||||
update t1 set f2 = 4 where f1 = 1 and f2 is null;
|
||||
|
||||
-- echo (b) Number of rows updated:
|
||||
select row_count();
|
||||
|
||||
insert into t1 values (3, 1, null);
|
||||
|
||||
-- echo (b) After update and insert query.
|
||||
select rowid, f1, f2 from t1;
|
||||
|
||||
commit;
|
||||
|
||||
connection a;
|
||||
|
||||
-- echo (a) Before the update statement is executed.
|
||||
select rowid, f1, f2 from t1;
|
||||
|
||||
SET SESSION debug="+d,bug14007649";
|
||||
update t1 set f2 = 6 where f1 = 1 and f2 is null;
|
||||
|
||||
-- echo (a) Number of rows updated:
|
||||
select row_count();
|
||||
|
||||
-- echo (a) After the update statement is executed.
|
||||
select rowid, f1, f2 from t1;
|
||||
|
||||
commit;
|
||||
|
||||
--echo "The trx with consistent snapshot ended."
|
||||
|
||||
select rowid, f1, f2 from t1;
|
||||
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
|
||||
drop table t1;
|
@ -2792,6 +2792,8 @@ btr_estimate_n_rows_in_range(
|
||||
n_rows = n_rows * 2;
|
||||
}
|
||||
|
||||
DBUG_EXECUTE_IF("bug14007649", return(n_rows););
|
||||
|
||||
/* Do not estimate the number of rows in the range
|
||||
to over 1 / 2 of the estimated rows in the whole
|
||||
table */
|
||||
|
@ -3180,6 +3180,30 @@ table_opened:
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
handler*
|
||||
ha_innobase::clone(
|
||||
/*===============*/
|
||||
const char* name, /*!< in: table name */
|
||||
MEM_ROOT* mem_root) /*!< in: memory context */
|
||||
{
|
||||
ha_innobase* new_handler;
|
||||
|
||||
DBUG_ENTER("ha_innobase::clone");
|
||||
|
||||
new_handler = static_cast<ha_innobase*>(handler::clone(name,
|
||||
mem_root));
|
||||
if (new_handler) {
|
||||
DBUG_ASSERT(new_handler->prebuilt != NULL);
|
||||
DBUG_ASSERT(new_handler->user_thd == user_thd);
|
||||
DBUG_ASSERT(new_handler->prebuilt->trx == prebuilt->trx);
|
||||
|
||||
new_handler->prebuilt->select_lock_type
|
||||
= prebuilt->select_lock_type;
|
||||
}
|
||||
|
||||
DBUG_RETURN(new_handler);
|
||||
}
|
||||
|
||||
uint
|
||||
ha_innobase::max_supported_key_part_length() const
|
||||
{
|
||||
|
@ -117,6 +117,7 @@ class ha_innobase: public handler
|
||||
const key_map *keys_to_use_for_scanning() { return &key_map_full; }
|
||||
|
||||
int open(const char *name, int mode, uint test_if_locked);
|
||||
handler* clone(const char *name, MEM_ROOT *mem_root);
|
||||
int close(void);
|
||||
double scan_time();
|
||||
double read_time(uint index, uint ranges, ha_rows rows);
|
||||
|
@ -3194,6 +3194,8 @@ btr_estimate_n_rows_in_range(
|
||||
n_rows = n_rows * 2;
|
||||
}
|
||||
|
||||
DBUG_EXECUTE_IF("bug14007649", return(n_rows););
|
||||
|
||||
/* Do not estimate the number of rows in the range
|
||||
to over 1 / 2 of the estimated rows in the whole
|
||||
table */
|
||||
|
@ -3889,6 +3889,31 @@ table_opened:
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
UNIV_INTERN
|
||||
handler*
|
||||
ha_innobase::clone(
|
||||
/*===============*/
|
||||
const char* name, /*!< in: table name */
|
||||
MEM_ROOT* mem_root) /*!< in: memory context */
|
||||
{
|
||||
ha_innobase* new_handler;
|
||||
|
||||
DBUG_ENTER("ha_innobase::clone");
|
||||
|
||||
new_handler = static_cast<ha_innobase*>(handler::clone(name,
|
||||
mem_root));
|
||||
if (new_handler) {
|
||||
DBUG_ASSERT(new_handler->prebuilt != NULL);
|
||||
DBUG_ASSERT(new_handler->user_thd == user_thd);
|
||||
DBUG_ASSERT(new_handler->prebuilt->trx == prebuilt->trx);
|
||||
|
||||
new_handler->prebuilt->select_lock_type
|
||||
= prebuilt->select_lock_type;
|
||||
}
|
||||
|
||||
DBUG_RETURN(new_handler);
|
||||
}
|
||||
|
||||
UNIV_INTERN
|
||||
uint
|
||||
ha_innobase::max_supported_key_part_length() const
|
||||
|
@ -132,6 +132,7 @@ class ha_innobase: public handler
|
||||
const key_map* keys_to_use_for_scanning();
|
||||
|
||||
int open(const char *name, int mode, uint test_if_locked);
|
||||
handler* clone(const char *name, MEM_ROOT *mem_root);
|
||||
int close(void);
|
||||
double scan_time();
|
||||
double read_time(uint index, uint ranges, ha_rows rows);
|
||||
|
Loading…
x
Reference in New Issue
Block a user