2001-02-17 13:19:19 +01:00
|
|
|
/******************************************************
|
|
|
|
Transaction system
|
|
|
|
|
|
|
|
(c) 1996 Innobase Oy
|
|
|
|
|
|
|
|
Created 3/26/1996 Heikki Tuuri
|
|
|
|
*******************************************************/
|
|
|
|
|
|
|
|
#include "trx0sys.h"
|
|
|
|
|
|
|
|
#ifdef UNIV_NONINL
|
|
|
|
#include "trx0sys.ic"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "fsp0fsp.h"
|
|
|
|
#include "mtr0mtr.h"
|
|
|
|
#include "trx0trx.h"
|
|
|
|
#include "trx0rseg.h"
|
|
|
|
#include "trx0undo.h"
|
|
|
|
#include "srv0srv.h"
|
|
|
|
#include "trx0purge.h"
|
srv0srv.h Support raw disk partitions as data files
srv0start.c Support raw disk partitions as data files
srv0srv.c Support raw disk partitions as data files
row0purge.c < 4 GB rows, doublewrite, hang fixes
row0row.c < 4 GB rows, doublewrite, hang fixes
row0sel.c < 4 GB rows, doublewrite, hang fixes
row0uins.c < 4 GB rows, doublewrite, hang fixes
row0umod.c < 4 GB rows, doublewrite, hang fixes
row0undo.c < 4 GB rows, doublewrite, hang fixes
row0upd.c < 4 GB rows, doublewrite, hang fixes
srv0srv.c < 4 GB rows, doublewrite, hang fixes
srv0start.c < 4 GB rows, doublewrite, hang fixes
sync0rw.c < 4 GB rows, doublewrite, hang fixes
sync0sync.c < 4 GB rows, doublewrite, hang fixes
trx0purge.c < 4 GB rows, doublewrite, hang fixes
trx0rec.c < 4 GB rows, doublewrite, hang fixes
trx0sys.c < 4 GB rows, doublewrite, hang fixes
btr0btr.c < 4 GB rows, doublewrite, hang fixes
btr0cur.c < 4 GB rows, doublewrite, hang fixes
buf0buf.c < 4 GB rows, doublewrite, hang fixes
buf0flu.c < 4 GB rows, doublewrite, hang fixes
buf0rea.c < 4 GB rows, doublewrite, hang fixes
data0data.c < 4 GB rows, doublewrite, hang fixes
fil0fil.c < 4 GB rows, doublewrite, hang fixes
fsp0fsp.c < 4 GB rows, doublewrite, hang fixes
ibuf0ibuf.c < 4 GB rows, doublewrite, hang fixes
lock0lock.c < 4 GB rows, doublewrite, hang fixes
log0log.c < 4 GB rows, doublewrite, hang fixes
log0recv.c < 4 GB rows, doublewrite, hang fixes
os0file.c < 4 GB rows, doublewrite, hang fixes
page0cur.c < 4 GB rows, doublewrite, hang fixes
pars0pars.c < 4 GB rows, doublewrite, hang fixes
rem0cmp.c < 4 GB rows, doublewrite, hang fixes
rem0rec.c < 4 GB rows, doublewrite, hang fixes
row0ins.c < 4 GB rows, doublewrite, hang fixes
row0mysql.c < 4 GB rows, doublewrite, hang fixes
univ.i < 4 GB rows, doublewrite, hang fixes
data0data.ic < 4 GB rows, doublewrite, hang fixes
mach0data.ic < 4 GB rows, doublewrite, hang fixes
rem0rec.ic < 4 GB rows, doublewrite, hang fixes
row0upd.ic < 4 GB rows, doublewrite, hang fixes
trx0rec.ic < 4 GB rows, doublewrite, hang fixes
rem0cmp.h < 4 GB rows, doublewrite, hang fixes
rem0rec.h < 4 GB rows, doublewrite, hang fixes
row0ins.h < 4 GB rows, doublewrite, hang fixes
row0mysql.h < 4 GB rows, doublewrite, hang fixes
row0row.h < 4 GB rows, doublewrite, hang fixes
row0upd.h < 4 GB rows, doublewrite, hang fixes
srv0srv.h < 4 GB rows, doublewrite, hang fixes
sync0sync.h < 4 GB rows, doublewrite, hang fixes
trx0rec.h < 4 GB rows, doublewrite, hang fixes
trx0sys.h < 4 GB rows, doublewrite, hang fixes
trx0types.h < 4 GB rows, doublewrite, hang fixes
trx0undo.h < 4 GB rows, doublewrite, hang fixes
ut0dbg.h < 4 GB rows, doublewrite, hang fixes
ut0ut.h < 4 GB rows, doublewrite, hang fixes
btr0btr.h < 4 GB rows, doublewrite, hang fixes
btr0cur.h < 4 GB rows, doublewrite, hang fixes
buf0buf.h < 4 GB rows, doublewrite, hang fixes
buf0flu.h < 4 GB rows, doublewrite, hang fixes
data0data.h < 4 GB rows, doublewrite, hang fixes
dict0mem.h < 4 GB rows, doublewrite, hang fixes
fil0fil.h < 4 GB rows, doublewrite, hang fixes
fsp0fsp.h < 4 GB rows, doublewrite, hang fixes
os0file.h < 4 GB rows, doublewrite, hang fixes
2001-08-04 18:36:14 +02:00
|
|
|
#include "log0log.h"
|
2001-02-17 13:19:19 +01:00
|
|
|
|
|
|
|
/* The transaction system */
|
srv0srv.h Support raw disk partitions as data files
srv0start.c Support raw disk partitions as data files
srv0srv.c Support raw disk partitions as data files
row0purge.c < 4 GB rows, doublewrite, hang fixes
row0row.c < 4 GB rows, doublewrite, hang fixes
row0sel.c < 4 GB rows, doublewrite, hang fixes
row0uins.c < 4 GB rows, doublewrite, hang fixes
row0umod.c < 4 GB rows, doublewrite, hang fixes
row0undo.c < 4 GB rows, doublewrite, hang fixes
row0upd.c < 4 GB rows, doublewrite, hang fixes
srv0srv.c < 4 GB rows, doublewrite, hang fixes
srv0start.c < 4 GB rows, doublewrite, hang fixes
sync0rw.c < 4 GB rows, doublewrite, hang fixes
sync0sync.c < 4 GB rows, doublewrite, hang fixes
trx0purge.c < 4 GB rows, doublewrite, hang fixes
trx0rec.c < 4 GB rows, doublewrite, hang fixes
trx0sys.c < 4 GB rows, doublewrite, hang fixes
btr0btr.c < 4 GB rows, doublewrite, hang fixes
btr0cur.c < 4 GB rows, doublewrite, hang fixes
buf0buf.c < 4 GB rows, doublewrite, hang fixes
buf0flu.c < 4 GB rows, doublewrite, hang fixes
buf0rea.c < 4 GB rows, doublewrite, hang fixes
data0data.c < 4 GB rows, doublewrite, hang fixes
fil0fil.c < 4 GB rows, doublewrite, hang fixes
fsp0fsp.c < 4 GB rows, doublewrite, hang fixes
ibuf0ibuf.c < 4 GB rows, doublewrite, hang fixes
lock0lock.c < 4 GB rows, doublewrite, hang fixes
log0log.c < 4 GB rows, doublewrite, hang fixes
log0recv.c < 4 GB rows, doublewrite, hang fixes
os0file.c < 4 GB rows, doublewrite, hang fixes
page0cur.c < 4 GB rows, doublewrite, hang fixes
pars0pars.c < 4 GB rows, doublewrite, hang fixes
rem0cmp.c < 4 GB rows, doublewrite, hang fixes
rem0rec.c < 4 GB rows, doublewrite, hang fixes
row0ins.c < 4 GB rows, doublewrite, hang fixes
row0mysql.c < 4 GB rows, doublewrite, hang fixes
univ.i < 4 GB rows, doublewrite, hang fixes
data0data.ic < 4 GB rows, doublewrite, hang fixes
mach0data.ic < 4 GB rows, doublewrite, hang fixes
rem0rec.ic < 4 GB rows, doublewrite, hang fixes
row0upd.ic < 4 GB rows, doublewrite, hang fixes
trx0rec.ic < 4 GB rows, doublewrite, hang fixes
rem0cmp.h < 4 GB rows, doublewrite, hang fixes
rem0rec.h < 4 GB rows, doublewrite, hang fixes
row0ins.h < 4 GB rows, doublewrite, hang fixes
row0mysql.h < 4 GB rows, doublewrite, hang fixes
row0row.h < 4 GB rows, doublewrite, hang fixes
row0upd.h < 4 GB rows, doublewrite, hang fixes
srv0srv.h < 4 GB rows, doublewrite, hang fixes
sync0sync.h < 4 GB rows, doublewrite, hang fixes
trx0rec.h < 4 GB rows, doublewrite, hang fixes
trx0sys.h < 4 GB rows, doublewrite, hang fixes
trx0types.h < 4 GB rows, doublewrite, hang fixes
trx0undo.h < 4 GB rows, doublewrite, hang fixes
ut0dbg.h < 4 GB rows, doublewrite, hang fixes
ut0ut.h < 4 GB rows, doublewrite, hang fixes
btr0btr.h < 4 GB rows, doublewrite, hang fixes
btr0cur.h < 4 GB rows, doublewrite, hang fixes
buf0buf.h < 4 GB rows, doublewrite, hang fixes
buf0flu.h < 4 GB rows, doublewrite, hang fixes
data0data.h < 4 GB rows, doublewrite, hang fixes
dict0mem.h < 4 GB rows, doublewrite, hang fixes
fil0fil.h < 4 GB rows, doublewrite, hang fixes
fsp0fsp.h < 4 GB rows, doublewrite, hang fixes
os0file.h < 4 GB rows, doublewrite, hang fixes
2001-08-04 18:36:14 +02:00
|
|
|
trx_sys_t* trx_sys = NULL;
|
|
|
|
trx_doublewrite_t* trx_doublewrite = NULL;
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
Creates or initialializes the doublewrite buffer at a database start. */
|
|
|
|
static
|
|
|
|
void
|
|
|
|
trx_doublewrite_init(
|
|
|
|
/*=================*/
|
|
|
|
byte* doublewrite) /* in: pointer to the doublewrite buf
|
|
|
|
header on trx sys page */
|
|
|
|
{
|
|
|
|
trx_doublewrite = mem_alloc(sizeof(trx_doublewrite_t));
|
|
|
|
|
|
|
|
mutex_create(&(trx_doublewrite->mutex));
|
|
|
|
mutex_set_level(&(trx_doublewrite->mutex), SYNC_DOUBLEWRITE);
|
|
|
|
|
|
|
|
trx_doublewrite->first_free = 0;
|
|
|
|
|
|
|
|
trx_doublewrite->block1 = mach_read_from_4(
|
|
|
|
doublewrite
|
|
|
|
+ TRX_SYS_DOUBLEWRITE_BLOCK1);
|
|
|
|
trx_doublewrite->block2 = mach_read_from_4(
|
|
|
|
doublewrite
|
|
|
|
+ TRX_SYS_DOUBLEWRITE_BLOCK2);
|
|
|
|
trx_doublewrite->write_buf_unaligned =
|
|
|
|
ut_malloc(
|
|
|
|
(1 + 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE)
|
|
|
|
* UNIV_PAGE_SIZE);
|
|
|
|
|
|
|
|
trx_doublewrite->write_buf = ut_align(
|
|
|
|
trx_doublewrite->write_buf_unaligned,
|
|
|
|
UNIV_PAGE_SIZE);
|
|
|
|
trx_doublewrite->buf_block_arr = mem_alloc(
|
|
|
|
2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
|
|
|
|
* sizeof(void*));
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
Creates the doublewrite buffer at a database start. The header of the
|
|
|
|
doublewrite buffer is placed on the trx system header page. */
|
|
|
|
|
|
|
|
void
|
|
|
|
trx_sys_create_doublewrite_buf(void)
|
|
|
|
/*================================*/
|
|
|
|
{
|
|
|
|
page_t* page;
|
|
|
|
page_t* page2;
|
|
|
|
page_t* new_page;
|
|
|
|
byte* doublewrite;
|
|
|
|
byte* fseg_header;
|
|
|
|
ulint page_no;
|
|
|
|
ulint prev_page_no;
|
|
|
|
ulint i;
|
|
|
|
mtr_t mtr;
|
|
|
|
|
|
|
|
if (trx_doublewrite) {
|
|
|
|
/* Already inited */
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
start_again:
|
|
|
|
mtr_start(&mtr);
|
|
|
|
|
|
|
|
page = buf_page_get(TRX_SYS_SPACE, TRX_SYS_PAGE_NO, RW_X_LATCH, &mtr);
|
|
|
|
buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK);
|
|
|
|
|
|
|
|
doublewrite = page + TRX_SYS_DOUBLEWRITE;
|
|
|
|
|
|
|
|
if (mach_read_from_4(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC)
|
|
|
|
== TRX_SYS_DOUBLEWRITE_MAGIC_N) {
|
|
|
|
|
|
|
|
/* The doublewrite buffer has already been created:
|
|
|
|
just read in some numbers */
|
|
|
|
|
|
|
|
trx_doublewrite_init(doublewrite);
|
|
|
|
|
|
|
|
mtr_commit(&mtr);
|
|
|
|
} else {
|
|
|
|
fprintf(stderr,
|
|
|
|
"InnoDB: Doublewrite buffer not found: creating new\n");
|
|
|
|
|
|
|
|
if (buf_pool_get_curr_size() <
|
|
|
|
(2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
|
|
|
|
+ FSP_EXTENT_SIZE / 2 + 100)
|
|
|
|
* UNIV_PAGE_SIZE) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"InnoDB: Cannot create doublewrite buffer: you must\n"
|
|
|
|
"InnoDB: increase your buffer pool size.\n"
|
|
|
|
"InnoDB: Cannot continue operation.\n");
|
|
|
|
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
page2 = fseg_create(TRX_SYS_SPACE, TRX_SYS_PAGE_NO,
|
|
|
|
TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_FSEG, &mtr);
|
|
|
|
|
|
|
|
/* fseg_create acquires a second latch on the page,
|
|
|
|
therefore we must declare it: */
|
|
|
|
|
|
|
|
buf_page_dbg_add_level(page2, SYNC_NO_ORDER_CHECK);
|
|
|
|
|
|
|
|
if (page2 == NULL) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"InnoDB: Cannot create doublewrite buffer: you must\n"
|
|
|
|
"InnoDB: increase your tablespace size.\n"
|
|
|
|
"InnoDB: Cannot continue operation.\n");
|
|
|
|
|
|
|
|
/* We exit without committing the mtr to prevent
|
|
|
|
its modifications to the database getting to disk */
|
|
|
|
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
fseg_header = page + TRX_SYS_DOUBLEWRITE
|
|
|
|
+ TRX_SYS_DOUBLEWRITE_FSEG;
|
|
|
|
prev_page_no = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
|
|
|
|
+ FSP_EXTENT_SIZE / 2; i++) {
|
|
|
|
page_no = fseg_alloc_free_page(fseg_header,
|
|
|
|
prev_page_no + 1,
|
|
|
|
FSP_UP, &mtr);
|
|
|
|
if (page_no == FIL_NULL) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"InnoDB: Cannot create doublewrite buffer: you must\n"
|
|
|
|
"InnoDB: increase your tablespace size.\n"
|
|
|
|
"InnoDB: Cannot continue operation.\n");
|
|
|
|
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We read the allocated pages to the buffer pool;
|
|
|
|
when they are written to disk in a flush, the space
|
|
|
|
id and page number fields are also written to the
|
|
|
|
pages. When we at database startup read pages
|
|
|
|
from the doublewrite buffer, we know that if the
|
|
|
|
space id and page number in them are the same as
|
|
|
|
the page position in the tablespace, then the page
|
|
|
|
has not been written to in doublewrite. */
|
|
|
|
|
|
|
|
new_page = buf_page_get(TRX_SYS_SPACE, page_no,
|
|
|
|
RW_X_LATCH, &mtr);
|
|
|
|
buf_page_dbg_add_level(new_page, SYNC_NO_ORDER_CHECK);
|
|
|
|
|
|
|
|
/* Make a dummy change to the page to ensure it will
|
|
|
|
be written to disk in a flush */
|
|
|
|
|
|
|
|
mlog_write_ulint(new_page + FIL_PAGE_DATA,
|
|
|
|
TRX_SYS_DOUBLEWRITE_MAGIC_N,
|
|
|
|
MLOG_4BYTES, &mtr);
|
|
|
|
|
|
|
|
if (i == FSP_EXTENT_SIZE / 2) {
|
|
|
|
mlog_write_ulint(doublewrite
|
|
|
|
+ TRX_SYS_DOUBLEWRITE_BLOCK1,
|
|
|
|
page_no, MLOG_4BYTES, &mtr);
|
|
|
|
mlog_write_ulint(doublewrite
|
|
|
|
+ TRX_SYS_DOUBLEWRITE_REPEAT
|
|
|
|
+ TRX_SYS_DOUBLEWRITE_BLOCK1,
|
|
|
|
page_no, MLOG_4BYTES, &mtr);
|
|
|
|
} else if (i == FSP_EXTENT_SIZE / 2
|
|
|
|
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
|
|
|
|
mlog_write_ulint(doublewrite
|
|
|
|
+ TRX_SYS_DOUBLEWRITE_BLOCK2,
|
|
|
|
page_no, MLOG_4BYTES, &mtr);
|
|
|
|
mlog_write_ulint(doublewrite
|
|
|
|
+ TRX_SYS_DOUBLEWRITE_REPEAT
|
|
|
|
+ TRX_SYS_DOUBLEWRITE_BLOCK2,
|
|
|
|
page_no, MLOG_4BYTES, &mtr);
|
|
|
|
} else if (i > FSP_EXTENT_SIZE / 2) {
|
|
|
|
ut_a(page_no == prev_page_no + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
prev_page_no = page_no;
|
|
|
|
}
|
|
|
|
|
|
|
|
mlog_write_ulint(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC,
|
|
|
|
TRX_SYS_DOUBLEWRITE_MAGIC_N, MLOG_4BYTES, &mtr);
|
|
|
|
mlog_write_ulint(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC
|
|
|
|
+ TRX_SYS_DOUBLEWRITE_REPEAT,
|
|
|
|
TRX_SYS_DOUBLEWRITE_MAGIC_N, MLOG_4BYTES, &mtr);
|
|
|
|
mtr_commit(&mtr);
|
|
|
|
|
|
|
|
/* Flush the modified pages to disk and make a checkpoint */
|
|
|
|
log_make_checkpoint_at(ut_dulint_max, TRUE);
|
|
|
|
|
|
|
|
fprintf(stderr, "InnoDB: Doublewrite buffer created\n");
|
|
|
|
|
|
|
|
goto start_again;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
At a database startup uses a possible doublewrite buffer to restore
|
|
|
|
half-written pages in the data files. */
|
|
|
|
|
|
|
|
void
|
|
|
|
trx_sys_doublewrite_restore_corrupt_pages(void)
|
|
|
|
/*===========================================*/
|
|
|
|
{
|
|
|
|
byte* buf;
|
|
|
|
byte* read_buf;
|
|
|
|
byte* unaligned_read_buf;
|
|
|
|
ulint block1;
|
|
|
|
ulint block2;
|
|
|
|
byte* page;
|
|
|
|
byte* doublewrite;
|
|
|
|
ulint space_id;
|
|
|
|
ulint page_no;
|
|
|
|
ulint i;
|
|
|
|
|
|
|
|
/* We do the file i/o past the buffer pool */
|
|
|
|
|
|
|
|
unaligned_read_buf = ut_malloc(2 * UNIV_PAGE_SIZE);
|
|
|
|
read_buf = ut_align(unaligned_read_buf, UNIV_PAGE_SIZE);
|
|
|
|
|
|
|
|
/* Read the trx sys header to check if we are using the
|
|
|
|
doublewrite buffer */
|
|
|
|
|
|
|
|
fil_io(OS_FILE_READ, TRUE, TRX_SYS_SPACE, TRX_SYS_PAGE_NO, 0,
|
|
|
|
UNIV_PAGE_SIZE, read_buf, NULL);
|
|
|
|
|
|
|
|
doublewrite = read_buf + TRX_SYS_DOUBLEWRITE;
|
|
|
|
|
|
|
|
if (mach_read_from_4(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC)
|
|
|
|
== TRX_SYS_DOUBLEWRITE_MAGIC_N) {
|
|
|
|
/* The doublewrite buffer has been created */
|
|
|
|
|
|
|
|
trx_doublewrite_init(doublewrite);
|
|
|
|
|
|
|
|
block1 = trx_doublewrite->block1;
|
|
|
|
block2 = trx_doublewrite->block2;
|
|
|
|
|
|
|
|
buf = trx_doublewrite->write_buf;
|
|
|
|
} else {
|
|
|
|
goto leave_func;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read the pages from the doublewrite buffer to memory */
|
|
|
|
|
|
|
|
fil_io(OS_FILE_READ, TRUE, TRX_SYS_SPACE, block1, 0,
|
|
|
|
TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE,
|
|
|
|
buf, NULL);
|
|
|
|
fil_io(OS_FILE_READ, TRUE, TRX_SYS_SPACE, block2, 0,
|
|
|
|
TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE,
|
|
|
|
buf + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE,
|
|
|
|
NULL);
|
|
|
|
/* Check if any of these pages is half-written in data files, in the
|
|
|
|
intended position */
|
|
|
|
|
|
|
|
page = buf;
|
|
|
|
|
|
|
|
for (i = 0; i < TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 2; i++) {
|
|
|
|
|
|
|
|
space_id = mach_read_from_4(page + FIL_PAGE_SPACE);
|
|
|
|
page_no = mach_read_from_4(page + FIL_PAGE_OFFSET);
|
|
|
|
|
|
|
|
if (!fil_check_adress_in_tablespace(space_id, page_no)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"InnoDB: Warning: an inconsistent page in the doublewrite buffer\n"
|
|
|
|
"InnoDB: space id %lu page number %lu, %lu'th page in dblwr buf.\n",
|
|
|
|
space_id, page_no, i);
|
|
|
|
|
|
|
|
} else if (space_id == TRX_SYS_SPACE
|
|
|
|
&& ( (page_no >= block1
|
|
|
|
&& page_no
|
|
|
|
< block1 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE)
|
|
|
|
|| (page_no >= block2
|
|
|
|
&& page_no
|
|
|
|
< block2 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE))) {
|
|
|
|
|
|
|
|
/* It is an unwritten doublewrite buffer page:
|
|
|
|
do nothing */
|
|
|
|
|
|
|
|
} else {
|
|
|
|
/* Read in the actual page from the data files */
|
|
|
|
|
|
|
|
fil_io(OS_FILE_READ, TRUE, space_id, page_no, 0,
|
|
|
|
UNIV_PAGE_SIZE, read_buf, NULL);
|
|
|
|
/* Check if the page is corrupt */
|
|
|
|
|
|
|
|
if (buf_page_is_corrupted(read_buf)) {
|
|
|
|
|
|
|
|
fprintf(stderr,
|
|
|
|
"InnoDB: Warning: database page corruption or a failed\n"
|
|
|
|
"InnoDB: file read of page %lu.\n", page_no);
|
|
|
|
fprintf(stderr,
|
|
|
|
"InnoDB: Trying to recover it from the doublewrite buffer.\n");
|
|
|
|
|
|
|
|
if (buf_page_is_corrupted(page)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"InnoDB: Also the page in the doublewrite buffer is corrupt.\n"
|
|
|
|
"InnoDB: Cannot continue operation.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write the good page from the
|
|
|
|
doublewrite buffer to the intended
|
|
|
|
position */
|
|
|
|
|
|
|
|
fil_io(OS_FILE_WRITE, TRUE, space_id,
|
|
|
|
page_no, 0,
|
|
|
|
UNIV_PAGE_SIZE, page, NULL);
|
|
|
|
fprintf(stderr,
|
|
|
|
"InnoDB: Recovered the page from the doublewrite buffer.\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
page += UNIV_PAGE_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
fil_flush_file_spaces(FIL_TABLESPACE);
|
|
|
|
|
|
|
|
leave_func:
|
|
|
|
ut_free(unaligned_read_buf);
|
|
|
|
}
|
2001-02-17 13:19:19 +01:00
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
Checks that trx is in the trx list. */
|
|
|
|
|
|
|
|
ibool
|
|
|
|
trx_in_trx_list(
|
|
|
|
/*============*/
|
|
|
|
/* out: TRUE if is in */
|
|
|
|
trx_t* in_trx) /* in: trx */
|
|
|
|
{
|
|
|
|
trx_t* trx;
|
|
|
|
|
|
|
|
ut_ad(mutex_own(&(kernel_mutex)));
|
|
|
|
|
|
|
|
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
|
|
|
|
|
|
|
|
while (trx != NULL) {
|
|
|
|
|
|
|
|
if (trx == in_trx) {
|
|
|
|
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
trx = UT_LIST_GET_NEXT(trx_list, trx);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
Writes the value of max_trx_id to the file based trx system header. */
|
|
|
|
|
|
|
|
void
|
|
|
|
trx_sys_flush_max_trx_id(void)
|
|
|
|
/*==========================*/
|
|
|
|
{
|
|
|
|
trx_sysf_t* sys_header;
|
|
|
|
mtr_t mtr;
|
|
|
|
|
|
|
|
ut_ad(mutex_own(&kernel_mutex));
|
|
|
|
|
|
|
|
mtr_start(&mtr);
|
|
|
|
|
|
|
|
sys_header = trx_sysf_get(&mtr);
|
|
|
|
|
|
|
|
mlog_write_dulint(sys_header + TRX_SYS_TRX_ID_STORE,
|
|
|
|
trx_sys->max_trx_id, MLOG_8BYTES, &mtr);
|
|
|
|
mtr_commit(&mtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
Looks for a free slot for a rollback segment in the trx system file copy. */
|
|
|
|
|
|
|
|
ulint
|
|
|
|
trx_sysf_rseg_find_free(
|
|
|
|
/*====================*/
|
|
|
|
/* out: slot index or ULINT_UNDEFINED if not found */
|
|
|
|
mtr_t* mtr) /* in: mtr */
|
|
|
|
{
|
|
|
|
trx_sysf_t* sys_header;
|
|
|
|
ulint page_no;
|
|
|
|
ulint i;
|
|
|
|
|
|
|
|
ut_ad(mutex_own(&(kernel_mutex)));
|
|
|
|
|
|
|
|
sys_header = trx_sysf_get(mtr);
|
|
|
|
|
|
|
|
for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
|
|
|
|
|
|
|
|
page_no = trx_sysf_rseg_get_page_no(sys_header, i, mtr);
|
|
|
|
|
|
|
|
if (page_no == FIL_NULL) {
|
|
|
|
|
|
|
|
return(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return(ULINT_UNDEFINED);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
Creates the file page for the transaction system. This function is called only
|
|
|
|
at the database creation, before trx_sys_init. */
|
|
|
|
static
|
|
|
|
void
|
|
|
|
trx_sysf_create(
|
|
|
|
/*============*/
|
|
|
|
mtr_t* mtr) /* in: mtr */
|
|
|
|
{
|
|
|
|
trx_sysf_t* sys_header;
|
|
|
|
ulint slot_no;
|
|
|
|
page_t* page;
|
|
|
|
ulint page_no;
|
|
|
|
ulint i;
|
|
|
|
|
|
|
|
ut_ad(mtr);
|
|
|
|
|
|
|
|
/* Note that below we first reserve the file space x-latch, and
|
|
|
|
then enter the kernel: we must do it in this order to conform
|
|
|
|
to the latching order rules. */
|
|
|
|
|
|
|
|
mtr_x_lock(fil_space_get_latch(TRX_SYS_SPACE), mtr);
|
|
|
|
mutex_enter(&kernel_mutex);
|
|
|
|
|
|
|
|
/* Create the trx sys file block in a new allocated file segment */
|
|
|
|
page = fseg_create(TRX_SYS_SPACE, 0, TRX_SYS + TRX_SYS_FSEG_HEADER,
|
|
|
|
mtr);
|
|
|
|
ut_a(buf_frame_get_page_no(page) == TRX_SYS_PAGE_NO);
|
|
|
|
|
|
|
|
buf_page_dbg_add_level(page, SYNC_TRX_SYS_HEADER);
|
|
|
|
|
|
|
|
sys_header = trx_sysf_get(mtr);
|
|
|
|
|
|
|
|
/* Start counting transaction ids from number 1 up */
|
|
|
|
mlog_write_dulint(sys_header + TRX_SYS_TRX_ID_STORE,
|
|
|
|
ut_dulint_create(0, 1), MLOG_8BYTES, mtr);
|
|
|
|
|
|
|
|
/* Reset the rollback segment slots */
|
|
|
|
for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
|
|
|
|
|
|
|
|
trx_sysf_rseg_set_page_no(sys_header, i, FIL_NULL, mtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create the first rollback segment in the SYSTEM tablespace */
|
|
|
|
page_no = trx_rseg_header_create(TRX_SYS_SPACE, ULINT_MAX, &slot_no,
|
|
|
|
mtr);
|
|
|
|
ut_a(slot_no == TRX_SYS_SYSTEM_RSEG_ID);
|
|
|
|
ut_a(page_no != FIL_NULL);
|
|
|
|
|
|
|
|
mutex_exit(&kernel_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
Creates and initializes the central memory structures for the transaction
|
|
|
|
system. This is called when the database is started. */
|
|
|
|
|
|
|
|
void
|
|
|
|
trx_sys_init_at_db_start(void)
|
|
|
|
/*==========================*/
|
|
|
|
{
|
|
|
|
trx_sysf_t* sys_header;
|
|
|
|
mtr_t mtr;
|
|
|
|
|
|
|
|
mtr_start(&mtr);
|
|
|
|
|
|
|
|
ut_ad(trx_sys == NULL);
|
|
|
|
|
|
|
|
mutex_enter(&kernel_mutex);
|
|
|
|
|
|
|
|
trx_sys = mem_alloc(sizeof(trx_sys_t));
|
|
|
|
|
|
|
|
sys_header = trx_sysf_get(&mtr);
|
|
|
|
|
|
|
|
trx_rseg_list_and_array_init(sys_header, &mtr);
|
|
|
|
|
|
|
|
trx_sys->latest_rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
|
|
|
|
|
|
|
|
/* VERY important: after the database is started, max_trx_id value is
|
|
|
|
divisible by TRX_SYS_TRX_ID_WRITE_MARGIN, and the 'if' in
|
|
|
|
trx_sys_get_new_trx_id will evaluate to TRUE when the function
|
|
|
|
is first time called, and the value for trx id will be written
|
|
|
|
to the disk-based header! Thus trx id values will not overlap when
|
|
|
|
the database is repeatedly started! */
|
|
|
|
|
|
|
|
trx_sys->max_trx_id = ut_dulint_add(
|
|
|
|
ut_dulint_align_up(
|
|
|
|
mtr_read_dulint(sys_header
|
|
|
|
+ TRX_SYS_TRX_ID_STORE,
|
|
|
|
MLOG_8BYTES, &mtr),
|
|
|
|
TRX_SYS_TRX_ID_WRITE_MARGIN),
|
|
|
|
2 * TRX_SYS_TRX_ID_WRITE_MARGIN);
|
trx0roll.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
trx0sys.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
trx0trx.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
row0mysql.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
row0purge.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
row0sel.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
row0uins.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
row0umod.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
row0upd.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
srv0srv.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
srv0start.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
sync0arr.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
fil0fil.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
ibuf0ibuf.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
lock0lock.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
os0file.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
btr0btr.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
btr0cur.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
btr0sea.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
buf0buf.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
data0data.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
srv0srv.h Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
trx0sys.h Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
trx0trx.h Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
btr0cur.h Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
buf0buf.h Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
data0data.h Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
ha_innobase.cc Fix the auto-inc+REPLACE+replication bug, improve InnoDB Monitor prints
2001-08-29 18:42:23 +02:00
|
|
|
|
|
|
|
UT_LIST_INIT(trx_sys->mysql_trx_list);
|
2001-02-17 13:19:19 +01:00
|
|
|
trx_lists_init_at_db_start();
|
|
|
|
|
|
|
|
if (UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
|
|
|
|
fprintf(stderr,
|
2001-06-07 19:24:53 +02:00
|
|
|
"InnoDB: %lu uncommitted transaction(s) which must be rolled back\n",
|
2001-02-17 13:19:19 +01:00
|
|
|
UT_LIST_GET_LEN(trx_sys->trx_list));
|
2001-10-30 16:38:44 +01:00
|
|
|
|
|
|
|
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));
|
2001-02-17 13:19:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
UT_LIST_INIT(trx_sys->view_list);
|
|
|
|
|
|
|
|
trx_purge_sys_create();
|
|
|
|
|
|
|
|
mutex_exit(&kernel_mutex);
|
|
|
|
|
|
|
|
mtr_commit(&mtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
Creates and initializes the transaction system at the database creation. */
|
|
|
|
|
|
|
|
void
|
|
|
|
trx_sys_create(void)
|
|
|
|
/*================*/
|
|
|
|
{
|
|
|
|
mtr_t mtr;
|
|
|
|
|
|
|
|
mtr_start(&mtr);
|
|
|
|
|
|
|
|
trx_sysf_create(&mtr);
|
|
|
|
|
|
|
|
mtr_commit(&mtr);
|
|
|
|
|
|
|
|
trx_sys_init_at_db_start();
|
|
|
|
}
|