Commit f7e76f23 authored by marko's avatar marko

branches/innodb+: Merge revisions 2678:2774 from branches/zip.

parent 899c10e7
2008-10-08 The InnoDB Team
* dict/dict0crea.c, trx/trx0roll.c, include/row0mysql.h,
row/row0merge.c, row/row0mysql.c: When dropping a table, hold the
data dictionary latch until the transaction has been committed.
The data dictionary latch is supposed to prevent lock waits and
deadlocks in the data dictionary tables. Due to this bug,
DROP TABLE could cause a deadlock or hang. Note that because of
Bug#33650 and Bug#39833, MySQL may also drop a (temporary) table
when executing CREATE INDEX or ALTER TABLE ... ADD INDEX.
2008-10-04 The InnoDB Team
* handler/ha_innodb.cc, mysql-test/innodb_bug39438-master.opt,
mysql-test/innodb_bug39438.result, mysql-test/innodb_bug39438.test:
Fix Bug#39438 Testcase for Bug#39436 crashes on 5.1 in
fil_space_get_latch
2008-10-04 The InnoDB Team
* include/lock0lock.h, lock/lock0lock.c,
mysql-test/innodb_bug38231.result, mysql-test/innodb_bug38231.test,
row/row0mysql.c:
Fix Bug#38231 Innodb crash in lock_reset_all_on_table() on TRUNCATE +
LOCK / UNLOCK
2008-10-04 The InnoDB Team
* handler/ha_innodb.cc:
Fix Bug#35498 Cannot get table test/table1 auto-inccounter value in
::info
2008-10-04 The InnoDB Team
* handler/ha_innodb.cc, handler/ha_innodb.h:
Fix Bug#37788 InnoDB Plugin: AUTO_INCREMENT wrong for compressed
tables
2008-10-04 The InnoDB Team
* dict/dict0dict.c, handler/ha_innodb.cc, handler/ha_innodb.h,
include/dict0dict.h, include/dict0mem.h, row/row0mysql.c:
Fix Bug#39830 Table autoinc value not updated on first insert
2008-10-03 The InnoDB Team
* mysql-test/innodb-index.test, mysql-test/innodb-index.result,
mysql-test/innodb-timeout.test, mysql-test/innodb-timeout.result,
srv/srv0srv.c, include/srv0srv.h,
handler/ha_innodb.cc, include/ha_prototypes.h:
Fix Bug#36285 innodb_lock_wait_timeout is not dynamic, not per session
2008-09-19 The InnoDB Team 2008-09-19 The InnoDB Team
* os/os0proc.c: * os/os0proc.c:
......
...@@ -1198,8 +1198,8 @@ btr_root_raise_and_insert( ...@@ -1198,8 +1198,8 @@ btr_root_raise_and_insert(
ut_a(new_page_zip); ut_a(new_page_zip);
/* Copy the page byte for byte. */ /* Copy the page byte for byte. */
page_zip_copy(new_page_zip, new_page, page_zip_copy_recs(new_page_zip, new_page,
root_page_zip, root, index, mtr); root_page_zip, root, index, mtr);
} }
/* If this is a pessimistic insert which is actually done to /* If this is a pessimistic insert which is actually done to
...@@ -1963,8 +1963,8 @@ btr_page_split_and_insert( ...@@ -1963,8 +1963,8 @@ btr_page_split_and_insert(
as appropriate. Deleting will always succeed. */ as appropriate. Deleting will always succeed. */
ut_a(new_page_zip); ut_a(new_page_zip);
page_zip_copy(new_page_zip, new_page, page_zip_copy_recs(new_page_zip, new_page,
page_zip, page, cursor->index, mtr); page_zip, page, cursor->index, mtr);
page_delete_rec_list_end(move_limit - page + new_page, page_delete_rec_list_end(move_limit - page + new_page,
new_block, cursor->index, new_block, cursor->index,
ULINT_UNDEFINED, ULINT_UNDEFINED,
...@@ -1990,8 +1990,8 @@ btr_page_split_and_insert( ...@@ -1990,8 +1990,8 @@ btr_page_split_and_insert(
as appropriate. Deleting will always succeed. */ as appropriate. Deleting will always succeed. */
ut_a(new_page_zip); ut_a(new_page_zip);
page_zip_copy(new_page_zip, new_page, page_zip_copy_recs(new_page_zip, new_page,
page_zip, page, cursor->index, mtr); page_zip, page, cursor->index, mtr);
page_delete_rec_list_start(move_limit - page page_delete_rec_list_start(move_limit - page
+ new_page, new_block, + new_page, new_block,
cursor->index, mtr); cursor->index, mtr);
...@@ -2353,20 +2353,23 @@ btr_lift_page_up( ...@@ -2353,20 +2353,23 @@ btr_lift_page_up(
ut_a(page_zip); ut_a(page_zip);
/* Copy the page byte for byte. */ /* Copy the page byte for byte. */
page_zip_copy(father_page_zip, father_page, page_zip_copy_recs(father_page_zip, father_page,
page_zip, page, index, mtr); page_zip, page, index, mtr);
} }
lock_update_copy_and_discard(father_block, block); lock_update_copy_and_discard(father_block, block);
/* Go upward to root page, decrementing levels by one. */ /* Go upward to root page, decrementing levels by one. */
for (i = 0; i < n_blocks; i++, page_level++) { for (i = 0; i < n_blocks; i++, page_level++) {
page_t* page = buf_block_get_frame(blocks[i]); page_t* page = buf_block_get_frame(blocks[i]);
page_zip_des_t* page_zip= buf_block_get_page_zip(blocks[i]);
ut_ad(btr_page_get_level(page, mtr) == page_level + 1); ut_ad(btr_page_get_level(page, mtr) == page_level + 1);
btr_page_set_level(page, buf_block_get_page_zip(blocks[i]), btr_page_set_level(page, page_zip, page_level, mtr);
page_level, mtr); #ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page));
#endif /* UNIV_ZIP_DEBUG */
} }
/* Free the file page */ /* Free the file page */
...@@ -2661,6 +2664,9 @@ btr_compress( ...@@ -2661,6 +2664,9 @@ btr_compress(
} }
ut_ad(page_validate(merge_page, index)); ut_ad(page_validate(merge_page, index));
#ifdef UNIV_ZIP_DEBUG
ut_a(!merge_page_zip || page_zip_validate(merge_page_zip, merge_page));
#endif /* UNIV_ZIP_DEBUG */
/* Free the file page */ /* Free the file page */
btr_page_free(index, block, mtr); btr_page_free(index, block, mtr);
......
...@@ -1193,7 +1193,6 @@ btr_cur_optimistic_insert( ...@@ -1193,7 +1193,6 @@ btr_cur_optimistic_insert(
modification log. */ modification log. */
ulint free_space_zip = page_zip_empty_size( ulint free_space_zip = page_zip_empty_size(
cursor->index->n_fields, zip_size) - 1; cursor->index->n_fields, zip_size) - 1;
ulint extra;
ulint n_uniq = dict_index_get_n_unique_in_tree(index); ulint n_uniq = dict_index_get_n_unique_in_tree(index);
ut_ad(dict_table_is_comp(index->table)); ut_ad(dict_table_is_comp(index->table));
...@@ -1203,10 +1202,10 @@ btr_cur_optimistic_insert( ...@@ -1203,10 +1202,10 @@ btr_cur_optimistic_insert(
infinite page splits. */ infinite page splits. */
if (UNIV_LIKELY(entry->n_fields >= n_uniq) if (UNIV_LIKELY(entry->n_fields >= n_uniq)
&& UNIV_UNLIKELY(rec_get_converted_size_comp( && UNIV_UNLIKELY(REC_NODE_PTR_SIZE
index, REC_STATUS_NODE_PTR, + rec_get_converted_size_comp_prefix(
entry->fields, n_uniq, index, entry->fields, n_uniq,
&extra) NULL)
/* On a compressed page, there is /* On a compressed page, there is
a two-byte entry in the dense a two-byte entry in the dense
page directory for every record. page directory for every record.
......
...@@ -44,6 +44,11 @@ initial segment in buf_LRU_get_recent_limit */ ...@@ -44,6 +44,11 @@ initial segment in buf_LRU_get_recent_limit */
#define BUF_LRU_INITIAL_RATIO 8 #define BUF_LRU_INITIAL_RATIO 8
/* When dropping the search hash index entries before deleting an ibd
file, we build a local array of pages belonging to that tablespace
in the buffer pool. Following is the size of that array. */
#define BUF_LRU_DROP_SEARCH_HASH_SIZE 1024
/* If we switch on the InnoDB monitor because there are too few available /* If we switch on the InnoDB monitor because there are too few available
frames in the buffer pool, we set this to TRUE */ frames in the buffer pool, we set this to TRUE */
UNIV_INTERN ibool buf_lru_switched_on_innodb_mon = FALSE; UNIV_INTERN ibool buf_lru_switched_on_innodb_mon = FALSE;
...@@ -157,6 +162,133 @@ buf_LRU_evict_from_unzip_LRU(void) ...@@ -157,6 +162,133 @@ buf_LRU_evict_from_unzip_LRU(void)
return(unzip_avg <= io_avg * BUF_LRU_IO_TO_UNZIP_FACTOR); return(unzip_avg <= io_avg * BUF_LRU_IO_TO_UNZIP_FACTOR);
} }
/**********************************************************************
Attempts to drop page hash index on a batch of pages belonging to a
particular space id. */
static
void
buf_LRU_drop_page_hash_batch(
/*=========================*/
ulint space_id, /* in: space id */
ulint zip_size, /* in: compressed page size in bytes
or 0 for uncompressed pages */
const ulint* arr, /* in: array of page_no */
ulint count) /* in: number of entries in array */
{
ulint i;
ut_ad(arr != NULL);
ut_ad(count <= BUF_LRU_DROP_SEARCH_HASH_SIZE);
for (i = 0; i < count; ++i) {
btr_search_drop_page_hash_when_freed(space_id, zip_size,
arr[i]);
}
}
/**********************************************************************
When doing a DROP TABLE/DISCARD TABLESPACE we have to drop all page
hash index entries belonging to that table. This function tries to
do that in batch. Note that this is a 'best effort' attempt and does
not guarantee that ALL hash entries will be removed. */
static
void
buf_LRU_drop_page_hash_for_tablespace(
/*==================================*/
ulint id) /* in: space id */
{
buf_page_t* bpage;
ulint* page_arr;
ulint num_entries;
ulint zip_size;
zip_size = fil_space_get_zip_size(id);
if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
/* Somehow, the tablespace does not exist. Nothing to drop. */
ut_ad(0);
return;
}
page_arr = ut_malloc(sizeof(ulint)
* BUF_LRU_DROP_SEARCH_HASH_SIZE);
buf_pool_mutex_enter();
scan_again:
num_entries = 0;
bpage = UT_LIST_GET_LAST(buf_pool->LRU);
while (bpage != NULL) {
mutex_t* block_mutex = buf_page_get_mutex(bpage);
buf_page_t* prev_bpage;
mutex_enter(block_mutex);
prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
ut_a(buf_page_in_file(bpage));
if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE
|| bpage->space != id
|| bpage->buf_fix_count > 0
|| bpage->io_fix != BUF_IO_NONE) {
/* We leave the fixed pages as is in this scan.
To be dealt with later in the final scan. */
mutex_exit(block_mutex);
goto next_page;
}
if (((buf_block_t*) bpage)->is_hashed) {
/* Store the offset(i.e.: page_no) in the array
so that we can drop hash index in a batch
later. */
page_arr[num_entries] = bpage->offset;
mutex_exit(block_mutex);
ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE);
++num_entries;
if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) {
goto next_page;
}
/* Array full. We release the buf_pool->mutex to
obey the latching order. */
buf_pool_mutex_exit();
buf_LRU_drop_page_hash_batch(id, zip_size, page_arr,
num_entries);
num_entries = 0;
buf_pool_mutex_enter();
} else {
mutex_exit(block_mutex);
}
next_page:
/* Note that we may have released the buf_pool mutex
above after reading the prev_bpage during processing
of a page_hash_batch (i.e.: when the array was full).
This means that prev_bpage can change in LRU list.
This is OK because this function is a 'best effort'
to drop as many search hash entries as possible and
it does not guarantee that ALL such entries will be
dropped. */
bpage = prev_bpage;
/* If, however, bpage has been removed from LRU list
to the free list then we should restart the scan.
bpage->state is protected by buf_pool mutex. */
if (bpage && !buf_page_in_file(bpage)) {
ut_a(num_entries == 0);
goto scan_again;
}
}
buf_pool_mutex_exit();
/* Drop any remaining batch of search hashed pages. */
buf_LRU_drop_page_hash_batch(id, zip_size, page_arr, num_entries);
ut_free(page_arr);
}
/********************************************************************** /**********************************************************************
Invalidates all pages belonging to a given tablespace when we are deleting Invalidates all pages belonging to a given tablespace when we are deleting
the data file(s) of that tablespace. */ the data file(s) of that tablespace. */
...@@ -170,6 +302,14 @@ buf_LRU_invalidate_tablespace( ...@@ -170,6 +302,14 @@ buf_LRU_invalidate_tablespace(
ulint page_no; ulint page_no;
ibool all_freed; ibool all_freed;
/* Before we attempt to drop pages one by one we first
attempt to drop page hash index entries in batches to make
it more efficient. The batching attempt is a best effort
attempt and does not guarantee that all pages hash entries
will be dropped. We get rid of remaining page hash entries
one by one below. */
buf_LRU_drop_page_hash_for_tablespace(id);
scan_again: scan_again:
buf_pool_mutex_enter(); buf_pool_mutex_enter();
......
...@@ -1225,7 +1225,6 @@ dict_create_or_check_foreign_constraint_tables(void) ...@@ -1225,7 +1225,6 @@ dict_create_or_check_foreign_constraint_tables(void)
" FOR_COL_NAME CHAR, REF_COL_NAME CHAR);\n" " FOR_COL_NAME CHAR, REF_COL_NAME CHAR);\n"
"CREATE UNIQUE CLUSTERED INDEX ID_IND" "CREATE UNIQUE CLUSTERED INDEX ID_IND"
" ON SYS_FOREIGN_COLS (ID, POS);\n" " ON SYS_FOREIGN_COLS (ID, POS);\n"
"COMMIT WORK;\n"
"END;\n" "END;\n"
, FALSE, trx); , FALSE, trx);
...@@ -1248,7 +1247,7 @@ dict_create_or_check_foreign_constraint_tables(void) ...@@ -1248,7 +1247,7 @@ dict_create_or_check_foreign_constraint_tables(void)
error = DB_MUST_GET_MORE_FILE_SPACE; error = DB_MUST_GET_MORE_FILE_SPACE;
} }
trx->op_info = ""; trx_commit_for_mysql(trx);
row_mysql_unlock_data_dictionary(trx); row_mysql_unlock_data_dictionary(trx);
......
...@@ -287,8 +287,7 @@ dict_table_autoinc_lock( ...@@ -287,8 +287,7 @@ dict_table_autoinc_lock(
} }
/************************************************************************ /************************************************************************
Initializes the autoinc counter. It is not an error to initialize an already Unconditionally set the autoinc counter. */
initialized counter. */
UNIV_INTERN UNIV_INTERN
void void
dict_table_autoinc_initialize( dict_table_autoinc_initialize(
...@@ -298,7 +297,6 @@ dict_table_autoinc_initialize( ...@@ -298,7 +297,6 @@ dict_table_autoinc_initialize(
{ {
ut_ad(mutex_own(&table->autoinc_mutex)); ut_ad(mutex_own(&table->autoinc_mutex));
table->autoinc_inited = TRUE;
table->autoinc = value; table->autoinc = value;
} }
...@@ -312,18 +310,9 @@ dict_table_autoinc_read( ...@@ -312,18 +310,9 @@ dict_table_autoinc_read(
/* out: value for a new row, or 0 */ /* out: value for a new row, or 0 */
const dict_table_t* table) /* in: table */ const dict_table_t* table) /* in: table */
{ {
ib_int64_t value;
ut_ad(mutex_own(&table->autoinc_mutex)); ut_ad(mutex_own(&table->autoinc_mutex));
if (!table->autoinc_inited) { return(table->autoinc);
value = 0;
} else {
value = table->autoinc;
}
return(value);
} }
/************************************************************************ /************************************************************************
...@@ -331,14 +320,15 @@ Updates the autoinc counter if the value supplied is greater than the ...@@ -331,14 +320,15 @@ Updates the autoinc counter if the value supplied is greater than the
current value. If not inited, does nothing. */ current value. If not inited, does nothing. */
UNIV_INTERN UNIV_INTERN
void void
dict_table_autoinc_update( dict_table_autoinc_update_if_greater(
/*======================*/ /*=================================*/
dict_table_t* table, /* in/out: table */ dict_table_t* table, /* in/out: table */
ib_uint64_t value) /* in: value which was assigned to a row */ ib_uint64_t value) /* in: value which was assigned to a row */
{ {
if (table->autoinc_inited && value > table->autoinc) { ut_ad(mutex_own(&table->autoinc_mutex));
if (value > table->autoinc) {
table->autoinc = value; table->autoinc = value;
} }
} }
......
...@@ -62,10 +62,6 @@ dict_mem_table_create( ...@@ -62,10 +62,6 @@ dict_mem_table_create(
mutex_create(&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX); mutex_create(&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
/* The actual increment value will be set by MySQL, we simply
default to 1 here.*/
table->autoinc_increment = 1;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
table->magic_n = DICT_TABLE_MAGIC_N; table->magic_n = DICT_TABLE_MAGIC_N;
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
......
...@@ -699,6 +699,7 @@ xdes_get_descriptor_with_space_hdr( ...@@ -699,6 +699,7 @@ xdes_get_descriptor_with_space_hdr(
MTR_MEMO_X_LOCK)); MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_S_FIX) ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_S_FIX)
|| mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX)); || mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET);
/* Read free limit and space size */ /* Read free limit and space size */
limit = mach_read_from_4(sp_header + FSP_FREE_LIMIT); limit = mach_read_from_4(sp_header + FSP_FREE_LIMIT);
size = mach_read_from_4(sp_header + FSP_SIZE); size = mach_read_from_4(sp_header + FSP_SIZE);
...@@ -1311,6 +1312,7 @@ fsp_fill_free_list( ...@@ -1311,6 +1312,7 @@ fsp_fill_free_list(
mtr_t ibuf_mtr; mtr_t ibuf_mtr;
ut_ad(header && mtr); ut_ad(header && mtr);
ut_ad(page_offset(header) == FSP_HEADER_OFFSET);
/* Check if we can fill free list from above the free list limit */ /* Check if we can fill free list from above the free list limit */
size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr); size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
...@@ -1860,6 +1862,8 @@ fsp_alloc_seg_inode_page( ...@@ -1860,6 +1862,8 @@ fsp_alloc_seg_inode_page(
ulint zip_size; ulint zip_size;
ulint i; ulint i;
ut_ad(page_offset(space_header) == FSP_HEADER_OFFSET);
space = page_get_space_id(page_align(space_header)); space = page_get_space_id(page_align(space_header));
zip_size = dict_table_flags_to_zip_size( zip_size = dict_table_flags_to_zip_size(
mach_read_from_4(FSP_SPACE_FLAGS + space_header)); mach_read_from_4(FSP_SPACE_FLAGS + space_header));
...@@ -1913,6 +1917,8 @@ fsp_alloc_seg_inode( ...@@ -1913,6 +1917,8 @@ fsp_alloc_seg_inode(
ulint zip_size; ulint zip_size;
ulint n; ulint n;
ut_ad(page_offset(space_header) == FSP_HEADER_OFFSET);
if (flst_get_len(space_header + FSP_SEG_INODES_FREE, mtr) == 0) { if (flst_get_len(space_header + FSP_SEG_INODES_FREE, mtr) == 0) {
/* Allocate a new segment inode page */ /* Allocate a new segment inode page */
...@@ -2392,6 +2398,7 @@ fseg_fill_free_list( ...@@ -2392,6 +2398,7 @@ fseg_fill_free_list(
ulint used; ulint used;
ut_ad(inode && mtr); ut_ad(inode && mtr);
ut_ad(!((page_offset(inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
reserved = fseg_n_reserved_pages_low(inode, &used, mtr); reserved = fseg_n_reserved_pages_low(inode, &used, mtr);
...@@ -2452,6 +2459,8 @@ fseg_alloc_free_extent( ...@@ -2452,6 +2459,8 @@ fseg_alloc_free_extent(
dulint seg_id; dulint seg_id;
fil_addr_t first; fil_addr_t first;
ut_ad(!((page_offset(inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
if (flst_get_len(inode + FSEG_FREE, mtr) > 0) { if (flst_get_len(inode + FSEG_FREE, mtr) > 0) {
/* Segment free list is not empty, allocate from it */ /* Segment free list is not empty, allocate from it */
...@@ -2521,6 +2530,7 @@ fseg_alloc_free_page_low( ...@@ -2521,6 +2530,7 @@ fseg_alloc_free_page_low(
ut_ad((direction >= FSP_UP) && (direction <= FSP_NO_DIR)); ut_ad((direction >= FSP_UP) && (direction <= FSP_NO_DIR));
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
== FSEG_MAGIC_N_VALUE); == FSEG_MAGIC_N_VALUE);
ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
seg_id = mtr_read_dulint(seg_inode + FSEG_ID, mtr); seg_id = mtr_read_dulint(seg_inode + FSEG_ID, mtr);
ut_ad(!ut_dulint_is_zero(seg_id)); ut_ad(!ut_dulint_is_zero(seg_id));
...@@ -3110,6 +3120,7 @@ fseg_mark_page_used( ...@@ -3110,6 +3120,7 @@ fseg_mark_page_used(
ulint not_full_n_used; ulint not_full_n_used;
ut_ad(seg_inode && mtr); ut_ad(seg_inode && mtr);
ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
descr = xdes_get_descriptor(space, zip_size, page, mtr); descr = xdes_get_descriptor(space, zip_size, page, mtr);
...@@ -3172,6 +3183,7 @@ fseg_free_page_low( ...@@ -3172,6 +3183,7 @@ fseg_free_page_low(
ut_ad(seg_inode && mtr); ut_ad(seg_inode && mtr);
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
== FSEG_MAGIC_N_VALUE); == FSEG_MAGIC_N_VALUE);
ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
/* Drop search system page hash index if the page is found in /* Drop search system page hash index if the page is found in
the pool and is hashed */ the pool and is hashed */
......
This diff is collapsed.
...@@ -73,12 +73,15 @@ class ha_innobase: public handler ...@@ -73,12 +73,15 @@ class ha_innobase: public handler
void update_thd(); void update_thd();
int change_active_index(uint keynr); int change_active_index(uint keynr);
int general_fetch(uchar* buf, uint direction, uint match_mode); int general_fetch(uchar* buf, uint direction, uint match_mode);
int innobase_read_and_init_auto_inc(ulonglong* ret); ulint innobase_lock_autoinc();
ulong innobase_autoinc_lock(); ulonglong innobase_peek_autoinc();
ulong innobase_set_max_autoinc(ulonglong auto_inc); ulint innobase_set_max_autoinc(ulonglong auto_inc);
ulong innobase_reset_autoinc(ulonglong auto_inc); ulint innobase_reset_autoinc(ulonglong auto_inc);
ulong innobase_get_auto_increment(ulonglong* value); ulint innobase_get_autoinc(ulonglong* value);
ulint innobase_update_autoinc(ulonglong auto_inc);
ulint innobase_initialize_autoinc();
dict_index_t* innobase_get_index(uint keynr); dict_index_t* innobase_get_index(uint keynr);
ulonglong innobase_get_int_col_max_value(const Field* field);
/* Init values for the class: */ /* Init values for the class: */
public: public:
......
...@@ -798,7 +798,9 @@ ha_innobase::add_index( ...@@ -798,7 +798,9 @@ ha_innobase::add_index(
const char* old_name; const char* old_name;
char* tmp_name; char* tmp_name;
case DB_SUCCESS: case DB_SUCCESS:
ut_ad(!dict_locked); ut_a(!dict_locked);
row_mysql_lock_data_dictionary(trx);
dict_locked = TRUE;
if (!new_primary) { if (!new_primary) {
error = row_merge_rename_indexes(trx, indexed_table); error = row_merge_rename_indexes(trx, indexed_table);
...@@ -819,9 +821,6 @@ ha_innobase::add_index( ...@@ -819,9 +821,6 @@ ha_innobase::add_index(
tmp_name = innobase_create_temporary_tablename(heap, '2', tmp_name = innobase_create_temporary_tablename(heap, '2',
old_name); old_name);
row_mysql_lock_data_dictionary(trx);
dict_locked = TRUE;
error = row_merge_rename_tables(innodb_table, indexed_table, error = row_merge_rename_tables(innodb_table, indexed_table,
tmp_name, trx); tmp_name, trx);
...@@ -865,6 +864,11 @@ ha_innobase::add_index( ...@@ -865,6 +864,11 @@ ha_innobase::add_index(
if (new_primary) { if (new_primary) {
row_merge_drop_table(trx, indexed_table); row_merge_drop_table(trx, indexed_table);
} else { } else {
if (!dict_locked) {
row_mysql_lock_data_dictionary(trx);
dict_locked = TRUE;
}
row_merge_drop_indexes(trx, indexed_table, row_merge_drop_indexes(trx, indexed_table,
index, num_created); index, num_created);
} }
...@@ -1136,25 +1140,22 @@ ha_innobase::final_drop_index( ...@@ -1136,25 +1140,22 @@ ha_innobase::final_drop_index(
row_merge_lock_table(prebuilt->trx, prebuilt->table, LOCK_X), row_merge_lock_table(prebuilt->trx, prebuilt->table, LOCK_X),
prebuilt->table->flags, user_thd); prebuilt->table->flags, user_thd);
row_mysql_lock_data_dictionary(trx);
if (UNIV_UNLIKELY(err)) { if (UNIV_UNLIKELY(err)) {
/* Unmark the indexes to be dropped. */ /* Unmark the indexes to be dropped. */
row_mysql_lock_data_dictionary(trx);
for (index = dict_table_get_first_index(prebuilt->table); for (index = dict_table_get_first_index(prebuilt->table);
index; index = dict_table_get_next_index(index)) { index; index = dict_table_get_next_index(index)) {
index->to_be_dropped = FALSE; index->to_be_dropped = FALSE;
} }
row_mysql_unlock_data_dictionary(trx);
goto func_exit; goto func_exit;
} }
/* Drop indexes marked to be dropped */ /* Drop indexes marked to be dropped */
row_mysql_lock_data_dictionary(trx);
index = dict_table_get_first_index(prebuilt->table); index = dict_table_get_first_index(prebuilt->table);
while (index) { while (index) {
...@@ -1179,11 +1180,11 @@ ha_innobase::final_drop_index( ...@@ -1179,11 +1180,11 @@ ha_innobase::final_drop_index(
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
dict_table_check_for_dup_indexes(prebuilt->table); dict_table_check_for_dup_indexes(prebuilt->table);
#endif #endif
row_mysql_unlock_data_dictionary(trx);
func_exit: func_exit:
trx_commit_for_mysql(trx); trx_commit_for_mysql(trx);
trx_commit_for_mysql(prebuilt->trx); trx_commit_for_mysql(prebuilt->trx);
row_mysql_unlock_data_dictionary(trx);
/* Flush the log to reduce probability that the .frm files and /* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs the InnoDB data dictionary get out-of-sync if the user runs
......
...@@ -172,8 +172,7 @@ dict_table_autoinc_lock( ...@@ -172,8 +172,7 @@ dict_table_autoinc_lock(
/*====================*/ /*====================*/
dict_table_t* table); /* in/out: table */ dict_table_t* table); /* in/out: table */
/************************************************************************ /************************************************************************
Initializes the autoinc counter. It is not an error to initialize an already Unconditionally set the autoinc counter. */
initialized counter. */
UNIV_INTERN UNIV_INTERN
void void
dict_table_autoinc_initialize( dict_table_autoinc_initialize(
...@@ -194,8 +193,8 @@ Updates the autoinc counter if the value supplied is equal or bigger than the ...@@ -194,8 +193,8 @@ Updates the autoinc counter if the value supplied is equal or bigger than the
current value. If not inited, does nothing. */ current value. If not inited, does nothing. */
UNIV_INTERN UNIV_INTERN
void void
dict_table_autoinc_update( dict_table_autoinc_update_if_greater(
/*======================*/ /*=================================*/
dict_table_t* table, /* in/out: table */ dict_table_t* table, /* in/out: table */
ib_uint64_t value); /* in: value which was assigned to a row */ ib_uint64_t value); /* in: value which was assigned to a row */
......
...@@ -441,16 +441,8 @@ struct dict_table_struct{ ...@@ -441,16 +441,8 @@ struct dict_table_struct{
mutex_t autoinc_mutex; mutex_t autoinc_mutex;
/* mutex protecting the autoincrement /* mutex protecting the autoincrement
counter */ counter */
ibool autoinc_inited;
/* TRUE if the autoinc counter has been
inited; MySQL gets the init value by executing
SELECT MAX(auto inc column) */
ib_uint64_t autoinc;/* autoinc counter value to give to the ib_uint64_t autoinc;/* autoinc counter value to give to the
next inserted row */ next inserted row */
ib_int64_t autoinc_increment;
/* The increment step of the auto increment
column. Value must be greater than or equal
to 1 */
/*----------------------*/ /*----------------------*/
ulong n_waiting_or_granted_auto_inc_locks; ulong n_waiting_or_granted_auto_inc_locks;
/* This counter is used to track the number /* This counter is used to track the number
...@@ -461,6 +453,7 @@ struct dict_table_struct{ ...@@ -461,6 +453,7 @@ struct dict_table_struct{
acquired the AUTOINC lock or not. Of course acquired the AUTOINC lock or not. Of course
only one transaction can be granted the only one transaction can be granted the
lock but there can be multiple waiters. */ lock but there can be multiple waiters. */
/*----------------------*/
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
ulint magic_n;/* magic number */ ulint magic_n;/* magic number */
......
...@@ -215,5 +215,15 @@ thd_is_strict( ...@@ -215,5 +215,15 @@ thd_is_strict(
/* out: true if thd is in strict mode */ /* out: true if thd is in strict mode */
void* thd); /* in: thread handle (THD*) */ void* thd); /* in: thread handle (THD*) */
/**********************************************************************
Returns the lock wait timeout for the current connection. */
ulong
thd_lock_wait_timeout(
/*==================*/
/* out: the lock wait timeout, in seconds */
void* thd); /* in: thread handle (THD*), or NULL to query
the global innodb_lock_wait_timeout */
#endif #endif
#endif #endif
...@@ -513,14 +513,21 @@ void ...@@ -513,14 +513,21 @@ void
lock_cancel_waiting_and_release( lock_cancel_waiting_and_release(
/*============================*/ /*============================*/
lock_t* lock); /* in: waiting lock request */ lock_t* lock); /* in: waiting lock request */
/************************************************************************* /*************************************************************************
Resets all locks, both table and record locks, on a table to be dropped. Removes locks on a table to be dropped or truncated.
No lock is allowed to be a wait lock. */ If remove_also_table_sx_locks is TRUE then table-level S and X locks are
also removed in addition to other table-level and record-level locks.
No lock, that is going to be removed, is allowed to be a wait lock. */
UNIV_INTERN UNIV_INTERN
void void
lock_reset_all_on_table( lock_remove_all_on_table(
/*====================*/ /*=====================*/
dict_table_t* table); /* in: table to be dropped */ dict_table_t* table, /* in: table to be dropped
or truncated */
ibool remove_also_table_sx_locks);/* in: also removes
table S and X locks */
/************************************************************************* /*************************************************************************
Calculates the fold value of a page file address: used in inserting or Calculates the fold value of a page file address: used in inserting or
searching for a lock in the hash table. */ searching for a lock in the hash table. */
......
...@@ -695,8 +695,7 @@ void ...@@ -695,8 +695,7 @@ void
page_mem_free( page_mem_free(
/*==========*/ /*==========*/
page_t* page, /* in/out: index page */ page_t* page, /* in/out: index page */
page_zip_des_t* page_zip,/* in/out: compressed page with at least page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
6 bytes available, or NULL */
rec_t* rec, /* in: pointer to the (origin of) record */ rec_t* rec, /* in: pointer to the (origin of) record */
dict_index_t* index, /* in: index of rec */ dict_index_t* index, /* in: index of rec */
const ulint* offsets);/* in: array returned by rec_get_offsets() */ const ulint* offsets);/* in: array returned by rec_get_offsets() */
......
...@@ -1011,8 +1011,7 @@ void ...@@ -1011,8 +1011,7 @@ void
page_mem_free( page_mem_free(
/*==========*/ /*==========*/
page_t* page, /* in/out: index page */ page_t* page, /* in/out: index page */
page_zip_des_t* page_zip,/* in/out: compressed page with at least page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
6 bytes available, or NULL */
rec_t* rec, /* in: pointer to the (origin of) record */ rec_t* rec, /* in: pointer to the (origin of) record */
dict_index_t* index, /* in: index of rec */ dict_index_t* index, /* in: index of rec */
const ulint* offsets)/* in: array returned by rec_get_offsets() */ const ulint* offsets)/* in: array returned by rec_get_offsets() */
......
...@@ -128,6 +128,18 @@ page_zip_simple_validate( ...@@ -128,6 +128,18 @@ page_zip_simple_validate(
Check that the compressed and decompressed pages match. */ Check that the compressed and decompressed pages match. */
UNIV_INTERN UNIV_INTERN
ibool ibool
page_zip_validate_low(
/*==================*/
/* out: TRUE if valid, FALSE if not */
const page_zip_des_t* page_zip,/* in: compressed page */
const page_t* page, /* in: uncompressed page */
ibool sloppy) /* in: FALSE=strict,
TRUE=ignore the MIN_REC_FLAG */
__attribute__((nonnull));
/**************************************************************************
Check that the compressed and decompressed pages match. */
UNIV_INTERN
ibool
page_zip_validate( page_zip_validate(
/*==============*/ /*==============*/
const page_zip_des_t* page_zip,/* in: compressed page */ const page_zip_des_t* page_zip,/* in: compressed page */
...@@ -373,11 +385,13 @@ page_zip_reorganize( ...@@ -373,11 +385,13 @@ page_zip_reorganize(
mtr_t* mtr) /* in: mini-transaction */ mtr_t* mtr) /* in: mini-transaction */
__attribute__((nonnull)); __attribute__((nonnull));
/************************************************************************** /**************************************************************************
Copy a page byte for byte, except for the file page header and trailer. */ Copy the records of a page byte for byte. Do not copy the page header
or trailer, except those B-tree header fields that are directly
related to the storage of records. */
UNIV_INTERN UNIV_INTERN
void void
page_zip_copy( page_zip_copy_recs(
/*==========*/ /*===============*/
page_zip_des_t* page_zip, /* out: copy of src_zip page_zip_des_t* page_zip, /* out: copy of src_zip
(n_blobs, m_start, m_end, (n_blobs, m_start, m_end,
m_nonempty, data[0..size-1]) */ m_nonempty, data[0..size-1]) */
......
...@@ -693,6 +693,20 @@ rec_get_converted_extra_size( ...@@ -693,6 +693,20 @@ rec_get_converted_extra_size(
ulint n_ext) /* in: number of externally stored columns */ ulint n_ext) /* in: number of externally stored columns */
__attribute__((const)); __attribute__((const));
/************************************************************** /**************************************************************
Determines the size of a data tuple prefix in ROW_FORMAT=COMPACT. */
UNIV_INTERN
ulint
rec_get_converted_size_comp_prefix(
/*===============================*/
/* out: total size */
const dict_index_t* index, /* in: record descriptor;
dict_table_is_comp() is
assumed to hold, even if
it does not */
const dfield_t* fields, /* in: array of data fields */
ulint n_fields,/* in: number of data fields */
ulint* extra); /* out: extra size */
/**************************************************************
Determines the size of a data tuple in ROW_FORMAT=COMPACT. */ Determines the size of a data tuple in ROW_FORMAT=COMPACT. */
UNIV_INTERN UNIV_INTERN
ulint ulint
......
...@@ -54,7 +54,9 @@ row_merge_lock_table( ...@@ -54,7 +54,9 @@ row_merge_lock_table(
dict_table_t* table, /* in: table to lock */ dict_table_t* table, /* in: table to lock */
enum lock_mode mode); /* in: LOCK_X or LOCK_S */ enum lock_mode mode); /* in: LOCK_X or LOCK_S */
/************************************************************************* /*************************************************************************
Drop an index from the InnoDB system tables. */ Drop an index from the InnoDB system tables. The data dictionary must
have been locked exclusively by the caller, because the transaction
will not be committed. */
UNIV_INTERN UNIV_INTERN
void void
row_merge_drop_index( row_merge_drop_index(
...@@ -63,8 +65,10 @@ row_merge_drop_index( ...@@ -63,8 +65,10 @@ row_merge_drop_index(
dict_table_t* table, /* in: table */ dict_table_t* table, /* in: table */
trx_t* trx); /* in: transaction handle */ trx_t* trx); /* in: transaction handle */
/************************************************************************* /*************************************************************************
Drop those indexes which were created before an error occurred Drop those indexes which were created before an error occurred when
when building an index. */ building an index. The data dictionary must have been locked
exclusively by the caller, because the transaction will not be
committed. */
UNIV_INTERN UNIV_INTERN
void void
row_merge_drop_indexes( row_merge_drop_indexes(
...@@ -80,7 +84,9 @@ void ...@@ -80,7 +84,9 @@ void
row_merge_drop_temp_indexes(void); row_merge_drop_temp_indexes(void);
/*=============================*/ /*=============================*/
/************************************************************************* /*************************************************************************
Rename the tables in the data dictionary. */ Rename the tables in the data dictionary. The data dictionary must
have been locked exclusively by the caller, because the transaction
will not be committed. */
UNIV_INTERN UNIV_INTERN
ulint ulint
row_merge_rename_tables( row_merge_rename_tables(
...@@ -109,7 +115,9 @@ row_merge_create_temporary_table( ...@@ -109,7 +115,9 @@ row_merge_create_temporary_table(
trx_t* trx); /* in/out: transaction trx_t* trx); /* in/out: transaction
(sets error_state) */ (sets error_state) */
/************************************************************************* /*************************************************************************
Rename the temporary indexes in the dictionary to permanent ones. */ Rename the temporary indexes in the dictionary to permanent ones. The
data dictionary must have been locked exclusively by the caller,
because the transaction will not be committed. */
UNIV_INTERN UNIV_INTERN
ulint ulint
row_merge_rename_indexes( row_merge_rename_indexes(
......
...@@ -411,10 +411,12 @@ row_truncate_table_for_mysql( ...@@ -411,10 +411,12 @@ row_truncate_table_for_mysql(
dict_table_t* table, /* in: table handle */ dict_table_t* table, /* in: table handle */
trx_t* trx); /* in: transaction handle */ trx_t* trx); /* in: transaction handle */
/************************************************************************* /*************************************************************************
Drops a table for MySQL. If the name of the dropped table ends in Drops a table for MySQL. If the name of the dropped table ends in
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor", one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
"innodb_table_monitor", then this will also stop the printing of monitor "innodb_table_monitor", then this will also stop the printing of monitor
output by the master thread. */ output by the master thread. If the data dictionary was not already locked
by the transaction, the transaction will be committed. Otherwise, the
data dictionary will remain locked. */
UNIV_INTERN UNIV_INTERN
int int
row_drop_table_for_mysql( row_drop_table_for_mysql(
...@@ -425,20 +427,6 @@ row_drop_table_for_mysql( ...@@ -425,20 +427,6 @@ row_drop_table_for_mysql(
ibool drop_db);/* in: TRUE=dropping whole database */ ibool drop_db);/* in: TRUE=dropping whole database */
/************************************************************************* /*************************************************************************
Drops a table for MySQL but does not commit the transaction. If the
name of the dropped table ends in one of "innodb_monitor",
"innodb_lock_monitor", "innodb_tablespace_monitor",
"innodb_table_monitor", then this will also stop the printing of
monitor output by the master thread. */
UNIV_INTERN
int
row_drop_table_for_mysql_no_commit(
/*===============================*/
/* out: error code or DB_SUCCESS */
const char* name, /* in: table name */
trx_t* trx, /* in: transaction handle */
ibool drop_db);/* in: TRUE=dropping whole database */
/*************************************************************************
Discards the tablespace of a table which stored in an .ibd file. Discarding Discards the tablespace of a table which stored in an .ibd file. Discarding
means that this function deletes the .ibd file and assigns a new table id for means that this function deletes the .ibd file and assigns a new table id for
the table. Also the flag table->ibd_file_missing is set TRUE. */ the table. Also the flag table->ibd_file_missing is set TRUE. */
...@@ -708,7 +696,16 @@ struct row_prebuilt_struct { ...@@ -708,7 +696,16 @@ struct row_prebuilt_struct {
to this heap */ to this heap */
mem_heap_t* old_vers_heap; /* memory heap where a previous mem_heap_t* old_vers_heap; /* memory heap where a previous
version is built in consistent read */ version is built in consistent read */
ulonglong last_value; /* last value of AUTO-INC interval */ /*----------------------*/
ulonglong autoinc_last_value;/* last value of AUTO-INC interval */
ulonglong autoinc_increment;/* The increment step of the auto
increment column. Value must be
greater than or equal to 1. Required to
calculate the next value */
ulonglong autoinc_offset; /* The offset passed to
get_auto_increment() by MySQL. Required
to calculate the next value */
/*----------------------*/
UT_LIST_NODE_T(row_prebuilt_t) prebuilts; UT_LIST_NODE_T(row_prebuilt_t) prebuilts;
/* list node of table->prebuilts */ /* list node of table->prebuilts */
ulint magic_n2; /* this should be the same as ulint magic_n2; /* this should be the same as
......
...@@ -107,8 +107,6 @@ extern ibool srv_archive_recovery; ...@@ -107,8 +107,6 @@ extern ibool srv_archive_recovery;
extern dulint srv_archive_recovery_limit_lsn; extern dulint srv_archive_recovery_limit_lsn;
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
extern ulint srv_lock_wait_timeout;
extern char* srv_file_flush_method_str; extern char* srv_file_flush_method_str;
extern ulint srv_unix_file_flush_method; extern ulint srv_unix_file_flush_method;
extern ulint srv_win_file_flush_method; extern ulint srv_win_file_flush_method;
......
...@@ -4066,15 +4066,25 @@ lock_cancel_waiting_and_release( ...@@ -4066,15 +4066,25 @@ lock_cancel_waiting_and_release(
trx_end_lock_wait(lock->trx); trx_end_lock_wait(lock->trx);
} }
/* True if a lock mode is S or X */
#define IS_LOCK_S_OR_X(lock) \
(lock_get_mode(lock) == LOCK_S \
|| lock_get_mode(lock) == LOCK_X)
/************************************************************************* /*************************************************************************
Resets all record and table locks of a transaction on a table to be dropped. Removes locks of a transaction on a table to be dropped.
No lock is allowed to be a wait lock. */ If remove_also_table_sx_locks is TRUE then table-level S and X locks are
also removed in addition to other table-level and record-level locks.
No lock, that is going to be removed, is allowed to be a wait lock. */
static static
void void
lock_reset_all_on_table_for_trx( lock_remove_all_on_table_for_trx(
/*============================*/ /*=============================*/
dict_table_t* table, /* in: table to be dropped */ dict_table_t* table, /* in: table to be dropped */
trx_t* trx) /* in: a transaction */ trx_t* trx, /* in: a transaction */
ibool remove_also_table_sx_locks)/* in: also removes
table S and X locks */
{ {
lock_t* lock; lock_t* lock;
lock_t* prev_lock; lock_t* prev_lock;
...@@ -4092,7 +4102,9 @@ lock_reset_all_on_table_for_trx( ...@@ -4092,7 +4102,9 @@ lock_reset_all_on_table_for_trx(
lock_rec_discard(lock); lock_rec_discard(lock);
} else if (lock_get_type_low(lock) & LOCK_TABLE } else if (lock_get_type_low(lock) & LOCK_TABLE
&& lock->un_member.tab_lock.table == table) { && lock->un_member.tab_lock.table == table
&& (remove_also_table_sx_locks
|| !IS_LOCK_S_OR_X(lock))) {
ut_a(!lock_get_wait(lock)); ut_a(!lock_get_wait(lock));
...@@ -4104,26 +4116,65 @@ lock_reset_all_on_table_for_trx( ...@@ -4104,26 +4116,65 @@ lock_reset_all_on_table_for_trx(
} }
/************************************************************************* /*************************************************************************
Resets all locks, both table and record locks, on a table to be dropped. Removes locks on a table to be dropped or truncated.
No lock is allowed to be a wait lock. */ If remove_also_table_sx_locks is TRUE then table-level S and X locks are
also removed in addition to other table-level and record-level locks.
No lock, that is going to be removed, is allowed to be a wait lock. */
UNIV_INTERN UNIV_INTERN
void void
lock_reset_all_on_table( lock_remove_all_on_table(
/*====================*/ /*=====================*/
dict_table_t* table) /* in: table to be dropped */ dict_table_t* table, /* in: table to be dropped
or truncated */
ibool remove_also_table_sx_locks)/* in: also removes
table S and X locks */
{ {
lock_t* lock; lock_t* lock;
lock_t* prev_lock;
mutex_enter(&kernel_mutex); mutex_enter(&kernel_mutex);
lock = UT_LIST_GET_FIRST(table->locks); lock = UT_LIST_GET_FIRST(table->locks);
while (lock) { while (lock != NULL) {
ut_a(!lock_get_wait(lock));
lock_reset_all_on_table_for_trx(table, lock->trx); prev_lock = UT_LIST_GET_PREV(un_member.tab_lock.locks,
lock);
lock = UT_LIST_GET_FIRST(table->locks); /* If we should remove all locks (remove_also_table_sx_locks
is TRUE), or if the lock is not table-level S or X lock,
then check we are not going to remove a wait lock. */
if (remove_also_table_sx_locks
|| !(lock_get_type(lock) == LOCK_TABLE
&& IS_LOCK_S_OR_X(lock))) {
ut_a(!lock_get_wait(lock));
}
lock_remove_all_on_table_for_trx(table, lock->trx,
remove_also_table_sx_locks);
if (prev_lock == NULL) {
if (lock == UT_LIST_GET_FIRST(table->locks)) {
/* lock was not removed, pick its successor */
lock = UT_LIST_GET_NEXT(
un_member.tab_lock.locks, lock);
} else {
/* lock was removed, pick the first one */
lock = UT_LIST_GET_FIRST(table->locks);
}
} else if (UT_LIST_GET_NEXT(un_member.tab_lock.locks,
prev_lock) != lock) {
/* If lock was removed by
lock_remove_all_on_table_for_trx() then pick the
successor of prev_lock ... */
lock = UT_LIST_GET_NEXT(
un_member.tab_lock.locks, prev_lock);
} else {
/* ... otherwise pick the successor of lock. */
lock = UT_LIST_GET_NEXT(
un_member.tab_lock.locks, lock);
}
} }
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
......
...@@ -1341,6 +1341,16 @@ recv_recover_page( ...@@ -1341,6 +1341,16 @@ recv_recover_page(
recv = UT_LIST_GET_NEXT(rec_list, recv); recv = UT_LIST_GET_NEXT(rec_list, recv);
} }
#ifdef UNIV_ZIP_DEBUG
if (fil_page_get_type(page) == FIL_PAGE_INDEX) {
page_zip_des_t* page_zip = buf_block_get_page_zip(block);
if (page_zip) {
ut_a(page_zip_validate_low(page_zip, page, FALSE));
}
}
#endif /* UNIV_ZIP_DEBUG */
mutex_enter(&(recv_sys->mutex)); mutex_enter(&(recv_sys->mutex));
if (recv_max_page_lsn < page_lsn) { if (recv_max_page_lsn < page_lsn) {
......
...@@ -196,3 +196,388 @@ c1 c2 ...@@ -196,3 +196,388 @@ c1 c2
3 8 3 8
5 9 5 9
DROP TABLE t1; DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 100
auto_increment_offset 10
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL),(5),(NULL);
INSERT INTO t1 VALUES (250),(NULL);
SELECT * FROM t1;
c1
5
10
110
250
310
INSERT INTO t1 VALUES (1000);
SET @@INSERT_ID=400;
INSERT INTO t1 VALUES(NULL),(NULL);
SELECT * FROM t1;
c1
5
10
110
250
310
400
410
1000
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(0);
SELECT * FROM t1;
c1
1
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
INSERT INTO t1 VALUES (-1), (NULL),(2),(NULL);
INSERT INTO t1 VALUES (250),(NULL);
SELECT * FROM t1;
c1
-1
1
2
10
110
250
410
SET @@INSERT_ID=400;
INSERT INTO t1 VALUES(NULL),(NULL);
Got one of the listed errors
SELECT * FROM t1;
c1
-1
1
2
10
110
250
410
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(-1);
SELECT * FROM t1;
c1
-1
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 100
auto_increment_offset 10
INSERT INTO t1 VALUES (-2), (NULL),(2),(NULL);
INSERT INTO t1 VALUES (250),(NULL);
SELECT * FROM t1;
c1
-2
-1
1
2
10
250
310
INSERT INTO t1 VALUES (1000);
SET @@INSERT_ID=400;
INSERT INTO t1 VALUES(NULL),(NULL);
SELECT * FROM t1;
c1
-2
-1
1
2
10
250
310
400
410
1000
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(-1);
Warnings:
Warning 1264 Out of range value for column 'c1' at row 1
SELECT * FROM t1;
c1
1
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 100
auto_increment_offset 10
INSERT INTO t1 VALUES (-2);
Warnings:
Warning 1264 Out of range value for column 'c1' at row 1
INSERT INTO t1 VALUES (NULL);
INSERT INTO t1 VALUES (2);
INSERT INTO t1 VALUES (NULL);
INSERT INTO t1 VALUES (250);
INSERT INTO t1 VALUES (NULL);
SELECT * FROM t1;
c1
1
2
10
110
210
250
310
INSERT INTO t1 VALUES (1000);
SET @@INSERT_ID=400;
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
c1
1
2
10
110
210
250
310
400
1000
1010
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(-1);
Warnings:
Warning 1264 Out of range value for column 'c1' at row 1
SELECT * FROM t1;
c1
1
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 100
auto_increment_offset 10
INSERT INTO t1 VALUES (-2),(NULL),(2),(NULL);
Warnings:
Warning 1264 Out of range value for column 'c1' at row 1
INSERT INTO t1 VALUES (250),(NULL);
SELECT * FROM t1;
c1
1
2
10
110
210
250
410
INSERT INTO t1 VALUES (1000);
SET @@INSERT_ID=400;
INSERT INTO t1 VALUES(NULL),(NULL);
Got one of the listed errors
SELECT * FROM t1;
c1
1
2
10
110
210
250
410
1000
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 BIGINT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES (9223372036854775794);
SELECT * FROM t1;
c1
1
9223372036854775794
SET @@SESSION.AUTO_INCREMENT_INCREMENT=2, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 2
auto_increment_offset 10
INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
SELECT * FROM t1;
c1
1
9223372036854775794
9223372036854775796
9223372036854775798
9223372036854775800
9223372036854775802
9223372036854775804
9223372036854775806
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES (18446744073709551603);
SELECT * FROM t1;
c1
1
18446744073709551603
SET @@SESSION.AUTO_INCREMENT_INCREMENT=2, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 2
auto_increment_offset 10
INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
SELECT * FROM t1;
c1
0
1
18446744073709551603
18446744073709551604
18446744073709551606
18446744073709551608
18446744073709551610
18446744073709551612
18446744073709551614
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES (18446744073709551603);
SELECT * FROM t1;
c1
1
18446744073709551603
SET @@SESSION.AUTO_INCREMENT_INCREMENT=5, @@SESSION.AUTO_INCREMENT_OFFSET=7;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 5
auto_increment_offset 7
INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
Got one of the listed errors
SELECT * FROM t1;
c1
1
18446744073709551603
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 BIGINT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES(-9223372036854775806);
INSERT INTO t1 VALUES(-9223372036854775807);
INSERT INTO t1 VALUES(-9223372036854775808);
SELECT * FROM t1;
c1
-9223372036854775808
-9223372036854775807
-9223372036854775806
1
SET @@SESSION.AUTO_INCREMENT_INCREMENT=3, @@SESSION.AUTO_INCREMENT_OFFSET=3;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 3
auto_increment_offset 3
INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
SELECT * FROM t1;
c1
-9223372036854775808
-9223372036854775807
-9223372036854775806
1
3
6
9
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES (18446744073709551610);
SELECT * FROM t1;
c1
1
18446744073709551610
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1152921504606846976, @@SESSION.AUTO_INCREMENT_OFFSET=1152921504606846976;
Warnings:
Warning 1292 Truncated incorrect auto_increment_increment value: '1152921504606846976'
Warning 1292 Truncated incorrect auto_increment_offset value: '1152921504606846976'
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 65535
auto_increment_offset 65535
INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
SELECT * FROM t1;
c1
1
65534
65535
18446744073709551610
18446744073709551615
DROP TABLE t1;
...@@ -156,7 +156,218 @@ DROP TABLE IF EXISTS t1; ...@@ -156,7 +156,218 @@ DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) ENGINE=InnoDB; CREATE TABLE t1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL, 1); INSERT INTO t1 VALUES (NULL, 1);
DELETE FROM t1 WHERE c1 = 1; DELETE FROM t1 WHERE c1 = 1;
INSERT INTO t1 VALUES (2,1), (NULL, 8); INSERT INTO t1 VALUES (2,1), (NULL, 8);
INSERT INTO t1 VALUES (NULL,9); INSERT INTO t1 VALUES (NULL,9);
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
#
# Test changes to AUTOINC next value calculation
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL),(5),(NULL);
INSERT INTO t1 VALUES (250),(NULL);
SELECT * FROM t1;
INSERT INTO t1 VALUES (1000);
SET @@INSERT_ID=400;
INSERT INTO t1 VALUES(NULL),(NULL);
SELECT * FROM t1;
DROP TABLE t1;
# Test with SIGNED INT column, by inserting a 0 for the first column value
# 0 is treated in the same was NULL.
# Reset the AUTOINC session variables
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(0);
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
INSERT INTO t1 VALUES (-1), (NULL),(2),(NULL);
INSERT INTO t1 VALUES (250),(NULL);
SELECT * FROM t1;
SET @@INSERT_ID=400;
# Duplicate error expected here for autoinc_lock_mode != TRADITIONAL
-- error ER_DUP_ENTRY,1062
INSERT INTO t1 VALUES(NULL),(NULL);
SELECT * FROM t1;
DROP TABLE t1;
# Test with SIGNED INT column
# Reset the AUTOINC session variables
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(-1);
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
INSERT INTO t1 VALUES (-2), (NULL),(2),(NULL);
INSERT INTO t1 VALUES (250),(NULL);
SELECT * FROM t1;
INSERT INTO t1 VALUES (1000);
SET @@INSERT_ID=400;
INSERT INTO t1 VALUES(NULL),(NULL);
SELECT * FROM t1;
DROP TABLE t1;
# Test with UNSIGNED INT column, single insert
# The sign in the value is ignored and a new column value is generated
# Reset the AUTOINC session variables
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(-1);
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
INSERT INTO t1 VALUES (-2);
INSERT INTO t1 VALUES (NULL);
INSERT INTO t1 VALUES (2);
INSERT INTO t1 VALUES (NULL);
INSERT INTO t1 VALUES (250);
INSERT INTO t1 VALUES (NULL);
SELECT * FROM t1;
INSERT INTO t1 VALUES (1000);
SET @@INSERT_ID=400;
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
DROP TABLE t1;
# Test with UNSIGNED INT column, multi-value inserts
# The sign in the value is ignored and a new column value is generated
# Reset the AUTOINC session variables
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(-1);
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
INSERT INTO t1 VALUES (-2),(NULL),(2),(NULL);
INSERT INTO t1 VALUES (250),(NULL);
SELECT * FROM t1;
INSERT INTO t1 VALUES (1000);
SET @@INSERT_ID=400;
# Duplicate error expected here for autoinc_lock_mode != TRADITIONAL
-- error ER_DUP_ENTRY,1062
INSERT INTO t1 VALUES(NULL),(NULL);
SELECT * FROM t1;
DROP TABLE t1;
#
# Check for overflow handling when increment is > 1
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 BIGINT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
# TODO: Fix the autoinc init code
# We have to do this because of a bug in the AUTOINC init code.
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES (9223372036854775794); -- 2^63 - 14
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=2, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
# This should just fit
INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
SELECT * FROM t1;
DROP TABLE t1;
#
# Check for overflow handling when increment and offser are > 1
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
# TODO: Fix the autoinc init code
# We have to do this because of a bug in the AUTOINC init code.
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES (18446744073709551603); -- 2^64 - 13
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=2, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
# This should fail because of overflow but it doesn't, it seems to be
# a MySQL server bug. It wraps around to 0 for the last value.
# See MySQL Bug# 39828
INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
SELECT * FROM t1;
DROP TABLE t1;
#
# Check for overflow handling when increment and offset are odd numbers
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
# TODO: Fix the autoinc init code
# We have to do this because of a bug in the AUTOINC init code.
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES (18446744073709551603); -- 2^64 - 13
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=5, @@SESSION.AUTO_INCREMENT_OFFSET=7;
SHOW VARIABLES LIKE "%auto_inc%";
# This should fail because of overflow but it doesn't. It fails with
# a duplicate entry message because of a MySQL server bug, it wraps
# around. See MySQL Bug# 39828, once MySQL fix the bug we can replace
# the ER_DUP_ENTRY, 1062 below with the appropriate error message
-- error ER_DUP_ENTRY,1062
INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
SELECT * FROM t1;
DROP TABLE t1;
# Check for overflow handling when increment and offset are odd numbers
# and check for large -ve numbers
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 BIGINT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
# TODO: Fix the autoinc init code
# We have to do this because of a bug in the AUTOINC init code.
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES(-9223372036854775806); -- -2^63 + 2
INSERT INTO t1 VALUES(-9223372036854775807); -- -2^63 + 1
INSERT INTO t1 VALUES(-9223372036854775808); -- -2^63
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=3, @@SESSION.AUTO_INCREMENT_OFFSET=3;
SHOW VARIABLES LIKE "%auto_inc%";
INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
SELECT * FROM t1;
DROP TABLE t1;
#
# Check for overflow handling when increment and offset are very
# large numbers 2^60
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
# TODO: Fix the autoinc init code
# We have to do this because of a bug in the AUTOINC init code.
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES (18446744073709551610); -- 2^64 - 2
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1152921504606846976, @@SESSION.AUTO_INCREMENT_OFFSET=1152921504606846976;
SHOW VARIABLES LIKE "%auto_inc%";
# This should fail because of overflow but it doesn't. It wraps around
# and the autoinc values look bogus too.
# See MySQL Bug# 39828, once MySQL fix the bug we can enable the error
# code expected test.
# -- error ER_AUTOINC_READ_FAILED,1467
INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
SELECT * FROM t1;
DROP TABLE t1;
...@@ -847,10 +847,12 @@ create table t2(a int, b varchar(255), primary key(a,b)) engine=innodb; ...@@ -847,10 +847,12 @@ create table t2(a int, b varchar(255), primary key(a,b)) engine=innodb;
insert into t2 select a,left(b,255) from t1; insert into t2 select a,left(b,255) from t1;
drop table t1; drop table t1;
rename table t2 to t1; rename table t2 to t1;
set innodb_lock_wait_timeout=1;
begin; begin;
select a from t1 limit 1 for update; select a from t1 limit 1 for update;
a a
22 22
set innodb_lock_wait_timeout=1;
create index t1ba on t1 (b,a); create index t1ba on t1 (b,a);
ERROR HY000: Lock wait timeout exceeded; try restarting transaction ERROR HY000: Lock wait timeout exceeded; try restarting transaction
commit; commit;
......
...@@ -304,10 +304,12 @@ rename table t2 to t1; ...@@ -304,10 +304,12 @@ rename table t2 to t1;
connect (a,localhost,root,,); connect (a,localhost,root,,);
connect (b,localhost,root,,); connect (b,localhost,root,,);
connection a; connection a;
set innodb_lock_wait_timeout=1;
begin; begin;
# Obtain an IX lock on the table # Obtain an IX lock on the table
select a from t1 limit 1 for update; select a from t1 limit 1 for update;
connection b; connection b;
set innodb_lock_wait_timeout=1;
# This would require an S lock on the table, conflicting with the IX lock. # This would require an S lock on the table, conflicting with the IX lock.
--error ER_LOCK_WAIT_TIMEOUT --error ER_LOCK_WAIT_TIMEOUT
create index t1ba on t1 (b,a); create index t1ba on t1 (b,a);
...@@ -467,20 +469,20 @@ CREATE TABLE t2( ...@@ -467,20 +469,20 @@ CREATE TABLE t2(
PRIMARY KEY (c1) PRIMARY KEY (c1)
) ENGINE=InnoDB DEFAULT CHARSET=latin1; ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--replace_regex /'test\.#sql-[0-9a-f-]*_1'/'#sql-temporary'/ --replace_regex /'test\.#sql-[0-9_a-f-]*'/'#sql-temporary'/
--error ER_CANT_CREATE_TABLE --error ER_CANT_CREATE_TABLE
ALTER TABLE t2 ADD CONSTRAINT fk_t2_ca ALTER TABLE t2 ADD CONSTRAINT fk_t2_ca
FOREIGN KEY (c3,c2) REFERENCES t1(c1,c1); FOREIGN KEY (c3,c2) REFERENCES t1(c1,c1);
--replace_regex /'test\.#sql-[0-9a-f-]*_1'/'#sql-temporary'/ --replace_regex /'test\.#sql-[0-9_a-f-]*'/'#sql-temporary'/
--error ER_CANT_CREATE_TABLE --error ER_CANT_CREATE_TABLE
ALTER TABLE t2 ADD CONSTRAINT fk_t2_ca ALTER TABLE t2 ADD CONSTRAINT fk_t2_ca
FOREIGN KEY (c3,c2) REFERENCES t1(c1,c2); FOREIGN KEY (c3,c2) REFERENCES t1(c1,c2);
--replace_regex /'test\.#sql-[0-9a-f-]*_1'/'#sql-temporary'/ --replace_regex /'test\.#sql-[0-9_a-f-]*'/'#sql-temporary'/
--error ER_CANT_CREATE_TABLE --error ER_CANT_CREATE_TABLE
ALTER TABLE t2 ADD CONSTRAINT fk_t2_ca ALTER TABLE t2 ADD CONSTRAINT fk_t2_ca
FOREIGN KEY (c3,c2) REFERENCES t1(c2,c1); FOREIGN KEY (c3,c2) REFERENCES t1(c2,c1);
ALTER TABLE t1 MODIFY COLUMN c2 BIGINT(12) NOT NULL; ALTER TABLE t1 MODIFY COLUMN c2 BIGINT(12) NOT NULL;
--replace_regex /'test\.#sql-[0-9a-f-]*_1'/'#sql-temporary'/ --replace_regex /'test\.#sql-[0-9_a-f-]*'/'#sql-temporary'/
--error ER_CANT_CREATE_TABLE --error ER_CANT_CREATE_TABLE
ALTER TABLE t2 ADD CONSTRAINT fk_t2_ca ALTER TABLE t2 ADD CONSTRAINT fk_t2_ca
FOREIGN KEY (c3,c2) REFERENCES t1(c1,c2); FOREIGN KEY (c3,c2) REFERENCES t1(c1,c2);
......
set global innodb_lock_wait_timeout=42;
select @@innodb_lock_wait_timeout;
@@innodb_lock_wait_timeout
42
set innodb_lock_wait_timeout=1;
select @@innodb_lock_wait_timeout;
@@innodb_lock_wait_timeout
1
select @@innodb_lock_wait_timeout;
@@innodb_lock_wait_timeout
42
set global innodb_lock_wait_timeout=347;
select @@innodb_lock_wait_timeout;
@@innodb_lock_wait_timeout
42
set innodb_lock_wait_timeout=1;
select @@innodb_lock_wait_timeout;
@@innodb_lock_wait_timeout
1
select @@innodb_lock_wait_timeout;
@@innodb_lock_wait_timeout
347
create table t1(a int primary key)engine=innodb;
begin;
insert into t1 values(1),(2),(3);
select * from t1 for update;
commit;
a
1
2
3
begin;
insert into t1 values(4);
select * from t1 for update;
commit;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
drop table t1;
set global innodb_lock_wait_timeout=50;
-- source include/have_innodb.inc
let $timeout=`select @@innodb_lock_wait_timeout`;
set global innodb_lock_wait_timeout=42;
connect (a,localhost,root,,);
connect (b,localhost,root,,);
connection a;
select @@innodb_lock_wait_timeout;
set innodb_lock_wait_timeout=1;
select @@innodb_lock_wait_timeout;
connection b;
select @@innodb_lock_wait_timeout;
set global innodb_lock_wait_timeout=347;
select @@innodb_lock_wait_timeout;
set innodb_lock_wait_timeout=1;
select @@innodb_lock_wait_timeout;
connect (c,localhost,root,,);
connection c;
select @@innodb_lock_wait_timeout;
connection default;
disconnect c;
connection a;
create table t1(a int primary key)engine=innodb;
begin;
insert into t1 values(1),(2),(3);
connection b;
--send
select * from t1 for update;
connection a;
commit;
connection b;
reap;
connection a;
begin;
insert into t1 values(4);
connection b;
--send
select * from t1 for update;
connection a;
sleep 2;
commit;
connection b;
--error ER_LOCK_WAIT_TIMEOUT
reap;
drop table t1;
connection default;
disconnect a;
disconnect b;
eval set global innodb_lock_wait_timeout=$timeout;
...@@ -8,7 +8,7 @@ in mind when adding new patches here: ...@@ -8,7 +8,7 @@ in mind when adding new patches here:
* The patch filename must end in ".diff". * The patch filename must end in ".diff".
* All patches here are expected to apply cleanly to the latest MySQL 5.1 * All patches here are expected to apply cleanly to the latest MySQL 5.1
tree with storage/innobase is replaced with this InnoDB branch. If tree when storage/innobase is replaced with this InnoDB branch. If
changes to either of those cause the patch to fail, then please check changes to either of those cause the patch to fail, then please check
whether the patch is still needed and, if yes, adjust it so it applies whether the patch is still needed and, if yes, adjust it so it applies
cleanly. cleanly.
...@@ -19,7 +19,7 @@ in mind when adding new patches here: ...@@ -19,7 +19,7 @@ in mind when adding new patches here:
* If the patch cannot be proposed for inclusion in the MySQL source tree * If the patch cannot be proposed for inclusion in the MySQL source tree
(via http://bugs.mysql.com) then add a comment at the beginning of the (via http://bugs.mysql.com) then add a comment at the beginning of the
patch explaining the problem it is solving, how it does solve it and patch, explaining the problem it is solving, how it does solve it and
why it is not applicable for inclusion in the MySQL source tree. why it is not applicable for inclusion in the MySQL source tree.
Obviously this is a very bad situation and should be avoided at all Obviously this is a very bad situation and should be avoided at all
costs, especially for files that are in the MySQL source repository costs, especially for files that are in the MySQL source repository
......
diff -pu sql/mysql_priv.h sql/mysql_priv.h
--- sql/mysql_priv.h 2007-11-14 15:28:19.000000000 +0200
+++ sql/mysql_priv.h 2008-01-08 10:45:53.000000000 +0200
@@ -2094,6 +2094,7 @@ uint build_table_shadow_filename(char *b
#define FN_TO_IS_TMP (1 << 1)
#define FN_IS_TMP (FN_FROM_IS_TMP | FN_TO_IS_TMP)
#define NO_FRM_RENAME (1 << 2)
+#define FN_FRM_ONLY (1 << 3)
/* from hostname.cc */
struct in_addr;
diff -pu sql/sql_table.cc sql/sql_table.cc
--- sql/sql_table.cc 2007-11-02 00:48:11.000000000 +0200
+++ sql/sql_table.cc 2008-01-08 10:46:04.000000000 +0200
@@ -1791,8 +1791,9 @@ bool quick_rm_table(handlerton *base,con
if (my_delete(path,MYF(0)))
error= 1; /* purecov: inspected */
path[path_length - reg_ext_length]= '\0'; // Remove reg_ext
- DBUG_RETURN(ha_delete_table(current_thd, base, path, db, table_name, 0) ||
- error);
+ if (!(flags & FN_FRM_ONLY))
+ error|= ha_delete_table(current_thd, base, path, db, table_name, 0);
+ DBUG_RETURN(error);
}
/*
@@ -6680,7 +6681,10 @@ err1:
close_temporary_table(thd, new_table, 1, 1);
}
else
- VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
+ VOID(quick_rm_table(new_db_type, new_db, tmp_name,
+ create_info->frm_only
+ ? FN_IS_TMP | FN_FRM_ONLY
+ : FN_IS_TMP));
err:
/*
--- mysql-test/t/type_bit_innodb.test.orig 2008-10-07 11:32:32.000000000 +0300
+++ mysql-test/t/type_bit_innodb.test 2008-10-07 11:56:40.000000000 +0300
@@ -40,6 +40,7 @@
create table t1 (a bit) engine=innodb;
insert into t1 values (b'0'), (b'1'), (b'000'), (b'100'), (b'001');
select hex(a) from t1;
+--replace_regex /entry '(.*)' for/entry '' for/
--error ER_DUP_ENTRY
alter table t1 add unique (a);
drop table t1;
InnoDB's estimate for the index cardinality depends on a pseudo random
number generator (it picks up random pages to sample). After an
optimization that was made in r2625 the following EXPLAINs started
returning a different number of rows (3 instead of 4).
This patch adjusts the result file.
This patch cannot be proposed to MySQL because the failures occur only
in this tree and do not occur in the standard InnoDB 5.1. Furthermore,
the file index_merge2.inc is used by other engines too.
--- mysql-test/r/index_merge_innodb.result.orig 2008-09-30 18:32:13.000000000 +0300
+++ mysql-test/r/index_merge_innodb.result 2008-09-30 18:33:01.000000000 +0300
@@ -111,7 +111,7 @@
explain select count(*) from t1 where
key1a = 2 and key1b is null and key2a = 2 and key2b is null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL 4 Using intersect(i1,i2); Using where; Using index
+1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL 3 Using intersect(i1,i2); Using where; Using index
select count(*) from t1 where
key1a = 2 and key1b is null and key2a = 2 and key2b is null;
count(*)
@@ -119,7 +119,7 @@
explain select count(*) from t1 where
key1a = 2 and key1b is null and key3a = 2 and key3b is null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL 4 Using intersect(i1,i3); Using where; Using index
+1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL 3 Using intersect(i1,i3); Using where; Using index
select count(*) from t1 where
key1a = 2 and key1b is null and key3a = 2 and key3b is null;
count(*)
diff mysql-test/r/information_schema.result.orig mysql-test/r/information_schema.result
--- mysql-test/r/information_schema.result.orig 2008-08-04 09:27:49.000000000 +0300
+++ mysql-test/r/information_schema.result 2008-10-07 11:21:51.000000000 +0300
@@ -64,6 +64,13 @@
TRIGGERS
USER_PRIVILEGES
VIEWS
+INNODB_CMP_RESET
+INNODB_TRX
+INNODB_CMPMEM_RESET
+INNODB_LOCK_WAITS
+INNODB_CMPMEM
+INNODB_CMP
+INNODB_LOCKS
columns_priv
db
event
@@ -795,6 +802,8 @@
TABLES UPDATE_TIME datetime
TABLES CHECK_TIME datetime
TRIGGERS CREATED datetime
+INNODB_TRX trx_started datetime
+INNODB_TRX trx_wait_started datetime
event execute_at datetime
event last_executed datetime
event starts datetime
@@ -848,7 +857,7 @@
flush privileges;
SELECT table_schema, count(*) FROM information_schema.TABLES where table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA;
table_schema count(*)
-information_schema 28
+information_schema 35
mysql 22
create table t1 (i int, j int);
create trigger trg1 before insert on t1 for each row
@@ -1263,6 +1272,13 @@
TRIGGERS TRIGGER_SCHEMA
USER_PRIVILEGES GRANTEE
VIEWS TABLE_SCHEMA
+INNODB_CMP_RESET page_size
+INNODB_TRX trx_id
+INNODB_CMPMEM_RESET page_size
+INNODB_LOCK_WAITS requesting_trx_id
+INNODB_CMPMEM page_size
+INNODB_CMP page_size
+INNODB_LOCKS lock_id
SELECT t.table_name, c1.column_name
FROM information_schema.tables t
INNER JOIN
@@ -1306,6 +1322,13 @@
TRIGGERS TRIGGER_SCHEMA
USER_PRIVILEGES GRANTEE
VIEWS TABLE_SCHEMA
+INNODB_CMP_RESET page_size
+INNODB_TRX trx_id
+INNODB_CMPMEM_RESET page_size
+INNODB_LOCK_WAITS requesting_trx_id
+INNODB_CMPMEM page_size
+INNODB_CMP page_size
+INNODB_LOCKS lock_id
SELECT MAX(table_name) FROM information_schema.tables;
MAX(table_name)
VIEWS
@@ -1382,6 +1405,13 @@
FILES information_schema.FILES 1
GLOBAL_STATUS information_schema.GLOBAL_STATUS 1
GLOBAL_VARIABLES information_schema.GLOBAL_VARIABLES 1
+INNODB_CMP information_schema.INNODB_CMP 1
+INNODB_CMPMEM information_schema.INNODB_CMPMEM 1
+INNODB_CMPMEM_RESET information_schema.INNODB_CMPMEM_RESET 1
+INNODB_CMP_RESET information_schema.INNODB_CMP_RESET 1
+INNODB_LOCKS information_schema.INNODB_LOCKS 1
+INNODB_LOCK_WAITS information_schema.INNODB_LOCK_WAITS 1
+INNODB_TRX information_schema.INNODB_TRX 1
KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1
PARTITIONS information_schema.PARTITIONS 1
PLUGINS information_schema.PLUGINS 1
diff mysql-test/r/information_schema_db.result.orig mysql-test/r/information_schema_db.result
--- mysql-test/r/information_schema_db.result.orig 2008-08-04 09:27:49.000000000 +0300
+++ mysql-test/r/information_schema_db.result 2008-10-07 12:26:31.000000000 +0300
@@ -33,6 +33,13 @@
TRIGGERS
USER_PRIVILEGES
VIEWS
+INNODB_CMP_RESET
+INNODB_TRX
+INNODB_CMPMEM_RESET
+INNODB_LOCK_WAITS
+INNODB_CMPMEM
+INNODB_CMP
+INNODB_LOCKS
show tables from INFORMATION_SCHEMA like 'T%';
Tables_in_information_schema (T%)
TABLES
diff mysql-test/r/mysqlshow.result.orig mysql-test/r/mysqlshow.result
--- mysql-test/r/mysqlshow.result.orig 2008-08-04 09:27:51.000000000 +0300
+++ mysql-test/r/mysqlshow.result 2008-10-07 12:35:39.000000000 +0300
@@ -107,6 +107,13 @@
| TRIGGERS |
| USER_PRIVILEGES |
| VIEWS |
+| INNODB_CMP_RESET |
+| INNODB_TRX |
+| INNODB_CMPMEM_RESET |
+| INNODB_LOCK_WAITS |
+| INNODB_CMPMEM |
+| INNODB_CMP |
+| INNODB_LOCKS |
+---------------------------------------+
Database: INFORMATION_SCHEMA
+---------------------------------------+
@@ -140,6 +147,13 @@
| TRIGGERS |
| USER_PRIVILEGES |
| VIEWS |
+| INNODB_CMP_RESET |
+| INNODB_TRX |
+| INNODB_CMPMEM_RESET |
+| INNODB_LOCK_WAITS |
+| INNODB_CMPMEM |
+| INNODB_CMP |
+| INNODB_LOCKS |
+---------------------------------------+
Wildcard: inf_rmation_schema
+--------------------+
diff mysql-test/t/innodb_file_per_table_basic.test.orig mysql-test/t/innodb_file_per_table_basic.test
--- mysql-test/t/innodb_file_per_table_basic.test.orig 2008-10-07 11:32:30.000000000 +0300
+++ mysql-test/t/innodb_file_per_table_basic.test 2008-10-07 11:52:14.000000000 +0300
@@ -37,10 +37,6 @@
# Check if Value can set #
####################################################################
---error ER_INCORRECT_GLOBAL_LOCAL_VAR
-SET @@GLOBAL.innodb_file_per_table=1;
---echo Expected error 'Read only variable'
-
SELECT COUNT(@@GLOBAL.innodb_file_per_table);
--echo 1 Expected
@@ -52,7 +48,7 @@
# Check if the value in GLOBAL Table matches value in variable #
#################################################################
-SELECT @@GLOBAL.innodb_file_per_table = VARIABLE_VALUE
+SELECT IF(@@GLOBAL.innodb_file_per_table,'ON','OFF') = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_file_per_table';
--echo 1 Expected
diff mysql-test/t/innodb_file_per_table_basic.result.orig mysql-test/t/innodb_file_per_table_basic.result
--- mysql-test/r/innodb_file_per_table_basic.result.orig 2008-10-07 11:32:02.000000000 +0300
+++ mysql-test/r/innodb_file_per_table_basic.result 2008-10-07 11:52:47.000000000 +0300
@@ -4,18 +4,15 @@
1
1 Expected
'#---------------------BS_STVARS_028_02----------------------#'
-SET @@GLOBAL.innodb_file_per_table=1;
-ERROR HY000: Variable 'innodb_file_per_table' is a read only variable
-Expected error 'Read only variable'
SELECT COUNT(@@GLOBAL.innodb_file_per_table);
COUNT(@@GLOBAL.innodb_file_per_table)
1
1 Expected
'#---------------------BS_STVARS_028_03----------------------#'
-SELECT @@GLOBAL.innodb_file_per_table = VARIABLE_VALUE
+SELECT IF(@@GLOBAL.innodb_file_per_table,'ON','OFF') = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_file_per_table';
-@@GLOBAL.innodb_file_per_table = VARIABLE_VALUE
+IF(@@GLOBAL.innodb_file_per_table,'ON','OFF') = VARIABLE_VALUE
1
1 Expected
SELECT COUNT(@@GLOBAL.innodb_file_per_table);
--- mysql-test/t/innodb_lock_wait_timeout_basic.test.orig 2008-08-04 09:28:16.000000000 +0300
+++ mysql-test/t/innodb_lock_wait_timeout_basic.test 2008-10-07 11:14:15.000000000 +0300
@@ -37,10 +37,6 @@
# Check if Value can set #
####################################################################
---error ER_INCORRECT_GLOBAL_LOCAL_VAR
-SET @@GLOBAL.innodb_lock_wait_timeout=1;
---echo Expected error 'Read only variable'
-
SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
--echo 1 Expected
@@ -84,13 +80,9 @@
SELECT COUNT(@@innodb_lock_wait_timeout);
--echo 1 Expected
---Error ER_INCORRECT_GLOBAL_LOCAL_VAR
SELECT COUNT(@@local.innodb_lock_wait_timeout);
---echo Expected error 'Variable is a GLOBAL variable'
---Error ER_INCORRECT_GLOBAL_LOCAL_VAR
SELECT COUNT(@@SESSION.innodb_lock_wait_timeout);
---echo Expected error 'Variable is a GLOBAL variable'
SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
--echo 1 Expected
--- mysql-test/r/innodb_lock_wait_timeout_basic.result.orig 2008-08-04 09:27:50.000000000 +0300
+++ mysql-test/r/innodb_lock_wait_timeout_basic.result 2008-10-07 11:15:14.000000000 +0300
@@ -4,9 +4,6 @@
1
1 Expected
'#---------------------BS_STVARS_032_02----------------------#'
-SET @@GLOBAL.innodb_lock_wait_timeout=1;
-ERROR HY000: Variable 'innodb_lock_wait_timeout' is a read only variable
-Expected error 'Read only variable'
SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
COUNT(@@GLOBAL.innodb_lock_wait_timeout)
1
@@ -39,11 +36,11 @@
1
1 Expected
SELECT COUNT(@@local.innodb_lock_wait_timeout);
-ERROR HY000: Variable 'innodb_lock_wait_timeout' is a GLOBAL variable
-Expected error 'Variable is a GLOBAL variable'
+COUNT(@@local.innodb_lock_wait_timeout)
+1
SELECT COUNT(@@SESSION.innodb_lock_wait_timeout);
-ERROR HY000: Variable 'innodb_lock_wait_timeout' is a GLOBAL variable
-Expected error 'Variable is a GLOBAL variable'
+COUNT(@@SESSION.innodb_lock_wait_timeout)
+1
SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
COUNT(@@GLOBAL.innodb_lock_wait_timeout)
1
...@@ -593,8 +593,18 @@ page_copy_rec_list_end( ...@@ -593,8 +593,18 @@ page_copy_rec_list_end(
page_get_infimum_rec(new_page)); page_get_infimum_rec(new_page));
ulint log_mode = 0; /* remove warning */ ulint log_mode = 0; /* remove warning */
/* page_zip_validate() will fail here if btr_compress() #ifdef UNIV_ZIP_DEBUG
sets FIL_PAGE_PREV to FIL_NULL */ if (new_page_zip) {
page_zip_des_t* page_zip = buf_block_get_page_zip(block);
ut_a(page_zip);
/* Strict page_zip_validate() may fail here.
Furthermore, btr_compress() may set FIL_PAGE_PREV to
FIL_NULL on new_page while leaving it intact on
new_page_zip. So, we cannot validate new_page_zip. */
ut_a(page_zip_validate_low(page_zip, page, TRUE));
}
#endif /* UNIV_ZIP_DEBUG */
ut_ad(buf_block_get_frame(block) == page); ut_ad(buf_block_get_frame(block) == page);
ut_ad(page_is_leaf(page) == page_is_leaf(new_page)); ut_ad(page_is_leaf(page) == page_is_leaf(new_page));
ut_ad(page_is_comp(page) == page_is_comp(new_page)); ut_ad(page_is_comp(page) == page_is_comp(new_page));
...@@ -1057,10 +1067,19 @@ page_delete_rec_list_start( ...@@ -1057,10 +1067,19 @@ page_delete_rec_list_start(
ut_ad((ibool) !!page_rec_is_comp(rec) ut_ad((ibool) !!page_rec_is_comp(rec)
== dict_table_is_comp(index->table)); == dict_table_is_comp(index->table));
/* page_zip_validate() would detect a min_rec_mark mismatch #ifdef UNIV_ZIP_DEBUG
in btr_page_split_and_insert() {
between btr_attach_half_pages() and insert_page = ... page_zip_des_t* page_zip= buf_block_get_page_zip(block);
when btr_page_get_split_rec_to_left() holds (direction == FSP_DOWN). */ page_t* page = buf_block_get_frame(block);
/* page_zip_validate() would detect a min_rec_mark mismatch
in btr_page_split_and_insert()
between btr_attach_half_pages() and insert_page = ...
when btr_page_get_split_rec_to_left() holds
(direction == FSP_DOWN). */
ut_a(!page_zip || page_zip_validate_low(page_zip, page, TRUE));
}
#endif /* UNIV_ZIP_DEBUG */
if (page_rec_is_infimum(rec)) { if (page_rec_is_infimum(rec)) {
......
...@@ -77,6 +77,8 @@ page_zip_fail_func( ...@@ -77,6 +77,8 @@ page_zip_fail_func(
int res; int res;
va_list ap; va_list ap;
ut_print_timestamp(stderr);
fputs(" InnoDB: ", stderr);
va_start(ap, fmt); va_start(ap, fmt);
res = vfprintf(stderr, fmt, ap); res = vfprintf(stderr, fmt, ap);
va_end(ap); va_end(ap);
...@@ -2951,6 +2953,39 @@ page_zip_decompress( ...@@ -2951,6 +2953,39 @@ page_zip_decompress(
} }
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
/**************************************************************************
Dump a block of memory on the standard error stream. */
static
void
page_zip_hexdump_func(
/*==================*/
const char* name, /* in: name of the data structure */
const void* buf, /* in: data */
ulint size) /* in: length of the data, in bytes */
{
const byte* s = buf;
ulint addr;
const ulint width = 32; /* bytes per line */
fprintf(stderr, "%s:\n", name);
for (addr = 0; addr < size; addr += width) {
ulint i;
fprintf(stderr, "%04lx ", (ulong) addr);
i = ut_min(width, size - addr);
while (i--) {
fprintf(stderr, "%02x", *s++);
}
putc('\n', stderr);
}
}
#define page_zip_hexdump(buf, size) page_zip_hexdump_func(#buf, buf, size)
/* Flag: make page_zip_validate() compare page headers only */ /* Flag: make page_zip_validate() compare page headers only */
UNIV_INTERN ibool page_zip_validate_header_only = FALSE; UNIV_INTERN ibool page_zip_validate_header_only = FALSE;
...@@ -2958,11 +2993,13 @@ UNIV_INTERN ibool page_zip_validate_header_only = FALSE; ...@@ -2958,11 +2993,13 @@ UNIV_INTERN ibool page_zip_validate_header_only = FALSE;
Check that the compressed and decompressed pages match. */ Check that the compressed and decompressed pages match. */
UNIV_INTERN UNIV_INTERN
ibool ibool
page_zip_validate( page_zip_validate_low(
/*==============*/ /*==================*/
/* out: TRUE if valid, FALSE if not */ /* out: TRUE if valid, FALSE if not */
const page_zip_des_t* page_zip,/* in: compressed page */ const page_zip_des_t* page_zip,/* in: compressed page */
const page_t* page) /* in: uncompressed page */ const page_t* page, /* in: uncompressed page */
ibool sloppy) /* in: FALSE=strict,
TRUE=ignore the MIN_REC_FLAG */
{ {
page_zip_des_t temp_page_zip; page_zip_des_t temp_page_zip;
byte* temp_page_buf; byte* temp_page_buf;
...@@ -2975,6 +3012,9 @@ page_zip_validate( ...@@ -2975,6 +3012,9 @@ page_zip_validate(
|| memcmp(page_zip->data + FIL_PAGE_DATA, page + FIL_PAGE_DATA, || memcmp(page_zip->data + FIL_PAGE_DATA, page + FIL_PAGE_DATA,
PAGE_DATA - FIL_PAGE_DATA)) { PAGE_DATA - FIL_PAGE_DATA)) {
page_zip_fail(("page_zip_validate: page header\n")); page_zip_fail(("page_zip_validate: page header\n"));
page_zip_hexdump(page_zip, sizeof *page_zip);
page_zip_hexdump(page_zip->data, page_zip_get_size(page_zip));
page_zip_hexdump(page, UNIV_PAGE_SIZE);
return(FALSE); return(FALSE);
} }
...@@ -2991,7 +3031,9 @@ page_zip_validate( ...@@ -2991,7 +3031,9 @@ page_zip_validate(
#ifdef UNIV_DEBUG_VALGRIND #ifdef UNIV_DEBUG_VALGRIND
/* Get detailed information on the valid bits in case the /* Get detailed information on the valid bits in case the
UNIV_MEM_ASSERT_RW() checks fail. */ UNIV_MEM_ASSERT_RW() checks fail. The v-bits of page[],
page_zip->data[] or page_zip could be viewed at temp_page[] or
temp_page_zip in a debugger when running valgrind --db-attach. */
VALGRIND_GET_VBITS(page, temp_page, UNIV_PAGE_SIZE); VALGRIND_GET_VBITS(page, temp_page, UNIV_PAGE_SIZE);
UNIV_MEM_ASSERT_RW(page, UNIV_PAGE_SIZE); UNIV_MEM_ASSERT_RW(page, UNIV_PAGE_SIZE);
VALGRIND_GET_VBITS(page_zip, &temp_page_zip, sizeof temp_page_zip); VALGRIND_GET_VBITS(page_zip, &temp_page_zip, sizeof temp_page_zip);
...@@ -3032,14 +3074,71 @@ page_zip_validate( ...@@ -3032,14 +3074,71 @@ page_zip_validate(
} }
if (memcmp(page + PAGE_HEADER, temp_page + PAGE_HEADER, if (memcmp(page + PAGE_HEADER, temp_page + PAGE_HEADER,
UNIV_PAGE_SIZE - PAGE_HEADER - FIL_PAGE_DATA_END)) { UNIV_PAGE_SIZE - PAGE_HEADER - FIL_PAGE_DATA_END)) {
/* In crash recovery, the "minimum record" flag may be
set incorrectly until the mini-transaction is
committed. Let us tolerate that difference when we
are performing a sloppy validation. */
if (sloppy) {
byte info_bits_diff;
ulint offset
= rec_get_next_offs(page + PAGE_NEW_INFIMUM,
TRUE);
ut_a(offset >= PAGE_NEW_SUPREMUM);
offset -= 5 /* REC_NEW_INFO_BITS */;
info_bits_diff = page[offset] ^ temp_page[offset];
if (info_bits_diff == REC_INFO_MIN_REC_FLAG) {
temp_page[offset] = page[offset];
if (!memcmp(page + PAGE_HEADER,
temp_page + PAGE_HEADER,
UNIV_PAGE_SIZE - PAGE_HEADER
- FIL_PAGE_DATA_END)) {
/* Only the minimum record flag
differed. Let us ignore it. */
page_zip_fail(("page_zip_validate: "
"min_rec_flag "
"(ignored, "
"%lu,%lu,0x%02lx)\n",
page_get_space_id(page),
page_get_page_no(page),
(ulong) page[offset]));
goto func_exit;
}
}
}
page_zip_fail(("page_zip_validate: content\n")); page_zip_fail(("page_zip_validate: content\n"));
valid = FALSE; valid = FALSE;
} }
func_exit: func_exit:
if (!valid) {
page_zip_hexdump(page_zip, sizeof *page_zip);
page_zip_hexdump(page_zip->data, page_zip_get_size(page_zip));
page_zip_hexdump(page, UNIV_PAGE_SIZE);
page_zip_hexdump(temp_page, UNIV_PAGE_SIZE);
}
ut_free(temp_page_buf); ut_free(temp_page_buf);
return(valid); return(valid);
} }
/**************************************************************************
Check that the compressed and decompressed pages match. */
UNIV_INTERN
ibool
page_zip_validate(
/*==============*/
/* out: TRUE if valid, FALSE if not */
const page_zip_des_t* page_zip,/* in: compressed page */
const page_t* page) /* in: uncompressed page */
{
return(page_zip_validate_low(page_zip, page,
recv_recovery_is_on()));
}
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
...@@ -4302,11 +4401,13 @@ page_zip_reorganize( ...@@ -4302,11 +4401,13 @@ page_zip_reorganize(
} }
/************************************************************************** /**************************************************************************
Copy a page byte for byte, except for the file page header and trailer. */ Copy the records of a page byte for byte. Do not copy the page header
or trailer, except those B-tree header fields that are directly
related to the storage of records. */
UNIV_INTERN UNIV_INTERN
void void
page_zip_copy( page_zip_copy_recs(
/*==========*/ /*===============*/
page_zip_des_t* page_zip, /* out: copy of src_zip page_zip_des_t* page_zip, /* out: copy of src_zip
(n_blobs, m_start, m_end, (n_blobs, m_start, m_end,
m_nonempty, data[0..size-1]) */ m_nonempty, data[0..size-1]) */
...@@ -4319,7 +4420,11 @@ page_zip_copy( ...@@ -4319,7 +4420,11 @@ page_zip_copy(
ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
ut_ad(mtr_memo_contains_page(mtr, (page_t*) src, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr_memo_contains_page(mtr, (page_t*) src, MTR_MEMO_PAGE_X_FIX));
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(page_zip_validate(src_zip, src)); /* The B-tree operations that call this function may set
FIL_PAGE_PREV or PAGE_LEVEL, causing a temporary min_rec_flag
mismatch. A strict page_zip_validate() will be executed later
during the B-tree operations. */
ut_a(page_zip_validate_low(src_zip, src, TRUE));
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
ut_a(page_zip_get_size(page_zip) == page_zip_get_size(src_zip)); ut_a(page_zip_get_size(page_zip) == page_zip_get_size(src_zip));
if (UNIV_UNLIKELY(src_zip->n_blobs)) { if (UNIV_UNLIKELY(src_zip->n_blobs)) {
...@@ -4332,14 +4437,24 @@ page_zip_copy( ...@@ -4332,14 +4437,24 @@ page_zip_copy(
UNIV_MEM_ASSERT_RW(src, UNIV_PAGE_SIZE); UNIV_MEM_ASSERT_RW(src, UNIV_PAGE_SIZE);
UNIV_MEM_ASSERT_RW(src_zip->data, page_zip_get_size(page_zip)); UNIV_MEM_ASSERT_RW(src_zip->data, page_zip_get_size(page_zip));
/* Skip the file page header and trailer. */ /* Copy those B-tree page header fields that are related to
memcpy(page + FIL_PAGE_DATA, src + FIL_PAGE_DATA, the records stored in the page. Do not copy the field
UNIV_PAGE_SIZE - FIL_PAGE_DATA PAGE_MAX_TRX_ID. Skip the rest of the page header and
- FIL_PAGE_DATA_END); trailer. On the compressed page, there is no trailer. */
memcpy(page_zip->data + FIL_PAGE_DATA, #if PAGE_MAX_TRX_ID + 8 != PAGE_HEADER_PRIV_END
src_zip->data + FIL_PAGE_DATA, # error "PAGE_MAX_TRX_ID + 8 != PAGE_HEADER_PRIV_END"
page_zip_get_size(page_zip) - FIL_PAGE_DATA); #endif
memcpy(PAGE_HEADER + page, PAGE_HEADER + src,
PAGE_MAX_TRX_ID);
memcpy(PAGE_DATA + page, PAGE_DATA + src,
UNIV_PAGE_SIZE - PAGE_DATA - FIL_PAGE_DATA_END);
memcpy(PAGE_HEADER + page_zip->data, PAGE_HEADER + src_zip->data,
PAGE_MAX_TRX_ID);
memcpy(PAGE_DATA + page_zip->data, PAGE_DATA + src_zip->data,
page_zip_get_size(page_zip) - PAGE_DATA);
/* Copy all fields of src_zip to page_zip, except the pointer
to the compressed data page. */
{ {
page_zip_t* data = page_zip->data; page_zip_t* data = page_zip->data;
memcpy(page_zip, src_zip, sizeof *page_zip); memcpy(page_zip, src_zip, sizeof *page_zip);
......
...@@ -727,52 +727,31 @@ rec_get_nth_field_offs_old( ...@@ -727,52 +727,31 @@ rec_get_nth_field_offs_old(
} }
/************************************************************** /**************************************************************
Determines the size of a data tuple in ROW_FORMAT=COMPACT. */ Determines the size of a data tuple prefix in ROW_FORMAT=COMPACT. */
UNIV_INTERN UNIV_INTERN
ulint ulint
rec_get_converted_size_comp( rec_get_converted_size_comp_prefix(
/*========================*/ /*===============================*/
/* out: total size */ /* out: total size */
const dict_index_t* index, /* in: record descriptor; const dict_index_t* index, /* in: record descriptor;
dict_table_is_comp() is dict_table_is_comp() is
assumed to hold, even if assumed to hold, even if
it does not */ it does not */
ulint status, /* in: status bits of the record */
const dfield_t* fields, /* in: array of data fields */ const dfield_t* fields, /* in: array of data fields */
ulint n_fields,/* in: number of data fields */ ulint n_fields,/* in: number of data fields */
ulint* extra) /* out: extra size */ ulint* extra) /* out: extra size */
{ {
ulint extra_size; ulint extra_size;
ulint data_size; ulint data_size;
ulint i; ulint i;
ut_ad(index); ut_ad(index);
ut_ad(fields); ut_ad(fields);
ut_ad(n_fields > 0); ut_ad(n_fields > 0);
ut_ad(n_fields <= dict_index_get_n_fields(index));
switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
case REC_STATUS_ORDINARY:
ut_ad(n_fields == dict_index_get_n_fields(index));
data_size = 0;
break;
case REC_STATUS_NODE_PTR:
n_fields--;
ut_ad(n_fields == dict_index_get_n_unique_in_tree(index));
ut_ad(dfield_get_len(&fields[n_fields]) == 4);
data_size = 4; /* child page number */
break;
case REC_STATUS_INFIMUM:
case REC_STATUS_SUPREMUM:
/* infimum or supremum record, 8 data bytes */
extra_size = REC_N_NEW_EXTRA_BYTES;
data_size = 8;
goto func_exit;
default:
ut_error;
return(ULINT_UNDEFINED);
}
extra_size = REC_N_NEW_EXTRA_BYTES extra_size = REC_N_NEW_EXTRA_BYTES
+ UT_BITS_IN_BYTES(index->n_nullable); + UT_BITS_IN_BYTES(index->n_nullable);
data_size = 0;
/* read the lengths of fields 0..n */ /* read the lengths of fields 0..n */
for (i = 0; i < n_fields; i++) { for (i = 0; i < n_fields; i++) {
...@@ -815,7 +794,6 @@ rec_get_converted_size_comp( ...@@ -815,7 +794,6 @@ rec_get_converted_size_comp(
data_size += len; data_size += len;
} }
func_exit:
if (UNIV_LIKELY_NULL(extra)) { if (UNIV_LIKELY_NULL(extra)) {
*extra = extra_size; *extra = extra_size;
} }
...@@ -823,6 +801,54 @@ rec_get_converted_size_comp( ...@@ -823,6 +801,54 @@ rec_get_converted_size_comp(
return(extra_size + data_size); return(extra_size + data_size);
} }
/**************************************************************
Determines the size of a data tuple in ROW_FORMAT=COMPACT. */
UNIV_INTERN
ulint
rec_get_converted_size_comp(
/*========================*/
/* out: total size */
const dict_index_t* index, /* in: record descriptor;
dict_table_is_comp() is
assumed to hold, even if
it does not */
ulint status, /* in: status bits of the record */
const dfield_t* fields, /* in: array of data fields */
ulint n_fields,/* in: number of data fields */
ulint* extra) /* out: extra size */
{
ulint size;
ut_ad(index);
ut_ad(fields);
ut_ad(n_fields > 0);
switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
case REC_STATUS_ORDINARY:
ut_ad(n_fields == dict_index_get_n_fields(index));
size = 0;
break;
case REC_STATUS_NODE_PTR:
n_fields--;
ut_ad(n_fields == dict_index_get_n_unique_in_tree(index));
ut_ad(dfield_get_len(&fields[n_fields]) == REC_NODE_PTR_SIZE);
size = REC_NODE_PTR_SIZE; /* child page number */
break;
case REC_STATUS_INFIMUM:
case REC_STATUS_SUPREMUM:
/* infimum or supremum record, 8 data bytes */
if (UNIV_LIKELY_NULL(extra)) {
*extra = REC_N_NEW_EXTRA_BYTES;
}
return(REC_N_NEW_EXTRA_BYTES + 8);
default:
ut_error;
return(ULINT_UNDEFINED);
}
return(size + rec_get_converted_size_comp_prefix(index, fields,
n_fields, extra));
}
/*************************************************************** /***************************************************************
Sets the value of the ith field SQL null bit of an old-style record. */ Sets the value of the ith field SQL null bit of an old-style record. */
UNIV_INTERN UNIV_INTERN
......
...@@ -1747,7 +1747,9 @@ row_merge_lock_table( ...@@ -1747,7 +1747,9 @@ row_merge_lock_table(
} }
/************************************************************************* /*************************************************************************
Drop an index from the InnoDB system tables. */ Drop an index from the InnoDB system tables. The data dictionary must
have been locked exclusively by the caller, because the transaction
will not be committed. */
UNIV_INTERN UNIV_INTERN
void void
row_merge_drop_index( row_merge_drop_index(
...@@ -1757,7 +1759,6 @@ row_merge_drop_index( ...@@ -1757,7 +1759,6 @@ row_merge_drop_index(
trx_t* trx) /* in: transaction handle */ trx_t* trx) /* in: transaction handle */
{ {
ulint err; ulint err;
ibool dict_lock = FALSE;
pars_info_t* info = pars_info_create(); pars_info_t* info = pars_info_create();
/* We use the private SQL parser of Innobase to generate the /* We use the private SQL parser of Innobase to generate the
...@@ -1781,10 +1782,7 @@ row_merge_drop_index( ...@@ -1781,10 +1782,7 @@ row_merge_drop_index(
trx_start_if_not_started(trx); trx_start_if_not_started(trx);
trx->op_info = "dropping index"; trx->op_info = "dropping index";
if (trx->dict_operation_lock_mode == 0) { ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
row_mysql_lock_data_dictionary(trx);
dict_lock = TRUE;
}
err = que_eval_sql(info, str1, FALSE, trx); err = que_eval_sql(info, str1, FALSE, trx);
...@@ -1796,16 +1794,14 @@ row_merge_drop_index( ...@@ -1796,16 +1794,14 @@ row_merge_drop_index(
dict_table_replace_index_in_foreign_list(table, index); dict_table_replace_index_in_foreign_list(table, index);
dict_index_remove_from_cache(table, index); dict_index_remove_from_cache(table, index);
if (dict_lock) {
row_mysql_unlock_data_dictionary(trx);
}
trx->op_info = ""; trx->op_info = "";
} }
/************************************************************************* /*************************************************************************
Drop those indexes which were created before an error occurred Drop those indexes which were created before an error occurred when
when building an index. */ building an index. The data dictionary must have been locked
exclusively by the caller, because the transaction will not be
committed. */
UNIV_INTERN UNIV_INTERN
void void
row_merge_drop_indexes( row_merge_drop_indexes(
...@@ -1986,7 +1982,9 @@ row_merge_create_temporary_table( ...@@ -1986,7 +1982,9 @@ row_merge_create_temporary_table(
} }
/************************************************************************* /*************************************************************************
Rename the temporary indexes in the dictionary to permanent ones. */ Rename the temporary indexes in the dictionary to permanent ones. The
data dictionary must have been locked exclusively by the caller,
because the transaction will not be committed. */
UNIV_INTERN UNIV_INTERN
ulint ulint
row_merge_rename_indexes( row_merge_rename_indexes(
...@@ -1995,7 +1993,6 @@ row_merge_rename_indexes( ...@@ -1995,7 +1993,6 @@ row_merge_rename_indexes(
trx_t* trx, /* in/out: transaction */ trx_t* trx, /* in/out: transaction */
dict_table_t* table) /* in/out: table with new indexes */ dict_table_t* table) /* in/out: table with new indexes */
{ {
ibool dict_lock = FALSE;
ulint err = DB_SUCCESS; ulint err = DB_SUCCESS;
pars_info_t* info = pars_info_create(); pars_info_t* info = pars_info_create();
...@@ -2013,18 +2010,14 @@ row_merge_rename_indexes( ...@@ -2013,18 +2010,14 @@ row_merge_rename_indexes(
"WHERE TABLE_ID = :tableid AND SUBSTR(NAME,0,1)='\377';\n" "WHERE TABLE_ID = :tableid AND SUBSTR(NAME,0,1)='\377';\n"
"END;\n"; "END;\n";
ut_ad(table && trx); ut_ad(table);
ut_ad(trx);
ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
trx_start_if_not_started(trx);
trx->op_info = "renaming indexes"; trx->op_info = "renaming indexes";
pars_info_add_dulint_literal(info, "tableid", table->id); pars_info_add_dulint_literal(info, "tableid", table->id);
if (trx->dict_operation_lock_mode == 0) {
row_mysql_lock_data_dictionary(trx);
dict_lock = TRUE;
}
err = que_eval_sql(info, rename_indexes, FALSE, trx); err = que_eval_sql(info, rename_indexes, FALSE, trx);
if (err == DB_SUCCESS) { if (err == DB_SUCCESS) {
...@@ -2037,17 +2030,15 @@ row_merge_rename_indexes( ...@@ -2037,17 +2030,15 @@ row_merge_rename_indexes(
} while (index); } while (index);
} }
if (dict_lock) {
row_mysql_unlock_data_dictionary(trx);
}
trx->op_info = ""; trx->op_info = "";
return(err); return(err);
} }
/************************************************************************* /*************************************************************************
Rename the tables in the data dictionary. */ Rename the tables in the data dictionary. The data dictionary must
have been locked exclusively by the caller, because the transaction
will not be committed. */
UNIV_INTERN UNIV_INTERN
ulint ulint
row_merge_rename_tables( row_merge_rename_tables(
...@@ -2068,8 +2059,9 @@ row_merge_rename_tables( ...@@ -2068,8 +2059,9 @@ row_merge_rename_tables(
ut_ad(old_table != new_table); ut_ad(old_table != new_table);
ut_ad(mutex_own(&dict_sys->mutex)); ut_ad(mutex_own(&dict_sys->mutex));
ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
trx->op_info = "renaming tables"; trx->op_info = "renaming tables";
trx_start_if_not_started(trx);
/* We use the private SQL parser of Innobase to generate the query /* We use the private SQL parser of Innobase to generate the query
graphs needed in updating the dictionary data in system tables. */ graphs needed in updating the dictionary data in system tables. */
...@@ -2239,24 +2231,10 @@ row_merge_drop_table( ...@@ -2239,24 +2231,10 @@ row_merge_drop_table(
trx_t* trx, /* in: transaction */ trx_t* trx, /* in: transaction */
dict_table_t* table) /* in: table to drop */ dict_table_t* table) /* in: table to drop */
{ {
ulint err = DB_SUCCESS;
ibool dict_locked = FALSE;
if (trx->dict_operation_lock_mode == 0) {
row_mysql_lock_data_dictionary(trx);
dict_locked = TRUE;
}
/* There must be no open transactions on the table. */ /* There must be no open transactions on the table. */
ut_a(table->n_mysql_handles_opened == 0); ut_a(table->n_mysql_handles_opened == 0);
err = row_drop_table_for_mysql_no_commit(table->name, trx, FALSE); return(row_drop_table_for_mysql(table->name, trx, FALSE));
if (dict_locked) {
row_mysql_unlock_data_dictionary(trx);
}
return(err);
} }
/************************************************************************* /*************************************************************************
......
...@@ -625,6 +625,14 @@ row_create_prebuilt( ...@@ -625,6 +625,14 @@ row_create_prebuilt(
prebuilt->clust_ref = ref; prebuilt->clust_ref = ref;
prebuilt->autoinc_offset = 0;
/* Default to 1, we will set the actual value later in
ha_innobase::get_auto_increment(). */
prebuilt->autoinc_increment = 1;
prebuilt->autoinc_last_value = 0;
return(prebuilt); return(prebuilt);
} }
...@@ -1842,6 +1850,7 @@ row_create_table_for_mysql( ...@@ -1842,6 +1850,7 @@ row_create_table_for_mysql(
if (dict_table_get_low(table->name)) { if (dict_table_get_low(table->name)) {
row_drop_table_for_mysql(table->name, trx, FALSE); row_drop_table_for_mysql(table->name, trx, FALSE);
trx_commit_for_mysql(trx);
} }
break; break;
...@@ -1999,6 +2008,8 @@ row_create_index_for_mysql( ...@@ -1999,6 +2008,8 @@ row_create_index_for_mysql(
row_drop_table_for_mysql(table_name, trx, FALSE); row_drop_table_for_mysql(table_name, trx, FALSE);
trx_commit_for_mysql(trx);
trx->error_state = DB_SUCCESS; trx->error_state = DB_SUCCESS;
} }
...@@ -2066,6 +2077,8 @@ row_table_add_foreign_constraints( ...@@ -2066,6 +2077,8 @@ row_table_add_foreign_constraints(
row_drop_table_for_mysql(name, trx, FALSE); row_drop_table_for_mysql(name, trx, FALSE);
trx_commit_for_mysql(trx);
trx->error_state = DB_SUCCESS; trx->error_state = DB_SUCCESS;
} }
...@@ -2397,8 +2410,8 @@ row_discard_tablespace_for_mysql( ...@@ -2397,8 +2410,8 @@ row_discard_tablespace_for_mysql(
new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID); new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
/* Remove any locks there are on the table or its records */ /* Remove all locks except the table-level S and X locks. */
lock_reset_all_on_table(table); lock_remove_all_on_table(table, FALSE);
info = pars_info_create(); info = pars_info_create();
...@@ -2742,9 +2755,8 @@ row_truncate_table_for_mysql( ...@@ -2742,9 +2755,8 @@ row_truncate_table_for_mysql(
goto funct_exit; goto funct_exit;
} }
/* Remove any locks there are on the table or its records */ /* Remove all locks except the table-level S and X locks. */
lock_remove_all_on_table(table, FALSE);
lock_reset_all_on_table(table);
trx->table_id = table->id; trx->table_id = table->id;
...@@ -2908,7 +2920,7 @@ row_truncate_table_for_mysql( ...@@ -2908,7 +2920,7 @@ row_truncate_table_for_mysql(
/* MySQL calls ha_innobase::reset_auto_increment() which does /* MySQL calls ha_innobase::reset_auto_increment() which does
the same thing. */ the same thing. */
dict_table_autoinc_lock(table); dict_table_autoinc_lock(table);
dict_table_autoinc_initialize(table, 0); dict_table_autoinc_initialize(table, 1);
dict_table_autoinc_unlock(table); dict_table_autoinc_unlock(table);
dict_update_statistics(table); dict_update_statistics(table);
...@@ -2926,10 +2938,12 @@ row_truncate_table_for_mysql( ...@@ -2926,10 +2938,12 @@ row_truncate_table_for_mysql(
} }
/************************************************************************* /*************************************************************************
Drops a table for MySQL. If the name of the dropped table ends in Drops a table for MySQL. If the name of the dropped table ends in
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor", one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
"innodb_table_monitor", then this will also stop the printing of monitor "innodb_table_monitor", then this will also stop the printing of monitor
output by the master thread. */ output by the master thread. If the data dictionary was not already locked
by the transaction, the transaction will be committed. Otherwise, the
data dictionary will remain locked. */
UNIV_INTERN UNIV_INTERN
int int
row_drop_table_for_mysql( row_drop_table_for_mysql(
...@@ -2938,29 +2952,6 @@ row_drop_table_for_mysql( ...@@ -2938,29 +2952,6 @@ row_drop_table_for_mysql(
const char* name, /* in: table name */ const char* name, /* in: table name */
trx_t* trx, /* in: transaction handle */ trx_t* trx, /* in: transaction handle */
ibool drop_db)/* in: TRUE=dropping whole database */ ibool drop_db)/* in: TRUE=dropping whole database */
{
ulint err;
err = row_drop_table_for_mysql_no_commit(name, trx, drop_db);
trx_commit_for_mysql(trx);
return(err);
}
/*************************************************************************
Drops a table for MySQL but does not commit the transaction. If the
name of the dropped table ends in one of "innodb_monitor",
"innodb_lock_monitor", "innodb_tablespace_monitor",
"innodb_table_monitor", then this will also stop the printing of
monitor output by the master thread. */
UNIV_INTERN
int
row_drop_table_for_mysql_no_commit(
/*===============================*/
/* out: error code or DB_SUCCESS */
const char* name, /* in: table name */
trx_t* trx, /* in: transaction handle */
ibool drop_db)/* in: TRUE=dropping whole database */
{ {
dict_foreign_t* foreign; dict_foreign_t* foreign;
dict_table_t* table; dict_table_t* table;
...@@ -3165,9 +3156,8 @@ row_drop_table_for_mysql_no_commit( ...@@ -3165,9 +3156,8 @@ row_drop_table_for_mysql_no_commit(
goto funct_exit; goto funct_exit;
} }
/* Remove any locks there are on the table or its records */ /* Remove all locks there are on the table or its records */
lock_remove_all_on_table(table, TRUE);
lock_reset_all_on_table(table);
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE); trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
trx->table_id = table->id; trx->table_id = table->id;
...@@ -3330,6 +3320,8 @@ row_drop_table_for_mysql_no_commit( ...@@ -3330,6 +3320,8 @@ row_drop_table_for_mysql_no_commit(
funct_exit: funct_exit:
if (locked_dictionary) { if (locked_dictionary) {
trx_commit_for_mysql(trx);
row_mysql_unlock_data_dictionary(trx); row_mysql_unlock_data_dictionary(trx);
} }
...@@ -3458,8 +3450,7 @@ row_drop_database_for_mysql( ...@@ -3458,8 +3450,7 @@ row_drop_database_for_mysql(
} }
err = row_drop_table_for_mysql(table_name, trx, TRUE); err = row_drop_table_for_mysql(table_name, trx, TRUE);
trx_commit_for_mysql(trx);
mem_free(table_name);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
fputs("InnoDB: DROP DATABASE ", stderr); fputs("InnoDB: DROP DATABASE ", stderr);
...@@ -3468,8 +3459,11 @@ row_drop_database_for_mysql( ...@@ -3468,8 +3459,11 @@ row_drop_database_for_mysql(
(ulint) err); (ulint) err);
ut_print_name(stderr, trx, TRUE, table_name); ut_print_name(stderr, trx, TRUE, table_name);
putc('\n', stderr); putc('\n', stderr);
mem_free(table_name);
break; break;
} }
mem_free(table_name);
} }
if (err == DB_SUCCESS) { if (err == DB_SUCCESS) {
......
...@@ -154,8 +154,6 @@ UNIV_INTERN ibool srv_archive_recovery = 0; ...@@ -154,8 +154,6 @@ UNIV_INTERN ibool srv_archive_recovery = 0;
UNIV_INTERN ib_uint64_t srv_archive_recovery_limit_lsn; UNIV_INTERN ib_uint64_t srv_archive_recovery_limit_lsn;
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
UNIV_INTERN ulint srv_lock_wait_timeout = 1024 * 1024 * 1024;
/* This parameter is used to throttle the number of insert buffers that are /* This parameter is used to throttle the number of insert buffers that are
merged in a batch. By increasing this parameter on a faster disk you can merged in a batch. By increasing this parameter on a faster disk you can
possibly reduce the number of I/O operations performed to complete the possibly reduce the number of I/O operations performed to complete the
...@@ -1377,6 +1375,7 @@ srv_suspend_mysql_thread( ...@@ -1377,6 +1375,7 @@ srv_suspend_mysql_thread(
ulint diff_time; ulint diff_time;
ulint sec; ulint sec;
ulint ms; ulint ms;
ulong lock_wait_timeout;
ut_ad(!mutex_own(&kernel_mutex)); ut_ad(!mutex_own(&kernel_mutex));
...@@ -1515,8 +1514,14 @@ srv_suspend_mysql_thread( ...@@ -1515,8 +1514,14 @@ srv_suspend_mysql_thread(
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
if (srv_lock_wait_timeout < 100000000 /* InnoDB system transactions (such as the purge, and
&& wait_time > (double)srv_lock_wait_timeout) { incomplete transactions that are being rolled back after crash
recovery) will use the global value of
innodb_lock_wait_timeout, because trx->mysql_thd == NULL. */
lock_wait_timeout = thd_lock_wait_timeout(trx->mysql_thd);
if (lock_wait_timeout < 100000000
&& wait_time > (double) lock_wait_timeout) {
trx->error_state = DB_LOCK_WAIT_TIMEOUT; trx->error_state = DB_LOCK_WAIT_TIMEOUT;
} }
...@@ -1966,12 +1971,19 @@ srv_lock_timeout_and_monitor_thread( ...@@ -1966,12 +1971,19 @@ srv_lock_timeout_and_monitor_thread(
slot = srv_mysql_table + i; slot = srv_mysql_table + i;
if (slot->in_use) { if (slot->in_use) {
trx_t* trx;
ulong lock_wait_timeout;
some_waits = TRUE; some_waits = TRUE;
wait_time = ut_difftime(ut_time(), slot->suspend_time); wait_time = ut_difftime(ut_time(), slot->suspend_time);
if (srv_lock_wait_timeout < 100000000 trx = thr_get_trx(slot->thr);
&& (wait_time > (double) srv_lock_wait_timeout lock_wait_timeout = thd_lock_wait_timeout(
trx->mysql_thd);
if (lock_wait_timeout < 100000000
&& (wait_time > (double) lock_wait_timeout
|| wait_time < 0)) { || wait_time < 0)) {
/* Timeout exceeded or a wrap-around in system /* Timeout exceeded or a wrap-around in system
...@@ -1981,10 +1993,9 @@ srv_lock_timeout_and_monitor_thread( ...@@ -1981,10 +1993,9 @@ srv_lock_timeout_and_monitor_thread(
possible that the lock has already been possible that the lock has already been
granted: in that case do nothing */ granted: in that case do nothing */
if (thr_get_trx(slot->thr)->wait_lock) { if (trx->wait_lock) {
lock_cancel_waiting_and_release( lock_cancel_waiting_and_release(
thr_get_trx(slot->thr) trx->wait_lock);
->wait_lock);
} }
} }
} }
......
...@@ -506,6 +506,7 @@ trx_rollback_active( ...@@ -506,6 +506,7 @@ trx_rollback_active(
fputs(" in recovery\n", stderr); fputs(" in recovery\n", stderr);
err = row_drop_table_for_mysql(table->name, trx, TRUE); err = row_drop_table_for_mysql(table->name, trx, TRUE);
trx_commit_for_mysql(trx);
ut_a(err == (int) DB_SUCCESS); ut_a(err == (int) DB_SUCCESS);
} }
......
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