summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2020-05-28 22:22:19 +0300
committerAleksey Midenkov <midenok@gmail.com>2020-05-28 22:22:19 +0300
commitdd9773b72380eeb98b9dabba219452f29ee5603b (patch)
tree5f2d64cf0c82f8532e8d3269f96fee1ea77a1d43
parent3e9b96b6ff925f83427600956b86a984b726d3af (diff)
downloadmariadb-git-dd9773b72380eeb98b9dabba219452f29ee5603b.tar.gz
MDEV-22413 Server hangs upon UPDATE on a view reading from versioned partitioned table
UPDATE gets access to history records because versioning conditions are not set for VIEW. This leads to endless loop of inserting history records when clustered index is rebuilt and ha_rnd_next() returns newly inserted history record. Return back original behavior of failing on write-locked table in historical query. 35b679b9 assumed that SELECT_LEX::lock_type influences anything, but actually at this point table is already locked. Original bug report was tempesta-tech/mariadb#102
-rw-r--r--mysql-test/suite/versioning/r/partition.result26
-rw-r--r--mysql-test/suite/versioning/r/select.result3
-rw-r--r--mysql-test/suite/versioning/r/select2.result3
-rw-r--r--mysql-test/suite/versioning/t/partition.test36
-rw-r--r--mysql-test/suite/versioning/t/select.test1
-rw-r--r--mysql-test/suite/versioning/t/select2.test1
-rw-r--r--sql/sql_select.cc10
7 files changed, 67 insertions, 13 deletions
diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result
index c4fedb08ad6..4d0426512e6 100644
--- a/mysql-test/suite/versioning/r/partition.result
+++ b/mysql-test/suite/versioning/r/partition.result
@@ -650,6 +650,26 @@ pk f
update t1 set f=pk;
delete from t1;
drop table t1;
-# Test cleanup
-drop database test;
-create database test;
+#
+# MDEV-22413 Server hangs upon UPDATE/DELETE on a view reading from versioned partitioned table
+#
+create or replace table t1 (f char(6)) engine innodb with system versioning;
+insert into t1 values (null);
+update t1 set f= 'foo';
+update t1 set f= 'bar';
+create or replace view v1 as select * from t1 for system_time all;
+update v1 set f = '';
+ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
+create or replace table t1 (f char(6)) engine innodb with system versioning
+partition by system_time limit 1
+(partition p1 history, partition p2 history, partition pn current);
+insert into t1 values (null);
+update t1 set f= 'foo';
+update t1 set f= 'bar';
+create or replace view v1 as select * from t1 for system_time all;
+update v1 set f= '';
+ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
+delete from v1;
+ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
+drop view v1;
+drop table t1;
diff --git a/mysql-test/suite/versioning/r/select.result b/mysql-test/suite/versioning/r/select.result
index f1bdcccce59..74df243cf7c 100644
--- a/mysql-test/suite/versioning/r/select.result
+++ b/mysql-test/suite/versioning/r/select.result
@@ -206,8 +206,7 @@ ERROR HY000: Table `t1` is not system-versioned
create or replace table t1 (x int) with system versioning;
insert into t1 values (1);
select * from t1 for system_time all for update;
-x
-1
+ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
create or replace table t1 (a int not null auto_increment primary key) with system versioning;
select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1;
a
diff --git a/mysql-test/suite/versioning/r/select2.result b/mysql-test/suite/versioning/r/select2.result
index bb5c82ee444..7b20d68343b 100644
--- a/mysql-test/suite/versioning/r/select2.result
+++ b/mysql-test/suite/versioning/r/select2.result
@@ -229,8 +229,7 @@ ERROR HY000: Table `t1` is not system-versioned
create or replace table t1 (x int) with system versioning;
insert into t1 values (1);
select * from t1 for system_time as of now() for update;
-x
-1
+ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
create or replace table t1 (a int not null auto_increment primary key) with system versioning;
select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1;
a
diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test
index 6fee6f43847..6cd88caf1a9 100644
--- a/mysql-test/suite/versioning/t/partition.test
+++ b/mysql-test/suite/versioning/t/partition.test
@@ -583,7 +583,6 @@ update t1 left join t2 on a > b set b= 2 order by b;
# cleanup
drop table t1, t2;
---source suite/versioning/common_finish.inc
--echo #
--echo # MDEV-17091 Assertion `old_part_id == m_last_part' failed in
--echo # ha_partition::update_row or `part_id == m_last_part' in
@@ -605,6 +604,35 @@ update t1 set f=pk;
delete from t1;
drop table t1;
---echo # Test cleanup
-drop database test;
-create database test;
+--echo #
+--echo # MDEV-22413 Server hangs upon UPDATE/DELETE on a view reading from versioned partitioned table
+--echo #
+create or replace table t1 (f char(6)) engine innodb with system versioning;
+
+insert into t1 values (null);
+update t1 set f= 'foo';
+update t1 set f= 'bar';
+
+create or replace view v1 as select * from t1 for system_time all;
+--error ER_TABLE_NOT_LOCKED_FOR_WRITE
+update v1 set f = '';
+
+create or replace table t1 (f char(6)) engine innodb with system versioning
+partition by system_time limit 1
+(partition p1 history, partition p2 history, partition pn current);
+
+insert into t1 values (null);
+update t1 set f= 'foo';
+update t1 set f= 'bar';
+
+create or replace view v1 as select * from t1 for system_time all;
+--error ER_TABLE_NOT_LOCKED_FOR_WRITE
+update v1 set f= '';
+--error ER_TABLE_NOT_LOCKED_FOR_WRITE
+delete from v1;
+
+# cleanup
+drop view v1;
+drop table t1;
+
+--source suite/versioning/common_finish.inc
diff --git a/mysql-test/suite/versioning/t/select.test b/mysql-test/suite/versioning/t/select.test
index 069fe7a9a8d..16c2f34ab35 100644
--- a/mysql-test/suite/versioning/t/select.test
+++ b/mysql-test/suite/versioning/t/select.test
@@ -123,6 +123,7 @@ select * from t1 for system_time all;
create or replace table t1 (x int) with system versioning;
insert into t1 values (1);
+--error ER_TABLE_NOT_LOCKED_FOR_WRITE
select * from t1 for system_time all for update;
create or replace table t1 (a int not null auto_increment primary key) with system versioning;
diff --git a/mysql-test/suite/versioning/t/select2.test b/mysql-test/suite/versioning/t/select2.test
index d1b73fa799b..fa5d52c5143 100644
--- a/mysql-test/suite/versioning/t/select2.test
+++ b/mysql-test/suite/versioning/t/select2.test
@@ -128,6 +128,7 @@ select * from t1 for system_time all;
create or replace table t1 (x int) with system versioning;
insert into t1 values (1);
+--error ER_TABLE_NOT_LOCKED_FOR_WRITE
select * from t1 for system_time as of now() for update;
create or replace table t1 (a int not null auto_increment primary key) with system versioning;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 5694085d7da..05da4a1e750 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -832,10 +832,16 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables)
if (vers_conditions.is_set())
{
+ if (vers_conditions.was_set() &&
+ table->lock_type > TL_READ_NO_INSERT &&
+ !vers_conditions.delete_history)
+ {
+ my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table->alias.str);
+ DBUG_RETURN(-1);
+ }
+
if (vers_conditions.type == SYSTEM_TIME_ALL)
continue;
-
- lock_type= TL_READ; // ignore TL_WRITE, history is immutable anyway
}
const LEX_CSTRING *fstart=