Commit c0e8c9a1 authored by unknown's avatar unknown

Many files:

  Merge InnoDB-3.23.52b


innobase/btr/btr0btr.c:
  Merge InnoDB-3.23.52b
innobase/btr/btr0cur.c:
  Merge InnoDB-3.23.52b
innobase/btr/btr0sea.c:
  Merge InnoDB-3.23.52b
innobase/buf/buf0buf.c:
  Merge InnoDB-3.23.52b
innobase/ha/ha0ha.c:
  Merge InnoDB-3.23.52b
innobase/ibuf/ibuf0ibuf.c:
  Merge InnoDB-3.23.52b
innobase/include/btr0cur.h:
  Merge InnoDB-3.23.52b
innobase/include/buf0buf.h:
  Merge InnoDB-3.23.52b
innobase/include/ha0ha.h:
  Merge InnoDB-3.23.52b
innobase/include/ibuf0ibuf.h:
  Merge InnoDB-3.23.52b
innobase/include/lock0lock.h:
  Merge InnoDB-3.23.52b
innobase/include/log0log.h:
  Merge InnoDB-3.23.52b
innobase/include/os0file.h:
  Merge InnoDB-3.23.52b
innobase/include/rem0rec.ic:
  Merge InnoDB-3.23.52b
innobase/include/srv0srv.h:
  Merge InnoDB-3.23.52b
innobase/include/sync0arr.h:
  Merge InnoDB-3.23.52b
innobase/include/sync0sync.h:
  Merge InnoDB-3.23.52b
innobase/include/trx0trx.h:
  Merge InnoDB-3.23.52b
innobase/lock/lock0lock.c:
  Merge InnoDB-3.23.52b
innobase/log/log0log.c:
  Merge InnoDB-3.23.52b
innobase/os/os0file.c:
  Merge InnoDB-3.23.52b
innobase/row/row0mysql.c:
  Merge InnoDB-3.23.52b
innobase/row/row0umod.c:
  Merge InnoDB-3.23.52b
innobase/row/row0upd.c:
  Merge InnoDB-3.23.52b
innobase/srv/srv0srv.c:
  Merge InnoDB-3.23.52b
innobase/srv/srv0start.c:
  Merge InnoDB-3.23.52b
innobase/sync/sync0arr.c:
  Merge InnoDB-3.23.52b
innobase/sync/sync0sync.c:
  Merge InnoDB-3.23.52b
innobase/trx/trx0trx.c:
  Merge InnoDB-3.23.52b
sql/ha_innobase.h:
  Merge InnoDB-3.23.52b
sql/ha_innobase.cc:
  Merge InnoDB-3.23.52b
sql/sql_lex.h:
  Merge InnoDB-3.23.52b
sql/mysqld.cc:
  Merge InnoDB-3.23.52b
sql/sql_parse.cc:
  Merge InnoDB-3.23.52b
sql/sql_yacc.yy:
  Merge InnoDB-3.23.52b
parent 9eef017c
......@@ -2076,8 +2076,7 @@ btr_discard_page(
btr_search_drop_page_hash_index(page);
if ((left_page_no == FIL_NULL)
&& (btr_page_get_level(page, mtr) > 0)) {
if (left_page_no == FIL_NULL && btr_page_get_level(page, mtr) > 0) {
/* We have to mark the leftmost node pointer on the right
side page as the predefined minimum record */
......
......@@ -44,6 +44,8 @@ ulint btr_cur_rnd = 0;
ulint btr_cur_n_non_sea = 0;
ulint btr_cur_n_sea = 0;
ulint btr_cur_n_non_sea_old = 0;
ulint btr_cur_n_sea_old = 0;
/* In the optimistic insert, if the insert does not fit, but this much space
can be released by page reorganize, then it is reorganized */
......
......@@ -451,7 +451,9 @@ btr_search_info_update_slow(
rw_lock_x_unlock(&btr_search_latch);
}
if (build_index) {
if (build_index) {
ut_a(block->n_fields + block->n_bytes > 0);
btr_search_build_page_hash_index(block->frame,
block->n_fields,
block->n_bytes,
......@@ -676,6 +678,9 @@ btr_search_guess_on_hash(
rw_lock_s_lock(&btr_search_latch);
}
ut_a(btr_search_latch.writer != RW_LOCK_EX);
ut_a(btr_search_latch.reader_count > 0);
rec = ha_search_and_get_data(btr_search_sys->hash_index, fold);
if (!rec) {
......@@ -902,7 +907,7 @@ btr_search_drop_page_hash_index(
fold = rec_fold(rec, n_fields, n_bytes, tree_id);
if ((fold == prev_fold) && (prev_fold != 0)) {
if (fold == prev_fold && prev_fold != 0) {
goto next_rec;
}
......@@ -914,6 +919,7 @@ btr_search_drop_page_hash_index(
n_cached++;
next_rec:
rec = page_rec_get_next(rec);
prev_fold = fold;
}
rw_lock_x_lock(&btr_search_latch);
......@@ -954,7 +960,7 @@ btr_search_drop_page_hash_when_freed(
mtr_start(&mtr);
/* We assume that if the caller has a latch on the page,
then the caller has already drooped the hash index for the page,
then the caller has already dropped the hash index for the page,
and we never get here. Therefore we can acquire the s-latch to
the page without fearing a deadlock. */
......@@ -1177,6 +1183,8 @@ btr_search_move_or_delete_hash_entries(
rw_lock_s_unlock(&btr_search_latch);
ut_a(n_fields + n_bytes > 0);
btr_search_build_page_hash_index(new_page, n_fields, n_bytes,
side);
ut_a(n_fields == block->curr_n_fields);
......@@ -1217,9 +1225,11 @@ btr_search_update_hash_on_delete(
return;
}
ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
table = btr_search_sys->hash_index;
tree_id = ((cursor->index)->tree)->id;
tree_id = cursor->index->tree->id;
fold = rec_fold(rec, block->curr_n_fields, block->curr_n_bytes,
tree_id);
......@@ -1336,7 +1346,6 @@ btr_search_update_hash_on_insert(
if (rec != page_get_infimum_rec(page)) {
fold = rec_fold(rec, n_fields, n_bytes, tree_id);
} else {
if (side == BTR_SEARCH_LEFT_SIDE) {
......@@ -1421,7 +1430,7 @@ btr_search_print_info(void)
rw_lock_x_lock(&btr_search_latch);
ha_print_info(btr_search_sys->hash_index);
/* ha_print_info(btr_search_sys->hash_index); */
rw_lock_x_unlock(&btr_search_latch);
}
......@@ -1487,11 +1496,71 @@ btr_search_validate(void)
/*=====================*/
/* out: TRUE if ok */
{
buf_block_t* block;
page_t* page;
ha_node_t* node;
ulint n_page_dumps = 0;
ibool ok = TRUE;
ulint i;
char rec_str[500];
rw_lock_x_lock(&btr_search_latch);
for (i = 0; i < hash_get_n_cells(btr_search_sys->hash_index); i++) {
node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
while (node != NULL) {
block = buf_block_align(node->data);
page = buf_frame_align(node->data);
if (!block->is_hashed
|| node->fold != rec_fold((rec_t*)(node->data),
block->curr_n_fields,
block->curr_n_bytes,
btr_page_get_index_id(page))) {
ok = FALSE;
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Error in an adaptive hash index pointer to page %lu\n"
"ptr mem address %lu index id %lu %lu, node fold %lu, rec fold %lu\n",
buf_frame_get_page_no(page),
(ulint)(node->data),
ut_dulint_get_high(btr_page_get_index_id(page)),
ut_dulint_get_low(btr_page_get_index_id(page)),
node->fold, rec_fold((rec_t*)(node->data),
block->curr_n_fields,
block->curr_n_bytes,
btr_page_get_index_id(page)));
rec_sprintf(rec_str, 450, (rec_t*)(node->data));
fprintf(stderr,
"InnoDB: Record %s\n"
"InnoDB: on that page.", rec_str);
fprintf(stderr,
"Page mem address %lu, is hashed %lu, n fields %lu, n bytes %lu\n"
"side %lu\n",
(ulint)page, block->is_hashed, block->curr_n_fields,
block->curr_n_bytes, block->curr_side);
if (n_page_dumps < 20) {
buf_page_print(page);
n_page_dumps++;
}
}
node = node->next;
}
}
ut_a(ha_validate(btr_search_sys->hash_index));
if (!ha_validate(btr_search_sys->hash_index)) {
ok = FALSE;
}
rw_lock_x_unlock(&btr_search_latch);
return(TRUE);
return(ok);
}
......@@ -1798,8 +1798,10 @@ buf_get_n_pending_ios(void)
Prints info of the buffer i/o. */
void
buf_print_io(void)
/*==============*/
buf_print_io(
/*=========*/
char* buf, /* in/out: buffer where to print */
char* buf_end)/* in: buffer end */
{
time_t current_time;
double time_elapsed;
......@@ -1807,19 +1809,28 @@ buf_print_io(void)
ut_ad(buf_pool);
if (buf_end - buf < 400) {
return;
}
size = buf_pool_get_curr_size() / UNIV_PAGE_SIZE;
mutex_enter(&(buf_pool->mutex));
printf("Free list length %lu \n", UT_LIST_GET_LEN(buf_pool->free));
printf("LRU list length %lu \n", UT_LIST_GET_LEN(buf_pool->LRU));
printf("Flush list length %lu \n",
buf += sprintf(buf,
"Free list length %lu \n", UT_LIST_GET_LEN(buf_pool->free));
buf += sprintf(buf,
"LRU list length %lu \n", UT_LIST_GET_LEN(buf_pool->LRU));
buf += sprintf(buf,
"Flush list length %lu \n",
UT_LIST_GET_LEN(buf_pool->flush_list));
printf("Buffer pool size %lu\n", size);
buf += sprintf(buf, "Buffer pool size %lu\n", size);
printf("Pending reads %lu \n", buf_pool->n_pend_reads);
buf += sprintf(buf, "Pending reads %lu \n", buf_pool->n_pend_reads);
printf("Pending writes: LRU %lu, flush list %lu, single page %lu\n",
buf += sprintf(buf,
"Pending writes: LRU %lu, flush list %lu, single page %lu\n",
buf_pool->n_flush[BUF_FLUSH_LRU],
buf_pool->n_flush[BUF_FLUSH_LIST],
buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
......@@ -1829,10 +1840,10 @@ buf_print_io(void)
buf_pool->last_printout_time = current_time;
printf("Pages read %lu, created %lu, written %lu\n",
buf += sprintf(buf, "Pages read %lu, created %lu, written %lu\n",
buf_pool->n_pages_read, buf_pool->n_pages_created,
buf_pool->n_pages_written);
printf("%.2f reads/s, %.2f creates/s, %.2f writes/s\n",
buf += sprintf(buf, "%.2f reads/s, %.2f creates/s, %.2f writes/s\n",
(buf_pool->n_pages_read - buf_pool->n_pages_read_old)
/ time_elapsed,
(buf_pool->n_pages_created - buf_pool->n_pages_created_old)
......@@ -1841,13 +1852,14 @@ buf_print_io(void)
/ time_elapsed);
if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) {
printf("Buffer pool hit rate %lu / 1000\n",
buf += sprintf(buf, "Buffer pool hit rate %lu / 1000\n",
1000
- ((1000 *
(buf_pool->n_pages_read - buf_pool->n_pages_read_old))
/ (buf_pool->n_page_gets - buf_pool->n_page_gets_old)));
} else {
printf("No buffer pool activity since the last printout\n");
buf += sprintf(buf,
"No buffer pool activity since the last printout\n");
}
buf_pool->n_page_gets_old = buf_pool->n_page_gets;
......
......@@ -194,7 +194,7 @@ ha_delete(
node = ha_search_with_data(table, fold, data);
ut_ad(node);
ut_a(node);
ha_delete_hash_node(table, node);
}
......@@ -232,6 +232,16 @@ ha_remove_all_nodes_to_page(
node = ha_chain_get_next(table, node);
}
}
/* Check that all nodes really got deleted */
node = ha_chain_get_first(table, fold);
while (node) {
ut_a(buf_frame_align(ha_node_get_data(node)) != page);
node = ha_chain_get_next(table, node);
}
}
/*****************************************************************
......@@ -245,6 +255,7 @@ ha_validate(
{
hash_cell_t* cell;
ha_node_t* node;
ibool ok = TRUE;
ulint i;
for (i = 0; i < hash_get_n_cells(table); i++) {
......@@ -254,13 +265,21 @@ ha_validate(
node = cell->node;
while (node) {
ut_a(hash_calc_hash(node->fold, table) == i);
if (hash_calc_hash(node->fold, table) != i) {
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: Error: hash table node fold value %lu does not\n"
"InnoDB: match with the cell number %lu.\n",
node->fold, i);
ok = FALSE;
}
node = node->next;
}
}
return(TRUE);
return(ok);
}
/*****************************************************************
......@@ -269,16 +288,22 @@ Prints info of a hash table. */
void
ha_print_info(
/*==========*/
char* buf, /* in/out: buffer where to print */
char* buf_end,/* in: buffer end */
hash_table_t* table) /* in: hash table */
{
hash_cell_t* cell;
ha_node_t* node;
/* ha_node_t* node; */
ulint nodes = 0;
ulint cells = 0;
ulint len = 0;
ulint max_len = 0;
ulint i;
if (buf_end - buf < 200) {
return;
}
for (i = 0; i < hash_get_n_cells(table); i++) {
cell = hash_get_nth_cell(table, i);
......@@ -286,7 +311,7 @@ ha_print_info(
if (cell->node) {
cells++;
/*
len = 0;
node = cell->node;
......@@ -306,12 +331,10 @@ ha_print_info(
if (len > max_len) {
max_len = len;
}
*/
}
}
printf("Hash table size %lu, used cells %lu, nodes %lu\n",
hash_get_n_cells(table), cells, nodes);
printf("max chain length %lu\n", max_len);
ut_a(ha_validate(table));
buf += sprintf(buf, "Hash table size %lu, used cells %lu\n",
hash_get_n_cells(table), cells);
}
......@@ -2703,22 +2703,30 @@ ibuf_validate_low(void)
Prints info of ibuf. */
void
ibuf_print(void)
/*============*/
ibuf_print(
/*=======*/
char* buf, /* in/out: buffer where to print */
char* buf_end)/* in: buffer end */
{
ibuf_data_t* data;
#ifdef UNIV_IBUF_DEBUG
ulint i;
#endif
if (buf_end - buf < 500) {
return;
}
mutex_enter(&ibuf_mutex);
data = UT_LIST_GET_FIRST(ibuf->data_list);
while (data) {
printf(
buf += sprintf(buf,
"Ibuf for space %lu: size %lu, free list len %lu, seg size %lu,\n",
data->space, data->size, data->free_list_len, data->seg_size);
printf("%lu inserts, %lu merged recs, %lu merges\n",
buf += sprintf(buf,
"%lu inserts, %lu merged recs, %lu merges\n",
data->n_inserts, data->n_merged_recs, data->n_merges);
#ifdef UNIV_IBUF_DEBUG
for (i = 0; i < IBUF_COUNT_N_PAGES; i++) {
......
......@@ -710,6 +710,8 @@ allowed to free an inherited external field. */
extern ulint btr_cur_n_non_sea;
extern ulint btr_cur_n_sea;
extern ulint btr_cur_n_non_sea_old;
extern ulint btr_cur_n_sea_old;
#ifndef UNIV_NONINL
#include "btr0cur.ic"
......
......@@ -448,7 +448,7 @@ Prints info of the buffer pool data structure. */
void
buf_print(void);
/*===========*/
/*============*/
/*************************************************************************
Returns the number of pending buf pool ios. */
......@@ -459,8 +459,10 @@ buf_get_n_pending_ios(void);
Prints info of the buffer i/o. */
void
buf_print_io(void);
/*==============*/
buf_print_io(
/*=========*/
char* buf, /* in/out: buffer where to print */
char* buf_end);/* in: buffer end */
/*************************************************************************
Checks that all file pages in the buffer are in a replaceable state. */
......
......@@ -127,6 +127,8 @@ Prints info of a hash table. */
void
ha_print_info(
/*==========*/
char* buf, /* in/out: buffer where to print */
char* buf_end,/* in: buffer end */
hash_table_t* table); /* in: hash table */
......
......@@ -269,8 +269,10 @@ ibuf_count_get(
Prints info of ibuf. */
void
ibuf_print(void);
/*============*/
ibuf_print(
/*=======*/
char* buf, /* in/out: buffer where to print */
char* buf_end);/* in: buffer end */
#define IBUF_HEADER_PAGE_NO FSP_IBUF_HEADER_PAGE_NO
#define IBUF_TREE_ROOT_PAGE_NO FSP_IBUF_TREE_ROOT_PAGE_NO
......
......@@ -460,6 +460,8 @@ Prints info of a table lock. */
void
lock_table_print(
/*=============*/
char* buf, /* in/out: buffer where to print, must be at least
500 bytes */
lock_t* lock); /* in: table type lock */
/*************************************************************************
Prints info of a record lock. */
......@@ -467,13 +469,17 @@ Prints info of a record lock. */
void
lock_rec_print(
/*===========*/
char* buf, /* in/out: buffer where to print, must be at least
500 bytes */
lock_t* lock); /* in: record type lock */
/*************************************************************************
Prints info of locks for all transactions. */
void
lock_print_info(void);
/*=================*/
lock_print_info(
/*============*/
char* buf, /* in/out: buffer where to print */
char* buf_end);/* in: buffer end */
/*************************************************************************
Validates the lock queue on a table. */
......
......@@ -493,8 +493,10 @@ log_block_convert_lsn_to_no(
Prints info of the log. */
void
log_print(void);
/*===========*/
log_print(
/*======*/
char* buf, /* in/out: buffer where to print */
char* buf_end);/* in: buffer end */
extern log_t* log_sys;
......
......@@ -403,8 +403,10 @@ os_aio_validate(void);
Prints info of the aio arrays. */
void
os_aio_print(void);
/*==============*/
os_aio_print(
/*=========*/
char* buf, /* in/out: buffer where to print */
char* buf_end);/* in: buffer end */
/**************************************************************************
Checks that all slots in the system have been freed, that is, there are
no pending io operations. */
......
......@@ -970,8 +970,6 @@ rec_fold(
ut_ad(n_fields <= rec_get_n_fields(rec));
ut_ad((n_fields < rec_get_n_fields(rec)) || (n_bytes == 0));
ut_ad(n_fields + n_bytes > 0);
/* Only the page supremum and infimum records have 1 field: */
ut_ad(rec_get_n_fields(rec) > 1);
n_fields_rec = rec_get_n_fields(rec);
......
......@@ -356,6 +356,14 @@ srv_error_monitor_thread(
/* out: a dummy parameter */
void* arg); /* in: a dummy parameter required by
os_thread_create */
/**********************************************************************
Sprintfs to a buffer the output of the InnoDB Monitor. */
void
srv_sprintf_innodb_monitor(
/*=======================*/
char* buf, /* in/out: buffer which must be at least 4 kB */
ulint len); /* in: length of the buffer */
/* Types for the threads existing in the system. Threads of types 4 - 9
......
......@@ -114,6 +114,8 @@ Prints info of the wait array. */
void
sync_array_print_info(
/*==================*/
char* buf, /* in/out: buffer where to print */
char* buf_end,/* in: buffer end */
sync_array_t* arr); /* in: wait array */
......
......@@ -117,14 +117,18 @@ FUNCTION PROTOTYPES FOR DEBUGGING */
Prints wait info of the sync system. */
void
sync_print_wait_info(void);
/*======================*/
sync_print_wait_info(
/*=================*/
char* buf, /* in/out: buffer where to print */
char* buf_end); /* in: buffer end */
/***********************************************************************
Prints info of the sync system. */
void
sync_print(void);
/*============*/
sync_print(
/*=======*/
char* buf, /* in/out: buffer where to print */
char* buf_end); /* in: buffer end */
/**********************************************************************
Checks that the mutex has been initialized. */
......
......@@ -261,7 +261,9 @@ own the kernel mutex. */
void
trx_print(
/*======*/
trx_t* trx); /* in: transaction */
char* buf, /* in/out: buffer where to print, must be at least
500 bytes */
trx_t* trx); /* in: transaction */
/* Signal to a transaction */
......
......@@ -3326,34 +3326,37 @@ Prints info of a table lock. */
void
lock_table_print(
/*=============*/
char* buf, /* in/out: buffer where to print, must be at least
500 bytes */
lock_t* lock) /* in: table type lock */
{
ut_ad(mutex_own(&kernel_mutex));
ut_a(lock_get_type(lock) == LOCK_TABLE);
printf("TABLE LOCK table %s trx id %lu %lu",
buf += sprintf(buf, "TABLE LOCK table %s trx id %lu %lu",
lock->un_member.tab_lock.table->name,
(lock->trx)->id.high, (lock->trx)->id.low);
if (lock_get_mode(lock) == LOCK_S) {
printf(" lock mode S");
buf += sprintf(buf, " lock mode S");
} else if (lock_get_mode(lock) == LOCK_X) {
printf(" lock_mode X");
buf += sprintf(buf, " lock_mode X");
} else if (lock_get_mode(lock) == LOCK_IS) {
printf(" lock_mode IS");
buf += sprintf(buf, " lock_mode IS");
} else if (lock_get_mode(lock) == LOCK_IX) {
printf(" lock_mode IX");
buf += sprintf(buf, " lock_mode IX");
} else if (lock_get_mode(lock) == LOCK_AUTO_INC) {
printf(" lock_mode AUTO-INC");
buf += sprintf(buf, " lock_mode AUTO-INC");
} else {
printf(" unknown lock_mode %lu", lock_get_mode(lock));
buf += sprintf(buf,
" unknown lock_mode %lu", lock_get_mode(lock));
}
if (lock_get_wait(lock)) {
printf(" waiting");
buf += sprintf(buf, " waiting");
}
printf("\n");
buf += sprintf(buf, "\n");
}
/*************************************************************************
......@@ -3362,6 +3365,8 @@ Prints info of a record lock. */
void
lock_rec_print(
/*===========*/
char* buf, /* in/out: buffer where to print, must be at least
500 bytes */
lock_t* lock) /* in: record type lock */
{
page_t* page;
......@@ -3369,8 +3374,7 @@ lock_rec_print(
ulint page_no;
ulint i;
ulint count = 0;
ulint len;
char buf[200];
char* buf_start = buf;
mtr_t mtr;
ut_ad(mutex_own(&kernel_mutex));
......@@ -3379,32 +3383,32 @@ lock_rec_print(
space = lock->un_member.rec_lock.space;
page_no = lock->un_member.rec_lock.page_no;
printf("RECORD LOCKS space id %lu page no %lu n bits %lu",
buf += sprintf(buf, "RECORD LOCKS space id %lu page no %lu n bits %lu",
space, page_no, lock_rec_get_n_bits(lock));
printf(" table %s index %s trx id %lu %lu",
buf += sprintf(buf, " table %s index %s trx id %lu %lu",
lock->index->table->name, lock->index->name,
(lock->trx)->id.high, (lock->trx)->id.low);
if (lock_get_mode(lock) == LOCK_S) {
printf(" lock mode S");
buf += sprintf(buf, " lock mode S");
} else if (lock_get_mode(lock) == LOCK_X) {
printf(" lock_mode X");
buf += sprintf(buf, " lock_mode X");
} else {
ut_error;
}
if (lock_rec_get_gap(lock)) {
printf(" gap type lock");
buf += sprintf(buf, " gap type lock");
}
if (lock_get_wait(lock)) {
printf(" waiting");
buf += sprintf(buf, " waiting");
}
mtr_start(&mtr);
printf("\n");
buf += sprintf(buf, "\n");
/* If the page is not in the buffer pool, we cannot load it
because we have the kernel mutex and ibuf operations would
......@@ -3423,28 +3427,28 @@ lock_rec_print(
for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
if (buf - buf_start > 300) {
buf += sprintf(buf,
"Suppressing further record lock prints for this page\n");
return;
}
if (lock_rec_get_nth_bit(lock, i)) {
printf("Record lock, heap no %lu ", i);
buf += sprintf(buf, "Record lock, heap no %lu ", i);
if (page) {
len = rec_sprintf(buf, 190,
buf += rec_sprintf(buf, 120,
page_find_rec_with_heap_no(page, i));
buf[len] = '\0';
printf("%s", buf);
*buf = '\0';
}
printf("\n");
buf += sprintf(buf, "\n");
count++;
}
if (count >= 3) {
printf(
"3 LOCKS PRINTED FOR THIS TRX AND PAGE: SUPPRESSING FURTHER PRINTS\n");
goto end_prints;
}
}
end_prints:
mtr_commit(&mtr);
}
......@@ -3479,8 +3483,10 @@ lock_get_n_rec_locks(void)
Prints info of locks for all transactions. */
void
lock_print_info(void)
/*=================*/
lock_print_info(
/*============*/
char* buf, /* in/out: buffer where to print */
char* buf_end)/* in: buffer end */
{
lock_t* lock;
trx_t* trx;
......@@ -3493,11 +3499,15 @@ lock_print_info(void)
ulint i;
mtr_t mtr;
printf("Trx id counter %lu %lu\n",
if (buf_end - buf < 600) {
return;
}
buf += sprintf(buf, "Trx id counter %lu %lu\n",
ut_dulint_get_high(trx_sys->max_trx_id),
ut_dulint_get_low(trx_sys->max_trx_id));
printf(
buf += sprintf(buf,
"Purge done for trx's n:o < %lu %lu undo n:o < %lu %lu\n",
ut_dulint_get_high(purge_sys->purge_trx_no),
ut_dulint_get_low(purge_sys->purge_trx_no),
......@@ -3506,7 +3516,8 @@ lock_print_info(void)
lock_mutex_enter_kernel();
printf("Total number of lock structs in row lock hash table %lu\n",
buf += sprintf(buf,
"Total number of lock structs in row lock hash table %lu\n",
lock_get_n_rec_locks());
/* First print info on non-active transactions */
......@@ -3514,9 +3525,15 @@ lock_print_info(void)
trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
while (trx) {
if (buf_end - buf < 600) {
return;
}
if (trx->conc_state == TRX_NOT_STARTED) {
printf("---");
trx_print(trx);
buf += sprintf(buf, "---");
trx_print(buf, trx);
buf += strlen(buf);
}
trx = UT_LIST_GET_NEXT(mysql_trx_list, trx);
......@@ -3545,12 +3562,22 @@ lock_print_info(void)
return;
}
if (buf_end - buf < 600) {
return;
}
if (nth_lock == 0) {
printf("---");
trx_print(trx);
buf += sprintf(buf, "---");
trx_print(buf, trx);
buf += strlen(buf);
if (buf_end - buf < 500) {
return;
}
if (trx->read_view) {
printf(
buf += sprintf(buf,
"Trx read view will not see trx with id >= %lu %lu, sees < %lu %lu\n",
ut_dulint_get_high(trx->read_view->low_limit_id),
ut_dulint_get_low(trx->read_view->low_limit_id),
......@@ -3559,16 +3586,17 @@ lock_print_info(void)
}
if (trx->que_state == TRX_QUE_LOCK_WAIT) {
printf(
buf += sprintf(buf,
"------------------TRX IS WAITING FOR THE LOCK:\n");
if (lock_get_type(trx->wait_lock) == LOCK_REC) {
lock_rec_print(trx->wait_lock);
lock_rec_print(buf, trx->wait_lock);
} else {
lock_table_print(trx->wait_lock);
lock_table_print(buf, trx->wait_lock);
}
printf(
buf += strlen(buf);
buf += sprintf(buf,
"------------------\n");
}
}
......@@ -3597,6 +3625,10 @@ lock_print_info(void)
goto loop;
}
if (buf_end - buf < 500) {
return;
}
if (lock_get_type(lock) == LOCK_REC) {
space = lock->un_member.rec_lock.space;
page_no = lock->un_member.rec_lock.page_no;
......@@ -3617,19 +3649,21 @@ lock_print_info(void)
goto loop;
}
lock_rec_print(lock);
lock_rec_print(buf, lock);
} else {
ut_ad(lock_get_type(lock) == LOCK_TABLE);
lock_table_print(lock);
lock_table_print(buf, lock);
}
buf += strlen(buf);
load_page_first = TRUE;
nth_lock++;
if (nth_lock >= 10) {
printf(
buf += sprintf(buf,
"10 LOCKS PRINTED FOR THIS TRX: SUPPRESSING FURTHER PRINTS\n");
nth_trx++;
......
......@@ -3081,15 +3081,22 @@ log_check_log_recs(
Prints info of the log. */
void
log_print(void)
/*===========*/
log_print(
/*======*/
char* buf, /* in/out: buffer where to print */
char* buf_end)/* in: buffer end */
{
double time_elapsed;
time_t current_time;
if (buf_end - buf < 300) {
return;
}
mutex_enter(&(log_sys->mutex));
printf("Log sequence number %lu %lu\n"
buf += sprintf(buf, "Log sequence number %lu %lu\n"
"Log flushed up to %lu %lu\n"
"Last checkpoint at %lu %lu\n",
ut_dulint_get_high(log_sys->lsn),
......@@ -3103,7 +3110,7 @@ log_print(void)
time_elapsed = difftime(current_time, log_sys->last_printout_time);
printf(
buf += sprintf(buf,
"%lu pending log writes, %lu pending chkp writes\n"
"%lu log i/o's done, %.2f log i/o's/second\n",
log_sys->n_pending_writes,
......
......@@ -1094,7 +1094,9 @@ os_file_write(
fprintf(stderr,
" InnoDB: Error: File pointer positioning to file %s failed at\n"
"InnoDB: offset %lu %lu. Operating system error number %lu.\n",
"InnoDB: offset %lu %lu. Operating system error number %lu.\n"
"InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n"
"InnoDB: what the error number means.\n",
name, offset_high, offset,
(ulint)GetLastError());
......@@ -1125,8 +1127,10 @@ os_file_write(
" InnoDB: Error: Write to file %s failed at offset %lu %lu.\n"
"InnoDB: %lu bytes should have been written, only %lu were written.\n"
"InnoDB: Operating system error number %lu.\n"
"InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n"
"InnoDB: what the error number means.\n"
"InnoDB: Check that your OS and file system support files of this size.\n"
"InnoDB: Check also the disk is not full or a disk quota exceeded.\n",
"InnoDB: Check also that the disk is not full or a disk quota exceeded.\n",
name, offset_high, offset, n, len,
(ulint)GetLastError());
......@@ -1152,8 +1156,10 @@ os_file_write(
" InnoDB: Error: Write to file %s failed at offset %lu %lu.\n"
"InnoDB: %lu bytes should have been written, only %lu were written.\n"
"InnoDB: Operating system error number %lu.\n"
"InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n"
"InnoDB: what the error number means or use the perror program of MySQL.\n"
"InnoDB: Check that your OS and file system support files of this size.\n"
"InnoDB: Check also the disk is not full or a disk quota exceeded.\n",
"InnoDB: Check also that the disk is not full or a disk quota exceeded.\n",
name, offset_high, offset, n, (ulint)ret,
(ulint)errno);
os_has_said_disk_full = TRUE;
......@@ -1744,7 +1750,6 @@ os_aio(
ut_ad(buf);
ut_ad(n > 0);
ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad((ulint)buf % OS_FILE_LOG_BLOCK_SIZE == 0)
ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad(os_aio_validate());
......@@ -2388,8 +2393,10 @@ os_aio_validate(void)
Prints info of the aio arrays. */
void
os_aio_print(void)
/*==============*/
os_aio_print(
/*=========*/
char* buf, /* in/out: buffer where to print */
char* buf_end)/* in: buffer end */
{
os_aio_array_t* array;
os_aio_slot_t* slot;
......@@ -2399,12 +2406,17 @@ os_aio_print(void)
double avg_bytes_read;
ulint i;
if (buf_end - buf < 1000) {
return;
}
for (i = 0; i < srv_n_file_io_threads; i++) {
printf("I/O thread %lu state: %s\n", i,
buf += sprintf(buf, "I/O thread %lu state: %s\n", i,
srv_io_thread_op_info[i]);
}
printf("Pending normal aio reads:");
buf += sprintf(buf, "Pending normal aio reads:");
array = os_aio_read_array;
loop:
......@@ -2431,12 +2443,12 @@ os_aio_print(void)
ut_a(array->n_reserved == n_reserved);
printf(" %lu", n_reserved);
buf += sprintf(buf, " %lu", n_reserved);
os_mutex_exit(array->mutex);
if (array == os_aio_read_array) {
printf(", aio writes:");
buf += sprintf(buf, ", aio writes:");
array = os_aio_write_array;
......@@ -2444,34 +2456,36 @@ os_aio_print(void)
}
if (array == os_aio_write_array) {
printf(",\n ibuf aio reads:");
buf += sprintf(buf, ",\n ibuf aio reads:");
array = os_aio_ibuf_array;
goto loop;
}
if (array == os_aio_ibuf_array) {
printf(", log i/o's:");
buf += sprintf(buf, ", log i/o's:");
array = os_aio_log_array;
goto loop;
}
if (array == os_aio_log_array) {
printf(", sync i/o's:");
buf += sprintf(buf, ", sync i/o's:");
array = os_aio_sync_array;
goto loop;
}
printf("\n");
buf += sprintf(buf, "\n");
current_time = time(NULL);
time_elapsed = difftime(current_time, os_last_printout);
printf("Pending flushes (fsync) log: %lu; buffer pool: %lu\n",
buf += sprintf(buf,
"Pending flushes (fsync) log: %lu; buffer pool: %lu\n",
fil_n_pending_log_flushes, fil_n_pending_tablespace_flushes);
printf("%lu OS file reads, %lu OS file writes, %lu OS fsyncs\n",
buf += sprintf(buf,
"%lu OS file reads, %lu OS file writes, %lu OS fsyncs\n",
os_n_file_reads, os_n_file_writes, os_n_fsyncs);
if (os_n_file_reads == os_n_file_reads_old) {
......@@ -2481,7 +2495,7 @@ os_aio_print(void)
(os_n_file_reads - os_n_file_reads_old);
}
printf(
buf += sprintf(buf,
"%.2f reads/s, %lu avg bytes/read, %.2f writes/s, %.2f fsyncs/s\n",
(os_n_file_reads - os_n_file_reads_old)
/ time_elapsed,
......
......@@ -2416,6 +2416,14 @@ row_check_table_for_mysql(
index = dict_table_get_next_index(index);
}
/* We validate also the whole adaptive hash index for all tables
at every CHECK TABLE */
if (!btr_search_validate()) {
ret = DB_ERROR;
}
prebuilt->trx->op_info = "";
return(ret);
......
......@@ -437,11 +437,12 @@ row_undo_mod_del_unmark_sec(
rec_sprintf(err_buf, 900, btr_pcur_get_rec(&pcur));
fprintf(stderr, "InnoDB: record %s\n", err_buf);
trx_print(err_buf, thr_get_trx(thr));
fprintf(stderr,
"InnoDB: Make a detailed bug report and send it\n");
"%s\nInnoDB: Make a detailed bug report and send it\n",
err_buf);
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
trx_print(thr_get_trx(thr));
} else {
btr_cur = btr_pcur_get_btr_cur(&pcur);
......
......@@ -1095,11 +1095,12 @@ row_upd_sec_index_entry(
rec_sprintf(err_buf, 900, rec);
fprintf(stderr, "InnoDB: record %s\n", err_buf);
trx_print(err_buf, thr_get_trx(thr));
fprintf(stderr,
"InnoDB: Make a detailed bug report and send it\n");
"%s\nInnoDB: Make a detailed bug report and send it\n",
err_buf);
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
trx_print(thr_get_trx(thr));
} else {
/* Delete mark the old index record; it can already be
delete marked if we return after a lock wait in
......
......@@ -272,6 +272,8 @@ i/o handler thread */
char* srv_io_thread_op_info[SRV_MAX_N_IO_THREADS];
time_t srv_last_monitor_time;
/*
IMPLEMENTATION OF THE SERVER MAIN PROGRAM
=========================================
......@@ -2131,106 +2133,106 @@ srv_release_mysql_thread_if_suspended(
/* not found */
}
/*************************************************************************
A thread which wakes up threads whose lock wait may have lasted too long.
This also prints the info output by various InnoDB monitors. */
/**********************************************************************
Sprintfs to a buffer the output of the InnoDB Monitor. */
#ifndef __WIN__
void*
#else
ulint
#endif
srv_lock_timeout_and_monitor_thread(
/*================================*/
/* out: a dummy parameter */
void* arg) /* in: a dummy parameter required by
os_thread_create */
void
srv_sprintf_innodb_monitor(
/*=======================*/
char* buf, /* in/out: buffer which must be at least 4 kB */
ulint len) /* in: length of the buffer */
{
srv_slot_t* slot;
double time_elapsed;
time_t current_time;
time_t last_monitor_time;
time_t last_table_monitor_time;
ibool some_waits;
double wait_time;
ulint i;
char* buf_end = buf + len - 2000;
double time_elapsed;
time_t current_time;
UT_NOT_USED(arg);
last_monitor_time = time(NULL);
last_table_monitor_time = time(NULL);
loop:
srv_lock_timeout_and_monitor_active = TRUE;
/* When someone is waiting for a lock, we wake up every second
and check if a timeout has passed for a lock wait */
os_thread_sleep(1000000);
current_time = time(NULL);
/* In case mutex_exit is not a memory barrier, it is
theoretically possible some threads are left waiting though
the semaphore is already released. Wake up those threads: */
sync_arr_wake_threads_if_sema_free();
time_elapsed = difftime(current_time, srv_last_monitor_time);
current_time = time(NULL);
srv_last_monitor_time = time(NULL);
time_elapsed = difftime(current_time, last_monitor_time);
if (time_elapsed > 15) {
ut_a(len >= 4096);
if (srv_print_innodb_monitor) {
buf += sprintf(buf, "\n=====================================\n");
last_monitor_time = time(NULL);
ut_sprintf_timestamp(buf);
buf = buf + strlen(buf);
printf("=====================================\n");
ut_print_timestamp(stdout);
printf(" INNODB MONITOR OUTPUT\n"
buf += sprintf(buf, " INNODB MONITOR OUTPUT\n"
"=====================================\n");
printf("----------\n"
buf += sprintf(buf,
"Per second values calculated from the last %lu seconds\n",
(ulint)time_elapsed);
buf += sprintf(buf, "----------\n"
"SEMAPHORES\n"
"----------\n");
sync_print();
printf("------------\n"
sync_print(buf, buf_end);
buf = buf + strlen(buf);
buf += sprintf(buf, "------------\n"
"TRANSACTIONS\n"
"------------\n");
lock_print_info();
printf("--------\n"
lock_print_info(buf, buf_end);
buf = buf + strlen(buf);
buf += sprintf(buf, "--------\n"
"FILE I/O\n"
"--------\n");
os_aio_print();
printf("-------------------------------------\n"
os_aio_print(buf, buf_end);
buf = buf + strlen(buf);
buf += sprintf(buf, "-------------------------------------\n"
"INSERT BUFFER AND ADAPTIVE HASH INDEX\n"
"-------------------------------------\n");
ibuf_print();
printf("Successful hash searches %lu, non-hash searches %lu\n",
btr_cur_n_sea, btr_cur_n_non_sea);
printf("---\n"
ibuf_print(buf, buf_end);
buf = buf + strlen(buf);
ha_print_info(buf, buf_end, btr_search_sys->hash_index);
buf = buf + strlen(buf);
buf += sprintf(buf,
"%.2f hash searches/s, %.2f non-hash searches/s\n",
(btr_cur_n_sea - btr_cur_n_sea_old)
/ time_elapsed,
(btr_cur_n_non_sea - btr_cur_n_non_sea_old)
/ time_elapsed);
btr_cur_n_sea_old = btr_cur_n_sea;
btr_cur_n_non_sea_old = btr_cur_n_non_sea;
buf += sprintf(buf,"---\n"
"LOG\n"
"---\n");
log_print();
printf("----------------------\n"
log_print(buf, buf_end);
buf = buf + strlen(buf);
buf += sprintf(buf, "----------------------\n"
"BUFFER POOL AND MEMORY\n"
"----------------------\n");
printf(
buf += sprintf(buf,
"Total memory allocated %lu; in additional pool allocated %lu\n",
ut_total_allocated_memory,
mem_pool_get_reserved(mem_comm_pool));
buf_print_io();
printf("--------------\n"
buf_print_io(buf, buf_end);
buf = buf + strlen(buf);
buf += sprintf(buf, "--------------\n"
"ROW OPERATIONS\n"
"--------------\n");
printf(
buf += sprintf(buf,
"%ld queries inside InnoDB, %ld queries in queue; main thread: %s\n",
srv_conc_n_threads, srv_conc_n_waiting_threads,
srv_main_thread_op_info);
printf(
buf += sprintf(buf,
"Number of rows inserted %lu, updated %lu, deleted %lu, read %lu\n",
srv_n_rows_inserted,
srv_n_rows_updated,
srv_n_rows_deleted,
srv_n_rows_read);
printf(
buf += sprintf(buf,
"%.2f inserts/s, %.2f updates/s, %.2f deletes/s, %.2f reads/s\n",
(srv_n_rows_inserted - srv_n_rows_inserted_old)
/ time_elapsed,
......@@ -2246,9 +2248,70 @@ srv_lock_timeout_and_monitor_thread(
srv_n_rows_deleted_old = srv_n_rows_deleted;
srv_n_rows_read_old = srv_n_rows_read;
printf("----------------------------\n"
buf += sprintf(buf, "----------------------------\n"
"END OF INNODB MONITOR OUTPUT\n"
"============================\n");
}
/*************************************************************************
A thread which wakes up threads whose lock wait may have lasted too long.
This also prints the info output by various InnoDB monitors. */
#ifndef __WIN__
void*
#else
ulint
#endif
srv_lock_timeout_and_monitor_thread(
/*================================*/
/* out: a dummy parameter */
void* arg) /* in: a dummy parameter required by
os_thread_create */
{
srv_slot_t* slot;
double time_elapsed;
time_t current_time;
time_t last_table_monitor_time;
time_t last_monitor_time;
ibool some_waits;
double wait_time;
char* buf;
ulint i;
UT_NOT_USED(arg);
srv_last_monitor_time = time(NULL);
last_table_monitor_time = time(NULL);
last_monitor_time = time(NULL);
loop:
srv_lock_timeout_and_monitor_active = TRUE;
/* When someone is waiting for a lock, we wake up every second
and check if a timeout has passed for a lock wait */
os_thread_sleep(1000000);
/* In case mutex_exit is not a memory barrier, it is
theoretically possible some threads are left waiting though
the semaphore is already released. Wake up those threads: */
sync_arr_wake_threads_if_sema_free();
current_time = time(NULL);
time_elapsed = difftime(current_time, last_monitor_time);
if (time_elapsed > 15) {
last_monitor_time = time(NULL);
if (srv_print_innodb_monitor) {
buf = mem_alloc(100000);
srv_sprintf_innodb_monitor(buf, 100000);
printf("%s", buf);
mem_free(buf);
}
if (srv_print_innodb_tablespace_monitor
......@@ -2380,7 +2443,13 @@ srv_error_monitor_thread(
srv_error_monitor_active = TRUE;
os_thread_sleep(10000000);
/*
printf("Validating has index\n");
btr_search_validate();
printf("Hash index validated\n");
*/
sync_array_print_long_waits();
/* Flush stdout and stderr so that a database user gets their output
......
......@@ -896,7 +896,7 @@ test_measure_cont(
"Mutex res. l %lu, p %lu, k %lu s x %lu s s %lu s mut %lu of %lu\n",
lcount, pcount, kcount, s_xcount, s_scount, s_mcount, j);
sync_print_wait_info();
/* sync_print_wait_info(); */
fprintf(stderr,
"log i/o %lu n non sea %lu n succ %lu n h fail %lu\n",
......
......@@ -441,7 +441,8 @@ static
void
sync_array_cell_print(
/*==================*/
FILE* file, /* in: file where to print */
char* buf, /* in: buffer where to print, must be
at least 400 characters */
sync_cell_t* cell) /* in: sync cell */
{
mutex_t* mutex;
......@@ -451,7 +452,7 @@ sync_array_cell_print(
type = cell->request_type;
fprintf(file,
buf += sprintf(buf,
"--Thread %lu has waited at %s line %lu for %.2f seconds the semaphore:\n",
(ulint)cell->thread, cell->file, cell->line,
difftime(time(NULL), cell->reservation_time));
......@@ -461,54 +462,58 @@ sync_array_cell_print(
been freed meanwhile */
mutex = cell->old_wait_mutex;
fprintf(file,
buf += sprintf(buf,
"Mutex at %lx created file %s line %lu, lock var %lu\n",
(ulint)mutex, mutex->cfile_name, mutex->cline,
mutex->lock_word);
fprintf(file,
buf += sprintf(buf,
"Last time reserved in file %s line %lu, waiters flag %lu\n",
mutex->file_name, mutex->line, mutex->waiters);
} else if (type == RW_LOCK_EX || type == RW_LOCK_SHARED) {
if (type == RW_LOCK_EX) {
fprintf(file, "X-lock on");
buf += sprintf(buf, "X-lock on");
} else {
fprintf(file, "S-lock on");
buf += sprintf(buf, "S-lock on");
}
rwlock = cell->old_wait_rw_lock;
fprintf(file, " RW-latch at %lx created in file %s line %lu\n",
buf += sprintf(buf,
" RW-latch at %lx created in file %s line %lu\n",
(ulint)rwlock, rwlock->cfile_name, rwlock->cline);
if (rwlock->writer != RW_LOCK_NOT_LOCKED) {
fprintf(file,
buf += sprintf(buf,
"a writer (thread id %lu) has reserved it in mode",
(ulint)rwlock->writer_thread);
if (rwlock->writer == RW_LOCK_EX) {
fprintf(file, " exclusive\n");
buf += sprintf(buf, " exclusive\n");
} else {
fprintf(file, " wait exclusive\n");
buf += sprintf(buf, " wait exclusive\n");
}
}
fprintf(file, "number of readers %lu, waiters flag %lu\n",
buf += sprintf(buf,
"number of readers %lu, waiters flag %lu\n",
rwlock->reader_count, rwlock->waiters);
fprintf(file, "Last time read locked in file %s line %lu\n",
buf += sprintf(buf,
"Last time read locked in file %s line %lu\n",
rwlock->last_s_file_name, rwlock->last_s_line);
fprintf(file, "Last time write locked in file %s line %lu\n",
buf += sprintf(buf,
"Last time write locked in file %s line %lu\n",
rwlock->last_x_file_name, rwlock->last_x_line);
} else {
ut_error;
}
if (!cell->waiting) {
fprintf(file, "wait has ended\n");
buf += sprintf(buf, "wait has ended\n");
}
if (cell->event_set) {
fprintf(file, "wait is ending\n");
buf += sprintf(buf, "wait is ending\n");
}
}
......@@ -610,6 +615,7 @@ sync_array_detect_deadlock(
os_thread_id_t thread;
ibool ret;
rw_lock_debug_t* debug;
char buf[500];
ut_a(arr && start && cell);
ut_ad(cell->wait_object);
......@@ -642,11 +648,12 @@ sync_array_detect_deadlock(
ret = sync_array_deadlock_step(arr, start, thread, 0,
depth);
if (ret) {
sync_array_cell_print(buf, cell);
printf(
"Mutex %lx owned by thread %lu file %s line %lu\n",
"Mutex %lx owned by thread %lu file %s line %lu\n%s",
(ulint)mutex, mutex->thread_id,
mutex->file_name, mutex->line);
sync_array_cell_print(stdout, cell);
mutex->file_name, mutex->line,
buf);
return(TRUE);
}
}
......@@ -678,9 +685,9 @@ sync_array_detect_deadlock(
debug->pass,
depth);
if (ret) {
printf("rw-lock %lx ", (ulint) lock);
sync_array_cell_print(buf, cell);
printf("rw-lock %lx %s ", (ulint) lock, buf);
rw_lock_debug_print(debug);
sync_array_cell_print(stdout, cell);
return(TRUE);
}
......@@ -711,9 +718,9 @@ sync_array_detect_deadlock(
debug->pass,
depth);
if (ret) {
printf("rw-lock %lx ", (ulint) lock);
sync_array_cell_print(buf, cell);
printf("rw-lock %lx %s ", (ulint) lock, buf);
rw_lock_debug_print(debug);
sync_array_cell_print(stdout, cell);
return(TRUE);
}
......@@ -898,6 +905,7 @@ sync_array_print_long_waits(void)
sync_cell_t* cell;
ibool old_val;
ibool noticed = FALSE;
char buf[500];
ulint i;
for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
......@@ -907,9 +915,10 @@ sync_array_print_long_waits(void)
if (cell->wait_object != NULL
&& difftime(time(NULL), cell->reservation_time) > 240) {
sync_array_cell_print(buf, cell);
fprintf(stderr,
"InnoDB: Warning: a long semaphore wait:\n");
sync_array_cell_print(stderr, cell);
"InnoDB: Warning: a long semaphore wait:\n%s", buf);
noticed = TRUE;
}
......@@ -948,6 +957,8 @@ static
void
sync_array_output_info(
/*===================*/
char* buf, /* in/out: buffer where to print */
char* buf_end,/* in: buffer end */
sync_array_t* arr) /* in: wait array; NOTE! caller must own the
mutex */
{
......@@ -955,18 +966,29 @@ sync_array_output_info(
ulint count;
ulint i;
printf("OS WAIT ARRAY INFO: reservation count %ld, signal count %ld\n",
if (buf_end - buf < 500) {
return;
}
buf += sprintf(buf,
"OS WAIT ARRAY INFO: reservation count %ld, signal count %ld\n",
arr->res_count, arr->sg_count);
i = 0;
count = 0;
while (count < arr->n_reserved) {
if (buf_end - buf < 500) {
return;
}
cell = sync_array_get_nth_cell(arr, i);
if (cell->wait_object != NULL) {
count++;
sync_array_cell_print(stdout, cell);
sync_array_cell_print(buf, cell);
buf = buf + strlen(buf);
}
i++;
......@@ -979,11 +1001,13 @@ Prints info of the wait array. */
void
sync_array_print_info(
/*==================*/
char* buf, /* in/out: buffer where to print */
char* buf_end,/* in: buffer end */
sync_array_t* arr) /* in: wait array */
{
sync_array_enter(arr);
sync_array_output_info(arr);
sync_array_output_info(buf, buf_end, arr);
sync_array_exit(arr);
}
......@@ -874,6 +874,7 @@ sync_thread_levels_empty_gen(
sync_level_t* slot;
rw_lock_t* lock;
mutex_t* mutex;
char* buf;
ulint i;
if (!sync_order_checks_on) {
......@@ -907,7 +908,9 @@ sync_thread_levels_empty_gen(
mutex = slot->latch;
mutex_exit(&sync_thread_mutex);
sync_print();
buf = mem_alloc(20000);
sync_print(buf, buf + 18000);
ut_error;
return(FALSE);
......@@ -1243,14 +1246,21 @@ sync_close(void)
Prints wait info of the sync system. */
void
sync_print_wait_info(void)
/*======================*/
sync_print_wait_info(
/*=================*/
char* buf, /* in/out: buffer where to print */
char* buf_end) /* in: buffer end */
{
#ifdef UNIV_SYNC_DEBUG
printf("Mutex exits %lu, rws exits %lu, rwx exits %lu\n",
mutex_exit_count, rw_s_exit_count, rw_x_exit_count);
#endif
printf(
if (buf_end - buf < 500) {
return;
}
sprintf(buf,
"Mutex spin waits %lu, rounds %lu, OS waits %lu\n"
"RW-shared spins %lu, OS waits %lu; RW-excl spins %lu, OS waits %lu\n",
mutex_spin_wait_count, mutex_spin_round_count,
......@@ -1263,11 +1273,18 @@ sync_print_wait_info(void)
Prints info of the sync system. */
void
sync_print(void)
/*============*/
sync_print(
/*=======*/
char* buf, /* in/out: buffer where to print */
char* buf_end) /* in: buffer end */
{
mutex_list_print_info();
rw_lock_list_print_info();
sync_array_print_info(sync_primary_wait_array);
sync_print_wait_info();
sync_array_print_info(buf, buf_end, sync_primary_wait_array);
buf = buf + strlen(buf);
sync_print_wait_info(buf, buf_end);
}
......@@ -26,9 +26,11 @@ Created 3/26/1996 Heikki Tuuri
/* Copy of the prototype for innobase_mysql_print_thd: this
copy must be equal to the one in mysql/sql/ha_innobase.cc ! */
copy MUST be equal to the one in mysql/sql/ha_innobase.cc ! */
void innobase_mysql_print_thd(void* thd);
void innobase_mysql_print_thd(
char* buf,
void* thd);
/* Dummy session used currently in MySQL interface */
sess_t* trx_dummy_sess = NULL;
......@@ -1459,54 +1461,63 @@ own the kernel mutex. */
void
trx_print(
/*======*/
char* buf, /* in/out: buffer where to print, must be at least
500 bytes */
trx_t* trx) /* in: transaction */
{
printf("TRANSACTION %lu %lu, OS thread id %lu",
buf += sprintf(buf, "TRANSACTION %lu %lu, OS thread id %lu",
ut_dulint_get_high(trx->id),
ut_dulint_get_low(trx->id),
(ulint)trx->mysql_thread_id);
if (ut_strlen(trx->op_info) > 0) {
printf(" %s", trx->op_info);
buf += sprintf(buf, " %s", trx->op_info);
}
if (trx->type != TRX_USER) {
printf(" purge trx");
buf += sprintf(buf, " purge trx");
}
switch (trx->conc_state) {
case TRX_NOT_STARTED: printf(", not started"); break;
case TRX_ACTIVE: printf(", active"); break;
case TRX_COMMITTED_IN_MEMORY: printf(", committed in memory");
case TRX_NOT_STARTED: buf += sprintf(buf,
", not started"); break;
case TRX_ACTIVE: buf += sprintf(buf,
", active"); break;
case TRX_COMMITTED_IN_MEMORY: buf += sprintf(buf,
", committed in memory");
break;
default: printf(" state %lu", trx->conc_state);
default: buf += sprintf(buf, " state %lu", trx->conc_state);
}
switch (trx->que_state) {
case TRX_QUE_RUNNING: printf(", runs or sleeps"); break;
case TRX_QUE_LOCK_WAIT: printf(", lock wait"); break;
case TRX_QUE_ROLLING_BACK: printf(", rolling back"); break;
case TRX_QUE_COMMITTING: printf(", committing"); break;
default: printf(" que state %lu", trx->que_state);
case TRX_QUE_RUNNING: buf += sprintf(buf,
", runs or sleeps"); break;
case TRX_QUE_LOCK_WAIT: buf += sprintf(buf,
", lock wait"); break;
case TRX_QUE_ROLLING_BACK: buf += sprintf(buf,
", rolling back"); break;
case TRX_QUE_COMMITTING: buf += sprintf(buf,
", committing"); break;
default: buf += sprintf(buf, " que state %lu", trx->que_state);
}
if (0 < UT_LIST_GET_LEN(trx->trx_locks)) {
printf(", has %lu lock struct(s)",
buf += sprintf(buf, ", has %lu lock struct(s)",
UT_LIST_GET_LEN(trx->trx_locks));
}
if (trx->has_search_latch) {
printf(", holds adaptive hash latch");
buf += sprintf(buf, ", holds adaptive hash latch");
}
if (ut_dulint_cmp(trx->undo_no, ut_dulint_zero) != 0) {
printf(", undo log entries %lu",
buf += sprintf(buf, ", undo log entries %lu",
ut_dulint_get_low(trx->undo_no));
}
printf("\n");
buf += sprintf(buf, "\n");
if (trx->mysql_thd != NULL) {
innobase_mysql_print_thd(trx->mysql_thd);
innobase_mysql_print_thd(buf, trx->mysql_thd);
}
}
......@@ -269,35 +269,37 @@ the prototype for this function! */
void
innobase_mysql_print_thd(
/*=====================*/
char* buf, /* in/out: buffer where to print, must be at least
300 bytes */
void* input_thd)/* in: pointer to a MySQL THD object */
{
THD* thd;
thd = (THD*) input_thd;
printf("MySQL thread id %lu, query id %lu",
buf += sprintf(buf, "MySQL thread id %lu, query id %lu",
thd->thread_id, thd->query_id);
if (thd->host) {
printf(" %s", thd->host);
buf += sprintf(buf, " %.30s", thd->host);
}
if (thd->ip) {
printf(" %s", thd->ip);
buf += sprintf(buf, " %.20s", thd->ip);
}
if (thd->user) {
printf(" %s", thd->user);
buf += sprintf(buf, " %.20s", thd->user);
}
if (thd->proc_info) {
printf(" %s", thd->proc_info);
buf += sprintf(buf, " %.50s", thd->proc_info);
}
if (thd->query) {
printf("\n%.100s", thd->query);
buf += sprintf(buf, "\n%.150s", thd->query);
}
printf("\n");
buf += sprintf(buf, "\n");
}
}
......@@ -314,10 +316,12 @@ check_trx_exists(
{
trx_t* trx;
ut_a(thd == current_thd);
trx = (trx_t*) thd->transaction.all.innobase_tid;
if (trx == NULL) {
dbug_assert(thd != NULL);
ut_a(thd != NULL);
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
......@@ -368,7 +372,7 @@ ha_innobase::update_thd(
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
trx_t* trx;
trx = check_trx_exists(thd);
if (prebuilt->trx != trx) {
......@@ -1378,6 +1382,9 @@ ha_innobase::write_row(
DBUG_ENTER("ha_innobase::write_row");
ut_a(prebuilt->trx ==
(trx_t*) current_thd->transaction.all.innobase_tid);
statistic_increment(ha_write_count, &LOCK_status);
if (table->time_stamp) {
......@@ -1718,6 +1725,9 @@ ha_innobase::update_row(
DBUG_ENTER("ha_innobase::update_row");
ut_a(prebuilt->trx ==
(trx_t*) current_thd->transaction.all.innobase_tid);
if (table->time_stamp) {
update_timestamp(new_row + table->time_stamp - 1);
}
......@@ -1775,6 +1785,9 @@ ha_innobase::delete_row(
DBUG_ENTER("ha_innobase::delete_row");
ut_a(prebuilt->trx ==
(trx_t*) current_thd->transaction.all.innobase_tid);
if (last_query_id != user_thd->query_id) {
prebuilt->sql_stat_start = TRUE;
last_query_id = user_thd->query_id;
......@@ -1888,6 +1901,10 @@ ha_innobase::index_read(
ulint ret;
DBUG_ENTER("index_read");
ut_a(prebuilt->trx ==
(trx_t*) current_thd->transaction.all.innobase_tid);
statistic_increment(ha_read_key_count, &LOCK_status);
if (last_query_id != user_thd->query_id) {
......@@ -2062,6 +2079,9 @@ ha_innobase::general_fetch(
DBUG_ENTER("general_fetch");
ut_a(prebuilt->trx ==
(trx_t*) current_thd->transaction.all.innobase_tid);
srv_conc_enter_innodb(prebuilt->trx);
ret = row_search_for_mysql((byte*)buf, 0, prebuilt, match_mode,
......@@ -2272,6 +2292,9 @@ ha_innobase::rnd_pos(
DBUG_ENTER("rnd_pos");
statistic_increment(ha_read_rnd_count, &LOCK_status);
ut_a(prebuilt->trx ==
(trx_t*) current_thd->transaction.all.innobase_tid);
if (prebuilt->clust_index_was_generated) {
/* No primary key was defined for the table and we
generated the clustered index from the row id: the
......@@ -2310,6 +2333,9 @@ ha_innobase::position(
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
uint len;
ut_a(prebuilt->trx ==
(trx_t*) current_thd->transaction.all.innobase_tid);
if (prebuilt->clust_index_was_generated) {
/* No primary key was defined for the table and we
generated the clustered index from row id: the
......@@ -3067,6 +3093,8 @@ ha_innobase::check(
ulint ret;
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
ut_a(prebuilt->trx ==
(trx_t*) current_thd->transaction.all.innobase_tid);
if (prebuilt->mysql_template == NULL) {
/* Build the template; we will use a dummy template
......@@ -3301,6 +3329,51 @@ ha_innobase::external_lock(
DBUG_RETURN(error);
}
/****************************************************************************
Implements the SHOW INNODB STATUS command. Send the output of the InnoDB
Monitor to the client. */
int
innodb_show_status(
/*===============*/
THD* thd) /* in: the MySQL query thread of the caller */
{
String* packet = &thd->packet;
char* buf;
DBUG_ENTER("innodb_show_status");
/* We let the InnoDB Monitor to output at most 100 kB of text */
buf = (char*)ut_malloc(100 * 1024);
srv_sprintf_innodb_monitor(buf, 100 * 1024);
List<Item> field_list;
field_list.push_back(new Item_empty_string("Status", strlen(buf)));
if(send_fields(thd, field_list, 1)) {
DBUG_RETURN(-1);
}
packet->length(0);
net_store_data(packet, buf);
if (my_net_write(&thd->net, (char*)thd->packet.ptr(),
packet->length())) {
ut_free(buf);
DBUG_RETURN(-1);
}
ut_free(buf);
send_eof(&thd->net);
DBUG_RETURN(0);
}
/****************************************************************************
Handling the shared INNOBASE_SHARE structure that is needed to provide table
locking.
......@@ -3424,6 +3497,9 @@ ha_innobase::get_auto_increment()
longlong nr;
int error;
ut_a(prebuilt->trx ==
(trx_t*) current_thd->transaction.all.innobase_tid);
/* Also SHOW TABLE STATUS calls this function. Previously, when we did
always read the max autoinc key value, setting x-locks, users were
surprised that SHOW TABLE STATUS could end up in a deadlock with
......
......@@ -195,4 +195,5 @@ int innobase_report_binlog_offset_and_commit(
int innobase_rollback(THD *thd, void* trx_handle);
int innobase_close_connection(THD *thd);
int innobase_drop_database(char *path);
int innodb_show_status(THD* thd);
......@@ -3155,6 +3155,7 @@ struct show_var_st status_vars[]= {
{"Com_show_processlist", (char*) (com_stat+(uint) SQLCOM_SHOW_PROCESSLIST),SHOW_LONG},
{"Com_show_slave_status", (char*) (com_stat+(uint) SQLCOM_SHOW_SLAVE_STAT),SHOW_LONG},
{"Com_show_status", (char*) (com_stat+(uint) SQLCOM_SHOW_STATUS),SHOW_LONG},
{"Com_show_innodb_status", (char*) (com_stat+(uint) SQLCOM_SHOW_INNODB_STATUS),SHOW_LONG},
{"Com_show_tables", (char*) (com_stat+(uint) SQLCOM_SHOW_TABLES),SHOW_LONG},
{"Com_show_variables", (char*) (com_stat+(uint) SQLCOM_SHOW_VARIABLES),SHOW_LONG},
{"Com_slave_start", (char*) (com_stat+(uint) SQLCOM_SLAVE_START),SHOW_LONG},
......
......@@ -40,6 +40,7 @@ enum enum_sql_command {
SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS,
SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_LOGS, SQLCOM_SHOW_STATUS,
SQLCOM_SHOW_INNODB_STATUS,
SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT,
SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE,
......
......@@ -24,6 +24,10 @@
#include <my_dir.h>
#include <assert.h>
#ifdef HAVE_INNOBASE_DB
#include "ha_innobase.h"
#endif
#define SCRAMBLE_LENGTH 8
......@@ -1232,6 +1236,15 @@ mysql_execute_command(void)
res = show_binlog_info(thd);
break;
}
#ifdef HAVE_INNOBASE_DB
case SQLCOM_SHOW_INNODB_STATUS:
{
if (check_process_priv(thd))
goto error;
res = innodb_show_status(thd);
break;
}
#endif
case SQLCOM_LOAD_MASTER_TABLE:
if (!tables->db)
......
......@@ -2242,6 +2242,8 @@ show_param:
}
| STATUS_SYM wild
{ Lex->sql_command= SQLCOM_SHOW_STATUS; }
| INNOBASE_SYM STATUS_SYM
{ Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS;}
| opt_full PROCESSLIST_SYM
{ Lex->sql_command= SQLCOM_SHOW_PROCESSLIST;}
| VARIABLES wild
......
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