1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

MDEV-14829 Assertion `0' failed in Protocol::end_statement upon concurrent UPDATE

vers_insert_history_row(): do not insert rows with zero or negative lifetime.

mysql_update(): properly handle error from vers_insert_history_row()
This commit is contained in:
Eugene Kosov
2018-02-02 15:01:53 +03:00
committed by Sergei Golubchik
parent 75afaa7e00
commit edeeaac451
7 changed files with 67 additions and 15 deletions

View File

@ -6,6 +6,7 @@ innodb-cmpmem
innodb-cmp-per-index
innodb-trx
innodb-locks
innodb-lock-waits
innodb-buffer-pool-stats
innodb-buffer-page
innodb-buffer-page-lru
@ -24,6 +25,7 @@ innodb-cmpmem
innodb-cmp-per-index
innodb-trx
innodb-locks
innodb-lock-waits
innodb-metrics
innodb-buffer-pool-stats
innodb-buffer-page

View File

@ -371,3 +371,9 @@ create or replace table t1 (pk int primary key) with system versioning;
create trigger tr before insert on t1 for each row select 1 into @a;
insert into t1 values (1),(2);
drop table t1;
create table t1 (pk int primary key, i int) with system versioning;
replace into t1 values (1,10),(1,100),(1,1000);
select pk,i,row_end > '2038-01-01' from t1 for system_time all;
pk i row_end > '2038-01-01'
1 1000 1
drop table t1;

View File

@ -620,6 +620,20 @@ create or replace table t1 (a int primary key, b int)
with system versioning engine myisam;
insert into t1 (a) values (1);
replace t1 values (1,2),(1,3),(2,4);
ERROR 23000: Duplicate entry '1-YYYY-MM-DD hh:mm:ss.uuuuuu' for key 'PRIMARY'
create or replace table t1 (pk int, a char(3), b char(3), primary key(pk))
engine=innodb with system versioning;
insert into t1 (pk) values (1);
connect con1,localhost,root,,test;
start transaction;
select * from t1 for update;
pk a b
1 NULL NULL
connection default;
update t1 set b = 'foo';
connection con1;
update t1 set a = 'bar';
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
disconnect con1;
connection default;
drop database test;
create database test;

View File

@ -267,5 +267,12 @@ select *, row_start > @a, row_end > @a from t1 for system_time all;
create or replace table t1 (pk int primary key) with system versioning;
create trigger tr before insert on t1 for each row select 1 into @a;
insert into t1 values (1),(2);
drop table t1;
#
# MDEV-14794 Limitations which the row end as a part of PK imposes due to CURRENT_TIMESTAMP behavior and otherwise
#
create table t1 (pk int primary key, i int) with system versioning;
replace into t1 values (1,10),(1,100),(1,1000);
select pk,i,row_end > '2038-01-01' from t1 for system_time all;
drop table t1;

View File

@ -1,4 +1,4 @@
-- source suite/versioning/common.inc
--source suite/versioning/common.inc
delimiter ~~;
create procedure test_01(
@ -280,9 +280,30 @@ call verify_vtq;
create or replace table t1 (a int primary key, b int)
with system versioning engine myisam;
insert into t1 (a) values (1);
--replace_regex /'1-[- .\d:]+'/'1-YYYY-MM-DD hh:mm:ss.uuuuuu'/
--error ER_DUP_ENTRY
replace t1 values (1,2),(1,3),(2,4);
#
# MDEV-14829 Assertion `0' failed in Protocol::end_statement upon concurrent UPDATE
#
create or replace table t1 (pk int, a char(3), b char(3), primary key(pk))
engine=innodb with system versioning;
insert into t1 (pk) values (1);
connect (con1,localhost,root,,test);
start transaction;
select * from t1 for update;
connection default;
send update t1 set b = 'foo';
connection con1;
let $wait_condition= select count(*) from information_schema.innodb_lock_waits;
source include/wait_condition.inc;
error ER_LOCK_DEADLOCK;
update t1 set a = 'bar';
disconnect con1;
connection default;
reap;
drop database test;
create database test;

View File

@ -1640,6 +1640,11 @@ int vers_insert_history_row(TABLE *table)
// Set Sys_end to now()
table->vers_update_end();
Field *row_start= table->vers_start_field();
Field *row_end= table->vers_end_field();
if (row_start->cmp(row_start->ptr, row_end->ptr) >= 0)
return 0;
return table->file->ha_write_row(table->record[0]);
}

View File

@ -948,25 +948,22 @@ update_begin:
}
else if (!error)
{
updated++;
if (has_vers_fields && table->versioned())
{
if (table->versioned(VERS_TIMESTAMP))
{
store_record(table, record[2]);
if ((error = vers_insert_history_row(table)))
{
restore_record(table, record[2]);
break;
}
error= vers_insert_history_row(table);
restore_record(table, record[2]);
}
if (!error)
updated_sys_ver++;
}
if (!error)
updated++;
}
else if (!ignore ||
table->file->is_fatal_error(error, HA_CHECK_ALL))
if (error && (!ignore || table->file->is_fatal_error(error, HA_CHECK_ALL)))
{
/*
If (ignore && error is ignorable) we don't have to