Commit 57c3dd99 authored by Monty's avatar Monty

MDEV-15106 Unexpected ER_WRONG_INSERT_INTO_SEQUENCE upon INSERT with multiple locks on sequences

Fixed by removing the check of single lock in sequence insert and let MDL
code handle deadlock detection
parent 6c43068d
......@@ -27,3 +27,8 @@ DROP SEQUENCE s1;
ERROR HY000: Table 's1' was locked with a READ lock and can't be updated
unlock tables;
DROP SEQUENCE s1;
CREATE SEQUENCE seq1;
CREATE SEQUENCE seq2;
LOCK TABLE seq1 WRITE, seq2 WRITE;
INSERT INTO seq1 VALUES (1, 1, 100000, 1, 1, 100, 1, 1);
DROP SEQUENCE seq1, seq2;
......@@ -38,3 +38,16 @@ SELECT NEXTVAL(s);
DROP SEQUENCE s1;
unlock tables;
DROP SEQUENCE s1;
#
# MDEV-15106 Unexpected ER_WRONG_INSERT_INTO_SEQUENCE upon INSERT with
# multiple locks on sequences
#
CREATE SEQUENCE seq1;
CREATE SEQUENCE seq2;
LOCK TABLE seq1 WRITE, seq2 WRITE;
INSERT INTO seq1 VALUES (1, 1, 100000, 1, 1, 100, 1, 1);
DROP SEQUENCE seq1, seq2;
......@@ -49,10 +49,6 @@ insert into s1 (next_not_cached_value, minimum_value) values (100,1000);
ERROR HY000: Field 'maximum_value' doesn't have a default value
insert into s1 values (next value for s1, 1,9223372036854775806,1,1,1000,0,0);
ERROR HY000: Table 's1' is specified twice, both as a target for 'INSERT' and as a separate source for data
insert into s1 values (next value for s2, 1,9223372036854775806,1,1,1000,0,0);
ERROR HY000: Wrong INSERT into a SEQUENCE. One can only do single table INSERT into a sequence object (like with mysqldump). If you want to change the SEQUENCE, use ALTER SEQUENCE instead.
insert into s1 select * from s2;
ERROR HY000: Wrong INSERT into a SEQUENCE. One can only do single table INSERT into a sequence object (like with mysqldump). If you want to change the SEQUENCE, use ALTER SEQUENCE instead.
insert into s1 values(1000,9223372036854775806,1,1,1,1000,0,0);
ERROR HY000: Sequence 'test.s1' values are conflicting
insert into s1 values(0,9223372036854775806,1,1,1,1000,0,0);
......@@ -72,6 +68,20 @@ next_not_cached_value minimum_value maximum_value start_value increment cache_si
2000 1 9223372036854775806 1 1 1000 0 0
insert into s2 values(0, 1, 10, 1, 2, 1, 1, 0);
ERROR HY000: Sequence 'test.s2' values are conflicting
select * from s1;
next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
2000 1 9223372036854775806 1 1 1000 0 0
insert into s1 values (next value for s2, 1,9223372036854775806,1,1,1000,0,0);
select * from s1;
next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
1 1 9223372036854775806 1 1 1000 0 0
select * from s2;
next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
1001 1 9223372036854775806 1 1 1000 0 0
insert into s1 select * from s2;
select * from s1;
next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
1001 1 9223372036854775806 1 1 1000 0 0
drop sequence s1,s2;
#
# UPDATE and DELETE
......
......@@ -38,10 +38,6 @@ create sequence s2;
insert into s1 (next_not_cached_value, minimum_value) values (100,1000);
--error ER_UPDATE_TABLE_USED
insert into s1 values (next value for s1, 1,9223372036854775806,1,1,1000,0,0);
--error ER_WRONG_INSERT_INTO_SEQUENCE
insert into s1 values (next value for s2, 1,9223372036854775806,1,1,1000,0,0);
--error ER_WRONG_INSERT_INTO_SEQUENCE
insert into s1 select * from s2;
--error ER_SEQUENCE_INVALID_DATA
insert into s1 values(1000,9223372036854775806,1,1,1,1000,0,0);
--error ER_SEQUENCE_INVALID_DATA
......@@ -53,6 +49,13 @@ select next value for s1;
select * from s1;
--error ER_SEQUENCE_INVALID_DATA
insert into s2 values(0, 1, 10, 1, 2, 1, 1, 0);
select * from s1;
insert into s1 values (next value for s2, 1,9223372036854775806,1,1,1000,0,0);
select * from s1;
select * from s2;
insert into s1 select * from s2;
select * from s1;
drop sequence s1,s2;
--echo #
......
......@@ -84,14 +84,18 @@ int ha_sequence::open(const char *name, int mode, uint flags)
if (!(error= file->open(name, mode, flags)))
{
/*
Copy values set by handler::open() in the underlying handler
Reuse original storage engine data for duplicate key reference
It would be easier to do this if we would have another handler
call: fixup_after_open()...
*/
ref= file->ref;
Allocate ref in table's mem_root. We can't use table's ref
as it's allocated by ha_ caller that allocates this.
*/
ref_length= file->ref_length;
dup_ref= file->dup_ref;
if (!(ref= (uchar*) alloc_root(&table->mem_root,ALIGN_SIZE(ref_length)*2)))
{
file->ha_close();
error=HA_ERR_OUT_OF_MEM;
DBUG_RETURN(error);
}
file->ref= ref;
file->dup_ref= dup_ref= ref+ALIGN_SIZE(file->ref_length);
/*
ha_open() sets the following for us. We have to set this for the
......@@ -229,14 +233,10 @@ int ha_sequence::write_row(uchar *buf)
- Get an exclusive lock for the table. This is needed to ensure that
we excute all full inserts (same as ALTER SEQUENCE) in same order
on master and slaves
- Check that we are only using one table.
This is to avoid deadlock problems when upgrading lock to exlusive.
- Check that the new row is an accurate SEQUENCE object
*/
THD *thd= table->in_use;
if (thd->lock->table_count != 1)
DBUG_RETURN(ER_WRONG_INSERT_INTO_SEQUENCE);
if (table->s->tmp_table == NO_TMP_TABLE &&
thd->mdl_context.upgrade_shared_lock(table->mdl_ticket,
MDL_EXCLUSIVE,
......
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