diff options
author | unknown <monty@hundin.mysql.fi> | 2001-11-04 16:14:09 +0200 |
---|---|---|
committer | unknown <monty@hundin.mysql.fi> | 2001-11-04 16:14:09 +0200 |
commit | 0d1ba873aa11ea581ebbda9f450027329f2e1a3b (patch) | |
tree | 689c9d0271e23431f1ab0ac09e1af4d68a58ca76 /innobase/trx | |
parent | 9f90ff3f12f1fc2bcb70cde74dbd6f27e33e230c (diff) | |
parent | 0176dacd54b7eb62ebc4a81909b189517aee2cb4 (diff) | |
download | mariadb-git-0d1ba873aa11ea581ebbda9f450027329f2e1a3b.tar.gz |
merge with 3.23.44
BitKeeper/etc/ignore:
auto-union
BitKeeper/etc/logging_ok:
auto-union
Docs/manual.texi:
Auto merged
include/my_base.h:
Auto merged
mysql-test/t/func_time.test:
Auto merged
mysql-test/t/join.test:
Auto merged
mysql-test/t/rpl000012.test:
Auto merged
BUILD/FINISH.sh:
Auto merged
BitKeeper/deleted/.del-db_ext.h~a1e210bbd0de0a48:
Auto merged
BitKeeper/deleted/.del-mutex_ext.h~f20f47ddc346598b:
Auto merged
BitKeeper/deleted/.del-violite.c~984c09cffe14a11b:
Auto merged
BitKeeper/deleted/.del-violite.c~d7b85be615595ace:
Auto merged
Build-tools/Do-all-build-steps:
Auto merged
client/client_priv.h:
Auto merged
client/mysqladmin.c:
Auto merged
innobase/include/srv0srv.h:
Auto merged
innobase/include/univ.i:
Auto merged
innobase/log/log0log.c:
Auto merged
innobase/srv/srv0srv.c:
Auto merged
innobase/srv/srv0start.c:
Auto merged
isam/pack_isam.c:
Auto merged
libmysql_r/Makefile.am:
Auto merged
myisam/myisamchk.c:
Auto merged
mysql-test/t/having.test:
Auto merged
mysql-test/t/rpl000015-slave.sh:
Auto merged
mysql-test/t/rpl000016-slave.sh:
Auto merged
mysys/mf_cache.c:
Auto merged
mysys/mf_casecnv.c:
Auto merged
mysys/mf_tempfile.c:
Auto merged
readline/vi_mode.c:
Auto merged
strings/strto.c:
Auto merged
sql/field.cc:
Auto merged
sql/field.h:
Auto merged
sql/ha_berkeley.cc:
Auto merged
sql/ha_myisammrg.cc:
Auto merged
sql/handler.cc:
Auto merged
sql/item.h:
Auto merged
sql/log_event.cc:
Auto merged
sql/sql_acl.cc:
Auto merged
sql/time.cc:
Auto merged
BUILD/SETUP.sh:
Use -mcpu as default (safe for all x86 cpu's)
client/mysqldump.c:
Merge from 3.23.44
configure.in:
Update version number
extra/resolveip.c:
Portability fix
Diffstat (limited to 'innobase/trx')
-rw-r--r-- | innobase/trx/trx0purge.c | 37 | ||||
-rw-r--r-- | innobase/trx/trx0rec.c | 148 | ||||
-rw-r--r-- | innobase/trx/trx0roll.c | 16 | ||||
-rw-r--r-- | innobase/trx/trx0sys.c | 4 | ||||
-rw-r--r-- | innobase/trx/trx0trx.c | 40 | ||||
-rw-r--r-- | innobase/trx/trx0undo.c | 10 |
6 files changed, 196 insertions, 59 deletions
diff --git a/innobase/trx/trx0purge.c b/innobase/trx/trx0purge.c index c50ffb65e00..a91ac135f81 100644 --- a/innobase/trx/trx0purge.c +++ b/innobase/trx/trx0purge.c @@ -537,13 +537,13 @@ trx_purge_truncate_history(void) /* We play safe and set the truncate limit at most to the purge view low_limit number, though this is not necessary */ - if (ut_dulint_cmp(limit_trx_no, (purge_sys->view)->low_limit_no) >= 0) { - limit_trx_no = (purge_sys->view)->low_limit_no; + if (ut_dulint_cmp(limit_trx_no, purge_sys->view->low_limit_no) >= 0) { + limit_trx_no = purge_sys->view->low_limit_no; limit_undo_no = ut_dulint_zero; } ut_ad((ut_dulint_cmp(limit_trx_no, - (purge_sys->view)->low_limit_no) <= 0)); + purge_sys->view->low_limit_no) <= 0)); rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list); @@ -565,7 +565,7 @@ trx_purge_truncate_if_arr_empty(void) { ut_ad(mutex_own(&(purge_sys->mutex))); - if ((purge_sys->arr)->n_used == 0) { + if (purge_sys->arr->n_used == 0) { trx_purge_truncate_history(); @@ -783,7 +783,7 @@ trx_purge_get_next_rec( ut_ad(mutex_own(&(purge_sys->mutex))); ut_ad(purge_sys->next_stored); - space = (purge_sys->rseg)->space; + space = purge_sys->rseg->space; page_no = purge_sys->page_no; offset = purge_sys->offset; @@ -936,7 +936,7 @@ trx_purge_fetch_next_rec( } if (ut_dulint_cmp(purge_sys->purge_trx_no, - (purge_sys->view)->low_limit_no) >= 0) { + purge_sys->view->low_limit_no) >= 0) { purge_sys->state = TRX_STOP_PURGE; trx_purge_truncate_if_arr_empty(); @@ -1072,3 +1072,28 @@ trx_purge(void) return(purge_sys->n_pages_handled - old_pages_handled); } + +/********************************************************************** +Prints information of the purge system to stderr. */ + +void +trx_purge_sys_print(void) +/*=====================*/ +{ + fprintf(stderr, "InnoDB: Purge system view:\n"); + read_view_print(purge_sys->view); + + fprintf(stderr, "InnoDB: Purge trx n:o %lu %lu, undo n_o %lu %lu\n", + ut_dulint_get_high(purge_sys->purge_trx_no), + ut_dulint_get_low(purge_sys->purge_trx_no), + ut_dulint_get_high(purge_sys->purge_undo_no), + ut_dulint_get_low(purge_sys->purge_undo_no)); + fprintf(stderr, + "InnoDB: Purge next stored %lu, page_no %lu, offset %lu,\n" + "InnoDB: Purge hdr_page_no %lu, hdr_offset %lu\n", + purge_sys->next_stored, + purge_sys->page_no, + purge_sys->offset, + purge_sys->hdr_page_no, + purge_sys->hdr_offset); +} diff --git a/innobase/trx/trx0rec.c b/innobase/trx/trx0rec.c index 73153cfaa37..abce470bd1c 100644 --- a/innobase/trx/trx0rec.c +++ b/innobase/trx/trx0rec.c @@ -329,7 +329,7 @@ trx_undo_rec_get_pars( /************************************************************************** Reads from an undo log record a stored column value. */ -UNIV_INLINE +static byte* trx_undo_rec_get_col_val( /*=====================*/ @@ -374,13 +374,14 @@ trx_undo_rec_get_row_ref( mem_heap_t* heap) /* in: memory heap from which the memory needed is allocated */ { - ulint i; dfield_t* dfield; byte* field; ulint len; ulint ref_len; + ulint i; ut_ad(index && ptr && ref && heap); + ut_a(index->type & DICT_CLUSTERED); ref_len = dict_index_get_n_unique(index); @@ -411,12 +412,13 @@ trx_undo_rec_skip_row_ref( record, at the start of the row reference */ dict_index_t* index) /* in: clustered index */ { - ulint i; - byte* field; - ulint len; - ulint ref_len; + byte* field; + ulint len; + ulint ref_len; + ulint i; ut_ad(index && ptr); + ut_a(index->type & DICT_CLUSTERED); ref_len = dict_index_get_n_unique(index); @@ -468,7 +470,7 @@ trx_undo_page_report_modify( byte* type_cmpl_ptr; ulint i; - ut_ad(index->type & DICT_CLUSTERED); + ut_a(index->type & DICT_CLUSTERED); ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE) == TRX_UNDO_UPDATE); table = index->table; @@ -603,7 +605,7 @@ trx_undo_page_report_modify( /* Notify purge that it eventually has to free the old externally stored field */ - (trx->update_undo)->del_marks = TRUE; + trx->update_undo->del_marks = TRUE; *type_cmpl_ptr = *type_cmpl_ptr | TRX_UNDO_UPD_EXTERN; } else { @@ -634,7 +636,7 @@ trx_undo_page_report_modify( if (!update || !(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { - (trx->update_undo)->del_marks = TRUE; + trx->update_undo->del_marks = TRUE; if (trx_undo_left(undo_page, ptr) < 5) { @@ -787,7 +789,9 @@ Builds an update vector based on a remaining part of an undo log record. */ byte* trx_undo_update_rec_get_update( /*===========================*/ - /* out: remaining part of the record */ + /* out: remaining part of the record, + NULL if an error detected, which means that + the record is corrupted */ byte* ptr, /* in: remaining part in update undo log record, after reading the row reference NOTE that this copy of the undo log record must @@ -816,6 +820,8 @@ trx_undo_update_rec_get_update( ulint field_no; ulint i; + ut_a(index->type & DICT_CLUSTERED); + if (type != TRX_UNDO_DEL_MARK_REC) { ptr = trx_undo_update_rec_get_n_upd_fields(ptr, &n_fields); } else { @@ -846,11 +852,28 @@ trx_undo_update_rec_get_update( index); dfield_set_data(&(upd_field->new_val), buf, DATA_ROLL_PTR_LEN); - /* Store then the updated ordinary columns to update vector */ + /* Store then the updated ordinary columns to the update vector */ for (i = 0; i < n_fields; i++) { ptr = trx_undo_update_rec_get_field_no(ptr, &field_no); + + if (field_no >= dict_index_get_n_fields(index)) { + fprintf(stderr, + "InnoDB: Error: trying to access update undo rec field %lu in table %s\n" + "InnoDB: index %s, but index has only %lu fields\n", + field_no, index->table_name, index->name, + dict_index_get_n_fields(index)); + fprintf(stderr, + "InnoDB: Send a detailed bug report to mysql@lists.mysql.com"); + + fprintf(stderr, + "InnoDB: Run also CHECK TABLE on table %s\n", index->table_name); + fprintf(stderr, + "InnoDB: n_fields = %lu, i = %lu, ptr %lx\n", n_fields, i, (ulint)ptr); + return(NULL); + } + ptr = trx_undo_rec_get_col_val(ptr, &field, &len); upd_field = upd_get_nth_field(update, i); @@ -1005,7 +1028,7 @@ trx_undo_report_row_operation( the update vector, otherwise NULL */ ulint cmpl_info, /* in: compiler info on secondary index updates */ - rec_t* rec, /* in: case of an update or delete + rec_t* rec, /* in: in case of an update or delete marking, the record in the clustered index, otherwise NULL */ dulint* roll_ptr) /* out: rollback pointer to the @@ -1017,11 +1040,13 @@ trx_undo_report_row_operation( trx_undo_t* undo; page_t* undo_page; ulint offset; - mtr_t mtr; ulint page_no; ibool is_insert; trx_rseg_t* rseg; + mtr_t mtr; + ut_a(index->type & DICT_CLUSTERED); + if (flags & BTR_NO_UNDO_LOG_FLAG) { *roll_ptr = ut_dulint_zero; @@ -1030,7 +1055,7 @@ trx_undo_report_row_operation( } ut_ad(thr); - ut_ad(index->type & DICT_CLUSTERED); + ut_a(index->type & DICT_CLUSTERED); ut_ad((op_type != TRX_UNDO_INSERT_OP) || (clust_entry && !update && !rec)); @@ -1165,6 +1190,7 @@ trx_undo_get_undo_rec_low( dulint roll_ptr, /* in: roll pointer to record */ mem_heap_t* heap) /* in: memory heap where copied */ { + trx_undo_rec_t* undo_rec; ulint rseg_id; ulint page_no; ulint offset; @@ -1172,7 +1198,6 @@ trx_undo_get_undo_rec_low( trx_rseg_t* rseg; ibool is_insert; mtr_t mtr; - trx_undo_rec_t* undo_rec; trx_undo_decode_roll_ptr(roll_ptr, &is_insert, &rseg_id, &page_no, &offset); @@ -1234,7 +1259,8 @@ trx_undo_prev_version_build( /*========================*/ /* out: DB_SUCCESS, or DB_MISSING_HISTORY if the previous version is not >= purge_view, - which means that it may have been removed */ + which means that it may have been removed, + DB_ERROR if corrupted record */ rec_t* index_rec,/* in: clustered index record in the index tree */ mtr_t* index_mtr,/* in: mtr which contains the latch to @@ -1255,6 +1281,7 @@ trx_undo_prev_version_build( dulint table_id; dulint trx_id; dulint roll_ptr; + dulint old_roll_ptr; upd_t* update; byte* ptr; ulint info_bits; @@ -1263,19 +1290,38 @@ trx_undo_prev_version_build( byte* buf; ulint err; ulint i; + char err_buf[1000]; ut_ad(rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED)); ut_ad(mtr_memo_contains(index_mtr, buf_block_align(index_rec), MTR_MEMO_PAGE_S_FIX) || mtr_memo_contains(index_mtr, buf_block_align(index_rec), MTR_MEMO_PAGE_X_FIX)); + if (!(index->type & DICT_CLUSTERED)) { + fprintf(stderr, + "InnoDB: Error: trying to access update undo rec for table %s\n" + "InnoDB: index %s which is not a clustered index\n", + index->table_name, index->name); + fprintf(stderr, + "InnoDB: Send a detailed bug report to mysql@lists.mysql.com"); + + rec_sprintf(err_buf, 900, index_rec); + fprintf(stderr, "InnoDB: index record %s\n", err_buf); + + rec_sprintf(err_buf, 900, rec); + fprintf(stderr, "InnoDB: record version %s\n", err_buf); + + return(DB_ERROR); + } roll_ptr = row_get_rec_roll_ptr(rec, index); + old_roll_ptr = roll_ptr; + + *old_vers = NULL; if (trx_undo_roll_ptr_is_insert(roll_ptr)) { /* The record rec is the first inserted version */ - *old_vers = NULL; return(DB_SUCCESS); } @@ -1286,8 +1332,6 @@ trx_undo_prev_version_build( if (err != DB_SUCCESS) { - *old_vers = NULL; - return(err); } @@ -1298,8 +1342,70 @@ trx_undo_prev_version_build( &info_bits); ptr = trx_undo_rec_skip_row_ref(ptr, index); - trx_undo_update_rec_get_update(ptr, index, type, trx_id, roll_ptr, - info_bits, heap, &update); + ptr = trx_undo_update_rec_get_update(ptr, index, type, trx_id, + roll_ptr, info_bits, heap, &update); + + if (ut_dulint_cmp(table_id, index->table->id) != 0) { + ptr = NULL; + + fprintf(stderr, + "InnoDB: Error: trying to access update undo rec for table %s\n" + "InnoDB: but the table id in the undo record is wrong\n", + index->table_name); + fprintf(stderr, + "InnoDB: Send a detailed bug report to mysql@lists.mysql.com\n"); + + fprintf(stderr, + "InnoDB: Run also CHECK TABLE on table %s\n", index->table_name); + } + + if (ptr == NULL) { + /* The record was corrupted, return an error; these printfs + should catch an elusive bug in row_vers_old_has_index_entry */ + + fprintf(stderr, + "InnoDB: Table name %s, index name %s, n_uniq %lu\n", + index->table_name, index->name, + dict_index_get_n_unique(index)); + + fprintf(stderr, + "InnoDB: undo rec address %lx, type %lu cmpl_info %lu\n", + (ulint)undo_rec, type, cmpl_info); + fprintf(stderr, + "InnoDB: undo rec table id %lu %lu, index table id %lu %lu\n", + ut_dulint_get_high(table_id), + ut_dulint_get_low(table_id), + ut_dulint_get_high(index->table->id), + ut_dulint_get_low(index->table->id)); + + ut_sprintf_buf(err_buf, undo_rec, 150); + + fprintf(stderr, "InnoDB: dump of 150 bytes in undo rec: %s\n", + err_buf); + rec_sprintf(err_buf, 900, index_rec); + fprintf(stderr, "InnoDB: index record %s\n", err_buf); + + rec_sprintf(err_buf, 900, rec); + fprintf(stderr, "InnoDB: record version %s\n", err_buf); + + fprintf(stderr, + "InnoDB: Record trx id %lu %lu, update rec trx id %lu %lu\n", + ut_dulint_get_high(rec_trx_id), + ut_dulint_get_low(rec_trx_id), + ut_dulint_get_high(trx_id), + ut_dulint_get_low(trx_id)); + + fprintf(stderr, + "InnoDB: Roll ptr in rec %lu %lu, in update rec %lu %lu\n", + ut_dulint_get_high(old_roll_ptr), + ut_dulint_get_low(old_roll_ptr), + ut_dulint_get_high(roll_ptr), + ut_dulint_get_low(roll_ptr)); + + trx_purge_sys_print(); + + return(DB_ERROR); + } if (row_upd_changes_field_size(rec, index, update)) { diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c index 2adeb1cf57c..47fffea5e40 100644 --- a/innobase/trx/trx0roll.c +++ b/innobase/trx/trx0roll.c @@ -45,6 +45,8 @@ trx_general_rollback_for_mysql( que_thr_t* thr; roll_node_t* roll_node; + trx_start_if_not_started(trx); + heap = mem_heap_create(512); roll_node = roll_node_create(heap); @@ -108,6 +110,8 @@ trx_rollback_for_mysql( err = trx_general_rollback_for_mysql(trx, FALSE, NULL); + trx_mark_sql_stat_end(trx); + /* Tell Innobase server that there might be work for utility threads: */ @@ -144,7 +148,7 @@ trx_rollback_last_sql_stat_for_mysql( err = trx_general_rollback_for_mysql(trx, TRUE, &(trx->last_sql_stat_start)); trx_mark_sql_stat_end(trx); - + /* Tell Innobase server that there might be work for utility threads: */ @@ -229,8 +233,9 @@ loop: ut_a(thr == que_fork_start_command(fork, SESS_COMM_EXECUTE, 0)); - fprintf(stderr, "InnoDB: Rolling back trx no %lu\n", - ut_dulint_get_low(trx->id)); + fprintf(stderr, "InnoDB: Rolling back trx with id %lu %lu\n", + ut_dulint_get_high(trx->id), + ut_dulint_get_low(trx->id)); mutex_exit(&kernel_mutex); if (trx->dict_operation) { @@ -246,7 +251,7 @@ loop: mutex_exit(&kernel_mutex); fprintf(stderr, - "InnoDB: Waiting rollback of trx no %lu to end\n", + "InnoDB: Waiting for rollback of trx id %lu to end\n", ut_dulint_get_low(trx->id)); os_thread_sleep(100000); @@ -272,7 +277,8 @@ loop: mutex_exit(&(dict_sys->mutex)); } - fprintf(stderr, "InnoDB: Rolling back of trx no %lu completed\n", + fprintf(stderr, "InnoDB: Rolling back of trx id %lu %lu completed\n", + ut_dulint_get_high(trx->id), ut_dulint_get_low(trx->id)); mem_heap_free(heap); diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c index 0b8664013d7..e79e4594637 100644 --- a/innobase/trx/trx0sys.c +++ b/innobase/trx/trx0sys.c @@ -518,6 +518,10 @@ trx_sys_init_at_db_start(void) fprintf(stderr, "InnoDB: %lu uncommitted transaction(s) which must be rolled back\n", UT_LIST_GET_LEN(trx_sys->trx_list)); + + fprintf(stderr, "Trx id counter is %lu %lu\n", + ut_dulint_get_high(trx_sys->max_trx_id), + ut_dulint_get_low(trx_sys->max_trx_id)); } UT_LIST_INIT(trx_sys->view_list); diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 13b37775dce..18c80819245 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -499,7 +499,7 @@ trx_commit_off_kernel( rseg = trx->rseg; - if ((trx->insert_undo != NULL) || (trx->update_undo != NULL)) { + if (trx->insert_undo != NULL || trx->update_undo != NULL) { mutex_exit(&kernel_mutex); @@ -524,7 +524,13 @@ trx_commit_off_kernel( if (undo) { mutex_enter(&kernel_mutex); -#ifdef TRX_UPDATE_UNDO_OPT +#ifdef notdefined + /* ########## There is a bug here: purge and rollback + need the whole stack of old record versions even if no + consistent read would need them!! This is because they + decide on the basis of the old versions when we can + remove delete marked secondary index records! */ + if (!undo->del_marks && (undo->size == 1) && (UT_LIST_GET_LEN(trx_sys->view_list) == 1)) { @@ -584,9 +590,7 @@ trx_commit_off_kernel( mutex_enter(&kernel_mutex); } -#ifdef TRX_UPDATE_UNDO_OPT -shortcut: -#endif + ut_ad(trx->conc_state == TRX_ACTIVE); ut_ad(mutex_own(&kernel_mutex)); @@ -1286,6 +1290,8 @@ trx_commit_for_mysql( sig to the transaction, we must here make sure that trx has been started. */ + ut_a(trx); + trx->op_info = "committing"; trx_start_if_not_started(trx); @@ -1309,29 +1315,13 @@ trx_mark_sql_stat_end( /*==================*/ trx_t* trx) /* in: trx handle */ { - trx_start_if_not_started(trx); - - mutex_enter(&kernel_mutex); - - trx->last_sql_stat_start.least_undo_no = trx->undo_no; - - mutex_exit(&kernel_mutex); -} - -/************************************************************************** -Marks the latest SQL statement ended but does not start a new transaction -if the trx is not started. */ + ut_a(trx); -void -trx_mark_sql_stat_end_do_not_start_new( -/*===================================*/ - trx_t* trx) /* in: trx handle */ -{ - mutex_enter(&kernel_mutex); + if (trx->conc_state == TRX_NOT_STARTED) { + trx->undo_no = ut_dulint_zero; + } trx->last_sql_stat_start.least_undo_no = trx->undo_no; - - mutex_exit(&kernel_mutex); } /************************************************************************** diff --git a/innobase/trx/trx0undo.c b/innobase/trx/trx0undo.c index 598090bdee2..8b83163bfc2 100644 --- a/innobase/trx/trx0undo.c +++ b/innobase/trx/trx0undo.c @@ -1220,8 +1220,14 @@ trx_undo_lists_init( for (i = 0; i < TRX_RSEG_N_SLOTS; i++) { page_no = trx_rsegf_get_nth_undo(rseg_header, i, &mtr); - if (page_no != FIL_NULL) { - + /* In forced recovery: try to avoid operations which look + at database pages; undo logs are rapidly changing data, and + the probability that they are in an inconsistent state is + high */ + + if (page_no != FIL_NULL + && srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN) { + undo = trx_undo_mem_create_at_db_start(rseg, i, page_no, &mtr); size += undo->size; |