Many files:

  Merge InnoDB-3.23.52c; improve AUTO-INC algorithm with SHOW TABLE STATUS; new checksum in log
parent c5bdaee9
......@@ -1707,10 +1707,11 @@ buf_print(void)
mutex_enter(&(buf_pool->mutex));
printf("LRU len %lu \n", UT_LIST_GET_LEN(buf_pool->LRU));
printf("free len %lu \n", UT_LIST_GET_LEN(buf_pool->free));
printf("flush len %lu \n", UT_LIST_GET_LEN(buf_pool->flush_list));
printf("buf_pool size %lu \n", size);
printf("database pages %lu \n", UT_LIST_GET_LEN(buf_pool->LRU));
printf("free pages %lu \n", UT_LIST_GET_LEN(buf_pool->free));
printf("modified database pages %lu \n",
UT_LIST_GET_LEN(buf_pool->flush_list));
printf("n pending reads %lu \n", buf_pool->n_pend_reads);
......@@ -1819,13 +1820,20 @@ buf_print_io(
mutex_enter(&(buf_pool->mutex));
buf += sprintf(buf,
"Free list length %lu \n", UT_LIST_GET_LEN(buf_pool->free));
"Buffer pool size %lu\n", size);
buf += sprintf(buf,
"Free buffers %lu\n", UT_LIST_GET_LEN(buf_pool->free));
buf += sprintf(buf,
"Database pages %lu\n", UT_LIST_GET_LEN(buf_pool->LRU));
/*
buf += sprintf(buf,
"Lock heap buffers %lu\n", buf_pool->n_lock_heap_pages);
buf += sprintf(buf,
"LRU list length %lu \n", UT_LIST_GET_LEN(buf_pool->LRU));
"Hash index buffers %lu\n", buf_pool->n_adaptive_hash_pages);
*/
buf += sprintf(buf,
"Flush list length %lu \n",
"Modified db pages %lu\n",
UT_LIST_GET_LEN(buf_pool->flush_list));
buf += sprintf(buf, "Buffer pool size %lu\n", size);
buf += sprintf(buf, "Pending reads %lu \n", buf_pool->n_pend_reads);
......
......@@ -270,7 +270,7 @@ void
dict_table_autoinc_initialize(
/*==========================*/
dict_table_t* table, /* in: table */
ib_longlong value) /* in: value which was assigned to a row */
ib_longlong value) /* in: next value to assign to a row */
{
mutex_enter(&(table->autoinc_mutex));
......@@ -281,8 +281,8 @@ dict_table_autoinc_initialize(
}
/************************************************************************
Gets the next autoinc value, 0 if not yet initialized. If initialized,
increments the counter by 1. */
Gets the next autoinc value (== autoinc counter value), 0 if not yet
initialized. If initialized, increments the counter by 1. */
ib_longlong
dict_table_autoinc_get(
......@@ -298,8 +298,8 @@ dict_table_autoinc_get(
value = 0;
} else {
table->autoinc = table->autoinc + 1;
value = table->autoinc;
table->autoinc = table->autoinc + 1;
}
mutex_exit(&(table->autoinc_mutex));
......@@ -334,20 +334,43 @@ dict_table_autoinc_read(
}
/************************************************************************
Updates the autoinc counter if the value supplied is bigger than the
Peeks the autoinc counter value, 0 if not yet initialized. Does not
increment the counter. The read not protected by any mutex! */
ib_longlong
dict_table_autoinc_peek(
/*====================*/
/* out: value of the counter */
dict_table_t* table) /* in: table */
{
ib_longlong value;
if (!table->autoinc_inited) {
value = 0;
} else {
value = table->autoinc;
}
return(value);
}
/************************************************************************
Updates the autoinc counter if the value supplied is equal or bigger than the
current value. If not inited, does nothing. */
void
dict_table_autoinc_update(
/*======================*/
dict_table_t* table, /* in: table */
ib_longlong value) /* in: value which was assigned to a row */
{
mutex_enter(&(table->autoinc_mutex));
if (table->autoinc_inited) {
if (value > table->autoinc) {
table->autoinc = value;
if (value >= table->autoinc) {
table->autoinc = value + 1;
}
}
......
......@@ -578,7 +578,7 @@ fil_read_flushed_lsn_and_arch_log_no(
ulint arch_log_no;
buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
/* Align the memory for a possibel read from a raw device */
/* Align the memory for a possible read from a raw device */
buf = ut_align(buf2, UNIV_PAGE_SIZE);
os_file_read(data_file, buf, 0, 0, UNIV_PAGE_SIZE);
......
......@@ -933,6 +933,36 @@ fsp_header_get_free_limit(
return(limit);
}
/**************************************************************************
Gets the size of the tablespace from the tablespace header. If we do not
have an auto-extending data file, this should be equal to the size of the
data files. If there is an auto-extending data file, this can be smaller. */
ulint
fsp_header_get_tablespace_size(
/*===========================*/
/* out: size in pages */
ulint space) /* in: space id */
{
fsp_header_t* header;
ulint size;
mtr_t mtr;
ut_a(space == 0); /* We have only one log_fsp_current_... variable */
mtr_start(&mtr);
mtr_x_lock(fil_space_get_latch(space), &mtr);
header = fsp_get_space_header(space, &mtr);
size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, &mtr);
mtr_commit(&mtr);
return(size);
}
/***************************************************************************
Tries to extend the last data file file if it is defined as auto-extending. */
static
......
......@@ -335,6 +335,11 @@ ha_print_info(
}
}
buf += sprintf(buf, "Hash table size %lu, used cells %lu\n",
hash_get_n_cells(table), cells);
buf += sprintf(buf,
"Hash table size %lu, used cells %lu", hash_get_n_cells(table), cells);
if (table->heaps == NULL && table->heap != NULL) {
buf += sprintf(buf,
", node heap has %lu buffer(s)\n", UT_LIST_GET_LEN(table->heap->base));
}
}
......@@ -96,17 +96,17 @@ dict_col_get_clust_pos(
/*===================*/
dict_col_t* col);
/************************************************************************
Initializes the autoinc counter. It is not an error to initialize already
Initializes the autoinc counter. It is not an error to initialize an already
initialized counter. */
void
dict_table_autoinc_initialize(
/*==========================*/
dict_table_t* table, /* in: table */
ib_longlong value); /* in: value which was assigned to a row */
ib_longlong value); /* in: next value to assign to a row */
/************************************************************************
Gets the next autoinc value, 0 if not yet initialized. If initialized,
increments the counter by 1. */
Gets the next autoinc value (== autoinc counter value), 0 if not yet
initialized. If initialized, increments the counter by 1. */
ib_longlong
dict_table_autoinc_get(
......@@ -123,12 +123,22 @@ dict_table_autoinc_read(
/* out: value of the counter */
dict_table_t* table); /* in: table */
/************************************************************************
Updates the autoinc counter if the value supplied is bigger than the
Peeks the autoinc counter value, 0 if not yet initialized. Does not
increment the counter. The read not protected by any mutex! */
ib_longlong
dict_table_autoinc_peek(
/*====================*/
/* out: value of the counter */
dict_table_t* table); /* in: table */
/************************************************************************
Updates the autoinc counter if the value supplied is equal or bigger than the
current value. If not inited, does nothing. */
void
dict_table_autoinc_update(
/*======================*/
dict_table_t* table, /* in: table */
ib_longlong value); /* in: value which was assigned to a row */
/**************************************************************************
......
......@@ -388,8 +388,8 @@ struct dict_table_struct{
/* TRUE if the autoinc counter has been
inited; MySQL gets the init value by executing
SELECT MAX(auto inc column) */
ib_longlong autoinc;/* autoinc counter value already given to
a row */
ib_longlong autoinc;/* autoinc counter value to give to the
next inserted row */
ulint magic_n;/* magic number */
};
#define DICT_TABLE_MAGIC_N 76333786
......
......@@ -17,7 +17,9 @@ typedef struct dyn_block_struct dyn_block_t;
typedef dyn_block_t dyn_array_t;
/* This must be > MLOG_BUF_MARGIN + 30 */
/* This is the initial 'payload' size of a dynamic array;
this must be > MLOG_BUF_MARGIN + 30! */
#define DYN_ARRAY_DATA_SIZE 512
/*************************************************************************
......
......@@ -57,6 +57,16 @@ fsp_header_get_free_limit(
/* out: free limit in megabytes */
ulint space); /* in: space id */
/**************************************************************************
Gets the size of the tablespace from the tablespace header. If we do not
have an auto-extending data file, this should be equal to the size of the
data files. If there is an auto-extending data file, this can be smaller. */
ulint
fsp_header_get_tablespace_size(
/*===========================*/
/* out: size in pages */
ulint space); /* in: space id */
/**************************************************************************
Initializes the space header of a new created space. */
void
......
......@@ -431,15 +431,30 @@ log_block_set_data_len(
byte* log_block, /* in: log block */
ulint len); /* in: data length */
/****************************************************************
Gets a log block number stored in the trailer. */
Calculates the checksum for a log block. */
UNIV_INLINE
ulint
log_block_get_trl_no(
/*=================*/
/* out: log block number stored in the block
trailer */
log_block_calc_checksum(
/*====================*/
/* out: checksum */
byte* block); /* in: log block */
/****************************************************************
Gets a log block checksum field value. */
UNIV_INLINE
ulint
log_block_get_checksum(
/*===================*/
/* out: checksum */
byte* log_block); /* in: log block */
/****************************************************************
Sets a log block checksum field value. */
UNIV_INLINE
void
log_block_set_checksum(
/*===================*/
byte* log_block, /* in: log block */
ulint checksum); /* in: checksum */
/****************************************************************
Gets a log block first mtr log record group offset. */
UNIV_INLINE
ulint
......@@ -544,10 +559,11 @@ extern log_t* log_sys;
bytes */
/* Offsets of a log block trailer from the end of the block */
#define LOG_BLOCK_TRL_CHECKSUM 4 /* 1 byte checksum of the log block
contents */
#define LOG_BLOCK_TRL_NO 3 /* 3 lowest bytes of the log block
number */
#define LOG_BLOCK_CHECKSUM 4 /* 4 byte checksum of the log block
contents; in InnoDB versions
< 3.23.52 this did not contain the
checksum but the same value as
.._HDR_NO */
#define LOG_BLOCK_TRL_SIZE 4 /* trailer size in bytes */
/* Offsets for a checkpoint field */
......
......@@ -169,33 +169,6 @@ log_block_set_checkpoint_no(
ut_dulint_get_low(no));
}
/****************************************************************
Gets a log block number stored in the trailer. */
UNIV_INLINE
ulint
log_block_get_trl_no(
/*=================*/
/* out: log block number stored in the block
trailer */
byte* log_block) /* in: log block */
{
return(mach_read_from_3(log_block + OS_FILE_LOG_BLOCK_SIZE
- LOG_BLOCK_TRL_NO));
}
/****************************************************************
Sets the log block number stored in the trailer. */
UNIV_INLINE
void
log_block_set_trl_no(
/*=================*/
byte* log_block, /* in: log block */
ulint n) /* in: log block number */
{
mach_write_to_3(log_block + OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_NO,
n & 0xFFFFFF);
}
/****************************************************************
Converts a lsn to a log block number. */
UNIV_INLINE
......@@ -216,6 +189,61 @@ log_block_convert_lsn_to_no(
return(no + 1);
}
/****************************************************************
Calculates the checksum for a log block. */
UNIV_INLINE
ulint
log_block_calc_checksum(
/*====================*/
/* out: checksum */
byte* block) /* in: log block */
{
ulint sum;
ulint sh;
ulint i;
sum = 1;
sh = 0;
for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) {
sum = sum & 0x7FFFFFFF;
sum += ((ulint)(*(block + i))) << sh;
sh++;
if (sh > 24) {
sh = 0;
}
}
return(sum);
}
/****************************************************************
Gets a log block checksum field value. */
UNIV_INLINE
ulint
log_block_get_checksum(
/*===================*/
/* out: checksum */
byte* log_block) /* in: log block */
{
return(mach_read_from_4(log_block + OS_FILE_LOG_BLOCK_SIZE
- LOG_BLOCK_CHECKSUM));
}
/****************************************************************
Sets a log block checksum field value. */
UNIV_INLINE
void
log_block_set_checksum(
/*===================*/
byte* log_block, /* in: log block */
ulint checksum) /* in: checksum */
{
mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE
- LOG_BLOCK_CHECKSUM,
checksum);
}
/****************************************************************
Initializes a log block in the log buffer. */
UNIV_INLINE
......@@ -232,7 +260,6 @@ log_block_init(
no = log_block_convert_lsn_to_no(lsn);
log_block_set_hdr_no(log_block, no);
log_block_set_trl_no(log_block, no);
log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
log_block_set_first_rec_group(log_block, 0);
......@@ -256,7 +283,7 @@ log_block_init_in_old_format(
log_block_set_hdr_no(log_block, no);
mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE
- LOG_BLOCK_TRL_NO - 1, no);
- LOG_BLOCK_CHECKSUM, no);
log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
log_block_set_first_rec_group(log_block, 0);
}
......
......@@ -313,6 +313,10 @@ struct recv_sys_struct{
this lsn */
dulint limit_lsn;/* recovery should be made at most up to this
lsn */
ibool found_corrupt_log;
/* this is set to TRUE if we during log
scan find a corrupt log block, or a corrupt
log record */
log_group_t* archive_group;
/* in archive recovery: the log group whose
archive is read */
......@@ -328,6 +332,8 @@ extern ibool recv_recovery_on;
extern ibool recv_no_ibuf_operations;
extern ibool recv_needed_recovery;
extern ibool recv_is_making_a_backup;
/* Size of the parsing buffer; it must accommodate RECV_SCAN_SIZE many
times! */
#define RECV_PARSING_BUF_SIZE (2 * 1024 * 1024)
......
......@@ -257,6 +257,15 @@ void
trx_sys_print_mysql_binlog_offset(void);
/*===================================*/
/*********************************************************************
Prints to stdout the MySQL binlog info in the system header if the
magic number shows it valid. */
void
trx_sys_print_mysql_binlog_offset_from_page(
/*========================================*/
byte* page); /* in: buffer containing the trx system header page,
i.e., page number TRX_SYS_PAGE_NO in the tablespace */
/*********************************************************************
Prints to stderr the MySQL master log offset info in the trx system header if
the magic number shows it valid. */
......@@ -300,11 +309,11 @@ therefore 256; each slot is currently 8 bytes in size */
#define TRX_SYS_MYSQL_LOG_NAME_LEN 512
#define TRX_SYS_MYSQL_LOG_MAGIC_N 873422344
/* The offset of the MySQL replication info on the trx system header page;
/* The offset of the MySQL replication info in the trx system header;
this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
#define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)
/* The offset of the MySQL binlog offset info on the trx system header page */
/* The offset of the MySQL binlog offset info in the trx system header */
#define TRX_SYS_MYSQL_LOG_INFO (UNIV_PAGE_SIZE - 1000)
#define TRX_SYS_MYSQL_LOG_MAGIC_N_FLD 0 /* magic number which shows
if we have valid data in the
......
......@@ -309,6 +309,9 @@ struct trx_struct{
of view of concurrency control:
TRX_ACTIVE, TRX_COMMITTED_IN_MEMORY,
... */
time_t start_time; /* time the trx object was created
or the state last time became
TRX_ACTIVE */
ibool check_foreigns; /* normally TRUE, but if the user
wants to suppress foreign key checks,
(in table imports, for example) we
......@@ -468,6 +471,7 @@ struct trx_struct{
TRX_QUE_LOCK_WAIT, this points to
the lock request, otherwise this is
NULL */
time_t wait_started; /* lock wait started at this time */
UT_LIST_BASE_NODE_T(que_thr_t)
wait_thrs; /* query threads belonging to this
trx that are in the QUE_THR_LOCK_WAIT
......
......@@ -1565,6 +1565,7 @@ index->table_name);
}
trx->que_state = TRX_QUE_LOCK_WAIT;
trx->wait_started = time(NULL);
ut_a(que_thr_stop(thr));
......@@ -2961,6 +2962,7 @@ table->name);
}
trx->que_state = TRX_QUE_LOCK_WAIT;
trx->wait_started = time(NULL);
ut_a(que_thr_stop(thr));
......@@ -3503,6 +3505,10 @@ lock_print_info(
return;
}
buf += sprintf(buf, "Number of sessions %lu\n",
UT_LIST_GET_LEN(trx_sys->mysql_trx_list)
+ UT_LIST_GET_LEN(trx_sys->trx_list));
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));
......@@ -3587,7 +3593,8 @@ loop:
if (trx->que_state == TRX_QUE_LOCK_WAIT) {
buf += sprintf(buf,
"------------------TRX IS WAITING FOR THE LOCK:\n");
"------- TRX HAS BEEN WAITING %lu SEC FOR THIS LOCK TO BE GRANTED:\n",
(ulint)difftime(time(NULL), trx->wait_started));
if (lock_get_type(trx->wait_lock) == LOCK_REC) {
lock_rec_print(buf, trx->wait_lock);
......
......@@ -270,7 +270,7 @@ part_loop:
log->lsn = ut_dulint_add(log->lsn, len);
/* Initialize the next block header and trailer */
/* Initialize the next block header */
log_block_init(log_block + OS_FILE_LOG_BLOCK_SIZE, log->lsn);
} else {
log->lsn = ut_dulint_add(log->lsn, len);
......@@ -1070,28 +1070,16 @@ log_group_file_header_flush(
}
/**********************************************************
Stores a 1-byte checksum to the trailer checksum field of a log block
Stores a 4-byte checksum to the trailer checksum field of a log block
before writing it to a log file. This checksum is used in recovery to
check the consistency of a log block. The checksum is simply the 8 low
bits of 1 + the sum of the bytes in the log block except the trailer bytes. */
check the consistency of a log block. */
static
void
log_block_store_checksum(
/*=====================*/
byte* block) /* in/out: pointer to a log block */
{
ulint i;
ulint sum;
sum = 1;
for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) {
sum += (ulint)(*(block + i));
}
mach_write_to_1(block + OS_FILE_LOG_BLOCK_SIZE
- LOG_BLOCK_TRL_CHECKSUM,
0xFF & sum);
log_block_set_checksum(block, log_block_calc_checksum(block));
}
/**********************************************************
......
This diff is collapsed.
......@@ -666,7 +666,7 @@ mem_print_info_low(
mem_pool_print_info(outfile, mem_comm_pool);
mem_validate();
/* mem_validate(); */
/* fclose(outfile); */
#endif
......
......@@ -595,6 +595,11 @@ row_lock_table_autoinc_for_mysql(
ut_ad(trx);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
if (trx->auto_inc_lock) {
return(DB_SUCCESS);
}
trx->op_info = "setting auto-inc lock";
if (node == NULL) {
......
......@@ -2475,12 +2475,23 @@ srv_error_monitor_thread(
void* arg) /* in: a dummy parameter required by
os_thread_create */
{
ulint cnt = 0;
UT_NOT_USED(arg);
loop:
srv_error_monitor_active = TRUE;
os_thread_sleep(10000000);
cnt++;
os_thread_sleep(2000000);
/* mem_print_new_info();
if (cnt % 10 == 0) {
mem_print_info();
}
*/
sync_array_print_long_waits();
/* Flush stdout and stderr so that a database user gets their output
......
......@@ -927,6 +927,8 @@ innobase_start_or_create_for_mysql(void)
ulint max_arch_log_no;
ibool start_archive;
ulint sum_of_new_sizes;
ulint sum_of_data_file_sizes;
ulint tablespace_size_in_header;
ulint err;
ulint i;
ulint k;
......@@ -1325,6 +1327,32 @@ innobase_start_or_create_for_mysql(void)
SRV_MAX_N_IO_THREADS);
/* buf_debug_prints = TRUE; */
sum_of_data_file_sizes = 0;
for (i = 0; i < srv_n_data_files; i++) {
sum_of_data_file_sizes += srv_data_file_sizes[i];
}
tablespace_size_in_header = fsp_header_get_tablespace_size(0);
if (!srv_auto_extend_last_data_file
&& sum_of_data_file_sizes != tablespace_size_in_header) {
fprintf(stderr,
"InnoDB: Error: tablespace size stored in header is %lu pages, but\n"
"InnoDB: the sum of data file sizes is %lu pages\n",
tablespace_size_in_header, sum_of_data_file_sizes);
}
if (srv_auto_extend_last_data_file
&& sum_of_data_file_sizes < tablespace_size_in_header) {
fprintf(stderr,
"InnoDB: Error: tablespace size stored in header is %lu pages, but\n"
"InnoDB: the sum of data file sizes is only %lu pages\n",
tablespace_size_in_header, sum_of_data_file_sizes);
}
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Started\n");
......
......@@ -493,6 +493,34 @@ trx_sys_update_mysql_binlog_offset(
MLOG_4BYTES, mtr);
}
/*********************************************************************
Prints to stdout the MySQL binlog info in the system header if the
magic number shows it valid. */
void
trx_sys_print_mysql_binlog_offset_from_page(
/*========================================*/
byte* page) /* in: buffer containing the trx system header page,
i.e., page number TRX_SYS_PAGE_NO in the tablespace */
{
trx_sysf_t* sys_header;
sys_header = page + TRX_SYS;
if (mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
+ TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
== TRX_SYS_MYSQL_LOG_MAGIC_N) {
printf(
"ibbackup: Last MySQL binlog file position %lu %lu, file name %s\n",
mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW),
sys_header + TRX_SYS_MYSQL_LOG_INFO + TRX_SYS_MYSQL_LOG_NAME);
}
}
/*********************************************************************
Prints to stderr the MySQL binlog offset info in the trx system header if
the magic number shows it valid. */
......
......@@ -72,6 +72,7 @@ trx_create(
trx->type = TRX_USER;
trx->conc_state = TRX_NOT_STARTED;
trx->start_time = time(NULL);
trx->check_foreigns = TRUE;
trx->check_unique_secondary = TRUE;
......@@ -516,6 +517,7 @@ trx_start_low(
if (trx->type == TRX_PURGE) {
trx->id = ut_dulint_zero;
trx->conc_state = TRX_ACTIVE;
trx->start_time = time(NULL);
return(TRUE);
}
......@@ -539,6 +541,7 @@ trx_start_low(
trx->rseg = rseg;
trx->conc_state = TRX_ACTIVE;
trx->start_time = time(NULL);
UT_LIST_ADD_FIRST(trx_list, trx_sys->trx_list, trx);
......@@ -1465,9 +1468,25 @@ trx_print(
500 bytes */
trx_t* trx) /* in: transaction */
{
buf += sprintf(buf, "TRANSACTION %lu %lu, OS thread id %lu",
char* start_of_line;
buf += sprintf(buf, "TRANSACTION %lu %lu",
ut_dulint_get_high(trx->id),
ut_dulint_get_low(trx->id),
ut_dulint_get_low(trx->id));
switch (trx->conc_state) {
case TRX_NOT_STARTED: buf += sprintf(buf,
", not started"); break;
case TRX_ACTIVE: buf += sprintf(buf,
", ACTIVE %lu sec",
(ulint)difftime(time(NULL), trx->start_time)); break;
case TRX_COMMITTED_IN_MEMORY: buf += sprintf(buf,
", COMMITTED IN MEMORY");
break;
default: buf += sprintf(buf, " state %lu", trx->conc_state);
}
buf += sprintf(buf, ", OS thread id %lu",
(ulint)trx->mysql_thread_id);
if (ut_strlen(trx->op_info) > 0) {
......@@ -1478,32 +1497,28 @@ trx_print(
buf += sprintf(buf, " purge trx");
}
switch (trx->conc_state) {
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: buf += sprintf(buf, " state %lu", trx->conc_state);
}
buf += sprintf(buf, "\n");
start_of_line = buf;
switch (trx->que_state) {
case TRX_QUE_RUNNING: buf += sprintf(buf,
", runs or sleeps"); break;
case TRX_QUE_RUNNING: break;
case TRX_QUE_LOCK_WAIT: buf += sprintf(buf,
", lock wait"); break;
"LOCK WAIT "); break;
case TRX_QUE_ROLLING_BACK: buf += sprintf(buf,
", rolling back"); break;
"ROLLING BACK "); break;
case TRX_QUE_COMMITTING: buf += sprintf(buf,
", committing"); break;
default: buf += sprintf(buf, " que state %lu", trx->que_state);
"COMMITTING "); break;
default: buf += sprintf(buf, "que state %lu", trx->que_state);
}
if (0 < UT_LIST_GET_LEN(trx->trx_locks)) {
buf += sprintf(buf, ", has %lu lock struct(s)",
UT_LIST_GET_LEN(trx->trx_locks));
if (0 < UT_LIST_GET_LEN(trx->trx_locks) ||
mem_heap_get_size(trx->lock_heap) > 400) {
buf += sprintf(buf,
"%lu lock struct(s), heap size %lu",
UT_LIST_GET_LEN(trx->trx_locks),
mem_heap_get_size(trx->lock_heap));
}
if (trx->has_search_latch) {
......@@ -1515,7 +1530,10 @@ trx_print(
ut_dulint_get_low(trx->undo_no));
}
if (buf != start_of_line) {
buf += sprintf(buf, "\n");
}
if (trx->mysql_thd != NULL) {
innobase_mysql_print_thd(buf, trx->mysql_thd);
......
......@@ -266,10 +266,39 @@ innobase_mysql_print_thd(
thd = (THD*) input_thd;
buf += sprintf(buf, "MySQL thread id %lu, query id %lu",
thd->thread_id, thd->query_id);
if (thd->host) {
buf += sprintf(buf, " %.30s", thd->host);
}
if (thd->ip) {
buf += sprintf(buf, " %.20s", thd->ip);
}
if (thd->user) {
buf += sprintf(buf, " %.20s", thd->user);
}
if (thd->proc_info) {
buf += sprintf(buf, " %.50s", thd->proc_info);
}
if (thd->query) {
buf += sprintf(buf, "\n%.150s", thd->query);
}
buf += sprintf(buf, "\n");
#ifdef notdefined
/* July 30, 2002
Revert Monty's changes because they seem to make control
characters sometimes appear in the output */
/* We can't use value of sprintf() as this is not portable */
buf+= my_sprintf(buf,
(buf, "MySQL thread id %lu, query id %lu",
thd->thread_id, thd->query_id));
(buf, "MySQL thread id %lu",
thd->thread_id));
if (thd->host)
{
*buf++=' ';
......@@ -296,10 +325,11 @@ innobase_mysql_print_thd(
if (thd->query)
{
*buf++=' ';
*buf++='\n';
buf=strnmov(buf, thd->query, 150);
}
*buf='\n';
#endif
}
}
......@@ -1414,6 +1444,7 @@ ha_innobase::write_row(
row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
int error;
longlong auto_inc;
longlong dummy;
DBUG_ENTER("ha_innobase::write_row");
......@@ -1437,6 +1468,30 @@ ha_innobase::write_row(
/* This is the case where the table has an
auto-increment column */
/* Initialize the auto-inc counter if it has not been
initialized yet */
if (0 == dict_table_autoinc_peek(prebuilt->table)) {
/* This call initializes the counter */
error = innobase_read_and_init_auto_inc(&dummy);
if (error) {
/* Deadlock or lock wait timeout */
goto func_exit;
}
/* We have to set sql_stat_start to TRUE because
the above call probably has called a select, and
has reset that flag; row_insert_for_mysql has to
know to set the IX intention lock on the table,
something it only does at the start of each
statement */
prebuilt->sql_stat_start = TRUE;
}
/* Fetch the value the user possibly has set in the
autoincrement field */
......@@ -1469,10 +1524,9 @@ ha_innobase::write_row(
}
if (auto_inc != 0) {
/* This call will calculate the max of the
current value and the value supplied by the user, if
the auto_inc counter is already initialized
for the table */
/* This call will calculate the max of the current
value and the value supplied by the user and
update the counter accordingly */
/* We have to use the transactional lock mechanism
on the auto-inc counter of the table to ensure
......@@ -1512,45 +1566,17 @@ ha_innobase::write_row(
auto_inc = dict_table_autoinc_get(prebuilt->table);
srv_conc_exit_innodb(prebuilt->trx);
/* If auto_inc is now != 0 the autoinc counter
was already initialized for the table: we can give
the new value for MySQL to place in the field */
/* We can give the new value for MySQL to place in
the field */
if (auto_inc != 0) {
user_thd->next_insert_id = auto_inc;
}
}
update_auto_increment();
if (auto_inc == 0) {
/* The autoinc counter for our table was not yet
initialized, initialize it now */
/* This call of a handler.cc function places
user_thd->next_insert_id to the column value, if the column
value was not set by the user */
auto_inc = table->next_number_field->val_int();
srv_conc_enter_innodb(prebuilt->trx);
error = row_lock_table_autoinc_for_mysql(prebuilt);
srv_conc_exit_innodb(prebuilt->trx);
if (error != DB_SUCCESS) {
error = convert_error_code_to_mysql(error,
user_thd);
goto func_exit;
}
dict_table_autoinc_initialize(prebuilt->table,
auto_inc);
}
/* We have to set sql_stat_start to TRUE because
update_auto_increment may have called a select, and
has reset that flag; row_insert_for_mysql has to
know to set the IX intention lock on the table, something
it only does at the start of each statement */
prebuilt->sql_stat_start = TRUE;
update_auto_increment();
}
if (prebuilt->mysql_template == NULL
......@@ -3572,37 +3598,53 @@ ha_innobase::store_lock(
}
/***********************************************************************
Returns the next auto-increment column value for the table. write_row
normally fetches the value from the cache in the data dictionary. This
function in used by SHOW TABLE STATUS and when the first insert to the table
is done after database startup. */
This function initializes the auto-inc counter if it has not been
initialized yet. This function does not change the value of the auto-inc
counter if it already has been initialized. In parameter ret returns
the value of the auto-inc counter. */
longlong
ha_innobase::get_auto_increment()
/*=============================*/
/* out: the next auto-increment column value */
int
ha_innobase::innobase_read_and_init_auto_inc(
/*=========================================*/
/* out: 0 or error code: deadlock or
lock wait timeout */
longlong* ret) /* out: auto-inc value */
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
longlong nr;
longlong auto_inc;
int error;
ut_a(prebuilt);
ut_a(prebuilt->trx ==
(trx_t*) current_thd->transaction.all.innobase_tid);
ut_a(prebuilt->table);
/* 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
ordinary SQL queries. We avoid these deadlocks if the auto-inc
counter for the table has been initialized by fetching the value
from the table struct in dictionary cache. */
auto_inc = dict_table_autoinc_read(prebuilt->table);
assert(prebuilt->table);
if (auto_inc != 0) {
/* Already initialized */
*ret = auto_inc;
nr = dict_table_autoinc_read(prebuilt->table);
return(0);
}
if (nr != 0) {
srv_conc_enter_innodb(prebuilt->trx);
error = row_lock_table_autoinc_for_mysql(prebuilt);
srv_conc_exit_innodb(prebuilt->trx);
return(nr + 1);
if (error != DB_SUCCESS) {
error = convert_error_code_to_mysql(error, user_thd);
goto func_exit;
}
/* Check again if someone has initialized the counter meanwhile */
auto_inc = dict_table_autoinc_read(prebuilt->table);
if (auto_inc != 0) {
*ret = auto_inc;
return(0);
}
(void) extra(HA_EXTRA_KEYREAD);
......@@ -3627,16 +3669,57 @@ ha_innobase::get_auto_increment()
error = index_last(table->record[1]);
if (error) {
nr = 1;
if (error == HA_ERR_END_OF_FILE) {
/* The table was empty, initialize to 1 */
auto_inc = 1;
error = 0;
} else {
nr = (longlong) table->next_number_field->
/* Deadlock or a lock wait timeout */
auto_inc = -1;
goto func_exit;
}
} else {
/* Initialize to max(col) + 1 */
auto_inc = (longlong) table->next_number_field->
val_int_offset(table->rec_buff_length) + 1;
}
dict_table_autoinc_initialize(prebuilt->table, auto_inc);
func_exit:
(void) extra(HA_EXTRA_NO_KEYREAD);
index_end();
*ret = auto_inc;
return(error);
}
/***********************************************************************
This function initializes the auto-inc counter if it has not been
initialized yet. This function does not change the value of the auto-inc
counter if it already has been initialized. Returns the value of the
auto-inc counter. */
longlong
ha_innobase::get_auto_increment()
/*=============================*/
/* out: auto-increment column value, -1 if error
(deadlock or lock wait timeout) */
{
longlong nr;
int error;
error = innobase_read_and_init_auto_inc(&nr);
if (error) {
return(-1);
}
return(nr);
}
......
......@@ -68,6 +68,7 @@ class ha_innobase: public handler
int update_thd(THD* thd);
int change_active_index(uint keynr);
int general_fetch(byte* buf, uint direction, uint match_mode);
int innobase_read_and_init_auto_inc(longlong* ret);
/* Init values for the class: */
public:
......
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