summaryrefslogtreecommitdiff
path: root/innobase/trx
diff options
context:
space:
mode:
authorunknown <monty@hundin.mysql.fi>2001-11-04 16:14:09 +0200
committerunknown <monty@hundin.mysql.fi>2001-11-04 16:14:09 +0200
commit0d1ba873aa11ea581ebbda9f450027329f2e1a3b (patch)
tree689c9d0271e23431f1ab0ac09e1af4d68a58ca76 /innobase/trx
parent9f90ff3f12f1fc2bcb70cde74dbd6f27e33e230c (diff)
parent0176dacd54b7eb62ebc4a81909b189517aee2cb4 (diff)
downloadmariadb-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.c37
-rw-r--r--innobase/trx/trx0rec.c148
-rw-r--r--innobase/trx/trx0roll.c16
-rw-r--r--innobase/trx/trx0sys.c4
-rw-r--r--innobase/trx/trx0trx.c40
-rw-r--r--innobase/trx/trx0undo.c10
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;