mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 21:42:35 +01:00
baddc4e91c
innodb-5.1-ss1318 innodb-5.1-ss1330 innodb-5.1-ss1332 innodb-5.1-ss1340 Fixes: - Bug #21409: Incorrect result returned when in READ-COMMITTED with query_cache ON At low transaction isolation levels we let each consistent read set its own snapshot. - Bug #23666: strange Innodb_row_lock_time_% values in show status; also millisecs wrong On Windows ut_usectime returns secs and usecs relative to the UNIX epoch (which is Jan, 1 1970). - Bug #25494: LATEST DEADLOCK INFORMATION is not always cleared lock_deadlock_recursive(): When the search depth or length is exceeded, rewind lock_latest_err_file and display the two transactions at the point of aborting the search. - Bug #25927: Foreign key with ON DELETE SET NULL on NOT NULL can crash server Prevent ALTER TABLE ... MODIFY ... NOT NULL on columns for which there is a foreign key constraint ON ... SET NULL. - Bug #26835: Repeatable corruption of utf8-enabled tables inside InnoDB The bug could be reproduced as follows: Define a table so that the first column of the clustered index is a VARCHAR or a UTF-8 CHAR in a collation where sequences of bytes of differing length are considered equivalent. Insert and delete a record. Before the delete-marked record is purged, insert another record whose first column is of different length but equivalent to the first record. Under certain conditions, the insertion can be incorrectly performed as update-in-place. Likewise, an operation that could be done as update-in-place can unnecessarily be performed as delete and insert, but that would not cause corruption but merely degraded performance.
106 lines
3.1 KiB
Text
106 lines
3.1 KiB
Text
/******************************************************
|
|
The database buffer pool flush algorithm
|
|
|
|
(c) 1995 Innobase Oy
|
|
|
|
Created 11/5/1995 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#include "buf0buf.h"
|
|
#include "mtr0mtr.h"
|
|
|
|
/************************************************************************
|
|
Inserts a modified block into the flush list. */
|
|
|
|
void
|
|
buf_flush_insert_into_flush_list(
|
|
/*=============================*/
|
|
buf_block_t* block); /* in: block which is modified */
|
|
/************************************************************************
|
|
Inserts a modified block into the flush list in the right sorted position.
|
|
This function is used by recovery, because there the modifications do not
|
|
necessarily come in the order of lsn's. */
|
|
|
|
void
|
|
buf_flush_insert_sorted_into_flush_list(
|
|
/*====================================*/
|
|
buf_block_t* block); /* in: block which is modified */
|
|
|
|
/************************************************************************
|
|
This function should be called at a mini-transaction commit, if a page was
|
|
modified in it. Puts the block to the list of modified blocks, if it is not
|
|
already in it. */
|
|
UNIV_INLINE
|
|
void
|
|
buf_flush_note_modification(
|
|
/*========================*/
|
|
buf_block_t* block, /* in: block which is modified */
|
|
mtr_t* mtr) /* in: mtr */
|
|
{
|
|
ut_ad(block);
|
|
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
|
|
ut_ad(block->buf_fix_count > 0);
|
|
#ifdef UNIV_SYNC_DEBUG
|
|
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
|
|
#endif /* UNIV_SYNC_DEBUG */
|
|
ut_ad(mutex_own(&(buf_pool->mutex)));
|
|
|
|
ut_ad(ut_dulint_cmp(mtr->start_lsn, ut_dulint_zero) != 0);
|
|
ut_ad(mtr->modifications);
|
|
ut_ad(ut_dulint_cmp(block->newest_modification, mtr->end_lsn) <= 0);
|
|
|
|
block->newest_modification = mtr->end_lsn;
|
|
|
|
if (ut_dulint_is_zero(block->oldest_modification)) {
|
|
|
|
block->oldest_modification = mtr->start_lsn;
|
|
ut_ad(!ut_dulint_is_zero(block->oldest_modification));
|
|
|
|
buf_flush_insert_into_flush_list(block);
|
|
} else {
|
|
ut_ad(ut_dulint_cmp(block->oldest_modification,
|
|
mtr->start_lsn) <= 0);
|
|
}
|
|
|
|
++srv_buf_pool_write_requests;
|
|
}
|
|
|
|
/************************************************************************
|
|
This function should be called when recovery has modified a buffer page. */
|
|
UNIV_INLINE
|
|
void
|
|
buf_flush_recv_note_modification(
|
|
/*=============================*/
|
|
buf_block_t* block, /* in: block which is modified */
|
|
dulint start_lsn, /* in: start lsn of the first mtr in a
|
|
set of mtr's */
|
|
dulint end_lsn) /* in: end lsn of the last mtr in the
|
|
set of mtr's */
|
|
{
|
|
ut_ad(block);
|
|
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
|
|
ut_ad(block->buf_fix_count > 0);
|
|
#ifdef UNIV_SYNC_DEBUG
|
|
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
|
|
#endif /* UNIV_SYNC_DEBUG */
|
|
|
|
mutex_enter(&(buf_pool->mutex));
|
|
|
|
ut_ad(ut_dulint_cmp(block->newest_modification, end_lsn) <= 0);
|
|
|
|
block->newest_modification = end_lsn;
|
|
|
|
if (ut_dulint_is_zero(block->oldest_modification)) {
|
|
|
|
block->oldest_modification = start_lsn;
|
|
|
|
ut_ad(!ut_dulint_is_zero(block->oldest_modification));
|
|
|
|
buf_flush_insert_sorted_into_flush_list(block);
|
|
} else {
|
|
ut_ad(ut_dulint_cmp(block->oldest_modification,
|
|
start_lsn) <= 0);
|
|
}
|
|
|
|
mutex_exit(&(buf_pool->mutex));
|
|
}
|