Commit edeeaac4 authored by Eugene Kosov's avatar Eugene Kosov Committed by Sergei Golubchik

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()
parent 75afaa7e
......@@ -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
......
......@@ -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;
......@@ -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;
......@@ -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;
-- 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;
......@@ -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]);
}
......
......@@ -948,25 +948,22 @@ int mysql_update(THD *thd,
}
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]);
}
updated_sys_ver++;
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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment