Commit 293cb049 authored by Monty's avatar Monty

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
parent 4b6a3518
# 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:
# Connection 'default'.
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;
# delayed works differently in embedded server
--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
# (Can't be tested with purify :( )
......@@ -629,3 +636,37 @@ disconnect con1;
--echo # Connection 'default'.
connection default;
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 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx)
(void) ot_ctx->request_backoff_action(Open_table_context::OT_DISCOVER,
table_list);
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;
}
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.
*/
#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. */
#define MYSQL_OPEN_REOPEN (MYSQL_OPEN_IGNORE_FLUSH |\
......
......@@ -2014,6 +2014,7 @@ class Delayed_insert :public ilink {
mysql_cond_t cond, cond_client;
volatile uint tables_in_use,stacked_inserts;
volatile bool status;
bool retry;
/**
When the handler thread starts, it clones a metadata lock ticket
which protects against GRL and ticket for the table to be inserted.
......@@ -2038,7 +2039,7 @@ class Delayed_insert :public ilink {
Delayed_insert(SELECT_LEX *current_select)
: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");
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.is_error())
if (di->thd.is_error() && ! di->retry)
{
/*
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->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= &copy->def_read_set;
copy->write_set= &copy->def_write_set;
......@@ -2526,7 +2527,6 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
/* Got fatal error */
error:
tables_in_use--;
status=1;
mysql_cond_signal(&cond); // Inform thread about abort
DBUG_RETURN(0);
}
......@@ -2768,13 +2768,20 @@ bool Delayed_insert::open_and_lock_table()
/*
Use special prelocking strategy to get ER_DELAYED_NOT_SUPPORTED
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,
TL_WRITE_DELAYED,
MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK,
MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK |
MYSQL_OPEN_IGNORE_REPAIR,
&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;
}
......
......@@ -4925,6 +4925,7 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_SHUTDOWN:
#ifndef EMBEDDED_LIBRARY
DBUG_EXECUTE_IF("crash_shutdown", DBUG_SUICIDE(););
if (check_global_access(thd,SHUTDOWN_ACL))
goto error;
kill_mysql();
......
......@@ -2005,6 +2005,7 @@ struct TABLE_LIST
bool updating; /* for replicate-do/ignore table */
bool force_index; /* prefer index over table scan */
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 on_expr_dep_tables; /* tables on expression depends on */
struct st_nested_join *nested_join; /* if the element is a nested join */
......
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