Commit 4819f65a authored by Aleksandr Kuzminsky's avatar Aleksandr Kuzminsky

Sync with rev. 114

parent 2bde0c5e
...@@ -531,11 +531,10 @@ buf_buddy_relocate( ...@@ -531,11 +531,10 @@ buf_buddy_relocate(
UNIV_MEM_ASSERT_W(src, size); UNIV_MEM_ASSERT_W(src, size);
mutex = buf_page_get_mutex_enter(bpage); mutex = buf_page_get_mutex_enter(bpage);
ut_a(mutex);
mutex_enter(&zip_free_mutex); mutex_enter(&zip_free_mutex);
if (buf_page_can_relocate(bpage)) { if (mutex && buf_page_can_relocate(bpage)) {
/* Relocate the compressed page. */ /* Relocate the compressed page. */
ut_a(bpage->zip.data == src); ut_a(bpage->zip.data == src);
memcpy(dst, src, size); memcpy(dst, src, size);
...@@ -563,7 +562,9 @@ success: ...@@ -563,7 +562,9 @@ success:
rw_lock_x_unlock(&page_hash_latch); rw_lock_x_unlock(&page_hash_latch);
} }
mutex_exit(mutex); if (mutex) {
mutex_exit(mutex);
}
} else if (i == buf_buddy_get_slot(sizeof(buf_page_t))) { } else if (i == buf_buddy_get_slot(sizeof(buf_page_t))) {
/* This must be a buf_page_t object. */ /* This must be a buf_page_t object. */
UNIV_MEM_ASSERT_RW(src, size); UNIV_MEM_ASSERT_RW(src, size);
......
...@@ -52,6 +52,39 @@ Created 11/5/1995 Heikki Tuuri ...@@ -52,6 +52,39 @@ Created 11/5/1995 Heikki Tuuri
#include "log0recv.h" #include "log0recv.h"
#include "page0zip.h" #include "page0zip.h"
/* prototypes for new functions added to ha_innodb.cc */
trx_t* innobase_get_trx();
inline void _increment_page_get_statistics(buf_block_t* block, trx_t* trx)
{
ulint block_hash;
ulint block_hash_byte;
byte block_hash_offset;
ut_ad(block);
if (!innobase_get_slow_log() || !trx || !trx->take_stats)
return;
if (!trx->distinct_page_access_hash) {
trx->distinct_page_access_hash = mem_alloc(DPAH_SIZE);
memset(trx->distinct_page_access_hash, 0, DPAH_SIZE);
}
block_hash = ut_hash_ulint((block->page.space << 20) + block->page.space +
block->page.offset, DPAH_SIZE << 3);
block_hash_byte = block_hash >> 3;
block_hash_offset = (byte) block_hash & 0x07;
if (block_hash_byte < 0 || block_hash_byte >= DPAH_SIZE)
fprintf(stderr, "!!! block_hash_byte = %lu block_hash_offset = %lu !!!\n", block_hash_byte, block_hash_offset);
if (block_hash_offset < 0 || block_hash_offset > 7)
fprintf(stderr, "!!! block_hash_byte = %lu block_hash_offset = %lu !!!\n", block_hash_byte, block_hash_offset);
if ((trx->distinct_page_access_hash[block_hash_byte] & ((byte) 0x01 << block_hash_offset)) == 0)
trx->distinct_page_access++;
trx->distinct_page_access_hash[block_hash_byte] |= (byte) 0x01 << block_hash_offset;
return;
}
/* /*
IMPLEMENTATION OF THE BUFFER POOL IMPLEMENTATION OF THE BUFFER POOL
================================= =================================
...@@ -1696,10 +1729,18 @@ buf_page_get_zip( ...@@ -1696,10 +1729,18 @@ buf_page_get_zip(
buf_page_t* bpage; buf_page_t* bpage;
mutex_t* block_mutex; mutex_t* block_mutex;
ibool must_read; ibool must_read;
trx_t* trx = NULL;
ulint sec;
ulint ms;
ib_uint64_t start_time;
ib_uint64_t finish_time;
#ifndef UNIV_LOG_DEBUG #ifndef UNIV_LOG_DEBUG
ut_ad(!ibuf_inside()); ut_ad(!ibuf_inside());
#endif #endif
if (innobase_get_slow_log()) {
trx = innobase_get_trx();
}
buf_pool->n_page_gets++; buf_pool->n_page_gets++;
for (;;) { for (;;) {
...@@ -1716,7 +1757,7 @@ lookup: ...@@ -1716,7 +1757,7 @@ lookup:
//buf_pool_mutex_exit(); //buf_pool_mutex_exit();
rw_lock_s_unlock(&page_hash_latch); rw_lock_s_unlock(&page_hash_latch);
buf_read_page(space, zip_size, offset); buf_read_page(space, zip_size, offset, trx);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(++buf_dbg_counter % 37 || buf_validate()); ut_a(++buf_dbg_counter % 37 || buf_validate());
...@@ -1793,6 +1834,13 @@ got_block: ...@@ -1793,6 +1834,13 @@ got_block:
/* Let us wait until the read operation /* Let us wait until the read operation
completes */ completes */
if (innobase_get_slow_log() && trx && trx->take_stats)
{
ut_usectime(&sec, &ms);
start_time = (ib_uint64_t)sec * 1000000 + ms;
} else {
start_time = 0;
}
for (;;) { for (;;) {
enum buf_io_fix io_fix; enum buf_io_fix io_fix;
...@@ -1807,6 +1855,12 @@ got_block: ...@@ -1807,6 +1855,12 @@ got_block:
break; break;
} }
} }
if (innobase_get_slow_log() && trx && trx->take_stats && start_time)
{
ut_usectime(&sec, &ms);
finish_time = (ib_uint64_t)sec * 1000000 + ms;
trx->io_reads_wait_timer += (ulint)(finish_time - start_time);
}
} }
#ifdef UNIV_IBUF_COUNT_DEBUG #ifdef UNIV_IBUF_COUNT_DEBUG
...@@ -2062,6 +2116,11 @@ buf_page_get_gen( ...@@ -2062,6 +2116,11 @@ buf_page_get_gen(
ulint fix_type; ulint fix_type;
ibool must_read; ibool must_read;
mutex_t* block_mutex; mutex_t* block_mutex;
trx_t* trx = NULL;
ulint sec;
ulint ms;
ib_uint64_t start_time;
ib_uint64_t finish_time;
ut_ad(mtr); ut_ad(mtr);
ut_ad((rw_latch == RW_S_LATCH) ut_ad((rw_latch == RW_S_LATCH)
...@@ -2075,6 +2134,9 @@ buf_page_get_gen( ...@@ -2075,6 +2134,9 @@ buf_page_get_gen(
#ifndef UNIV_LOG_DEBUG #ifndef UNIV_LOG_DEBUG
ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL)); ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL));
#endif #endif
if (innobase_get_slow_log()) {
trx = innobase_get_trx();
}
buf_pool->n_page_gets++; buf_pool->n_page_gets++;
loop: loop:
block = guess; block = guess;
...@@ -2082,7 +2144,6 @@ loop: ...@@ -2082,7 +2144,6 @@ loop:
if (block) { if (block) {
block_mutex = buf_page_get_mutex_enter((buf_page_t*)block); block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
ut_a(block_mutex);
/* If the guess is a compressed page descriptor that /* If the guess is a compressed page descriptor that
has been allocated by buf_buddy_alloc(), it may have has been allocated by buf_buddy_alloc(), it may have
...@@ -2092,7 +2153,9 @@ loop: ...@@ -2092,7 +2153,9 @@ loop:
the guess may be pointing to a buffer pool chunk that the guess may be pointing to a buffer pool chunk that
has been released when resizing the buffer pool. */ has been released when resizing the buffer pool. */
if (!buf_block_is_uncompressed(block) if (!block_mutex) {
block = guess = NULL;
} else if (!buf_block_is_uncompressed(block)
|| offset != block->page.offset || offset != block->page.offset
|| space != block->page.space || space != block->page.space
|| buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) { || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
...@@ -2127,7 +2190,7 @@ loop2: ...@@ -2127,7 +2190,7 @@ loop2:
return(NULL); return(NULL);
} }
buf_read_page(space, zip_size, offset); buf_read_page(space, zip_size, offset, trx);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(++buf_dbg_counter % 37 || buf_validate()); ut_a(++buf_dbg_counter % 37 || buf_validate());
...@@ -2379,6 +2442,13 @@ wait_until_unfixed: ...@@ -2379,6 +2442,13 @@ wait_until_unfixed:
/* Let us wait until the read operation /* Let us wait until the read operation
completes */ completes */
if (innobase_get_slow_log() && trx && trx->take_stats)
{
ut_usectime(&sec, &ms);
start_time = (ib_uint64_t)sec * 1000000 + ms;
} else {
start_time = 0;
}
for (;;) { for (;;) {
enum buf_io_fix io_fix; enum buf_io_fix io_fix;
...@@ -2393,6 +2463,12 @@ wait_until_unfixed: ...@@ -2393,6 +2463,12 @@ wait_until_unfixed:
break; break;
} }
} }
if (innobase_get_slow_log() && trx && trx->take_stats && start_time)
{
ut_usectime(&sec, &ms);
finish_time = (ib_uint64_t)sec * 1000000 + ms;
trx->io_reads_wait_timer += (ulint)(finish_time - start_time);
}
} }
fix_type = MTR_MEMO_BUF_FIX; fix_type = MTR_MEMO_BUF_FIX;
...@@ -2418,13 +2494,17 @@ wait_until_unfixed: ...@@ -2418,13 +2494,17 @@ wait_until_unfixed:
/* In the case of a first access, try to apply linear /* In the case of a first access, try to apply linear
read-ahead */ read-ahead */
buf_read_ahead_linear(space, zip_size, offset); buf_read_ahead_linear(space, zip_size, offset, trx);
} }
#ifdef UNIV_IBUF_COUNT_DEBUG #ifdef UNIV_IBUF_COUNT_DEBUG
ut_a(ibuf_count_get(buf_block_get_space(block), ut_a(ibuf_count_get(buf_block_get_space(block),
buf_block_get_page_no(block)) == 0); buf_block_get_page_no(block)) == 0);
#endif #endif
if (innobase_get_slow_log()) {
_increment_page_get_statistics(block, trx);
}
return(block); return(block);
} }
...@@ -2447,6 +2527,7 @@ buf_page_optimistic_get_func( ...@@ -2447,6 +2527,7 @@ buf_page_optimistic_get_func(
ibool accessed; ibool accessed;
ibool success; ibool success;
ulint fix_type; ulint fix_type;
trx_t* trx = NULL;
ut_ad(mtr && block); ut_ad(mtr && block);
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH)); ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
...@@ -2520,13 +2601,17 @@ buf_page_optimistic_get_func( ...@@ -2520,13 +2601,17 @@ buf_page_optimistic_get_func(
#ifdef UNIV_DEBUG_FILE_ACCESSES #ifdef UNIV_DEBUG_FILE_ACCESSES
ut_a(block->page.file_page_was_freed == FALSE); ut_a(block->page.file_page_was_freed == FALSE);
#endif #endif
if (innobase_get_slow_log()) {
trx = innobase_get_trx();
}
if (UNIV_UNLIKELY(!accessed)) { if (UNIV_UNLIKELY(!accessed)) {
/* In the case of a first access, try to apply linear /* In the case of a first access, try to apply linear
read-ahead */ read-ahead */
buf_read_ahead_linear(buf_block_get_space(block), buf_read_ahead_linear(buf_block_get_space(block),
buf_block_get_zip_size(block), buf_block_get_zip_size(block),
buf_block_get_page_no(block)); buf_block_get_page_no(block), trx);
} }
#ifdef UNIV_IBUF_COUNT_DEBUG #ifdef UNIV_IBUF_COUNT_DEBUG
...@@ -2535,6 +2620,9 @@ buf_page_optimistic_get_func( ...@@ -2535,6 +2620,9 @@ buf_page_optimistic_get_func(
#endif #endif
buf_pool->n_page_gets++; buf_pool->n_page_gets++;
if (innobase_get_slow_log()) {
_increment_page_get_statistics(block, trx);
}
return(TRUE); return(TRUE);
} }
...@@ -2556,6 +2644,7 @@ buf_page_get_known_nowait( ...@@ -2556,6 +2644,7 @@ buf_page_get_known_nowait(
{ {
ibool success; ibool success;
ulint fix_type; ulint fix_type;
trx_t* trx = NULL;
ut_ad(mtr); ut_ad(mtr);
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH)); ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
...@@ -2623,6 +2712,11 @@ buf_page_get_known_nowait( ...@@ -2623,6 +2712,11 @@ buf_page_get_known_nowait(
#endif #endif
buf_pool->n_page_gets++; buf_pool->n_page_gets++;
if (innobase_get_slow_log()) {
trx = innobase_get_trx();
_increment_page_get_statistics(block, trx);
}
return(TRUE); return(TRUE);
} }
......
...@@ -994,9 +994,7 @@ buf_flush_try_neighbors( ...@@ -994,9 +994,7 @@ buf_flush_try_neighbors(
|| buf_page_is_old(bpage)) { || buf_page_is_old(bpage)) {
mutex_t* block_mutex = buf_page_get_mutex_enter(bpage); mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
ut_a(block_mutex); if (block_mutex && buf_flush_ready_for_flush(bpage, flush_type)
if (buf_flush_ready_for_flush(bpage, flush_type)
&& (i == offset || !bpage->buf_fix_count)) { && (i == offset || !bpage->buf_fix_count)) {
/* We only try to flush those /* We only try to flush those
neighbors != offset where the buf fix count is neighbors != offset where the buf fix count is
...@@ -1012,7 +1010,7 @@ buf_flush_try_neighbors( ...@@ -1012,7 +1010,7 @@ buf_flush_try_neighbors(
//buf_pool_mutex_enter(); //buf_pool_mutex_enter();
rw_lock_s_lock(&page_hash_latch); rw_lock_s_lock(&page_hash_latch);
} else { } else if (block_mutex) {
mutex_exit(block_mutex); mutex_exit(block_mutex);
} }
} }
...@@ -1123,11 +1121,14 @@ flush_next: ...@@ -1123,11 +1121,14 @@ flush_next:
mutex_t*block_mutex = buf_page_get_mutex_enter(bpage); mutex_t*block_mutex = buf_page_get_mutex_enter(bpage);
ibool ready; ibool ready;
ut_a(buf_page_in_file(bpage)); //ut_a(buf_page_in_file(bpage));
ut_a(block_mutex); if (block_mutex) {
ready = buf_flush_ready_for_flush(bpage, flush_type); ready = buf_flush_ready_for_flush(bpage, flush_type);
mutex_exit(block_mutex); mutex_exit(block_mutex);
} else {
ready = FALSE;
}
if (ready) { if (ready) {
space = buf_page_get_space(bpage); space = buf_page_get_space(bpage);
...@@ -1271,13 +1272,13 @@ buf_flush_LRU_recommendation(void) ...@@ -1271,13 +1272,13 @@ buf_flush_LRU_recommendation(void)
} }
block_mutex = buf_page_get_mutex_enter(bpage); block_mutex = buf_page_get_mutex_enter(bpage);
ut_a(block_mutex); if (block_mutex && buf_flush_ready_for_replace(bpage)) {
if (buf_flush_ready_for_replace(bpage)) {
n_replaceable++; n_replaceable++;
} }
mutex_exit(block_mutex); if (block_mutex) {
mutex_exit(block_mutex);
}
distance++; distance++;
......
...@@ -255,9 +255,12 @@ scan_again: ...@@ -255,9 +255,12 @@ scan_again:
mutex_t* block_mutex = buf_page_get_mutex_enter(bpage); mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
buf_page_t* prev_bpage; buf_page_t* prev_bpage;
ut_a(block_mutex);
prev_bpage = UT_LIST_GET_PREV(LRU, bpage); prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
if (!block_mutex) {
goto next_page;
}
ut_a(buf_page_in_file(bpage)); ut_a(buf_page_in_file(bpage));
if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE
...@@ -360,9 +363,13 @@ scan_again: ...@@ -360,9 +363,13 @@ scan_again:
ut_a(buf_page_in_file(bpage)); ut_a(buf_page_in_file(bpage));
ut_a(block_mutex);
prev_bpage = UT_LIST_GET_PREV(LRU, bpage); prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
if (!block_mutex) {
bpage = prev_bpage;
continue;
}
if (buf_page_get_space(bpage) == id) { if (buf_page_get_space(bpage) == id) {
if (bpage->buf_fix_count > 0 if (bpage->buf_fix_count > 0
|| buf_page_get_io_fix(bpage) != BUF_IO_NONE) { || buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
...@@ -634,7 +641,9 @@ restart: ...@@ -634,7 +641,9 @@ restart:
mutex_t* block_mutex mutex_t* block_mutex
= buf_page_get_mutex_enter(bpage); = buf_page_get_mutex_enter(bpage);
ut_a(block_mutex); if (!block_mutex) {
goto restart;
}
if (!bpage->in_LRU_list if (!bpage->in_LRU_list
|| !buf_page_in_file(bpage)) { || !buf_page_in_file(bpage)) {
......
...@@ -82,7 +82,8 @@ buf_read_page_low( ...@@ -82,7 +82,8 @@ buf_read_page_low(
treat the tablespace as dropped; this is a timestamp we treat the tablespace as dropped; this is a timestamp we
use to stop dangling page reads from a tablespace use to stop dangling page reads from a tablespace
which we have DISCARDed + IMPORTed back */ which we have DISCARDed + IMPORTed back */
ulint offset) /*!< in: page number */ ulint offset, /*!< in: page number */
trx_t* trx)
{ {
buf_page_t* bpage; buf_page_t* bpage;
ulint wake_later; ulint wake_later;
...@@ -183,15 +184,15 @@ not_to_recover: ...@@ -183,15 +184,15 @@ not_to_recover:
ut_ad(buf_page_in_file(bpage)); ut_ad(buf_page_in_file(bpage));
if (zip_size) { if (zip_size) {
*err = fil_io(OS_FILE_READ | wake_later, *err = _fil_io(OS_FILE_READ | wake_later,
sync, space, zip_size, offset, 0, zip_size, sync, space, zip_size, offset, 0, zip_size,
bpage->zip.data, bpage); bpage->zip.data, bpage, trx);
} else { } else {
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
*err = fil_io(OS_FILE_READ | wake_later, *err = _fil_io(OS_FILE_READ | wake_later,
sync, space, 0, offset, 0, UNIV_PAGE_SIZE, sync, space, 0, offset, 0, UNIV_PAGE_SIZE,
((buf_block_t*) bpage)->frame, bpage); ((buf_block_t*) bpage)->frame, bpage, trx);
} }
ut_a(*err == DB_SUCCESS); ut_a(*err == DB_SUCCESS);
...@@ -223,8 +224,9 @@ buf_read_ahead_random( ...@@ -223,8 +224,9 @@ buf_read_ahead_random(
/*==================*/ /*==================*/
ulint space, /*!< in: space id */ ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
ulint offset) /*!< in: page number of a page which the current thread ulint offset, /*!< in: page number of a page which the current thread
wants to access */ wants to access */
trx_t* trx)
{ {
ib_int64_t tablespace_version; ib_int64_t tablespace_version;
ulint recent_blocks = 0; ulint recent_blocks = 0;
...@@ -340,7 +342,7 @@ read_ahead: ...@@ -340,7 +342,7 @@ read_ahead:
&err, FALSE, &err, FALSE,
ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER, ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
space, zip_size, FALSE, space, zip_size, FALSE,
tablespace_version, i); tablespace_version, i, trx);
if (err == DB_TABLESPACE_DELETED) { if (err == DB_TABLESPACE_DELETED) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
...@@ -387,7 +389,8 @@ buf_read_page( ...@@ -387,7 +389,8 @@ buf_read_page(
/*==========*/ /*==========*/
ulint space, /*!< in: space id */ ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
ulint offset) /*!< in: page number */ ulint offset, /*!< in: page number */
trx_t* trx)
{ {
ib_int64_t tablespace_version; ib_int64_t tablespace_version;
ulint count; ulint count;
...@@ -396,14 +399,14 @@ buf_read_page( ...@@ -396,14 +399,14 @@ buf_read_page(
tablespace_version = fil_space_get_version(space); tablespace_version = fil_space_get_version(space);
count = buf_read_ahead_random(space, zip_size, offset); count = buf_read_ahead_random(space, zip_size, offset, trx);
/* We do the i/o in the synchronous aio mode to save thread /* We do the i/o in the synchronous aio mode to save thread
switches: hence TRUE */ switches: hence TRUE */
count2 = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space, count2 = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
zip_size, FALSE, zip_size, FALSE,
tablespace_version, offset); tablespace_version, offset, trx);
srv_buf_pool_reads+= count2; srv_buf_pool_reads+= count2;
if (err == DB_TABLESPACE_DELETED) { if (err == DB_TABLESPACE_DELETED) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
...@@ -454,8 +457,9 @@ buf_read_ahead_linear( ...@@ -454,8 +457,9 @@ buf_read_ahead_linear(
/*==================*/ /*==================*/
ulint space, /*!< in: space id */ ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
ulint offset) /*!< in: page number of a page; NOTE: the current thread ulint offset, /*!< in: page number of a page; NOTE: the current thread
must want access to this page (see NOTE 3 above) */ must want access to this page (see NOTE 3 above) */
trx_t* trx)
{ {
ib_int64_t tablespace_version; ib_int64_t tablespace_version;
buf_page_t* bpage; buf_page_t* bpage;
...@@ -670,7 +674,7 @@ buf_read_ahead_linear( ...@@ -670,7 +674,7 @@ buf_read_ahead_linear(
count += buf_read_page_low( count += buf_read_page_low(
&err, FALSE, &err, FALSE,
ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER, ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
space, zip_size, FALSE, tablespace_version, i); space, zip_size, FALSE, tablespace_version, i, trx);
if (err == DB_TABLESPACE_DELETED) { if (err == DB_TABLESPACE_DELETED) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
...@@ -760,7 +764,7 @@ buf_read_ibuf_merge_pages( ...@@ -760,7 +764,7 @@ buf_read_ibuf_merge_pages(
buf_read_page_low(&err, sync && (i + 1 == n_stored), buf_read_page_low(&err, sync && (i + 1 == n_stored),
BUF_READ_ANY_PAGE, space_ids[i], BUF_READ_ANY_PAGE, space_ids[i],
zip_size, TRUE, space_versions[i], zip_size, TRUE, space_versions[i],
page_nos[i]); page_nos[i], NULL);
if (UNIV_UNLIKELY(err == DB_TABLESPACE_DELETED)) { if (UNIV_UNLIKELY(err == DB_TABLESPACE_DELETED)) {
tablespace_deleted: tablespace_deleted:
...@@ -857,12 +861,12 @@ buf_read_recv_pages( ...@@ -857,12 +861,12 @@ buf_read_recv_pages(
if ((i + 1 == n_stored) && sync) { if ((i + 1 == n_stored) && sync) {
buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space, buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
zip_size, TRUE, tablespace_version, zip_size, TRUE, tablespace_version,
page_nos[i]); page_nos[i], NULL);
} else { } else {
buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE
| OS_AIO_SIMULATED_WAKE_LATER, | OS_AIO_SIMULATED_WAKE_LATER,
space, zip_size, TRUE, space, zip_size, TRUE,
tablespace_version, page_nos[i]); tablespace_version, page_nos[i], NULL);
} }
} }
......
...@@ -1231,7 +1231,7 @@ dict_col_name_is_reserved( ...@@ -1231,7 +1231,7 @@ dict_col_name_is_reserved(
ulint i; ulint i;
for (i = 0; i < UT_ARR_SIZE(reserved_names); i++) { for (i = 0; i < UT_ARR_SIZE(reserved_names); i++) {
if (strcmp(name, reserved_names[i]) == 0) { if (innobase_strcasecmp(name, reserved_names[i]) == 0) {
return(TRUE); return(TRUE);
} }
......
...@@ -4161,7 +4161,7 @@ fil_extend_space_to_desired_size( ...@@ -4161,7 +4161,7 @@ fil_extend_space_to_desired_size(
node->name, node->handle, buf, node->name, node->handle, buf,
offset_low, offset_high, offset_low, offset_high,
page_size * n_pages, page_size * n_pages,
NULL, NULL); NULL, NULL, NULL);
#endif #endif
if (success) { if (success) {
node->size += n_pages; node->size += n_pages;
...@@ -4488,7 +4488,7 @@ Reads or writes data. This operation is asynchronous (aio). ...@@ -4488,7 +4488,7 @@ Reads or writes data. This operation is asynchronous (aio).
i/o on a tablespace which does not exist */ i/o on a tablespace which does not exist */
UNIV_INTERN UNIV_INTERN
ulint ulint
fil_io( _fil_io(
/*===*/ /*===*/
ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE, ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE,
ORed to OS_FILE_LOG, if a log i/o ORed to OS_FILE_LOG, if a log i/o
...@@ -4513,8 +4513,9 @@ fil_io( ...@@ -4513,8 +4513,9 @@ fil_io(
void* buf, /*!< in/out: buffer where to store read data void* buf, /*!< in/out: buffer where to store read data
or from where to write; in aio this must be or from where to write; in aio this must be
appropriately aligned */ appropriately aligned */
void* message) /*!< in: message for aio handler if non-sync void* message, /*!< in: message for aio handler if non-sync
aio used, else ignored */ aio used, else ignored */
trx_t* trx)
{ {
ulint mode; ulint mode;
fil_space_t* space; fil_space_t* space;
...@@ -4684,7 +4685,7 @@ fil_io( ...@@ -4684,7 +4685,7 @@ fil_io(
#else #else
/* Queue the aio request */ /* Queue the aio request */
ret = os_aio(type, mode | wake_later, node->name, node->handle, buf, ret = os_aio(type, mode | wake_later, node->name, node->handle, buf,
offset_low, offset_high, len, node, message); offset_low, offset_high, len, node, message, trx);
#endif #endif
ut_a(ret); ut_a(ret);
......
This diff is collapsed.
...@@ -670,6 +670,23 @@ err_exit: ...@@ -670,6 +670,23 @@ err_exit:
DBUG_RETURN(error); DBUG_RETURN(error);
} }
/* Check for name conflicts (with reserved name) for
any user indices to be created. */
if (innobase_strcasecmp(key_info->name,
"GEN_CLUST_INDEX") == 0) {
/* Push warning to mysql */
push_warning_printf((THD*) trx->mysql_thd,
MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_CANT_CREATE_TABLE,
"Cannot Create Index with name "
"'%s'. The name is reserved "
"for the system default primary "
"index.",
"GEN_CLUST_INDEX");
error = ER_CANT_CREATE_TABLE;
goto err_exit;
}
/* Create table containing all indexes to be built in this /* Create table containing all indexes to be built in this
alter table add index so that they are in the correct order alter table add index so that they are in the correct order
in the table. */ in the table. */
......
...@@ -2953,3 +2953,140 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_index_stats = ...@@ -2953,3 +2953,140 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_index_stats =
STRUCT_FLD(system_vars, NULL), STRUCT_FLD(system_vars, NULL),
STRUCT_FLD(__reserved1, NULL) STRUCT_FLD(__reserved1, NULL)
}; };
/***********************************************************************
*/
static ST_FIELD_INFO i_s_innodb_admin_command_info[] =
{
{STRUCT_FLD(field_name, "result_message"),
STRUCT_FLD(field_length, 1024),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
END_OF_ST_FIELD_INFO
};
#ifndef INNODB_COMPATIBILITY_HOOKS
#error InnoDB needs MySQL to be built with #define INNODB_COMPATIBILITY_HOOKS
#endif
extern "C" {
char **thd_query(MYSQL_THD thd);
}
static
int
i_s_innodb_admin_command_fill(
/*==========================*/
THD* thd,
TABLE_LIST* tables,
COND* cond)
{
TABLE* i_s_table = (TABLE *) tables->table;
CHARSET_INFO *cs= system_charset_info;
char** query_str;
char* ptr;
char quote = '\0';
char* command_head = "XTRA_";
DBUG_ENTER("i_s_innodb_admin_command_fill");
/* deny access to non-superusers */
if (check_global_access(thd, PROCESS_ACL)) {
DBUG_RETURN(0);
}
if(thd_sql_command(thd) != SQLCOM_SELECT) {
field_store_string(i_s_table->field[0],
"SELECT command is only accepted.");
goto end_func;
}
query_str = thd_query(thd);
ptr = *query_str;
for (; *ptr; ptr++) {
if (*ptr == quote) {
quote = '\0';
} else if (quote) {
} else if (*ptr == '`' || *ptr == '"') {
quote = *ptr;
} else {
long i;
for (i = 0; command_head[i]; i++) {
if (toupper((int)(unsigned char)(ptr[i]))
!= toupper((int)(unsigned char)
(command_head[i]))) {
goto nomatch;
}
}
break;
nomatch:
;
}
}
if (!*ptr) {
field_store_string(i_s_table->field[0],
"No XTRA_* command in the SQL statement."
" Please add /*!XTRA_xxxx*/ to the SQL.");
goto end_func;
}
if (!strncasecmp("XTRA_HELLO", ptr, 10)) {
/* This is example command XTRA_HELLO */
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: administration command test for XtraDB"
" 'XTRA_HELLO' was detected.\n");
field_store_string(i_s_table->field[0],
"Hello!");
goto end_func;
}
field_store_string(i_s_table->field[0],
"Undefined XTRA_* command.");
goto end_func;
end_func:
if (schema_table_store_record(thd, i_s_table)) {
DBUG_RETURN(1);
} else {
DBUG_RETURN(0);
}
}
static
int
i_s_innodb_admin_command_init(
/*==========================*/
void* p)
{
DBUG_ENTER("i_s_innodb_admin_command_init");
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = i_s_innodb_admin_command_info;
schema->fill_table = i_s_innodb_admin_command_fill;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_mysql_plugin i_s_innodb_admin_command =
{
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
STRUCT_FLD(info, &i_s_info),
STRUCT_FLD(name, "XTRADB_ADMIN_COMMAND"),
STRUCT_FLD(author, plugin_author),
STRUCT_FLD(descr, "XtraDB specific command acceptor"),
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
STRUCT_FLD(init, i_s_innodb_admin_command_init),
STRUCT_FLD(deinit, i_s_common_deinit),
STRUCT_FLD(version, 0x0100 /* 1.0 */),
STRUCT_FLD(status_vars, NULL),
STRUCT_FLD(system_vars, NULL),
STRUCT_FLD(__reserved1, NULL)
};
...@@ -40,5 +40,6 @@ extern struct st_mysql_plugin i_s_innodb_patches; ...@@ -40,5 +40,6 @@ extern struct st_mysql_plugin i_s_innodb_patches;
extern struct st_mysql_plugin i_s_innodb_rseg; extern struct st_mysql_plugin i_s_innodb_rseg;
extern struct st_mysql_plugin i_s_innodb_table_stats; extern struct st_mysql_plugin i_s_innodb_table_stats;
extern struct st_mysql_plugin i_s_innodb_index_stats; extern struct st_mysql_plugin i_s_innodb_index_stats;
extern struct st_mysql_plugin i_s_innodb_admin_command;
#endif /* i_s_h */ #endif /* i_s_h */
...@@ -38,5 +38,8 @@ struct innodb_enhancement { ...@@ -38,5 +38,8 @@ struct innodb_enhancement {
{"innodb_stats","Additional features about InnoDB statistics/optimizer","","http://www.percona.com/docs/wiki/percona-xtradb"}, {"innodb_stats","Additional features about InnoDB statistics/optimizer","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_recovery_patches","Bugfixes and adjustments about recovery process","","http://www.percona.com/docs/wiki/percona-xtradb"}, {"innodb_recovery_patches","Bugfixes and adjustments about recovery process","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_purge_thread","Enable to use purge devoted thread","","http://www.percona.com/docs/wiki/percona-xtradb"}, {"innodb_purge_thread","Enable to use purge devoted thread","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_admin_command_base","XtraDB specific command interface through i_s","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_show_lock_name","Show mutex/lock name instead of crated file/line","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_extend_slow","Extended statistics in slow.log","It is InnoDB-part only. It needs to patch also to mysqld.","http://www.percona.com/docs/wiki/percona-xtradb"},
{NULL, NULL, NULL, NULL} {NULL, NULL, NULL, NULL}
}; };
...@@ -825,15 +825,15 @@ buf_page_get_newest_modification( ...@@ -825,15 +825,15 @@ buf_page_get_newest_modification(
ib_uint64_t lsn; ib_uint64_t lsn;
mutex_t* block_mutex = buf_page_get_mutex_enter(bpage); mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
ut_a(block_mutex); if (block_mutex && buf_page_in_file(bpage)) {
if (buf_page_in_file(bpage)) {
lsn = bpage->newest_modification; lsn = bpage->newest_modification;
} else { } else {
lsn = 0; lsn = 0;
} }
mutex_exit(block_mutex); if (block_mutex) {
mutex_exit(block_mutex);
}
return(lsn); return(lsn);
} }
......
...@@ -27,6 +27,7 @@ Created 11/5/1995 Heikki Tuuri ...@@ -27,6 +27,7 @@ Created 11/5/1995 Heikki Tuuri
#define buf0rea_h #define buf0rea_h
#include "univ.i" #include "univ.i"
#include "trx0types.h"
#include "buf0types.h" #include "buf0types.h"
/********************************************************************//** /********************************************************************//**
...@@ -43,7 +44,8 @@ buf_read_page( ...@@ -43,7 +44,8 @@ buf_read_page(
/*==========*/ /*==========*/
ulint space, /*!< in: space id */ ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
ulint offset);/*!< in: page number */ ulint offset, /*!< in: page number */
trx_t* trx);
/********************************************************************//** /********************************************************************//**
Applies linear read-ahead if in the buf_pool the page is a border page of Applies linear read-ahead if in the buf_pool the page is a border page of
a linear read-ahead area and all the pages in the area have been accessed. a linear read-ahead area and all the pages in the area have been accessed.
...@@ -74,8 +76,9 @@ buf_read_ahead_linear( ...@@ -74,8 +76,9 @@ buf_read_ahead_linear(
/*==================*/ /*==================*/
ulint space, /*!< in: space id */ ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
ulint offset);/*!< in: page number of a page; NOTE: the current thread ulint offset, /*!< in: page number of a page; NOTE: the current thread
must want access to this page (see NOTE 3 above) */ must want access to this page (see NOTE 3 above) */
trx_t* trx);
/********************************************************************//** /********************************************************************//**
Issues read requests for pages which the ibuf module wants to read in, in Issues read requests for pages which the ibuf module wants to read in, in
order to contract the insert buffer tree. Technically, this function is like order to contract the insert buffer tree. Technically, this function is like
......
...@@ -614,9 +614,12 @@ fil_space_get_n_reserved_extents( ...@@ -614,9 +614,12 @@ fil_space_get_n_reserved_extents(
Reads or writes data. This operation is asynchronous (aio). Reads or writes data. This operation is asynchronous (aio).
@return DB_SUCCESS, or DB_TABLESPACE_DELETED if we are trying to do @return DB_SUCCESS, or DB_TABLESPACE_DELETED if we are trying to do
i/o on a tablespace which does not exist */ i/o on a tablespace which does not exist */
#define fil_io(type, sync, space_id, zip_size, block_offset, byte_offset, len, buf, message) \
_fil_io(type, sync, space_id, zip_size, block_offset, byte_offset, len, buf, message, NULL)
UNIV_INTERN UNIV_INTERN
ulint ulint
fil_io( _fil_io(
/*===*/ /*===*/
ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE, ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE,
ORed to OS_FILE_LOG, if a log i/o ORed to OS_FILE_LOG, if a log i/o
...@@ -641,8 +644,9 @@ fil_io( ...@@ -641,8 +644,9 @@ fil_io(
void* buf, /*!< in/out: buffer where to store read data void* buf, /*!< in/out: buffer where to store read data
or from where to write; in aio this must be or from where to write; in aio this must be
appropriately aligned */ appropriately aligned */
void* message); /*!< in: message for aio handler if non-sync void* message, /*!< in: message for aio handler if non-sync
aio used, else ignored */ aio used, else ignored */
trx_t* trx);
/**********************************************************************//** /**********************************************************************//**
Waits for an aio operation to complete. This function is used to write the Waits for an aio operation to complete. This function is used to write the
handler for completed requests. The aio array of pending requests is divided handler for completed requests. The aio array of pending requests is divided
......
...@@ -53,6 +53,7 @@ Created 10/21/1995 Heikki Tuuri ...@@ -53,6 +53,7 @@ Created 10/21/1995 Heikki Tuuri
#define os0file_h #define os0file_h
#include "univ.i" #include "univ.i"
#include "trx0types.h"
#ifndef __WIN__ #ifndef __WIN__
#include <dirent.h> #include <dirent.h>
...@@ -497,9 +498,12 @@ os_file_get_last_error( ...@@ -497,9 +498,12 @@ os_file_get_last_error(
/*******************************************************************//** /*******************************************************************//**
Requests a synchronous read operation. Requests a synchronous read operation.
@return TRUE if request was successful, FALSE if fail */ @return TRUE if request was successful, FALSE if fail */
#define os_file_read(file, buf, offset, offset_high, n) \
_os_file_read(file, buf, offset, offset_high, n, NULL)
UNIV_INTERN UNIV_INTERN
ibool ibool
os_file_read( _os_file_read(
/*=========*/ /*=========*/
os_file_t file, /*!< in: handle to a file */ os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */ void* buf, /*!< in: buffer where to read */
...@@ -507,7 +511,8 @@ os_file_read( ...@@ -507,7 +511,8 @@ os_file_read(
offset where to read */ offset where to read */
ulint offset_high,/*!< in: most significant 32 bits of ulint offset_high,/*!< in: most significant 32 bits of
offset */ offset */
ulint n); /*!< in: number of bytes to read */ ulint n, /*!< in: number of bytes to read */
trx_t* trx);
/*******************************************************************//** /*******************************************************************//**
Rewind file to its start, read at most size - 1 bytes from it to str, and Rewind file to its start, read at most size - 1 bytes from it to str, and
NUL-terminate str. All errors are silently ignored. This function is NUL-terminate str. All errors are silently ignored. This function is
...@@ -654,10 +659,11 @@ os_aio( ...@@ -654,10 +659,11 @@ os_aio(
(can be used to identify a completed (can be used to identify a completed
aio operation); ignored if mode is aio operation); ignored if mode is
OS_AIO_SYNC */ OS_AIO_SYNC */
void* message2);/*!< in: message for the aio handler void* message2,/*!< in: message for the aio handler
(can be used to identify a completed (can be used to identify a completed
aio operation); ignored if mode is aio operation); ignored if mode is
OS_AIO_SYNC */ OS_AIO_SYNC */
trx_t* trx);
/************************************************************************//** /************************************************************************//**
Wakes up all async i/o threads so that they know to exit themselves in Wakes up all async i/o threads so that they know to exit themselves in
shutdown. */ shutdown. */
......
...@@ -80,6 +80,9 @@ at a time */ ...@@ -80,6 +80,9 @@ at a time */
#define SRV_AUTO_EXTEND_INCREMENT \ #define SRV_AUTO_EXTEND_INCREMENT \
(srv_auto_extend_increment * ((1024 * 1024) / UNIV_PAGE_SIZE)) (srv_auto_extend_increment * ((1024 * 1024) / UNIV_PAGE_SIZE))
/* prototypes for new functions added to ha_innodb.cc */
ibool innobase_get_slow_log();
/* This is set to TRUE if the MySQL user has set it in MySQL */ /* This is set to TRUE if the MySQL user has set it in MySQL */
extern ibool srv_lower_case_table_names; extern ibool srv_lower_case_table_names;
...@@ -134,7 +137,7 @@ extern ibool srv_extra_undoslots; ...@@ -134,7 +137,7 @@ extern ibool srv_extra_undoslots;
extern ibool srv_fast_recovery; extern ibool srv_fast_recovery;
extern ibool srv_use_purge_thread; extern ulint srv_use_purge_thread;
extern ibool srv_auto_extend_last_data_file; extern ibool srv_auto_extend_last_data_file;
extern ulint srv_last_file_size_max; extern ulint srv_last_file_size_max;
...@@ -428,6 +431,7 @@ enum srv_thread_type { ...@@ -428,6 +431,7 @@ enum srv_thread_type {
SRV_INSERT, /**< thread flushing the insert buffer to disk */ SRV_INSERT, /**< thread flushing the insert buffer to disk */
#endif #endif
SRV_PURGE, /* thread purging undo records */ SRV_PURGE, /* thread purging undo records */
SRV_PURGE_WORKER, /* thread purging undo records */
SRV_MASTER /**< the master thread, (whose type number must SRV_MASTER /**< the master thread, (whose type number must
be biggest) */ be biggest) */
}; };
...@@ -509,6 +513,13 @@ srv_purge_thread( ...@@ -509,6 +513,13 @@ srv_purge_thread(
/*=============*/ /*=============*/
void* arg); /* in: a dummy parameter required by void* arg); /* in: a dummy parameter required by
os_thread_create */ os_thread_create */
/*************************************************************************
The undo purge thread. */
UNIV_INTERN
os_thread_ret_t
srv_purge_worker_thread(
/*====================*/
void* arg);
/*******************************************************************//** /*******************************************************************//**
Tells the Innobase server that there has been activity in the database Tells the Innobase server that there has been activity in the database
and wakes up the master thread if it is suspended (not sleeping). Used and wakes up the master thread if it is suspended (not sleeping). Used
......
...@@ -120,7 +120,7 @@ is necessary only if the memory block containing it is freed. */ ...@@ -120,7 +120,7 @@ is necessary only if the memory block containing it is freed. */
# endif /* UNIV_SYNC_DEBUG */ # endif /* UNIV_SYNC_DEBUG */
#else /* UNIV_DEBUG */ #else /* UNIV_DEBUG */
# define rw_lock_create(L, level) \ # define rw_lock_create(L, level) \
rw_lock_create_func((L), __FILE__, __LINE__) rw_lock_create_func((L), #L, NULL, 0)
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
/******************************************************************//** /******************************************************************//**
...@@ -137,8 +137,8 @@ rw_lock_create_func( ...@@ -137,8 +137,8 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG # ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */ ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */ # endif /* UNIV_SYNC_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */ const char* cfile_name, /*!< in: file name where created */
ulint cline); /*!< in: file line where created */ ulint cline); /*!< in: file line where created */
/******************************************************************//** /******************************************************************//**
...@@ -540,7 +540,8 @@ struct rw_lock_struct { ...@@ -540,7 +540,8 @@ struct rw_lock_struct {
ulint level; /*!< Level in the global latching order. */ ulint level; /*!< Level in the global latching order. */
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
ulint count_os_wait; /*!< Count of os_waits. May not be accurate */ ulint count_os_wait; /*!< Count of os_waits. May not be accurate */
const char* cfile_name;/*!< File name where lock created */ //const char* cfile_name;/*!< File name where lock created */
const char* lock_name;/*!< lock name */
/* last s-lock file/line is not guaranteed to be correct */ /* last s-lock file/line is not guaranteed to be correct */
const char* last_s_file_name;/*!< File name where last s-locked */ const char* last_s_file_name;/*!< File name where last s-locked */
const char* last_x_file_name;/*!< File name where last x-locked */ const char* last_x_file_name;/*!< File name where last x-locked */
...@@ -551,7 +552,7 @@ struct rw_lock_struct { ...@@ -551,7 +552,7 @@ struct rw_lock_struct {
are at the start of this struct, thus we can are at the start of this struct, thus we can
peek this field without causing much memory peek this field without causing much memory
bus traffic */ bus traffic */
unsigned cline:14; /*!< Line where created */ //unsigned cline:14; /*!< Line where created */
unsigned last_s_line:14; /*!< Line number where last time s-locked */ unsigned last_s_line:14; /*!< Line number where last time s-locked */
unsigned last_x_line:14; /*!< Line number where last time x-locked */ unsigned last_x_line:14; /*!< Line number where last time x-locked */
ulint magic_n; /*!< RW_LOCK_MAGIC_N */ ulint magic_n; /*!< RW_LOCK_MAGIC_N */
......
...@@ -80,7 +80,7 @@ necessary only if the memory block containing it is freed. */ ...@@ -80,7 +80,7 @@ necessary only if the memory block containing it is freed. */
# endif # endif
#else #else
# define mutex_create(M, level) \ # define mutex_create(M, level) \
mutex_create_func((M), __FILE__, __LINE__) mutex_create_func((M), #M, NULL, 0)
#endif #endif
/******************************************************************//** /******************************************************************//**
...@@ -93,8 +93,8 @@ void ...@@ -93,8 +93,8 @@ void
mutex_create_func( mutex_create_func(
/*==============*/ /*==============*/
mutex_t* mutex, /*!< in: pointer to memory */ mutex_t* mutex, /*!< in: pointer to memory */
#ifdef UNIV_DEBUG
const char* cmutex_name, /*!< in: mutex name */ const char* cmutex_name, /*!< in: mutex name */
#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG # ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */ ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */ # endif /* UNIV_SYNC_DEBUG */
...@@ -524,9 +524,9 @@ struct mutex_struct { ...@@ -524,9 +524,9 @@ struct mutex_struct {
ulint line; /*!< Line where the mutex was locked */ ulint line; /*!< Line where the mutex was locked */
ulint level; /*!< Level in the global latching order */ ulint level; /*!< Level in the global latching order */
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
#ifdef UNIV_DEBUG
const char* cfile_name;/*!< File name where mutex created */ const char* cfile_name;/*!< File name where mutex created */
ulint cline; /*!< Line where created */ ulint cline; /*!< Line where created */
#ifdef UNIV_DEBUG
os_thread_id_t thread_id; /*!< The thread id of the thread os_thread_id_t thread_id; /*!< The thread id of the thread
which locked the mutex. */ which locked the mutex. */
ulint magic_n; /*!< MUTEX_MAGIC_N */ ulint magic_n; /*!< MUTEX_MAGIC_N */
...@@ -541,9 +541,9 @@ struct mutex_struct { ...@@ -541,9 +541,9 @@ struct mutex_struct {
ulong count_os_yield; /*!< count of os_wait */ ulong count_os_yield; /*!< count of os_wait */
ulonglong lspent_time; /*!< mutex os_wait timer msec */ ulonglong lspent_time; /*!< mutex os_wait timer msec */
ulonglong lmax_spent_time;/*!< mutex os_wait timer msec */ ulonglong lmax_spent_time;/*!< mutex os_wait timer msec */
const char* cmutex_name; /*!< mutex name */
ulint mutex_type; /*!< 0=usual mutex, 1=rw_lock mutex */ ulint mutex_type; /*!< 0=usual mutex, 1=rw_lock mutex */
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
const char* cmutex_name; /*!< mutex name */
}; };
/** The global array of wait cells for implementation of the databases own /** The global array of wait cells for implementation of the databases own
......
...@@ -108,6 +108,25 @@ UNIV_INTERN ...@@ -108,6 +108,25 @@ UNIV_INTERN
ulint ulint
trx_purge(void); trx_purge(void);
/*===========*/ /*===========*/
/**********************************************************************
This function runs a purge worker batch */
UNIV_INTERN
void
trx_purge_worker(
/*=============*/
ulint worker_id);
/**********************************************************************
This function waits the event for worker batch */
UNIV_INTERN
void
trx_purge_worker_wait(void);
/*========================*/
/**********************************************************************
This function wakes the waiting worker batch */
UNIV_INTERN
void
trx_purge_worker_wake(void);
/*========================*/
/******************************************************************//** /******************************************************************//**
Prints information of the purge system to stderr. */ Prints information of the purge system to stderr. */
UNIV_INTERN UNIV_INTERN
...@@ -125,6 +144,11 @@ struct trx_purge_struct{ ...@@ -125,6 +144,11 @@ struct trx_purge_struct{
of the trx system and it never ends */ of the trx system and it never ends */
que_t* query; /*!< The query graph which will do the que_t* query; /*!< The query graph which will do the
parallelized purge operation */ parallelized purge operation */
ulint n_worker;
os_event_t worker_event;
sess_t** sess_arr;
trx_t** trx_arr;
que_t** query_arr;
rw_lock_t latch; /*!< The latch protecting the purge view. rw_lock_t latch; /*!< The latch protecting the purge view.
A purge operation must acquire an A purge operation must acquire an
x-latch here for the instant at which x-latch here for the instant at which
......
...@@ -729,6 +729,17 @@ struct trx_struct{ ...@@ -729,6 +729,17 @@ struct trx_struct{
/*------------------------------*/ /*------------------------------*/
char detailed_error[256]; /*!< detailed error message for last char detailed_error[256]; /*!< detailed error message for last
error, or empty. */ error, or empty. */
/*------------------------------*/
ulint io_reads;
ib_uint64_t io_read;
ulint io_reads_wait_timer;
ib_uint64_t lock_que_wait_ustarted;
ulint lock_que_wait_timer;
ulint innodb_que_wait_timer;
ulint distinct_page_access;
#define DPAH_SIZE 8192
byte* distinct_page_access_hash;
ibool take_stats;
}; };
#define TRX_MAX_N_THREADS 32 /* maximum number of #define TRX_MAX_N_THREADS 32 /* maximum number of
......
...@@ -1739,6 +1739,8 @@ lock_rec_enqueue_waiting( ...@@ -1739,6 +1739,8 @@ lock_rec_enqueue_waiting(
{ {
lock_t* lock; lock_t* lock;
trx_t* trx; trx_t* trx;
ulint sec;
ulint ms;
ut_ad(mutex_own(&kernel_mutex)); ut_ad(mutex_own(&kernel_mutex));
...@@ -1797,6 +1799,10 @@ lock_rec_enqueue_waiting( ...@@ -1797,6 +1799,10 @@ lock_rec_enqueue_waiting(
trx->que_state = TRX_QUE_LOCK_WAIT; trx->que_state = TRX_QUE_LOCK_WAIT;
trx->was_chosen_as_deadlock_victim = FALSE; trx->was_chosen_as_deadlock_victim = FALSE;
trx->wait_started = time(NULL); trx->wait_started = time(NULL);
if (innobase_get_slow_log() && trx->take_stats) {
ut_usectime(&sec, &ms);
trx->lock_que_wait_ustarted = (ib_uint64_t)sec * 1000000 + ms;
}
ut_a(que_thr_stop(thr)); ut_a(que_thr_stop(thr));
...@@ -3607,6 +3613,8 @@ lock_table_enqueue_waiting( ...@@ -3607,6 +3613,8 @@ lock_table_enqueue_waiting(
{ {
lock_t* lock; lock_t* lock;
trx_t* trx; trx_t* trx;
ulint sec;
ulint ms;
ut_ad(mutex_own(&kernel_mutex)); ut_ad(mutex_own(&kernel_mutex));
...@@ -3660,6 +3668,10 @@ lock_table_enqueue_waiting( ...@@ -3660,6 +3668,10 @@ lock_table_enqueue_waiting(
return(DB_SUCCESS); return(DB_SUCCESS);
} }
if (innobase_get_slow_log() && trx->take_stats) {
ut_usectime(&sec, &ms);
trx->lock_que_wait_ustarted = (ib_uint64_t)sec * 1000000 + ms;
}
trx->que_state = TRX_QUE_LOCK_WAIT; trx->que_state = TRX_QUE_LOCK_WAIT;
trx->was_chosen_as_deadlock_victim = FALSE; trx->was_chosen_as_deadlock_victim = FALSE;
trx->wait_started = time(NULL); trx->wait_started = time(NULL);
......
...@@ -3120,6 +3120,16 @@ loop: ...@@ -3120,6 +3120,16 @@ loop:
goto loop; goto loop;
} }
/* Check that the purge threads ended */
if (srv_use_purge_thread
&& (srv_n_threads_active[SRV_PURGE] != 0
|| srv_n_threads_active[SRV_PURGE_WORKER] != 0)) {
mutex_exit(&kernel_mutex);
goto loop;
}
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
mutex_enter(&(log_sys->mutex)); mutex_enter(&(log_sys->mutex));
......
...@@ -1125,6 +1125,7 @@ t2 CREATE TABLE `t2` ( ...@@ -1125,6 +1125,7 @@ t2 CREATE TABLE `t2` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t2; DROP TABLE t2;
DROP TABLE t1; DROP TABLE t1;
call mtr.add_suppression("InnoDB: insufficient history for index");
CREATE TABLE t1 (a INT, b CHAR(1)) ENGINE=InnoDB; CREATE TABLE t1 (a INT, b CHAR(1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (3,'a'),(3,'b'),(1,'c'),(0,'d'),(1,'e'); INSERT INTO t1 VALUES (3,'a'),(3,'b'),(1,'c'),(0,'d'),(1,'e');
BEGIN; BEGIN;
......
...@@ -499,6 +499,8 @@ SHOW CREATE TABLE t2; ...@@ -499,6 +499,8 @@ SHOW CREATE TABLE t2;
DROP TABLE t2; DROP TABLE t2;
DROP TABLE t1; DROP TABLE t1;
call mtr.add_suppression("InnoDB: insufficient history for index");
connect (a,localhost,root,,); connect (a,localhost,root,,);
connect (b,localhost,root,,); connect (b,localhost,root,,);
connection a; connection a;
......
set @old_innodb_file_format=@@innodb_file_format; call mtr.add_suppression("InnoDB: invalid innodb_file_format_check value");
select @@innodb_file_format; select @@innodb_file_format;
@@innodb_file_format @@innodb_file_format
Antelope Antelope
...@@ -43,5 +43,3 @@ ERROR HY000: Incorrect arguments to SET ...@@ -43,5 +43,3 @@ ERROR HY000: Incorrect arguments to SET
select @@innodb_file_format_check; select @@innodb_file_format_check;
@@innodb_file_format_check @@innodb_file_format_check
Barracuda Barracuda
set global innodb_file_format=@old_innodb_file_format;
set global innodb_file_format_check=Antelope;
-- source include/have_innodb.inc -- source include/have_innodb.inc
set @old_innodb_file_format=@@innodb_file_format;
call mtr.add_suppression("InnoDB: invalid innodb_file_format_check value");
let $format=`select @@innodb_file_format`;
let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
select @@innodb_file_format; select @@innodb_file_format;
select @@innodb_file_format_check; select @@innodb_file_format_check;
...@@ -28,5 +32,11 @@ set global innodb_file_format=on; ...@@ -28,5 +32,11 @@ set global innodb_file_format=on;
set global innodb_file_format=off; set global innodb_file_format=off;
select @@innodb_file_format_check; select @@innodb_file_format_check;
set global innodb_file_format=@old_innodb_file_format; #
set global innodb_file_format_check=Antelope; # restore environment to the state it was before this test execution
#
-- disable_query_log
eval set global innodb_file_format=$format;
eval set global innodb_file_format_check=$innodb_file_format_check_orig;
-- enable_query_log
SET @old_innodb_file_format=@@innodb_file_format; SET @old_innodb_file_format=@@innodb_file_format;
SET @old_innodb_file_per_table=@@innodb_file_per_table; SET @old_innodb_file_per_table=@@innodb_file_per_table;
SET @old_innodb_file_format_check=@@innodb_file_format_check;
SET GLOBAL innodb_file_format='Barracuda'; SET GLOBAL innodb_file_format='Barracuda';
SET GLOBAL innodb_file_per_table=ON; SET GLOBAL innodb_file_per_table=ON;
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
SET @old_innodb_file_format=@@innodb_file_format; SET @old_innodb_file_format=@@innodb_file_format;
SET @old_innodb_file_per_table=@@innodb_file_per_table; SET @old_innodb_file_per_table=@@innodb_file_per_table;
SET @old_innodb_file_format_check=@@innodb_file_format_check; let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
SET GLOBAL innodb_file_format='Barracuda'; SET GLOBAL innodb_file_format='Barracuda';
SET GLOBAL innodb_file_per_table=ON; SET GLOBAL innodb_file_per_table=ON;
...@@ -41,4 +41,4 @@ ALTER TABLE test1 ENGINE=MyISAM; ...@@ -41,4 +41,4 @@ ALTER TABLE test1 ENGINE=MyISAM;
DROP TABLE test1; DROP TABLE test1;
SET GLOBAL innodb_file_format=@old_innodb_file_format; SET GLOBAL innodb_file_format=@old_innodb_file_format;
SET GLOBAL innodb_file_per_table=@old_innodb_file_per_table; SET GLOBAL innodb_file_per_table=@old_innodb_file_per_table;
SET GLOBAL innodb_file_format_check=@old_innodb_file_format_check; eval set global innodb_file_format_check=$innodb_file_format_check_orig;
--- mysql-test/t/disabled.def.orig 2009-09-21 20:12:29.000000000 +0000 --- mysql-test/t/disabled.def.orig 2009-10-25 05:54:05.000000000 +0000
+++ mysql-test/t/disabled.def 2009-09-21 20:20:16.000000000 +0000 +++ mysql-test/t/disabled.def 2009-10-25 05:54:25.000000000 +0000
@@ -13,4 +13,6 @@ @@ -14,3 +14,5 @@
innodb_bug39438 : Bug#42383 2009-01-28 lsoares "This fails in embedded and on windows. Note that this test is not run on windows and on embedded in PB for main trees currently"
query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically
init_connect : Bug#44920 2009-07-06 pcrews MTR not processing master.opt input properly on Windows. *Must be done this way due to the nature of the bug* partition_innodb_builtin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes
partition_innodb_plugin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes
+read_many_rows_innodb : Bug#433409 2009-09-20 the test fails on 5.1.37 https://bugs.launchpad.net/bugs/433409 +read_many_rows_innodb : Bug#433409 2009-09-20 the test fails on 5.1.37 https://bugs.launchpad.net/bugs/433409
+innodb-zip : Bug#47495 2009-09-21 the test fails on ubuntu +innodb-zip : Bug#47495 2009-09-21 the test fails on ubuntu
--- mysql-test/r/innodb_bug46000.result.orig 2009-10-07 03:21:43.000000000 +0900
+++ mysql-test/r/innodb_bug46000.result 2009-10-28 14:08:55.000000000 +0900
@@ -8,10 +8,10 @@
Error 1005 Can't create table 'test.bug46000' (errno: -1)
create table bug46000(id int) engine=innodb;
create index GEN_CLUST_INDEX on bug46000(id);
-ERROR HY000: Can't create table '#sql-temporary' (errno: -1)
+ERROR HY000: Got error 1005 from storage engine
show errors;
Level Code Message
Error 1005 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index.
-Error 1005 Can't create table '#sql-temporary' (errno: -1)
+Error 1030 Got error 1005 from storage engine
create index idx on bug46000(id);
drop table bug46000;
--- mysql-test/t/innodb_bug46000.test.orig 2009-10-07 03:21:12.000000000 +0900
+++ mysql-test/t/innodb_bug46000.test 2009-10-28 14:08:37.000000000 +0900
@@ -20,7 +20,7 @@
# This 'create index' operation should fail.
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_GET_ERRNO
create index GEN_CLUST_INDEX on bug46000(id);
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
...@@ -55,6 +55,7 @@ Created 10/21/1995 Heikki Tuuri ...@@ -55,6 +55,7 @@ Created 10/21/1995 Heikki Tuuri
#include "srv0start.h" #include "srv0start.h"
#include "fil0fil.h" #include "fil0fil.h"
#include "buf0buf.h" #include "buf0buf.h"
#include "trx0sys.h"
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
# include "os0sync.h" # include "os0sync.h"
# include "os0thread.h" # include "os0thread.h"
...@@ -2046,20 +2047,28 @@ os_file_flush( ...@@ -2046,20 +2047,28 @@ os_file_flush(
/*******************************************************************//** /*******************************************************************//**
Does a synchronous read operation in Posix. Does a synchronous read operation in Posix.
@return number of bytes read, -1 if error */ @return number of bytes read, -1 if error */
#define os_file_pread(file, buf, n, offset, offset_high) \
_os_file_pread(file, buf, n, offset, offset_high, NULL);
static static
ssize_t ssize_t
os_file_pread( _os_file_pread(
/*==========*/ /*==========*/
os_file_t file, /*!< in: handle to a file */ os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */ void* buf, /*!< in: buffer where to read */
ulint n, /*!< in: number of bytes to read */ ulint n, /*!< in: number of bytes to read */
ulint offset, /*!< in: least significant 32 bits of file ulint offset, /*!< in: least significant 32 bits of file
offset from where to read */ offset from where to read */
ulint offset_high) /*!< in: most significant 32 bits of ulint offset_high, /*!< in: most significant 32 bits of
offset */ offset */
trx_t* trx)
{ {
off_t offs; off_t offs;
ssize_t n_bytes; ssize_t n_bytes;
ulint sec;
ulint ms;
ib_uint64_t start_time;
ib_uint64_t finish_time;
ut_a((offset & 0xFFFFFFFFUL) == offset); ut_a((offset & 0xFFFFFFFFUL) == offset);
...@@ -2080,6 +2089,15 @@ os_file_pread( ...@@ -2080,6 +2089,15 @@ os_file_pread(
os_n_file_reads++; os_n_file_reads++;
if (innobase_get_slow_log() && trx && trx->take_stats)
{
trx->io_reads++;
trx->io_read += n;
ut_usectime(&sec, &ms);
start_time = (ib_uint64_t)sec * 1000000 + ms;
} else {
start_time = 0;
}
#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD) #if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
os_mutex_enter(os_file_count_mutex); os_mutex_enter(os_file_count_mutex);
os_file_n_pending_preads++; os_file_n_pending_preads++;
...@@ -2093,6 +2111,13 @@ os_file_pread( ...@@ -2093,6 +2111,13 @@ os_file_pread(
os_n_pending_reads--; os_n_pending_reads--;
os_mutex_exit(os_file_count_mutex); os_mutex_exit(os_file_count_mutex);
if (innobase_get_slow_log() && trx && trx->take_stats && start_time)
{
ut_usectime(&sec, &ms);
finish_time = (ib_uint64_t)sec * 1000000 + ms;
trx->io_reads_wait_timer += (ulint)(finish_time - start_time);
}
return(n_bytes); return(n_bytes);
#else #else
{ {
...@@ -2123,6 +2148,13 @@ os_file_pread( ...@@ -2123,6 +2148,13 @@ os_file_pread(
os_n_pending_reads--; os_n_pending_reads--;
os_mutex_exit(os_file_count_mutex); os_mutex_exit(os_file_count_mutex);
if (innobase_get_slow_log() && trx && trx->take_stats && start_time)
{
ut_usectime(&sec, &ms);
finish_time = (ib_uint64_t)sec * 1000000 + ms;
trx->io_reads_wait_timer += (ulint)(finish_time - start_time);
}
return(ret); return(ret);
} }
#endif #endif
...@@ -2247,7 +2279,7 @@ Requests a synchronous positioned read operation. ...@@ -2247,7 +2279,7 @@ Requests a synchronous positioned read operation.
@return TRUE if request was successful, FALSE if fail */ @return TRUE if request was successful, FALSE if fail */
UNIV_INTERN UNIV_INTERN
ibool ibool
os_file_read( _os_file_read(
/*=========*/ /*=========*/
os_file_t file, /*!< in: handle to a file */ os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */ void* buf, /*!< in: buffer where to read */
...@@ -2255,7 +2287,8 @@ os_file_read( ...@@ -2255,7 +2287,8 @@ os_file_read(
offset where to read */ offset where to read */
ulint offset_high, /*!< in: most significant 32 bits of ulint offset_high, /*!< in: most significant 32 bits of
offset */ offset */
ulint n) /*!< in: number of bytes to read */ ulint n, /*!< in: number of bytes to read */
trx_t* trx)
{ {
#ifdef __WIN__ #ifdef __WIN__
BOOL ret; BOOL ret;
...@@ -2319,7 +2352,7 @@ try_again: ...@@ -2319,7 +2352,7 @@ try_again:
os_bytes_read_since_printout += n; os_bytes_read_since_printout += n;
try_again: try_again:
ret = os_file_pread(file, buf, n, offset, offset_high); ret = _os_file_pread(file, buf, n, offset, offset_high, trx);
if ((ulint)ret == n) { if ((ulint)ret == n) {
...@@ -3211,7 +3244,8 @@ os_aio_array_reserve_slot( ...@@ -3211,7 +3244,8 @@ os_aio_array_reserve_slot(
offset */ offset */
ulint offset_high, /*!< in: most significant 32 bits of ulint offset_high, /*!< in: most significant 32 bits of
offset */ offset */
ulint len) /*!< in: length of the block to read or write */ ulint len, /*!< in: length of the block to read or write */
trx_t* trx)
{ {
os_aio_slot_t* slot; os_aio_slot_t* slot;
#ifdef WIN_ASYNC_IO #ifdef WIN_ASYNC_IO
...@@ -3482,10 +3516,11 @@ os_aio( ...@@ -3482,10 +3516,11 @@ os_aio(
(can be used to identify a completed (can be used to identify a completed
aio operation); ignored if mode is aio operation); ignored if mode is
OS_AIO_SYNC */ OS_AIO_SYNC */
void* message2)/*!< in: message for the aio handler void* message2,/*!< in: message for the aio handler
(can be used to identify a completed (can be used to identify a completed
aio operation); ignored if mode is aio operation); ignored if mode is
OS_AIO_SYNC */ OS_AIO_SYNC */
trx_t* trx)
{ {
os_aio_array_t* array; os_aio_array_t* array;
os_aio_slot_t* slot; os_aio_slot_t* slot;
...@@ -3524,8 +3559,8 @@ os_aio( ...@@ -3524,8 +3559,8 @@ os_aio(
wait in the Windows case. */ wait in the Windows case. */
if (type == OS_FILE_READ) { if (type == OS_FILE_READ) {
return(os_file_read(file, buf, offset, return(_os_file_read(file, buf, offset,
offset_high, n)); offset_high, n, trx));
} }
ut_a(type == OS_FILE_WRITE); ut_a(type == OS_FILE_WRITE);
...@@ -3558,8 +3593,13 @@ try_again: ...@@ -3558,8 +3593,13 @@ try_again:
ut_error; ut_error;
} }
if (trx && type == OS_FILE_READ)
{
trx->io_reads++;
trx->io_read += n;
}
slot = os_aio_array_reserve_slot(type, array, message1, message2, file, slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
name, buf, offset, offset_high, n); name, buf, offset, offset_high, n, trx);
if (type == OS_FILE_READ) { if (type == OS_FILE_READ) {
if (os_aio_use_native_aio) { if (os_aio_use_native_aio) {
#ifdef WIN_ASYNC_IO #ifdef WIN_ASYNC_IO
......
...@@ -1770,7 +1770,6 @@ row_create_table_for_mysql( ...@@ -1770,7 +1770,6 @@ row_create_table_for_mysql(
const char* table_name; const char* table_name;
ulint table_name_len; ulint table_name_len;
ulint err; ulint err;
ulint i;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
...@@ -1805,15 +1804,6 @@ err_exit: ...@@ -1805,15 +1804,6 @@ err_exit:
goto err_exit; goto err_exit;
} }
/* Check that no reserved column names are used. */
for (i = 0; i < dict_table_get_n_user_cols(table); i++) {
if (dict_col_name_is_reserved(
dict_table_get_col_name(table, i))) {
goto err_exit;
}
}
trx_start_if_not_started(trx); trx_start_if_not_started(trx);
/* The table name is prefixed with the database name and a '/'. /* The table name is prefixed with the database name and a '/'.
......
...@@ -103,6 +103,9 @@ Created 10/8/1995 Heikki Tuuri ...@@ -103,6 +103,9 @@ Created 10/8/1995 Heikki Tuuri
#include "ha_prototypes.h" #include "ha_prototypes.h"
#include "trx0i_s.h" #include "trx0i_s.h"
/* prototypes for new functions added to ha_innodb.cc */
ibool innobase_get_slow_log();
/* This is set to TRUE if the MySQL user has set it in MySQL; currently /* This is set to TRUE if the MySQL user has set it in MySQL; currently
affects only FOREIGN KEY definition parsing */ affects only FOREIGN KEY definition parsing */
UNIV_INTERN ibool srv_lower_case_table_names = FALSE; UNIV_INTERN ibool srv_lower_case_table_names = FALSE;
...@@ -162,7 +165,7 @@ UNIV_INTERN ibool srv_extra_undoslots = FALSE; ...@@ -162,7 +165,7 @@ UNIV_INTERN ibool srv_extra_undoslots = FALSE;
UNIV_INTERN ibool srv_fast_recovery = FALSE; UNIV_INTERN ibool srv_fast_recovery = FALSE;
UNIV_INTERN ibool srv_use_purge_thread = FALSE; UNIV_INTERN ulint srv_use_purge_thread = 0;
/* if TRUE, then we auto-extend the last data file */ /* if TRUE, then we auto-extend the last data file */
UNIV_INTERN ibool srv_auto_extend_last_data_file = FALSE; UNIV_INTERN ibool srv_auto_extend_last_data_file = FALSE;
...@@ -1154,6 +1157,10 @@ srv_conc_enter_innodb( ...@@ -1154,6 +1157,10 @@ srv_conc_enter_innodb(
ibool has_slept = FALSE; ibool has_slept = FALSE;
srv_conc_slot_t* slot = NULL; srv_conc_slot_t* slot = NULL;
ulint i; ulint i;
ib_uint64_t start_time = 0L;
ib_uint64_t finish_time = 0L;
ulint sec;
ulint ms;
if (trx->mysql_thd != NULL if (trx->mysql_thd != NULL
&& thd_is_replication_slave_thread(trx->mysql_thd)) { && thd_is_replication_slave_thread(trx->mysql_thd)) {
...@@ -1230,6 +1237,7 @@ retry: ...@@ -1230,6 +1237,7 @@ retry:
switches. */ switches. */
if (SRV_THREAD_SLEEP_DELAY > 0) { if (SRV_THREAD_SLEEP_DELAY > 0) {
os_thread_sleep(SRV_THREAD_SLEEP_DELAY); os_thread_sleep(SRV_THREAD_SLEEP_DELAY);
trx->innodb_que_wait_timer += SRV_THREAD_SLEEP_DELAY;
} }
trx->op_info = ""; trx->op_info = "";
...@@ -1285,12 +1293,25 @@ retry: ...@@ -1285,12 +1293,25 @@ retry:
/* Go to wait for the event; when a thread leaves InnoDB it will /* Go to wait for the event; when a thread leaves InnoDB it will
release this thread */ release this thread */
if (innobase_get_slow_log() && trx->take_stats) {
ut_usectime(&sec, &ms);
start_time = (ib_uint64_t)sec * 1000000 + ms;
} else {
start_time = 0;
}
trx->op_info = "waiting in InnoDB queue"; trx->op_info = "waiting in InnoDB queue";
os_event_wait(slot->event); os_event_wait(slot->event);
trx->op_info = ""; trx->op_info = "";
if (innobase_get_slow_log() && trx->take_stats && start_time) {
ut_usectime(&sec, &ms);
finish_time = (ib_uint64_t)sec * 1000000 + ms;
trx->innodb_que_wait_timer += (ulint)(finish_time - start_time);
}
os_fast_mutex_lock(&srv_conc_mutex); os_fast_mutex_lock(&srv_conc_mutex);
srv_conc_n_waiting_threads--; srv_conc_n_waiting_threads--;
...@@ -3130,6 +3151,7 @@ srv_purge_thread( ...@@ -3130,6 +3151,7 @@ srv_purge_thread(
ulint n_pages_purged_sum = 1; /* dummy */ ulint n_pages_purged_sum = 1; /* dummy */
ulint history_len; ulint history_len;
ulint sleep_ms= 10000; /* initial: 10 sec. */ ulint sleep_ms= 10000; /* initial: 10 sec. */
ibool can_be_last = FALSE;
#ifdef UNIV_DEBUG_THREAD_CREATION #ifdef UNIV_DEBUG_THREAD_CREATION
fprintf(stderr, "Purge thread starts, id %lu\n", fprintf(stderr, "Purge thread starts, id %lu\n",
...@@ -3142,8 +3164,21 @@ srv_purge_thread( ...@@ -3142,8 +3164,21 @@ srv_purge_thread(
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
loop: loop:
if (srv_fast_shutdown && srv_shutdown_state > 0) { if (srv_shutdown_state > 0) {
goto exit_func; if (srv_fast_shutdown) {
/* someone other should wait the end of the workers */
goto exit_func;
}
mutex_enter(&kernel_mutex);
if (srv_n_threads_active[SRV_PURGE_WORKER]) {
can_be_last = FALSE;
} else {
can_be_last = TRUE;
}
mutex_exit(&kernel_mutex);
sleep_ms = 10;
} }
os_thread_sleep( sleep_ms * 1000 ); os_thread_sleep( sleep_ms * 1000 );
...@@ -3164,6 +3199,15 @@ loop: ...@@ -3164,6 +3199,15 @@ loop:
n_pages_purged_sum += n_pages_purged; n_pages_purged_sum += n_pages_purged;
} while (n_pages_purged); } while (n_pages_purged);
if (srv_shutdown_state > 0 && can_be_last) {
/* the last trx_purge() is executed without workers */
goto exit_func;
}
if (n_pages_purged_sum) {
srv_active_wake_master_thread();
}
if (n_pages_purged_sum == 0) if (n_pages_purged_sum == 0)
sleep_ms *= 10; sleep_ms *= 10;
if (sleep_ms > 10000) if (sleep_ms > 10000)
...@@ -3172,9 +3216,62 @@ loop: ...@@ -3172,9 +3216,62 @@ loop:
goto loop; goto loop;
exit_func: exit_func:
/* We count the number of threads in os_thread_exit(). A created trx_purge_worker_wake(); /* It may not make sense. for safety only */
thread should always use that to exit and not use return() to exit. */
/* wake master thread to flush the pages */
srv_wake_master_thread();
mutex_enter(&kernel_mutex);
srv_n_threads_active[SRV_PURGE]--;
mutex_exit(&kernel_mutex);
os_thread_exit(NULL);
OS_THREAD_DUMMY_RETURN;
}
/*************************************************************************
A thread which is devoted to purge, for take over the master thread's
purging */
UNIV_INTERN
os_thread_ret_t
srv_purge_worker_thread(
/*====================*/
void* arg)
{
ulint worker_id; /* index for array */
worker_id = *((ulint*)arg);
#ifdef UNIV_DEBUG_THREAD_CREATION
fprintf(stderr, "Purge worker thread starts, id %lu\n",
os_thread_pf(os_thread_get_curr_id()));
#endif
srv_table_reserve_slot(SRV_PURGE_WORKER);
mutex_enter(&kernel_mutex);
srv_n_threads_active[SRV_PURGE_WORKER]++;
mutex_exit(&kernel_mutex);
loop:
/* purge worker threads only works when srv_shutdown_state==0 */
/* for safety and exactness. */
if (srv_shutdown_state > 0) {
goto exit_func;
}
trx_purge_worker_wait();
if (srv_shutdown_state > 0) {
goto exit_func;
}
trx_purge_worker(worker_id);
goto loop;
exit_func:
mutex_enter(&kernel_mutex);
srv_n_threads_active[SRV_PURGE_WORKER]--;
mutex_exit(&kernel_mutex);
os_thread_exit(NULL); os_thread_exit(NULL);
OS_THREAD_DUMMY_RETURN; OS_THREAD_DUMMY_RETURN;
......
...@@ -141,9 +141,9 @@ static mutex_t ios_mutex; ...@@ -141,9 +141,9 @@ static mutex_t ios_mutex;
static ulint ios; static ulint ios;
/** io_handler_thread parameters for thread identification */ /** io_handler_thread parameters for thread identification */
static ulint n[SRV_MAX_N_IO_THREADS + 5]; static ulint n[SRV_MAX_N_IO_THREADS + 5 + 64];
/** io_handler_thread identifiers */ /** io_handler_thread identifiers */
static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 5]; static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 5 + 64];
/** We use this mutex to test the return value of pthread_mutex_trylock /** We use this mutex to test the return value of pthread_mutex_trylock
on successful locking. HP-UX does NOT return 0, though Linux et al do. */ on successful locking. HP-UX does NOT return 0, though Linux et al do. */
...@@ -1739,8 +1739,17 @@ innobase_start_or_create_for_mysql(void) ...@@ -1739,8 +1739,17 @@ innobase_start_or_create_for_mysql(void)
+ (1 + SRV_MAX_N_IO_THREADS)); + (1 + SRV_MAX_N_IO_THREADS));
if (srv_use_purge_thread) { if (srv_use_purge_thread) {
ulint i;
os_thread_create(&srv_purge_thread, NULL, thread_ids os_thread_create(&srv_purge_thread, NULL, thread_ids
+ (4 + SRV_MAX_N_IO_THREADS)); + (4 + SRV_MAX_N_IO_THREADS));
for (i = 0; i < srv_use_purge_thread - 1; i++) {
n[5 + i + SRV_MAX_N_IO_THREADS] = i; /* using as index for arrays in purge_sys */
os_thread_create(&srv_purge_worker_thread,
n + (5 + i + SRV_MAX_N_IO_THREADS),
thread_ids + (5 + i + SRV_MAX_N_IO_THREADS));
}
} }
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
/* buf_debug_prints = TRUE; */ /* buf_debug_prints = TRUE; */
......
...@@ -492,12 +492,12 @@ sync_array_cell_print( ...@@ -492,12 +492,12 @@ sync_array_cell_print(
mutex = cell->old_wait_mutex; mutex = cell->old_wait_mutex;
fprintf(file, fprintf(file,
"Mutex at %p created file %s line %lu, lock var %lu\n" "Mutex at %p '%s', lock var %lu\n"
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
"Last time reserved in file %s line %lu, " "Last time reserved in file %s line %lu, "
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
"waiters flag %lu\n", "waiters flag %lu\n",
(void*) mutex, mutex->cfile_name, (ulong) mutex->cline, (void*) mutex, mutex->cmutex_name,
(ulong) mutex->lock_word, (ulong) mutex->lock_word,
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
mutex->file_name, (ulong) mutex->line, mutex->file_name, (ulong) mutex->line,
...@@ -513,9 +513,8 @@ sync_array_cell_print( ...@@ -513,9 +513,8 @@ sync_array_cell_print(
rwlock = cell->old_wait_rw_lock; rwlock = cell->old_wait_rw_lock;
fprintf(file, fprintf(file,
" RW-latch at %p created in file %s line %lu\n", " RW-latch at %p '%s'\n",
(void*) rwlock, rwlock->cfile_name, (void*) rwlock, rwlock->lock_name);
(ulong) rwlock->cline);
writer = rw_lock_get_writer(rwlock); writer = rw_lock_get_writer(rwlock);
if (writer != RW_LOCK_NOT_LOCKED) { if (writer != RW_LOCK_NOT_LOCKED) {
fprintf(file, fprintf(file,
......
...@@ -230,8 +230,8 @@ rw_lock_create_func( ...@@ -230,8 +230,8 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG # ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */ ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */ # endif /* UNIV_SYNC_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */ const char* cfile_name, /*!< in: file name where created */
ulint cline) /*!< in: file line where created */ ulint cline) /*!< in: file line where created */
{ {
...@@ -241,14 +241,15 @@ rw_lock_create_func( ...@@ -241,14 +241,15 @@ rw_lock_create_func(
#ifndef INNODB_RW_LOCKS_USE_ATOMICS #ifndef INNODB_RW_LOCKS_USE_ATOMICS
mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK); mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
lock->mutex.cfile_name = cfile_name; ut_d(lock->mutex.cfile_name = cfile_name);
lock->mutex.cline = cline; ut_d(lock->mutex.cline = cline);
ut_d(lock->mutex.cmutex_name = cmutex_name); lock->mutex.cmutex_name = cmutex_name;
ut_d(lock->mutex.mutex_type = 1); ut_d(lock->mutex.mutex_type = 1);
#else /* INNODB_RW_LOCKS_USE_ATOMICS */ #else /* INNODB_RW_LOCKS_USE_ATOMICS */
# ifdef UNIV_DEBUG # ifdef UNIV_DEBUG
UT_NOT_USED(cmutex_name); UT_NOT_USED(cfile_name);
UT_NOT_USED(cline);
# endif # endif
#endif /* INNODB_RW_LOCKS_USE_ATOMICS */ #endif /* INNODB_RW_LOCKS_USE_ATOMICS */
...@@ -268,8 +269,7 @@ rw_lock_create_func( ...@@ -268,8 +269,7 @@ rw_lock_create_func(
lock->magic_n = RW_LOCK_MAGIC_N; lock->magic_n = RW_LOCK_MAGIC_N;
lock->cfile_name = cfile_name; lock->lock_name = cmutex_name;
lock->cline = (unsigned int) cline;
lock->count_os_wait = 0; lock->count_os_wait = 0;
lock->last_s_file_name = "not yet reserved"; lock->last_s_file_name = "not yet reserved";
...@@ -304,8 +304,6 @@ rw_lock_free( ...@@ -304,8 +304,6 @@ rw_lock_free(
ut_ad(rw_lock_validate(lock)); ut_ad(rw_lock_validate(lock));
ut_a(lock->lock_word == X_LOCK_DECR); ut_a(lock->lock_word == X_LOCK_DECR);
lock->magic_n = 0;
#ifndef INNODB_RW_LOCKS_USE_ATOMICS #ifndef INNODB_RW_LOCKS_USE_ATOMICS
mutex_free(rw_lock_get_mutex(lock)); mutex_free(rw_lock_get_mutex(lock));
#endif /* INNODB_RW_LOCKS_USE_ATOMICS */ #endif /* INNODB_RW_LOCKS_USE_ATOMICS */
...@@ -325,6 +323,8 @@ rw_lock_free( ...@@ -325,6 +323,8 @@ rw_lock_free(
UT_LIST_REMOVE(list, rw_lock_list, lock); UT_LIST_REMOVE(list, rw_lock_list, lock);
mutex_exit(&rw_lock_list_mutex); mutex_exit(&rw_lock_list_mutex);
lock->magic_n = 0;
} }
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
...@@ -390,10 +390,10 @@ lock_loop: ...@@ -390,10 +390,10 @@ lock_loop:
if (srv_print_latch_waits) { if (srv_print_latch_waits) {
fprintf(stderr, fprintf(stderr,
"Thread %lu spin wait rw-s-lock at %p" "Thread %lu spin wait rw-s-lock at %p"
" cfile %s cline %lu rnds %lu\n", " '%s' rnds %lu\n",
(ulong) os_thread_pf(os_thread_get_curr_id()), (ulong) os_thread_pf(os_thread_get_curr_id()),
(void*) lock, (void*) lock,
lock->cfile_name, (ulong) lock->cline, (ulong) i); lock->lock_name, (ulong) i);
} }
/* We try once again to obtain the lock */ /* We try once again to obtain the lock */
...@@ -426,10 +426,9 @@ lock_loop: ...@@ -426,10 +426,9 @@ lock_loop:
if (srv_print_latch_waits) { if (srv_print_latch_waits) {
fprintf(stderr, fprintf(stderr,
"Thread %lu OS wait rw-s-lock at %p" "Thread %lu OS wait rw-s-lock at %p"
" cfile %s cline %lu\n", " '%s'\n",
os_thread_pf(os_thread_get_curr_id()), os_thread_pf(os_thread_get_curr_id()),
(void*) lock, lock->cfile_name, (void*) lock, lock->lock_name);
(ulong) lock->cline);
} }
/* these stats may not be accurate */ /* these stats may not be accurate */
...@@ -648,9 +647,9 @@ lock_loop: ...@@ -648,9 +647,9 @@ lock_loop:
if (srv_print_latch_waits) { if (srv_print_latch_waits) {
fprintf(stderr, fprintf(stderr,
"Thread %lu spin wait rw-x-lock at %p" "Thread %lu spin wait rw-x-lock at %p"
" cfile %s cline %lu rnds %lu\n", " '%s' rnds %lu\n",
os_thread_pf(os_thread_get_curr_id()), (void*) lock, os_thread_pf(os_thread_get_curr_id()), (void*) lock,
lock->cfile_name, (ulong) lock->cline, (ulong) i); lock->lock_name, (ulong) i);
} }
sync_array_reserve_cell(sync_primary_wait_array, sync_array_reserve_cell(sync_primary_wait_array,
...@@ -671,9 +670,9 @@ lock_loop: ...@@ -671,9 +670,9 @@ lock_loop:
if (srv_print_latch_waits) { if (srv_print_latch_waits) {
fprintf(stderr, fprintf(stderr,
"Thread %lu OS wait for rw-x-lock at %p" "Thread %lu OS wait for rw-x-lock at %p"
" cfile %s cline %lu\n", " '%s'\n",
os_thread_pf(os_thread_get_curr_id()), (void*) lock, os_thread_pf(os_thread_get_curr_id()), (void*) lock,
lock->cfile_name, (ulong) lock->cline); lock->lock_name);
} }
/* these stats may not be accurate */ /* these stats may not be accurate */
......
...@@ -237,8 +237,8 @@ void ...@@ -237,8 +237,8 @@ void
mutex_create_func( mutex_create_func(
/*==============*/ /*==============*/
mutex_t* mutex, /*!< in: pointer to memory */ mutex_t* mutex, /*!< in: pointer to memory */
#ifdef UNIV_DEBUG
const char* cmutex_name, /*!< in: mutex name */ const char* cmutex_name, /*!< in: mutex name */
#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG # ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */ ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */ # endif /* UNIV_SYNC_DEBUG */
...@@ -262,11 +262,13 @@ mutex_create_func( ...@@ -262,11 +262,13 @@ mutex_create_func(
mutex->file_name = "not yet reserved"; mutex->file_name = "not yet reserved";
mutex->level = level; mutex->level = level;
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
#ifdef UNIV_DEBUG
mutex->cfile_name = cfile_name; mutex->cfile_name = cfile_name;
mutex->cline = cline; mutex->cline = cline;
#endif /* UNIV_DEBUG */
mutex->count_os_wait = 0; mutex->count_os_wait = 0;
#ifdef UNIV_DEBUG
mutex->cmutex_name= cmutex_name; mutex->cmutex_name= cmutex_name;
#ifdef UNIV_DEBUG
mutex->count_using= 0; mutex->count_using= 0;
mutex->mutex_type= 0; mutex->mutex_type= 0;
mutex->lspent_time= 0; mutex->lspent_time= 0;
...@@ -498,9 +500,9 @@ spin_loop: ...@@ -498,9 +500,9 @@ spin_loop:
#ifdef UNIV_SRV_PRINT_LATCH_WAITS #ifdef UNIV_SRV_PRINT_LATCH_WAITS
fprintf(stderr, fprintf(stderr,
"Thread %lu spin wait mutex at %p" "Thread %lu spin wait mutex at %p"
" cfile %s cline %lu rnds %lu\n", " '%s' rnds %lu\n",
(ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex, (ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex,
mutex->cfile_name, (ulong) mutex->cline, (ulong) i); mutex->cmutex_name, (ulong) i);
#endif #endif
mutex_spin_round_count += i; mutex_spin_round_count += i;
...@@ -575,9 +577,9 @@ spin_loop: ...@@ -575,9 +577,9 @@ spin_loop:
#ifdef UNIV_SRV_PRINT_LATCH_WAITS #ifdef UNIV_SRV_PRINT_LATCH_WAITS
fprintf(stderr, fprintf(stderr,
"Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n", "Thread %lu OS wait mutex at %p '%s' rnds %lu\n",
(ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex, (ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex,
mutex->cfile_name, (ulong) mutex->cline, (ulong) i); mutex->cmutex_name, (ulong) i);
#endif #endif
mutex_os_wait_count++; mutex_os_wait_count++;
...@@ -873,9 +875,8 @@ sync_thread_levels_g( ...@@ -873,9 +875,8 @@ sync_thread_levels_g(
if (mutex->magic_n == MUTEX_MAGIC_N) { if (mutex->magic_n == MUTEX_MAGIC_N) {
fprintf(stderr, fprintf(stderr,
"Mutex created at %s %lu\n", "Mutex '%s'\n",
mutex->cfile_name, mutex->cmutex_name);
(ulong) mutex->cline);
if (mutex_get_lock_word(mutex) != 0) { if (mutex_get_lock_word(mutex) != 0) {
const char* file_name; const char* file_name;
......
...@@ -184,8 +184,9 @@ this query graph. ...@@ -184,8 +184,9 @@ this query graph.
@return own: the query graph */ @return own: the query graph */
static static
que_t* que_t*
trx_purge_graph_build(void) trx_purge_graph_build(
/*=======================*/ /*=======================*/
trx_t* trx)
{ {
mem_heap_t* heap; mem_heap_t* heap;
que_fork_t* fork; que_fork_t* fork;
...@@ -194,7 +195,7 @@ trx_purge_graph_build(void) ...@@ -194,7 +195,7 @@ trx_purge_graph_build(void)
heap = mem_heap_create(512); heap = mem_heap_create(512);
fork = que_fork_create(NULL, NULL, QUE_FORK_PURGE, heap); fork = que_fork_create(NULL, NULL, QUE_FORK_PURGE, heap);
fork->trx = purge_sys->trx; fork->trx = trx;
thr = que_thr_create(fork, heap); thr = que_thr_create(fork, heap);
...@@ -243,10 +244,35 @@ trx_purge_sys_create(void) ...@@ -243,10 +244,35 @@ trx_purge_sys_create(void)
ut_a(trx_start_low(purge_sys->trx, ULINT_UNDEFINED)); ut_a(trx_start_low(purge_sys->trx, ULINT_UNDEFINED));
purge_sys->query = trx_purge_graph_build(); purge_sys->query = trx_purge_graph_build(purge_sys->trx);
purge_sys->view = read_view_oldest_copy_or_open_new(ut_dulint_zero, purge_sys->view = read_view_oldest_copy_or_open_new(ut_dulint_zero,
purge_sys->heap); purge_sys->heap);
purge_sys->n_worker = 0;
if (srv_use_purge_thread > 1) {
/* Use worker threads */
ulint i;
purge_sys->n_worker = srv_use_purge_thread - 1;
purge_sys->sess_arr = mem_alloc(sizeof(sess_t*) * purge_sys->n_worker);
purge_sys->trx_arr = mem_alloc(sizeof(trx_t*) * purge_sys->n_worker);
purge_sys->query_arr = mem_alloc(sizeof(que_t*) * purge_sys->n_worker);
purge_sys->worker_event = os_event_create(NULL);
os_event_reset(purge_sys->worker_event);
for (i = 0; i < purge_sys->n_worker; i++) {
purge_sys->sess_arr[i] = sess_open();
purge_sys->trx_arr[i] = purge_sys->sess_arr[i]->trx;
purge_sys->trx_arr[i]->is_purge = 1;
ut_a(trx_start_low(purge_sys->trx_arr[i], ULINT_UNDEFINED));
purge_sys->query_arr[i] = trx_purge_graph_build(purge_sys->trx_arr[i]);
}
}
} }
/*================ UNDO LOG HISTORY LIST =============================*/ /*================ UNDO LOG HISTORY LIST =============================*/
...@@ -1110,7 +1136,7 @@ trx_purge(void) ...@@ -1110,7 +1136,7 @@ trx_purge(void)
/* Handle at most 20 undo log pages in one purge batch */ /* Handle at most 20 undo log pages in one purge batch */
purge_sys->handle_limit = purge_sys->n_pages_handled + 20; purge_sys->handle_limit = purge_sys->n_pages_handled + 20 * (srv_use_purge_thread + 1);
old_pages_handled = purge_sys->n_pages_handled; old_pages_handled = purge_sys->n_pages_handled;
...@@ -1129,6 +1155,9 @@ trx_purge(void) ...@@ -1129,6 +1155,9 @@ trx_purge(void)
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
if (purge_sys->n_worker)
os_event_set(purge_sys->worker_event);
/* srv_que_task_enqueue(thr2); */ /* srv_que_task_enqueue(thr2); */
if (srv_print_thread_releases) { if (srv_print_thread_releases) {
...@@ -1138,6 +1167,9 @@ trx_purge(void) ...@@ -1138,6 +1167,9 @@ trx_purge(void)
que_run_threads(thr); que_run_threads(thr);
if (purge_sys->n_worker)
os_event_reset(purge_sys->worker_event);
if (srv_print_thread_releases) { if (srv_print_thread_releases) {
fprintf(stderr, fprintf(stderr,
...@@ -1148,6 +1180,52 @@ trx_purge(void) ...@@ -1148,6 +1180,52 @@ trx_purge(void)
return(purge_sys->n_pages_handled - old_pages_handled); return(purge_sys->n_pages_handled - old_pages_handled);
} }
/**********************************************************************
This function runs a purge worker batch */
UNIV_INTERN
void
trx_purge_worker(
/*=============*/
ulint worker_id)
{
que_thr_t* thr;
mutex_enter(&kernel_mutex);
thr = que_fork_start_command(purge_sys->query_arr[worker_id]);
ut_ad(thr);
mutex_exit(&kernel_mutex);
que_run_threads(thr);
if (purge_sys->state == TRX_STOP_PURGE) { /* optimistic */
os_event_reset(purge_sys->worker_event);
}
}
/**********************************************************************
This function waits the event for worker batch */
UNIV_INTERN
void
trx_purge_worker_wait(void)
/*=======================*/
{
os_event_wait(purge_sys->worker_event);
}
/**********************************************************************
This function wakes the waiting worker batch */
UNIV_INTERN
void
trx_purge_worker_wake(void)
/*=======================*/
{
if (purge_sys->n_worker)
os_event_set(purge_sys->worker_event);
}
/******************************************************************//** /******************************************************************//**
Prints information of the purge system to stderr. */ Prints information of the purge system to stderr. */
UNIV_INTERN UNIV_INTERN
......
...@@ -178,6 +178,15 @@ trx_create( ...@@ -178,6 +178,15 @@ trx_create(
trx->global_read_view = NULL; trx->global_read_view = NULL;
trx->read_view = NULL; trx->read_view = NULL;
trx->io_reads = 0;
trx->io_read = 0;
trx->io_reads_wait_timer = 0;
trx->lock_que_wait_timer = 0;
trx->innodb_que_wait_timer = 0;
trx->distinct_page_access = 0;
trx->distinct_page_access_hash = NULL;
trx->take_stats = FALSE;
/* Set X/Open XA transaction identification to NULL */ /* Set X/Open XA transaction identification to NULL */
memset(&trx->xid, 0, sizeof(trx->xid)); memset(&trx->xid, 0, sizeof(trx->xid));
trx->xid.formatID = -1; trx->xid.formatID = -1;
...@@ -215,6 +224,11 @@ trx_allocate_for_mysql(void) ...@@ -215,6 +224,11 @@ trx_allocate_for_mysql(void)
trx->mysql_process_no = os_proc_get_number(); trx->mysql_process_no = os_proc_get_number();
if (innobase_get_slow_log() && trx->take_stats) {
trx->distinct_page_access_hash = mem_alloc(DPAH_SIZE);
memset(trx->distinct_page_access_hash, 0, DPAH_SIZE);
}
return(trx); return(trx);
} }
...@@ -346,6 +360,12 @@ trx_free_for_mysql( ...@@ -346,6 +360,12 @@ trx_free_for_mysql(
/*===============*/ /*===============*/
trx_t* trx) /*!< in, own: trx object */ trx_t* trx) /*!< in, own: trx object */
{ {
if (trx->distinct_page_access_hash)
{
mem_free(trx->distinct_page_access_hash);
trx->distinct_page_access_hash= NULL;
}
mutex_enter(&kernel_mutex); mutex_enter(&kernel_mutex);
UT_LIST_REMOVE(mysql_trx_list, trx_sys->mysql_trx_list, trx); UT_LIST_REMOVE(mysql_trx_list, trx_sys->mysql_trx_list, trx);
...@@ -367,6 +387,12 @@ trx_free_for_background( ...@@ -367,6 +387,12 @@ trx_free_for_background(
/*====================*/ /*====================*/
trx_t* trx) /*!< in, own: trx object */ trx_t* trx) /*!< in, own: trx object */
{ {
if (trx->distinct_page_access_hash)
{
mem_free(trx->distinct_page_access_hash);
trx->distinct_page_access_hash= NULL;
}
mutex_enter(&kernel_mutex); mutex_enter(&kernel_mutex);
trx_free(trx); trx_free(trx);
...@@ -1072,6 +1098,9 @@ trx_end_lock_wait( ...@@ -1072,6 +1098,9 @@ trx_end_lock_wait(
trx_t* trx) /*!< in: transaction */ trx_t* trx) /*!< in: transaction */
{ {
que_thr_t* thr; que_thr_t* thr;
ulint sec;
ulint ms;
ib_uint64_t now;
ut_ad(mutex_own(&kernel_mutex)); ut_ad(mutex_own(&kernel_mutex));
ut_ad(trx->que_state == TRX_QUE_LOCK_WAIT); ut_ad(trx->que_state == TRX_QUE_LOCK_WAIT);
...@@ -1086,6 +1115,11 @@ trx_end_lock_wait( ...@@ -1086,6 +1115,11 @@ trx_end_lock_wait(
thr = UT_LIST_GET_FIRST(trx->wait_thrs); thr = UT_LIST_GET_FIRST(trx->wait_thrs);
} }
if (innobase_get_slow_log() && trx->take_stats) {
ut_usectime(&sec, &ms);
now = (ib_uint64_t)sec * 1000000 + ms;
trx->lock_que_wait_timer += (ulint)(now - trx->lock_que_wait_ustarted);
}
trx->que_state = TRX_QUE_RUNNING; trx->que_state = TRX_QUE_RUNNING;
} }
...@@ -1099,6 +1133,9 @@ trx_lock_wait_to_suspended( ...@@ -1099,6 +1133,9 @@ trx_lock_wait_to_suspended(
trx_t* trx) /*!< in: transaction in the TRX_QUE_LOCK_WAIT state */ trx_t* trx) /*!< in: transaction in the TRX_QUE_LOCK_WAIT state */
{ {
que_thr_t* thr; que_thr_t* thr;
ulint sec;
ulint ms;
ib_uint64_t now;
ut_ad(mutex_own(&kernel_mutex)); ut_ad(mutex_own(&kernel_mutex));
ut_ad(trx->que_state == TRX_QUE_LOCK_WAIT); ut_ad(trx->que_state == TRX_QUE_LOCK_WAIT);
...@@ -1113,6 +1150,11 @@ trx_lock_wait_to_suspended( ...@@ -1113,6 +1150,11 @@ trx_lock_wait_to_suspended(
thr = UT_LIST_GET_FIRST(trx->wait_thrs); thr = UT_LIST_GET_FIRST(trx->wait_thrs);
} }
if (innobase_get_slow_log() && trx->take_stats) {
ut_usectime(&sec, &ms);
now = (ib_uint64_t)sec * 1000000 + ms;
trx->lock_que_wait_timer += (ulint)(now - trx->lock_que_wait_ustarted);
}
trx->que_state = TRX_QUE_RUNNING; trx->que_state = TRX_QUE_RUNNING;
} }
......
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