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; ...@@ -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;
# 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; ...@@ -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: ...@@ -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)
{
if (!(flags & MYSQL_OPEN_IGNORE_REPAIR))
(void) ot_ctx->request_backoff_action(Open_table_context::OT_REPAIR, (void) ot_ctx->request_backoff_action(Open_table_context::OT_REPAIR,
table_list); 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, ...@@ -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: ...@@ -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: ...@@ -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, ...@@ -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) ...@@ -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= &copy->def_read_set; copy->read_set= &copy->def_read_set;
copy->write_set= &copy->def_write_set; copy->write_set= &copy->def_write_set;
...@@ -2526,7 +2527,6 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) ...@@ -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,12 +2768,19 @@ bool Delayed_insert::open_and_lock_table() ...@@ -2768,12 +2768,19 @@ 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)))
{ {
/* If table was crashed, then upper level should retry open+repair */
retry= table_list.crashed;
thd.fatal_error(); // Abort waiting inserts thd.fatal_error(); // Abort waiting inserts
return TRUE; return TRUE;
} }
......
...@@ -4925,6 +4925,7 @@ end_with_restore_list: ...@@ -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 ...@@ -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 */
......
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