Commit a7316cba authored by inaam's avatar inaam

branches/innodb+: Merge revisions 6448:6504 from branches/zip:

  ------------------------------------------------------------------------
  r6449 | marko | 2010-01-13 15:38:53 -0500 (Wed, 13 Jan 2010) | 18 lines
  
  branches/zip: lock_rec_validate_page(): Only validate the record
  queues when the thread is not holding a space->latch.
  
  When UNIV_DEBUG is defined while UNIV_SYNC_DEBUG is not,
  latching order violations will still occur and deadlocks will be possible.
  
  sync_thread_levels_nonempty_gen(): Renamed from
  sync_thread_levels_empty_gen().  Return the violating latch or NULL
  instead of FALSE or TRUE, except that there will be a ut_error before
  the non-NULL return.
  
  sync_thread_levels_empty_gen(): A macro that negates the return value of
  sync_thread_levels_nonempty_gen().
  
  sync_thread_levels_contains(): New function, based on
  sync_thread_levels_nonempty_gen().
  
  This should fix Issue #441.
  ------------------------------------------------------------------------
  r6463 | marko | 2010-01-14 08:43:37 -0500 (Thu, 14 Jan 2010) | 5 lines
  
  branches/zip: page_copy_rec_list_end(), page_copy_rec_list_start():
  Update PAGE_MAX_TRX_ID before attempting to compress the page.  This
  fixes Issue #382 (a debug assertion failure in page_zip_reorganize())
  and reduces the generated redo log.  There was no bug or crash in
  non-debug builds.
  ------------------------------------------------------------------------
  r6467 | inaam | 2010-01-14 13:46:00 -0500 (Thu, 14 Jan 2010) | 10 lines
  
  branches/zip rb://226
  
  log_sys->written_to_all_lsn does not accurately represent the LSN
  upto which write and flush has taken place. Under a race condition
  it can fall behind log_sys->flushed_to_disk_lsn which is accurate.
  Besides written_to_all_lsn is redundant as currently InnoDB supports
  only one log group.
  
  Approved by: Heikki
  
  ------------------------------------------------------------------------
  r6472 | calvin | 2010-01-15 18:53:47 -0500 (Fri, 15 Jan 2010) | 12 lines
  
  branches/zip: Merge revisions 6425:6471 from branches/5.1
  to pick up the first part fix of bug49396.
  
      ------------------------------------------------------------------------
      r6471 | calvin | 2010-01-15 17:43:27 -0600 (Fri, 15 Jan 2010) | 4 lines
  
      branches/5.1: fix bug#49396: main.innodb test fails in embedded mode
  
      Change replace_result by using $MYSQLD_DATADIR. Tested in both embedded
      mode and normal server mode.
      ------------------------------------------------------------------------
  
  ------------------------------------------------------------------------
  r6473 | calvin | 2010-01-15 18:58:16 -0500 (Fri, 15 Jan 2010) | 6 lines
  
  branches/zip: fix bug#49396: innodb.innodb-index test fails in
  embedded mode
  
  This is 2nd part of the fix for bug#49396. The 1st part is
  innodb.test. Tested in both embedded mode and normal server mode.
  
  ------------------------------------------------------------------------
  r6498 | marko | 2010-01-21 04:22:52 -0500 (Thu, 21 Jan 2010) | 15 lines
  
  branches/zip: buf_page_get_gen(): Obey recv_no_ibuf_operations
  and do not call ibuf_merge_or_delete_for_page() in crash recovery,
  before the redo log has been applied.
  This could cure some hard-to-repeat, hard-to-explain bugs
  related to secondary indexes.
  
  A possible recipe to repeat the bug:
  
  1. update a secondary index leaf page on a compressed table
  2. evict the page from the buffer pool while it is still dirty
  3. ibuf_insert() something for the page
  4. crash
  5. crash recovery; ibuf merge would be done too early,
  before applying redo log to the sec index page or the ibuf pages
  
  ------------------------------------------------------------------------
parent c8201405
2010-01-21 The InnoDB Team
* buf/buf0buf.c:
Do not merge buffered inserts to compressed pages before
the redo log has been applied in crash recovery.
2010-01-13 The InnoDB Team 2010-01-13 The InnoDB Team
* row/row0sel.c: * row/row0sel.c:
......
...@@ -2311,7 +2311,7 @@ wait_until_unfixed: ...@@ -2311,7 +2311,7 @@ wait_until_unfixed:
while not holding buf_pool_mutex or block->mutex. */ while not holding buf_pool_mutex or block->mutex. */
success = buf_zip_decompress(block, srv_use_checksums); success = buf_zip_decompress(block, srv_use_checksums);
if (UNIV_LIKELY(success)) { if (UNIV_LIKELY(success && !recv_no_ibuf_operations)) {
ibuf_merge_or_delete_for_page(block, space, offset, ibuf_merge_or_delete_for_page(block, space, offset,
zip_size, TRUE); zip_size, TRUE);
} }
......
...@@ -825,7 +825,17 @@ struct log_struct{ ...@@ -825,7 +825,17 @@ struct log_struct{
written to some log group; for this to written to some log group; for this to
be advanced, it is enough that the be advanced, it is enough that the
write i/o has been completed for all write i/o has been completed for all
log groups */ log groups.
Note that since InnoDB currently
has only one log group therefore
this value is redundant. Also it
is possible that this value
falls behind the
flushed_to_disk_lsn transiently.
It is appropriate to use either
flushed_to_disk_lsn or
write_lsn which are always
up-to-date and accurate. */
ib_uint64_t write_lsn; /*!< end lsn for the current running ib_uint64_t write_lsn; /*!< end lsn for the current running
write */ write */
ulint write_end_offset;/*!< the data in buffer has ulint write_end_offset;/*!< the data in buffer has
......
...@@ -238,16 +238,27 @@ ibool ...@@ -238,16 +238,27 @@ ibool
sync_thread_levels_empty(void); sync_thread_levels_empty(void);
/*==========================*/ /*==========================*/
/******************************************************************//** /******************************************************************//**
Checks that the level array for the current thread is empty. Checks if the level array for the current thread contains a
@return TRUE if empty except the exceptions specified below */ mutex or rw-latch at the specified level.
@return a matching latch, or NULL if not found */
UNIV_INTERN UNIV_INTERN
ibool void*
sync_thread_levels_empty_gen( sync_thread_levels_contains(
/*=========================*/ /*========================*/
ulint level); /*!< in: latching order level
(SYNC_DICT, ...)*/
/******************************************************************//**
Checks if the level array for the current thread is empty.
@return a latch, or NULL if empty except the exceptions specified below */
UNIV_INTERN
void*
sync_thread_levels_nonempty_gen(
/*============================*/
ibool dict_mutex_allowed); /*!< in: TRUE if dictionary mutex is ibool dict_mutex_allowed); /*!< in: TRUE if dictionary mutex is
allowed to be owned by the thread, allowed to be owned by the thread,
also purge_is_running mutex is also purge_is_running mutex is
allowed */ allowed */
#define sync_thread_levels_empty_gen(d) (!sync_thread_levels_nonempty_gen(d))
/******************************************************************//** /******************************************************************//**
Gets the debug information for a reserved mutex. */ Gets the debug information for a reserved mutex. */
UNIV_INTERN UNIV_INTERN
......
...@@ -4766,6 +4766,13 @@ loop: ...@@ -4766,6 +4766,13 @@ loop:
|| lock->trx->conc_state == TRX_PREPARED || lock->trx->conc_state == TRX_PREPARED
|| lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY); || lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY);
# ifdef UNIV_SYNC_DEBUG
/* Only validate the record queues when this thread is not
holding a space->latch. Deadlocks are possible due to
latching order violation when UNIV_DEBUG is defined while
UNIV_SYNC_DEBUG is not. */
if (!sync_thread_levels_contains(SYNC_FSP))
# endif /* UNIV_SYNC_DEBUG */
for (i = nth_bit; i < lock_rec_get_n_bits(lock); i++) { for (i = nth_bit; i < lock_rec_get_n_bits(lock); i++) {
if (i == 1 || lock_rec_get_nth_bit(lock, i)) { if (i == 1 || lock_rec_get_nth_bit(lock, i)) {
......
...@@ -2013,7 +2013,7 @@ log_checkpoint( ...@@ -2013,7 +2013,7 @@ log_checkpoint(
return(TRUE); return(TRUE);
} }
ut_ad(log_sys->written_to_all_lsn >= oldest_lsn); ut_ad(log_sys->flushed_to_disk_lsn >= oldest_lsn);
if (log_sys->n_pending_checkpoint_writes > 0) { if (log_sys->n_pending_checkpoint_writes > 0) {
/* A checkpoint write is running */ /* A checkpoint write is running */
......
-- source include/have_innodb.inc -- source include/have_innodb.inc
let $MYSQLD_DATADIR= `select @@datadir`;
let $innodb_file_format_check_orig=`select @@innodb_file_format_check`; let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb; create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb;
...@@ -136,7 +138,9 @@ delete from t1; ...@@ -136,7 +138,9 @@ delete from t1;
--error ER_CANT_DROP_FIELD_OR_KEY --error ER_CANT_DROP_FIELD_OR_KEY
drop index dc on t4; drop index dc on t4;
# there is no foreign key dc on t3 # there is no foreign key dc on t3
--replace_regex /'\.\/test\/#sql2-[0-9a-f-]*'/'#sql2-temporary'/ --replace_regex /'[^']*test\/#sql2-[0-9a-f-]*'/'#sql2-temporary'/
# Embedded server doesn't chdir to data directory
--replace_result $MYSQLD_DATADIR ./ master-data/ ''
--error ER_ERROR_ON_RENAME --error ER_ERROR_ON_RENAME
alter table t3 drop foreign key dc; alter table t3 drop foreign key dc;
alter table t4 drop foreign key dc; alter table t4 drop foreign key dc;
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
-- source include/have_innodb.inc -- source include/have_innodb.inc
let $MYSQLD_DATADIR= `select @@datadir`;
# Save the original values of some variables in order to be able to # Save the original values of some variables in order to be able to
# estimate how much they have changed during the tests. Previously this # estimate how much they have changed during the tests. Previously this
# test assumed that e.g. rows_deleted is 0 here and after deleting 23 # test assumed that e.g. rows_deleted is 0 here and after deleting 23
...@@ -1700,7 +1702,7 @@ set foreign_key_checks=0; ...@@ -1700,7 +1702,7 @@ set foreign_key_checks=0;
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1;
create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8; create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8;
# Embedded server doesn't chdir to data directory # Embedded server doesn't chdir to data directory
--replace_result $MYSQLTEST_VARDIR . master-data/ '' --replace_result $MYSQLD_DATADIR ./ master-data/ ''
-- error 1025 -- error 1025
rename table t3 to t1; rename table t3 to t1;
set foreign_key_checks=1; set foreign_key_checks=1;
...@@ -2340,7 +2342,7 @@ ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1 (a) ON DELETE SET NULL; ...@@ -2340,7 +2342,7 @@ ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1 (a) ON DELETE SET NULL;
# mysqltest first does replace_regex, then replace_result # mysqltest first does replace_regex, then replace_result
--replace_regex /'[^']*test\/#sql-[0-9a-f_]*'/'#sql-temporary'/ --replace_regex /'[^']*test\/#sql-[0-9a-f_]*'/'#sql-temporary'/
# Embedded server doesn't chdir to data directory # Embedded server doesn't chdir to data directory
--replace_result $MYSQLTEST_VARDIR . master-data/ '' --replace_result $MYSQLD_DATADIR ./ master-data/ ''
--error 1025 --error 1025
ALTER TABLE t2 MODIFY a INT NOT NULL; ALTER TABLE t2 MODIFY a INT NOT NULL;
DELETE FROM t1; DELETE FROM t1;
......
...@@ -658,6 +658,14 @@ page_copy_rec_list_end( ...@@ -658,6 +658,14 @@ page_copy_rec_list_end(
index, mtr); index, mtr);
} }
/* Update PAGE_MAX_TRX_ID on the uncompressed page.
Modifications will be redo logged and copied to the compressed
page in page_zip_compress() or page_zip_reorganize() below. */
if (dict_index_is_sec_or_ibuf(index) && page_is_leaf(page)) {
page_update_max_trx_id(new_block, NULL,
page_get_max_trx_id(page), mtr);
}
if (UNIV_LIKELY_NULL(new_page_zip)) { if (UNIV_LIKELY_NULL(new_page_zip)) {
mtr_set_log_mode(mtr, log_mode); mtr_set_log_mode(mtr, log_mode);
...@@ -696,15 +704,10 @@ page_copy_rec_list_end( ...@@ -696,15 +704,10 @@ page_copy_rec_list_end(
} }
} }
/* Update the lock table, MAX_TRX_ID, and possible hash index */ /* Update the lock table and possible hash index */
lock_move_rec_list_end(new_block, block, rec); lock_move_rec_list_end(new_block, block, rec);
if (dict_index_is_sec_or_ibuf(index) && page_is_leaf(page)) {
page_update_max_trx_id(new_block, new_page_zip,
page_get_max_trx_id(page), mtr);
}
btr_search_move_or_delete_hash_entries(new_block, block, index); btr_search_move_or_delete_hash_entries(new_block, block, index);
return(ret); return(ret);
...@@ -772,6 +775,16 @@ page_copy_rec_list_start( ...@@ -772,6 +775,16 @@ page_copy_rec_list_start(
mem_heap_free(heap); mem_heap_free(heap);
} }
/* Update PAGE_MAX_TRX_ID on the uncompressed page.
Modifications will be redo logged and copied to the compressed
page in page_zip_compress() or page_zip_reorganize() below. */
if (dict_index_is_sec_or_ibuf(index)
&& page_is_leaf(page_align(rec))) {
page_update_max_trx_id(new_block, NULL,
page_get_max_trx_id(page_align(rec)),
mtr);
}
if (UNIV_LIKELY_NULL(new_page_zip)) { if (UNIV_LIKELY_NULL(new_page_zip)) {
mtr_set_log_mode(mtr, log_mode); mtr_set_log_mode(mtr, log_mode);
...@@ -809,14 +822,7 @@ page_copy_rec_list_start( ...@@ -809,14 +822,7 @@ page_copy_rec_list_start(
} }
} }
/* Update MAX_TRX_ID, the lock table, and possible hash index */ /* Update the lock table and possible hash index */
if (dict_index_is_sec_or_ibuf(index)
&& page_is_leaf(page_align(rec))) {
page_update_max_trx_id(new_block, new_page_zip,
page_get_max_trx_id(page_align(rec)),
mtr);
}
lock_move_rec_list_start(new_block, block, rec, ret); lock_move_rec_list_start(new_block, block, rec, ret);
......
...@@ -957,13 +957,63 @@ sync_thread_levels_contain( ...@@ -957,13 +957,63 @@ sync_thread_levels_contain(
return(FALSE); return(FALSE);
} }
/******************************************************************//**
Checks if the level array for the current thread contains a
mutex or rw-latch at the specified level.
@return a matching latch, or NULL if not found */
UNIV_INTERN
void*
sync_thread_levels_contains(
/*========================*/
ulint level) /*!< in: latching order level
(SYNC_DICT, ...)*/
{
sync_level_t* arr;
sync_thread_t* thread_slot;
sync_level_t* slot;
ulint i;
if (!sync_order_checks_on) {
return(NULL);
}
mutex_enter(&sync_thread_mutex);
thread_slot = sync_thread_level_arrays_find_slot();
if (thread_slot == NULL) {
mutex_exit(&sync_thread_mutex);
return(NULL);
}
arr = thread_slot->levels;
for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
slot = sync_thread_levels_get_nth(arr, i);
if (slot->latch != NULL && slot->level == level) {
mutex_exit(&sync_thread_mutex);
return(slot->latch);
}
}
mutex_exit(&sync_thread_mutex);
return(NULL);
}
/******************************************************************//** /******************************************************************//**
Checks that the level array for the current thread is empty. Checks that the level array for the current thread is empty.
@return TRUE if empty except the exceptions specified below */ @return a latch, or NULL if empty except the exceptions specified below */
UNIV_INTERN UNIV_INTERN
ibool void*
sync_thread_levels_empty_gen( sync_thread_levels_nonempty_gen(
/*=========================*/ /*============================*/
ibool dict_mutex_allowed) /*!< in: TRUE if dictionary mutex is ibool dict_mutex_allowed) /*!< in: TRUE if dictionary mutex is
allowed to be owned by the thread, allowed to be owned by the thread,
also purge_is_running mutex is also purge_is_running mutex is
...@@ -976,7 +1026,7 @@ sync_thread_levels_empty_gen( ...@@ -976,7 +1026,7 @@ sync_thread_levels_empty_gen(
if (!sync_order_checks_on) { if (!sync_order_checks_on) {
return(TRUE); return(NULL);
} }
mutex_enter(&sync_thread_mutex); mutex_enter(&sync_thread_mutex);
...@@ -987,7 +1037,7 @@ sync_thread_levels_empty_gen( ...@@ -987,7 +1037,7 @@ sync_thread_levels_empty_gen(
mutex_exit(&sync_thread_mutex); mutex_exit(&sync_thread_mutex);
return(TRUE); return(NULL);
} }
arr = thread_slot->levels; arr = thread_slot->levels;
...@@ -1004,13 +1054,13 @@ sync_thread_levels_empty_gen( ...@@ -1004,13 +1054,13 @@ sync_thread_levels_empty_gen(
mutex_exit(&sync_thread_mutex); mutex_exit(&sync_thread_mutex);
ut_error; ut_error;
return(FALSE); return(slot->latch);
} }
} }
mutex_exit(&sync_thread_mutex); mutex_exit(&sync_thread_mutex);
return(TRUE); return(NULL);
} }
/******************************************************************//** /******************************************************************//**
......
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