mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-9621 INSERT DELAYED fails on insert for tables with many columns
This fix also fixes a connection hang when trying to do INSERT DELAYED to a crashed table. Added crash_mysqld.inc to allow easy crash+restart of mysqld
This commit is contained in:
18
mysql-test/include/crash_mysqld.inc
Normal file
18
mysql-test/include/crash_mysqld.inc
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Crash mysqld hard and wait until it's restarted
|
||||||
|
|
||||||
|
--source include/have_debug_sync.inc
|
||||||
|
--source include/not_embedded.inc
|
||||||
|
|
||||||
|
# Write file to make mysql-test-run.pl expect crash and restart
|
||||||
|
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||||
|
|
||||||
|
# Setup the mysqld to crash at shutdown
|
||||||
|
SET debug_dbug="d,crash_shutdown";
|
||||||
|
--error 2013
|
||||||
|
shutdown;
|
||||||
|
|
||||||
|
# Turn on reconnect
|
||||||
|
--enable_reconnect
|
||||||
|
|
||||||
|
# Call script that will poll the server waiting for it to be back online again
|
||||||
|
--source include/wait_until_connected_again.inc
|
@ -466,3 +466,37 @@ commit;
|
|||||||
# Reaping ALTER TABLE:
|
# Reaping ALTER TABLE:
|
||||||
# Connection 'default'.
|
# Connection 'default'.
|
||||||
drop tables tm, t1, t2;
|
drop tables tm, t1, t2;
|
||||||
|
#
|
||||||
|
# MDEV-9621 INSERT DELAYED fails on insert for tables with many columns
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
a int,b int,c int,d int,e int,f int,g int,h int,i int,j int,k int,l int,m int,n int,o int,p int,q int,r int,s int,t int,u int,v int,x int,y int,z int
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
INSERT DELAYED INTO t1 (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,x,y,z)
|
||||||
|
values (1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1);
|
||||||
|
INSERT DELAYED INTO t1 (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,x,y,z)
|
||||||
|
values (1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1);
|
||||||
|
drop table t1;
|
||||||
|
#
|
||||||
|
# INSERT DELAYED hangs if table was crashed
|
||||||
|
#
|
||||||
|
create table t1 (a int, b int) engine=myisam;
|
||||||
|
insert into t1 values (1,1);
|
||||||
|
SET debug_dbug="d,crash_shutdown";
|
||||||
|
shutdown;
|
||||||
|
ERROR HY000: Lost connection to MySQL server during query
|
||||||
|
call mtr.add_suppression(" marked as crashed and should be repaired");
|
||||||
|
call mtr.add_suppression("Checking table");
|
||||||
|
insert delayed into t1 values (2,2);
|
||||||
|
Warnings:
|
||||||
|
Error 145 Table './test/t1' is marked as crashed and should be repaired
|
||||||
|
Error 1194 Table 't1' is marked as crashed and should be repaired
|
||||||
|
Error 1034 1 client is using or hasn't closed the table properly
|
||||||
|
insert delayed into t1 values (3,3);
|
||||||
|
flush tables t1;
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
1 1
|
||||||
|
2 2
|
||||||
|
3 3
|
||||||
|
drop table t1;
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
# delayed works differently in embedded server
|
# delayed works differently in embedded server
|
||||||
--source include/not_embedded.inc
|
--source include/not_embedded.inc
|
||||||
|
# Don't test this under valgrind, memory leaks will occur
|
||||||
|
--source include/not_valgrind.inc
|
||||||
|
# Avoid CrashReporter popup on Mac
|
||||||
|
--source include/not_crashrep.inc
|
||||||
|
# Binary must be compiled with debug for crash to occur
|
||||||
|
--source include/have_debug_sync.inc
|
||||||
|
|
||||||
#
|
#
|
||||||
# test of DELAYED insert and timestamps
|
# test of DELAYED insert and timestamps
|
||||||
# (Can't be tested with purify :( )
|
# (Can't be tested with purify :( )
|
||||||
@ -629,3 +636,37 @@ disconnect con1;
|
|||||||
--echo # Connection 'default'.
|
--echo # Connection 'default'.
|
||||||
connection default;
|
connection default;
|
||||||
drop tables tm, t1, t2;
|
drop tables tm, t1, t2;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-9621 INSERT DELAYED fails on insert for tables with many columns
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
a int,b int,c int,d int,e int,f int,g int,h int,i int,j int,k int,l int,m int,n int,o int,p int,q int,r int,s int,t int,u int,v int,x int,y int,z int
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
INSERT DELAYED INTO t1 (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,x,y,z)
|
||||||
|
values (1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1);
|
||||||
|
INSERT DELAYED INTO t1 (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,x,y,z)
|
||||||
|
values (1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1);
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # INSERT DELAYED hangs if table was crashed
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
create table t1 (a int, b int) engine=myisam;
|
||||||
|
insert into t1 values (1,1);
|
||||||
|
|
||||||
|
# Will come back with t1 crashed.
|
||||||
|
--source include/crash_mysqld.inc
|
||||||
|
|
||||||
|
call mtr.add_suppression(" marked as crashed and should be repaired");
|
||||||
|
call mtr.add_suppression("Checking table");
|
||||||
|
|
||||||
|
--replace_result '\\' '/'
|
||||||
|
insert delayed into t1 values (2,2);
|
||||||
|
insert delayed into t1 values (3,3);
|
||||||
|
flush tables t1;
|
||||||
|
select * from t1;
|
||||||
|
drop table t1;
|
||||||
|
@ -2570,8 +2570,13 @@ retry_share:
|
|||||||
(void) ot_ctx->request_backoff_action(Open_table_context::OT_DISCOVER,
|
(void) ot_ctx->request_backoff_action(Open_table_context::OT_DISCOVER,
|
||||||
table_list);
|
table_list);
|
||||||
else if (share->crashed)
|
else if (share->crashed)
|
||||||
(void) ot_ctx->request_backoff_action(Open_table_context::OT_REPAIR,
|
{
|
||||||
table_list);
|
if (!(flags & MYSQL_OPEN_IGNORE_REPAIR))
|
||||||
|
(void) ot_ctx->request_backoff_action(Open_table_context::OT_REPAIR,
|
||||||
|
table_list);
|
||||||
|
else
|
||||||
|
table_list->crashed= 1; /* Mark that table was crashed */
|
||||||
|
}
|
||||||
goto err_lock;
|
goto err_lock;
|
||||||
}
|
}
|
||||||
if (open_table_entry_fini(thd, share, table))
|
if (open_table_entry_fini(thd, share, table))
|
||||||
|
@ -107,6 +107,10 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
|
|||||||
table flush, wait on thr_lock.c locks) while opening and locking table.
|
table flush, wait on thr_lock.c locks) while opening and locking table.
|
||||||
*/
|
*/
|
||||||
#define MYSQL_OPEN_IGNORE_KILLED 0x8000
|
#define MYSQL_OPEN_IGNORE_KILLED 0x8000
|
||||||
|
/**
|
||||||
|
Don't try to auto-repair table
|
||||||
|
*/
|
||||||
|
#define MYSQL_OPEN_IGNORE_REPAIR 0x10000
|
||||||
|
|
||||||
/** Please refer to the internals manual. */
|
/** Please refer to the internals manual. */
|
||||||
#define MYSQL_OPEN_REOPEN (MYSQL_OPEN_IGNORE_FLUSH |\
|
#define MYSQL_OPEN_REOPEN (MYSQL_OPEN_IGNORE_FLUSH |\
|
||||||
|
@ -2014,6 +2014,7 @@ public:
|
|||||||
mysql_cond_t cond, cond_client;
|
mysql_cond_t cond, cond_client;
|
||||||
volatile uint tables_in_use,stacked_inserts;
|
volatile uint tables_in_use,stacked_inserts;
|
||||||
volatile bool status;
|
volatile bool status;
|
||||||
|
bool retry;
|
||||||
/**
|
/**
|
||||||
When the handler thread starts, it clones a metadata lock ticket
|
When the handler thread starts, it clones a metadata lock ticket
|
||||||
which protects against GRL and ticket for the table to be inserted.
|
which protects against GRL and ticket for the table to be inserted.
|
||||||
@ -2038,7 +2039,7 @@ public:
|
|||||||
|
|
||||||
Delayed_insert(SELECT_LEX *current_select)
|
Delayed_insert(SELECT_LEX *current_select)
|
||||||
:locks_in_memory(0), table(0),tables_in_use(0),stacked_inserts(0),
|
:locks_in_memory(0), table(0),tables_in_use(0),stacked_inserts(0),
|
||||||
status(0), handler_thread_initialized(FALSE), group_count(0)
|
status(0), retry(0), handler_thread_initialized(FALSE), group_count(0)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Delayed_insert constructor");
|
DBUG_ENTER("Delayed_insert constructor");
|
||||||
thd.security_ctx->user=(char*) delayed_user;
|
thd.security_ctx->user=(char*) delayed_user;
|
||||||
@ -2291,7 +2292,7 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request,
|
|||||||
}
|
}
|
||||||
if (di->thd.killed)
|
if (di->thd.killed)
|
||||||
{
|
{
|
||||||
if (di->thd.is_error())
|
if (di->thd.is_error() && ! di->retry)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Copy the error message. Note that we don't treat fatal
|
Copy the error message. Note that we don't treat fatal
|
||||||
@ -2517,7 +2518,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
|
|||||||
copy->vcol_set= copy->def_vcol_set;
|
copy->vcol_set= copy->def_vcol_set;
|
||||||
}
|
}
|
||||||
copy->tmp_set.bitmap= 0; // To catch errors
|
copy->tmp_set.bitmap= 0; // To catch errors
|
||||||
bzero((char*) bitmap, share->column_bitmap_size + (share->vfields ? 3 : 2));
|
bzero((char*) bitmap, share->column_bitmap_size * (share->vfields ? 3 : 2));
|
||||||
copy->read_set= ©->def_read_set;
|
copy->read_set= ©->def_read_set;
|
||||||
copy->write_set= ©->def_write_set;
|
copy->write_set= ©->def_write_set;
|
||||||
|
|
||||||
@ -2526,7 +2527,6 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
|
|||||||
/* Got fatal error */
|
/* Got fatal error */
|
||||||
error:
|
error:
|
||||||
tables_in_use--;
|
tables_in_use--;
|
||||||
status=1;
|
|
||||||
mysql_cond_signal(&cond); // Inform thread about abort
|
mysql_cond_signal(&cond); // Inform thread about abort
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
@ -2768,13 +2768,20 @@ bool Delayed_insert::open_and_lock_table()
|
|||||||
/*
|
/*
|
||||||
Use special prelocking strategy to get ER_DELAYED_NOT_SUPPORTED
|
Use special prelocking strategy to get ER_DELAYED_NOT_SUPPORTED
|
||||||
error for tables with engines which don't support delayed inserts.
|
error for tables with engines which don't support delayed inserts.
|
||||||
|
|
||||||
|
We can't do auto-repair in insert delayed thread, as it would hang
|
||||||
|
when trying to an exclusive MDL_LOCK on the table during repair
|
||||||
|
as the connection thread has a SHARED_WRITE lock.
|
||||||
*/
|
*/
|
||||||
if (!(table= open_n_lock_single_table(&thd, &table_list,
|
if (!(table= open_n_lock_single_table(&thd, &table_list,
|
||||||
TL_WRITE_DELAYED,
|
TL_WRITE_DELAYED,
|
||||||
MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK,
|
MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK |
|
||||||
|
MYSQL_OPEN_IGNORE_REPAIR,
|
||||||
&prelocking_strategy)))
|
&prelocking_strategy)))
|
||||||
{
|
{
|
||||||
thd.fatal_error(); // Abort waiting inserts
|
/* If table was crashed, then upper level should retry open+repair */
|
||||||
|
retry= table_list.crashed;
|
||||||
|
thd.fatal_error(); // Abort waiting inserts
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4925,6 +4925,7 @@ end_with_restore_list:
|
|||||||
}
|
}
|
||||||
case SQLCOM_SHUTDOWN:
|
case SQLCOM_SHUTDOWN:
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
|
DBUG_EXECUTE_IF("crash_shutdown", DBUG_SUICIDE(););
|
||||||
if (check_global_access(thd,SHUTDOWN_ACL))
|
if (check_global_access(thd,SHUTDOWN_ACL))
|
||||||
goto error;
|
goto error;
|
||||||
kill_mysql();
|
kill_mysql();
|
||||||
|
@ -2005,6 +2005,7 @@ struct TABLE_LIST
|
|||||||
bool updating; /* for replicate-do/ignore table */
|
bool updating; /* for replicate-do/ignore table */
|
||||||
bool force_index; /* prefer index over table scan */
|
bool force_index; /* prefer index over table scan */
|
||||||
bool ignore_leaves; /* preload only non-leaf nodes */
|
bool ignore_leaves; /* preload only non-leaf nodes */
|
||||||
|
bool crashed; /* Table was found crashed */
|
||||||
table_map dep_tables; /* tables the table depends on */
|
table_map dep_tables; /* tables the table depends on */
|
||||||
table_map on_expr_dep_tables; /* tables on expression depends on */
|
table_map on_expr_dep_tables; /* tables on expression depends on */
|
||||||
struct st_nested_join *nested_join; /* if the element is a nested join */
|
struct st_nested_join *nested_join; /* if the element is a nested join */
|
||||||
|
Reference in New Issue
Block a user