mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
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
This commit is contained in:
parent
6c43068d63
commit
57c3dd991b
5 changed files with 50 additions and 19 deletions
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue