Commit 04056ffd authored by osku@127.(none)'s avatar osku@127.(none)

InnoDB: Print more than 300 characters of queries in various error conditions,

most notably deadlocked ones in SHOW INNODB STATUS. Fixes bug #7819.
parent 445bc133
...@@ -210,7 +210,7 @@ btr_pcur_restore_position( ...@@ -210,7 +210,7 @@ btr_pcur_restore_position(
&& cursor->pos_state != BTR_PCUR_IS_POSITIONED)) { && cursor->pos_state != BTR_PCUR_IS_POSITIONED)) {
ut_print_buf(stderr, (const byte*)cursor, sizeof(btr_pcur_t)); ut_print_buf(stderr, (const byte*)cursor, sizeof(btr_pcur_t));
if (cursor->trx_if_known) { if (cursor->trx_if_known) {
trx_print(stderr, cursor->trx_if_known); trx_print(stderr, cursor->trx_if_known, 0);
} }
ut_error; ut_error;
......
...@@ -329,17 +329,20 @@ trx_commit_step( ...@@ -329,17 +329,20 @@ trx_commit_step(
/*============*/ /*============*/
/* out: query thread to run next, or NULL */ /* out: query thread to run next, or NULL */
que_thr_t* thr); /* in: query thread */ que_thr_t* thr); /* in: query thread */
/************************************************************************** /**************************************************************************
Prints info about a transaction to the standard output. The caller must Prints info about a transaction to the given file. The caller must own the
own the kernel mutex and must have called kernel mutex and must have called
innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL or innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL
InnoDB cannot meanwhile change the info printed here. */ or InnoDB cannot meanwhile change the info printed here. */
void void
trx_print( trx_print(
/*======*/ /*======*/
FILE* f, /* in: output stream */ FILE* f, /* in: output stream */
trx_t* trx); /* in: transaction */ trx_t* trx, /* in: transaction */
uint max_query_len); /* in: max query length to print, or 0 to
use the default max length */
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
/************************************************************************** /**************************************************************************
......
...@@ -3297,7 +3297,7 @@ lock_deadlock_recursive( ...@@ -3297,7 +3297,7 @@ lock_deadlock_recursive(
fputs("\n*** (1) TRANSACTION:\n", ef); fputs("\n*** (1) TRANSACTION:\n", ef);
trx_print(ef, wait_lock->trx); trx_print(ef, wait_lock->trx, 3000);
fputs( fputs(
"*** (1) WAITING FOR THIS LOCK TO BE GRANTED:\n", ef); "*** (1) WAITING FOR THIS LOCK TO BE GRANTED:\n", ef);
...@@ -3310,7 +3310,7 @@ lock_deadlock_recursive( ...@@ -3310,7 +3310,7 @@ lock_deadlock_recursive(
fputs("*** (2) TRANSACTION:\n", ef); fputs("*** (2) TRANSACTION:\n", ef);
trx_print(ef, lock->trx); trx_print(ef, lock->trx, 3000);
fputs("*** (2) HOLDS THE LOCK(S):\n", ef); fputs("*** (2) HOLDS THE LOCK(S):\n", ef);
...@@ -4207,7 +4207,7 @@ lock_print_info_all_transactions( ...@@ -4207,7 +4207,7 @@ lock_print_info_all_transactions(
while (trx) { while (trx) {
if (trx->conc_state == TRX_NOT_STARTED) { if (trx->conc_state == TRX_NOT_STARTED) {
fputs("---", file); fputs("---", file);
trx_print(file, trx); trx_print(file, trx, 600);
} }
trx = UT_LIST_GET_NEXT(mysql_trx_list, trx); trx = UT_LIST_GET_NEXT(mysql_trx_list, trx);
...@@ -4239,7 +4239,7 @@ lock_print_info_all_transactions( ...@@ -4239,7 +4239,7 @@ lock_print_info_all_transactions(
if (nth_lock == 0) { if (nth_lock == 0) {
fputs("---", file); fputs("---", file);
trx_print(file, trx); trx_print(file, trx, 600);
if (trx->read_view) { if (trx->read_view) {
fprintf(file, fprintf(file,
......
...@@ -602,7 +602,7 @@ row_ins_foreign_report_err( ...@@ -602,7 +602,7 @@ row_ins_foreign_report_err(
rewind(ef); rewind(ef);
ut_print_timestamp(ef); ut_print_timestamp(ef);
fputs(" Transaction:\n", ef); fputs(" Transaction:\n", ef);
trx_print(ef, trx); trx_print(ef, trx, 600);
fputs("Foreign key constraint fails for table ", ef); fputs("Foreign key constraint fails for table ", ef);
ut_print_name(ef, trx, foreign->foreign_table_name); ut_print_name(ef, trx, foreign->foreign_table_name);
...@@ -653,7 +653,7 @@ row_ins_foreign_report_add_err( ...@@ -653,7 +653,7 @@ row_ins_foreign_report_add_err(
rewind(ef); rewind(ef);
ut_print_timestamp(ef); ut_print_timestamp(ef);
fputs(" Transaction:\n", ef); fputs(" Transaction:\n", ef);
trx_print(ef, trx); trx_print(ef, trx, 600);
fputs("Foreign key constraint fails for table ", ef); fputs("Foreign key constraint fails for table ", ef);
ut_print_name(ef, trx, foreign->foreign_table_name); ut_print_name(ef, trx, foreign->foreign_table_name);
fputs(":\n", ef); fputs(":\n", ef);
...@@ -1228,7 +1228,7 @@ row_ins_check_foreign_constraint( ...@@ -1228,7 +1228,7 @@ row_ins_check_foreign_constraint(
rewind(ef); rewind(ef);
ut_print_timestamp(ef); ut_print_timestamp(ef);
fputs(" Transaction:\n", ef); fputs(" Transaction:\n", ef);
trx_print(ef, trx); trx_print(ef, trx, 600);
fputs("Foreign key constraint fails for table ", ef); fputs("Foreign key constraint fails for table ", ef);
ut_print_name(ef, trx, foreign->foreign_table_name); ut_print_name(ef, trx, foreign->foreign_table_name);
fputs(":\n", ef); fputs(":\n", ef);
......
...@@ -2685,7 +2685,7 @@ row_sel_get_clust_rec_for_mysql( ...@@ -2685,7 +2685,7 @@ row_sel_get_clust_rec_for_mysql(
"InnoDB: clust index record ", stderr); "InnoDB: clust index record ", stderr);
rec_print(stderr, clust_rec, clust_index); rec_print(stderr, clust_rec, clust_index);
putc('\n', stderr); putc('\n', stderr);
trx_print(stderr, trx); trx_print(stderr, trx, 600);
fputs("\n" fputs("\n"
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr);
...@@ -3128,7 +3128,7 @@ row_search_for_mysql( ...@@ -3128,7 +3128,7 @@ row_search_for_mysql(
"InnoDB: Error: MySQL is trying to perform a SELECT\n" "InnoDB: Error: MySQL is trying to perform a SELECT\n"
"InnoDB: but it has not locked any tables in ::external_lock()!\n", "InnoDB: but it has not locked any tables in ::external_lock()!\n",
stderr); stderr);
trx_print(stderr, trx); trx_print(stderr, trx, 600);
fputc('\n', stderr); fputc('\n', stderr);
} }
...@@ -3455,7 +3455,7 @@ row_search_for_mysql( ...@@ -3455,7 +3455,7 @@ row_search_for_mysql(
fputs( fputs(
"InnoDB: Error: MySQL is trying to perform a consistent read\n" "InnoDB: Error: MySQL is trying to perform a consistent read\n"
"InnoDB: but the read view is not assigned!\n", stderr); "InnoDB: but the read view is not assigned!\n", stderr);
trx_print(stderr, trx); trx_print(stderr, trx, 600);
fputc('\n', stderr); fputc('\n', stderr);
ut_a(0); ut_a(0);
} }
......
...@@ -431,7 +431,7 @@ row_undo_mod_del_unmark_sec_and_undo_update( ...@@ -431,7 +431,7 @@ row_undo_mod_del_unmark_sec_and_undo_update(
"InnoDB: record ", stderr); "InnoDB: record ", stderr);
rec_print(stderr, btr_pcur_get_rec(&pcur), index); rec_print(stderr, btr_pcur_get_rec(&pcur), index);
putc('\n', stderr); putc('\n', stderr);
trx_print(stderr, trx); trx_print(stderr, trx, 0);
fputs("\n" fputs("\n"
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr);
} else { } else {
......
...@@ -1279,7 +1279,7 @@ row_upd_sec_index_entry( ...@@ -1279,7 +1279,7 @@ row_upd_sec_index_entry(
rec_print(stderr, rec, index); rec_print(stderr, rec, index);
putc('\n', stderr); putc('\n', stderr);
trx_print(stderr, trx); trx_print(stderr, trx, 0);
fputs("\n" fputs("\n"
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr);
......
...@@ -999,7 +999,7 @@ srv_conc_enter_innodb( ...@@ -999,7 +999,7 @@ srv_conc_enter_innodb(
fputs( fputs(
" InnoDB: Error: trying to declare trx to enter InnoDB, but\n" " InnoDB: Error: trying to declare trx to enter InnoDB, but\n"
"InnoDB: it already is declared.\n", stderr); "InnoDB: it already is declared.\n", stderr);
trx_print(stderr, trx); trx_print(stderr, trx, 0);
putc('\n', stderr); putc('\n', stderr);
os_fast_mutex_unlock(&srv_conc_mutex); os_fast_mutex_unlock(&srv_conc_mutex);
......
...@@ -31,7 +31,8 @@ copy MUST be equal to the one in mysql/sql/ha_innodb.cc ! */ ...@@ -31,7 +31,8 @@ copy MUST be equal to the one in mysql/sql/ha_innodb.cc ! */
void innobase_mysql_print_thd( void innobase_mysql_print_thd(
FILE* f, FILE* f,
void* thd); void* thd,
uint max_query_len);
/* Dummy session used currently in MySQL interface */ /* Dummy session used currently in MySQL interface */
sess_t* trx_dummy_sess = NULL; sess_t* trx_dummy_sess = NULL;
...@@ -262,7 +263,7 @@ trx_free( ...@@ -262,7 +263,7 @@ trx_free(
fputs( fputs(
" InnoDB: Error: Freeing a trx which is declared to be processing\n" " InnoDB: Error: Freeing a trx which is declared to be processing\n"
"InnoDB: inside InnoDB.\n", stderr); "InnoDB: inside InnoDB.\n", stderr);
trx_print(stderr, trx); trx_print(stderr, trx, 600);
putc('\n', stderr); putc('\n', stderr);
} }
...@@ -277,7 +278,7 @@ trx_free( ...@@ -277,7 +278,7 @@ trx_free(
(ulong)trx->n_mysql_tables_in_use, (ulong)trx->n_mysql_tables_in_use,
(ulong)trx->mysql_n_tables_locked); (ulong)trx->mysql_n_tables_locked);
trx_print(stderr, trx); trx_print(stderr, trx, 600);
ut_print_buf(stderr, (byte*)trx, sizeof(trx_t)); ut_print_buf(stderr, (byte*)trx, sizeof(trx_t));
} }
...@@ -1651,16 +1652,18 @@ trx_mark_sql_stat_end( ...@@ -1651,16 +1652,18 @@ trx_mark_sql_stat_end(
} }
/************************************************************************** /**************************************************************************
Prints info about a transaction to the standard output. The caller must Prints info about a transaction to the given file. The caller must own the
own the kernel mutex and must have called kernel mutex and must have called
innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL or innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL
InnoDB cannot meanwhile change the info printed here. */ or InnoDB cannot meanwhile change the info printed here. */
void void
trx_print( trx_print(
/*======*/ /*======*/
FILE* f, /* in: output stream */ FILE* f, /* in: output stream */
trx_t* trx) /* in: transaction */ trx_t* trx, /* in: transaction */
uint max_query_len) /* in: max query length to print, or 0 to
use the default max length */
{ {
ibool newline; ibool newline;
...@@ -1755,7 +1758,7 @@ trx_print( ...@@ -1755,7 +1758,7 @@ trx_print(
} }
if (trx->mysql_thd != NULL) { if (trx->mysql_thd != NULL) {
innobase_mysql_print_thd(f, trx->mysql_thd); innobase_mysql_print_thd(f, trx->mysql_thd, max_query_len);
} }
} }
......
...@@ -550,19 +550,20 @@ innobase_mysql_end_print_arbitrary_thd(void) ...@@ -550,19 +550,20 @@ innobase_mysql_end_print_arbitrary_thd(void)
} }
/***************************************************************** /*****************************************************************
Prints info of a THD object (== user session thread) to the Prints info of a THD object (== user session thread) to the given file.
standard output. NOTE that /mysql/innobase/trx/trx0trx.c must contain NOTE that /mysql/innobase/trx/trx0trx.c must contain the prototype for
the prototype for this function! */ this function! */
extern "C" extern "C"
void void
innobase_mysql_print_thd( innobase_mysql_print_thd(
/*=====================*/ /*=====================*/
FILE* f, /* in: output stream */ FILE* f, /* in: output stream */
void* input_thd)/* in: pointer to a MySQL THD object */ void* input_thd, /* in: pointer to a MySQL THD object */
uint max_query_len) /* in: max query length to print, or 0 to
use the default max length */
{ {
const THD* thd; const THD* thd;
const char* s; const char* s;
char buf[301];
thd = (const THD*) input_thd; thd = (const THD*) input_thd;
...@@ -589,25 +590,47 @@ innobase_mysql_print_thd( ...@@ -589,25 +590,47 @@ innobase_mysql_print_thd(
} }
if ((s = thd->query)) { if ((s = thd->query)) {
/* determine the length of the query string */ /* 3100 is chosen because currently 3000 is the maximum
uint32 i, len; max_query_len we ever give this. */
char buf[3100];
uint len;
/* If buf is too small, we dynamically allocate storage
in this. */
char* dyn_str = NULL;
/* Points to buf or dyn_str. */
char* str = buf;
if (max_query_len == 0)
{
/* ADDITIONAL SAFETY: the default is to print at
most 300 chars to reduce the probability of a
seg fault if there is a race in
thd->query_length in MySQL; after May 14, 2004
probably no race any more, but better be
safe */
max_query_len = 300;
}
len = thd->query_length; len = min(thd->query_length, max_query_len);
if (len > 300) { if (len > (sizeof(buf) - 1))
len = 300; /* ADDITIONAL SAFETY: print at most {
300 chars to reduce the probability of dyn_str = my_malloc(len + 1, MYF(0));
a seg fault if there is a race in str = dyn_str;
thd->query_length in MySQL; after
May 14, 2004 probably no race any more,
but better be safe */
} }
/* Use strmake to reduce the timeframe /* Use strmake to reduce the timeframe for a race,
for a race, compared to fwrite() */ compared to fwrite() */
i= (uint) (strmake(buf, s, len) - buf); len = (uint) (strmake(str, s, len) - str);
putc('\n', f); putc('\n', f);
fwrite(buf, 1, i, f); fwrite(str, 1, len, f);
if (dyn_str)
{
my_free(dyn_str, MYF(0));
}
} }
putc('\n', f); putc('\n', f);
......
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