mirror of
https://github.com/MariaDB/server.git
synced 2025-01-27 17:33:44 +01:00
9016198aa2
Apply innodb-5.0-* snapshots: ss1489 and ss1547. Fixes: Bug#9709: InnoDB inconsistensy causes "Operating System Error 32/33" Bug#22819: SHOW INNODB STATUS crashes the server with an assertion failure under high load Bug#25645: Assertion failure in file srv0srv.c Bug#27294: insert into ... select ... causes crash with innodb_locks_unsafe_for_binlog=1 Bug#28138: indexing column prefixes produces corruption in InnoDB innobase/btr/btr0btr.c: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1547: branches/5.0: Merge r1546 from trunk: When buffering an insert to a prefix index of a variable-length column, do not incorrectly mark the column as fixed-length. (Bug #28138) ibuf_entry_build(): Instead of prefix_len, pass fixed_len to dtype_new_store_for_order_and_null_size(). Add debug assertions. btr_index_rec_validate(): Correct a comment about prefix indexes. rec_get_converted_size_new(), rec_convert_dtuple_to_rec_new(): Add debug assertions and comments. dict_col_type_assert_equal(): New debug function. innobase/buf/buf0buf.c: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1502: branches/5.0: Add debug code for Bug 26081. This change has some debug assertions that have been promoted to normal assertions. These will need to be undone once we've nailed this bug. innobase/buf/buf0lru.c: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1502: branches/5.0: Add debug code for Bug 26081. This change has some debug assertions that have been promoted to normal assertions. These will need to be undone once we've nailed this bug. innobase/ibuf/ibuf0ibuf.c: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1547: branches/5.0: Merge r1546 from trunk: When buffering an insert to a prefix index of a variable-length column, do not incorrectly mark the column as fixed-length. (Bug #28138) ibuf_entry_build(): Instead of prefix_len, pass fixed_len to dtype_new_store_for_order_and_null_size(). Add debug assertions. btr_index_rec_validate(): Correct a comment about prefix indexes. rec_get_converted_size_new(), rec_convert_dtuple_to_rec_new(): Add debug assertions and comments. dict_col_type_assert_equal(): New debug function. innobase/include/buf0buf.ic: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1502: branches/5.0: Add debug code for Bug 26081. This change has some debug assertions that have been promoted to normal assertions. These will need to be undone once we've nailed this bug. innobase/include/buf0lru.h: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1502: branches/5.0: Add debug code for Bug 26081. This change has some debug assertions that have been promoted to normal assertions. These will need to be undone once we've nailed this bug. innobase/include/dict0dict.h: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1547: branches/5.0: Merge r1546 from trunk: When buffering an insert to a prefix index of a variable-length column, do not incorrectly mark the column as fixed-length. (Bug #28138) ibuf_entry_build(): Instead of prefix_len, pass fixed_len to dtype_new_store_for_order_and_null_size(). Add debug assertions. btr_index_rec_validate(): Correct a comment about prefix indexes. rec_get_converted_size_new(), rec_convert_dtuple_to_rec_new(): Add debug assertions and comments. dict_col_type_assert_equal(): New debug function. innobase/include/dict0dict.ic: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1547: branches/5.0: Merge r1546 from trunk: When buffering an insert to a prefix index of a variable-length column, do not incorrectly mark the column as fixed-length. (Bug #28138) ibuf_entry_build(): Instead of prefix_len, pass fixed_len to dtype_new_store_for_order_and_null_size(). Add debug assertions. btr_index_rec_validate(): Correct a comment about prefix indexes. rec_get_converted_size_new(), rec_convert_dtuple_to_rec_new(): Add debug assertions and comments. dict_col_type_assert_equal(): New debug function. innobase/include/dict0mem.h: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1537: branches/5.0: merge r1536 and partially r1535 Change the comment to a more appropriate one. Discussed with Heikki on IM. Document that DICT_MAX_INDEX_COL_LEN should not be changed. innobase/include/os0file.h: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1417: branches/5.0: Fix Bug#9709 by retrying (forever) if ERROR_SHARING_VIOLATION or ERROR_LOCK_VIOLATION is encountered during file operation. This is caused by backup software, so InnoDB should retry while the backup software is done with the file. Approved by: Heikki innobase/include/trx0trx.h: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1463: branches/5.0: merge r1462 from trunk: Fix typo in comment. innobase/lock/lock0lock.c: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1458: branches/5.0: Fix Bug#22819, remove assertion. (http://bugs.mysql.com/bug.php?id=22819) innobase/log/log0log.c: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1520: Patch to allow monitor threads to stop before proceeding with normal shutdown. Also have a separate time counter for tablespace monitor. reviewed by: Heikki Revision r1525: backport of r1524 Log: Undo bad space formatting introduced in earlier commit r1521 spotted by: Marko innobase/mtr/mtr0mtr.c: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1502: branches/5.0: Add debug code for Bug 26081. This change has some debug assertions that have been promoted to normal assertions. These will need to be undone once we've nailed this bug. innobase/os/os0file.c: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1417: branches/5.0: Fix Bug#9709 by retrying (forever) if ERROR_SHARING_VIOLATION or ERROR_LOCK_VIOLATION is encountered during file operation. This is caused by backup software, so InnoDB should retry while the backup software is done with the file. Approved by: Heikki innobase/rem/rem0rec.c: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1547: branches/5.0: Merge r1546 from trunk: When buffering an insert to a prefix index of a variable-length column, do not incorrectly mark the column as fixed-length. (Bug #28138) ibuf_entry_build(): Instead of prefix_len, pass fixed_len to dtype_new_store_for_order_and_null_size(). Add debug assertions. btr_index_rec_validate(): Correct a comment about prefix indexes. rec_get_converted_size_new(), rec_convert_dtuple_to_rec_new(): Add debug assertions and comments. dict_col_type_assert_equal(): New debug function. innobase/row/row0sel.c: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1456: branches/5.0: merge r1452 from trunk: Fix phantom reads (http://bugs.mysql.com/27197) following Heikki's patch in the bug followup. innobase/srv/srv0srv.c: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1460: branches/5.0: Merge r1459 from trunk: Fix typo in the comment. Revision r1520: Patch to allow monitor threads to stop before proceeding with normal shutdown. Also have a separate time counter for tablespace monitor. reviewed by: Heikki sql/ha_innodb.cc: Apply innodb-5.0-* snapshots: ss1489 and ss1547. Revision r1436: branches/5.0: Fix Bug#27294 by using trx returned by check_trx_exists() instead of prebuilt->trx. This has been fixed in 5.1 in r782. Approved by: Heikki Revision r1443: branches/5.0: merge r1442 from trunk: Potential fix for Bug#25645: "Move innobase_release_stat_resources(trx) outside the 'if' in ha_innobase::external_lock(). That would add more safety that whatever MySQL does at a query end, there would be no risk of a hang on the btr search latch." Also call innobase_release_temporary_latches() in the beginning of ha_innobase::close(). Approved by: Heikki Revision r1454: branches/5.0: merge r1453 from trunk: Bugfix: only call innobase_release_temporary_latches() in case of current_thd is not NULL, otherwise we get NULL pointer dereferencing. Revision r1504: branches/5.0: Apply patch for Bug 27650 from MySQL. Revision r1539: Backport of r1538 from 5.1 Do not return error in ha_innobase::info if srv_force_recovery >= 4. This is to allow for normal processing of the query by MySQL instead of generating an error. Reviewed by: Heikki
341 lines
8.2 KiB
C
341 lines
8.2 KiB
C
/******************************************************
|
|
Mini-transaction buffer
|
|
|
|
(c) 1995 Innobase Oy
|
|
|
|
Created 11/26/1995 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#include "mtr0mtr.h"
|
|
|
|
#ifdef UNIV_NONINL
|
|
#include "mtr0mtr.ic"
|
|
#endif
|
|
|
|
#include "buf0buf.h"
|
|
#include "page0types.h"
|
|
#include "mtr0log.h"
|
|
#include "log0log.h"
|
|
|
|
/*******************************************************************
|
|
Starts a mini-transaction and creates a mini-transaction handle
|
|
and buffer in the memory buffer given by the caller. */
|
|
|
|
mtr_t*
|
|
mtr_start_noninline(
|
|
/*================*/
|
|
/* out: mtr buffer which also acts as
|
|
the mtr handle */
|
|
mtr_t* mtr) /* in: memory buffer for the mtr buffer */
|
|
{
|
|
return(mtr_start(mtr));
|
|
}
|
|
|
|
/*********************************************************************
|
|
Releases the item in the slot given. */
|
|
UNIV_INLINE
|
|
void
|
|
mtr_memo_slot_release(
|
|
/*==================*/
|
|
mtr_t* mtr, /* in: mtr */
|
|
mtr_memo_slot_t* slot) /* in: memo slot */
|
|
{
|
|
void* object;
|
|
ulint type;
|
|
|
|
ut_ad(mtr && slot);
|
|
|
|
object = slot->object;
|
|
type = slot->type;
|
|
|
|
if (UNIV_LIKELY(object != NULL)) {
|
|
if (type <= MTR_MEMO_BUF_FIX) {
|
|
buf_page_release((buf_block_t*)object, type, mtr);
|
|
} else if (type == MTR_MEMO_S_LOCK) {
|
|
rw_lock_s_unlock((rw_lock_t*)object);
|
|
#ifdef UNIV_DEBUG
|
|
} else if (type == MTR_MEMO_X_LOCK) {
|
|
rw_lock_x_unlock((rw_lock_t*)object);
|
|
} else {
|
|
ut_ad(type == MTR_MEMO_MODIFY);
|
|
ut_ad(mtr_memo_contains(mtr, object,
|
|
MTR_MEMO_PAGE_X_FIX));
|
|
#else
|
|
} else {
|
|
rw_lock_x_unlock((rw_lock_t*)object);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
slot->object = NULL;
|
|
}
|
|
|
|
/**************************************************************
|
|
Releases the mlocks and other objects stored in an mtr memo. They are released
|
|
in the order opposite to which they were pushed to the memo. NOTE! It is
|
|
essential that the x-rw-lock on a modified buffer page is not released before
|
|
buf_page_note_modification is called for that page! Otherwise, some thread
|
|
might race to modify it, and the flush list sort order on lsn would be
|
|
destroyed. */
|
|
UNIV_INLINE
|
|
void
|
|
mtr_memo_pop_all(
|
|
/*=============*/
|
|
mtr_t* mtr) /* in: mtr */
|
|
{
|
|
mtr_memo_slot_t* slot;
|
|
dyn_array_t* memo;
|
|
ulint offset;
|
|
|
|
ut_ad(mtr);
|
|
ut_ad(mtr->magic_n == MTR_MAGIC_N);
|
|
ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in
|
|
commit */
|
|
memo = &(mtr->memo);
|
|
|
|
offset = dyn_array_get_data_size(memo);
|
|
|
|
while (offset > 0) {
|
|
offset -= sizeof(mtr_memo_slot_t);
|
|
slot = dyn_array_get_element(memo, offset);
|
|
|
|
mtr_memo_slot_release(mtr, slot);
|
|
}
|
|
}
|
|
|
|
/****************************************************************
|
|
Writes the contents of a mini-transaction log, if any, to the database log. */
|
|
static
|
|
void
|
|
mtr_log_reserve_and_write(
|
|
/*======================*/
|
|
mtr_t* mtr) /* in: mtr */
|
|
{
|
|
dyn_array_t* mlog;
|
|
dyn_block_t* block;
|
|
ulint data_size;
|
|
ibool success;
|
|
byte* first_data;
|
|
|
|
ut_ad(mtr);
|
|
|
|
mlog = &(mtr->log);
|
|
|
|
first_data = dyn_block_get_data(mlog);
|
|
|
|
if (mtr->n_log_recs > 1) {
|
|
mlog_catenate_ulint(mtr, MLOG_MULTI_REC_END, MLOG_1BYTE);
|
|
} else {
|
|
*first_data = (byte)((ulint)*first_data | MLOG_SINGLE_REC_FLAG);
|
|
}
|
|
|
|
if (mlog->heap == NULL) {
|
|
mtr->end_lsn = log_reserve_and_write_fast(first_data,
|
|
dyn_block_get_used(mlog),
|
|
&(mtr->start_lsn), &success);
|
|
if (success) {
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
data_size = dyn_array_get_data_size(mlog);
|
|
|
|
/* Open the database log for log_write_low */
|
|
mtr->start_lsn = log_reserve_and_open(data_size);
|
|
|
|
if (mtr->log_mode == MTR_LOG_ALL) {
|
|
|
|
block = mlog;
|
|
|
|
while (block != NULL) {
|
|
log_write_low(dyn_block_get_data(block),
|
|
dyn_block_get_used(block));
|
|
block = dyn_array_get_next_block(mlog, block);
|
|
}
|
|
} else {
|
|
ut_ad(mtr->log_mode == MTR_LOG_NONE);
|
|
/* Do nothing */
|
|
}
|
|
|
|
mtr->end_lsn = log_close();
|
|
}
|
|
|
|
/*******************************************************************
|
|
Commits a mini-transaction. */
|
|
|
|
void
|
|
mtr_commit(
|
|
/*=======*/
|
|
mtr_t* mtr) /* in: mini-transaction */
|
|
{
|
|
ut_ad(mtr);
|
|
ut_ad(mtr->magic_n == MTR_MAGIC_N);
|
|
ut_ad(mtr->state == MTR_ACTIVE);
|
|
#ifdef UNIV_DEBUG
|
|
mtr->state = MTR_COMMITTING;
|
|
#endif
|
|
if (mtr->modifications) {
|
|
mtr_log_reserve_and_write(mtr);
|
|
}
|
|
|
|
/* We first update the modification info to buffer pages, and only
|
|
after that release the log mutex: this guarantees that when the log
|
|
mutex is free, all buffer pages contain an up-to-date info of their
|
|
modifications. This fact is used in making a checkpoint when we look
|
|
at the oldest modification of any page in the buffer pool. It is also
|
|
required when we insert modified buffer pages in to the flush list
|
|
which must be sorted on oldest_modification. */
|
|
|
|
mtr_memo_pop_all(mtr);
|
|
|
|
if (mtr->modifications) {
|
|
log_release();
|
|
}
|
|
|
|
#ifdef UNIV_DEBUG
|
|
mtr->state = MTR_COMMITTED;
|
|
#endif
|
|
dyn_array_free(&(mtr->memo));
|
|
dyn_array_free(&(mtr->log));
|
|
}
|
|
|
|
/**************************************************************
|
|
Releases the latches stored in an mtr memo down to a savepoint.
|
|
NOTE! The mtr must not have made changes to buffer pages after the
|
|
savepoint, as these can be handled only by mtr_commit. */
|
|
|
|
void
|
|
mtr_rollback_to_savepoint(
|
|
/*======================*/
|
|
mtr_t* mtr, /* in: mtr */
|
|
ulint savepoint) /* in: savepoint */
|
|
{
|
|
mtr_memo_slot_t* slot;
|
|
dyn_array_t* memo;
|
|
ulint offset;
|
|
|
|
ut_ad(mtr);
|
|
ut_ad(mtr->magic_n == MTR_MAGIC_N);
|
|
ut_ad(mtr->state == MTR_ACTIVE);
|
|
|
|
memo = &(mtr->memo);
|
|
|
|
offset = dyn_array_get_data_size(memo);
|
|
ut_ad(offset >= savepoint);
|
|
|
|
while (offset > savepoint) {
|
|
offset -= sizeof(mtr_memo_slot_t);
|
|
|
|
slot = dyn_array_get_element(memo, offset);
|
|
|
|
ut_ad(slot->type != MTR_MEMO_MODIFY);
|
|
mtr_memo_slot_release(mtr, slot);
|
|
}
|
|
}
|
|
|
|
/*******************************************************
|
|
Releases an object in the memo stack. */
|
|
|
|
void
|
|
mtr_memo_release(
|
|
/*=============*/
|
|
mtr_t* mtr, /* in: mtr */
|
|
void* object, /* in: object */
|
|
ulint type) /* in: object type: MTR_MEMO_S_LOCK, ... */
|
|
{
|
|
mtr_memo_slot_t* slot;
|
|
dyn_array_t* memo;
|
|
ulint offset;
|
|
|
|
ut_ad(mtr);
|
|
ut_ad(mtr->magic_n == MTR_MAGIC_N);
|
|
ut_ad(mtr->state == MTR_ACTIVE);
|
|
|
|
memo = &(mtr->memo);
|
|
|
|
offset = dyn_array_get_data_size(memo);
|
|
|
|
while (offset > 0) {
|
|
offset -= sizeof(mtr_memo_slot_t);
|
|
|
|
slot = dyn_array_get_element(memo, offset);
|
|
|
|
if ((object == slot->object) && (type == slot->type)) {
|
|
|
|
mtr_memo_slot_release(mtr, slot);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************************************************
|
|
Reads 1 - 4 bytes from a file page buffered in the buffer pool. */
|
|
|
|
ulint
|
|
mtr_read_ulint(
|
|
/*===========*/
|
|
/* out: value read */
|
|
byte* ptr, /* in: pointer from where to read */
|
|
ulint type, /* in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */
|
|
mtr_t* mtr __attribute__((unused)))
|
|
/* in: mini-transaction handle */
|
|
{
|
|
ut_ad(mtr->state == MTR_ACTIVE);
|
|
ut_ad(mtr_memo_contains(mtr, buf_block_align(ptr),
|
|
MTR_MEMO_PAGE_S_FIX) ||
|
|
mtr_memo_contains(mtr, buf_block_align(ptr),
|
|
MTR_MEMO_PAGE_X_FIX));
|
|
if (type == MLOG_1BYTE) {
|
|
return(mach_read_from_1(ptr));
|
|
} else if (type == MLOG_2BYTES) {
|
|
return(mach_read_from_2(ptr));
|
|
} else {
|
|
ut_ad(type == MLOG_4BYTES);
|
|
return(mach_read_from_4(ptr));
|
|
}
|
|
}
|
|
|
|
/************************************************************
|
|
Reads 8 bytes from a file page buffered in the buffer pool. */
|
|
|
|
dulint
|
|
mtr_read_dulint(
|
|
/*===========*/
|
|
/* out: value read */
|
|
byte* ptr, /* in: pointer from where to read */
|
|
mtr_t* mtr __attribute__((unused)))
|
|
/* in: mini-transaction handle */
|
|
{
|
|
ut_ad(mtr->state == MTR_ACTIVE);
|
|
ut_ad(ptr && mtr);
|
|
ut_ad(mtr_memo_contains(mtr, buf_block_align(ptr),
|
|
MTR_MEMO_PAGE_S_FIX) ||
|
|
mtr_memo_contains(mtr, buf_block_align(ptr),
|
|
MTR_MEMO_PAGE_X_FIX));
|
|
return(mach_read_from_8(ptr));
|
|
}
|
|
|
|
/*************************************************************
|
|
Prints info of an mtr handle. */
|
|
|
|
void
|
|
mtr_print(
|
|
/*======*/
|
|
mtr_t* mtr) /* in: mtr */
|
|
{
|
|
fprintf(stderr,
|
|
"Mini-transaction handle: memo size %lu bytes log "
|
|
"size %lu bytes\n"
|
|
"state: %lu modifications: %lu n_lock_recs %lu\n"
|
|
"log_mode: %lu start_lsn: %lu:%lu end_lsn: %lu:%lu\n",
|
|
(ulong) dyn_array_get_data_size(&(mtr->memo)),
|
|
(ulong) dyn_array_get_data_size(&(mtr->log)),
|
|
mtr->state, (ulint) mtr->modifications,
|
|
mtr->n_log_recs, mtr->log_mode,
|
|
ut_dulint_get_high(mtr->start_lsn),
|
|
ut_dulint_get_low(mtr->start_lsn),
|
|
ut_dulint_get_high(mtr->end_lsn),
|
|
ut_dulint_get_low(mtr->end_lsn));
|
|
}
|