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:
|
||||
# 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;
|
||||
|
@ -1,5 +1,12 @@
|
||||
# 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 @@ retry_share:
|
||||
(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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
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= ©->def_read_set;
|
||||
copy->write_set= ©->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 @@ end_with_restore_list:
|
||||
}
|
||||
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 */
|
||||
|
Reference in New Issue
Block a user