summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2016-04-07 19:26:25 +0300
committerMonty <monty@mariadb.org>2016-04-07 19:31:10 +0300
commit293cb04959172f65b9d62124fd20339c47658eb0 (patch)
tree72433a6e0813d2e01038df7d44da8c4af340597d
parent4b6a3518e4dc9088d1f42cd9bc487d06137d2760 (diff)
downloadmariadb-git-293cb04959172f65b9d62124fd20339c47658eb0.tar.gz
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
-rw-r--r--mysql-test/include/crash_mysqld.inc18
-rw-r--r--mysql-test/r/delayed.result34
-rw-r--r--mysql-test/t/delayed.test41
-rw-r--r--sql/sql_base.cc9
-rw-r--r--sql/sql_base.h4
-rw-r--r--sql/sql_insert.cc19
-rw-r--r--sql/sql_parse.cc1
-rw-r--r--sql/table.h1
8 files changed, 119 insertions, 8 deletions
diff --git a/mysql-test/include/crash_mysqld.inc b/mysql-test/include/crash_mysqld.inc
new file mode 100644
index 00000000000..4190d24d801
--- /dev/null
+++ b/mysql-test/include/crash_mysqld.inc
@@ -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
diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result
index 98c8b599e88..8cc5645eeda 100644
--- a/mysql-test/r/delayed.result
+++ b/mysql-test/r/delayed.result
@@ -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;
diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test
index 2886dff8f91..644cbfbe6ce 100644
--- a/mysql-test/t/delayed.test
+++ b/mysql-test/t/delayed.test
@@ -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;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 98c63a92a86..e808fbafb50 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -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))
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 7407e230419..9e37a43aab8 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -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 |\
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index f8a755c8d5e..9b4238b513d 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -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= &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;
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 6fcb549f097..4c8bb05cc39 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -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();
diff --git a/sql/table.h b/sql/table.h
index 023d5e542b8..eb4076e02e2 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -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 */