29 #include "trx0undo.ic"
33 #ifndef UNIV_HOTBACKUP
108 #ifndef UNIV_HOTBACKUP
133 trx_undo_insert_header_reuse(
144 trx_undo_discard_latest_update_undo(
149 #ifndef UNIV_HOTBACKUP
155 trx_undo_get_prev_rec_from_prev_page(
212 return(trx_undo_get_prev_rec_from_prev_page(rec, page_no, offset,
221 trx_undo_get_next_rec_from_next_page(
239 log_hdr = undo_page + offset;
256 if (mode == RW_S_LATCH) {
260 ut_ad(mode == RW_X_LATCH);
293 return(trx_undo_get_next_rec_from_next_page(space, zip_size,
317 if (mode == RW_S_LATCH) {
330 return(trx_undo_get_next_rec_from_next_page(space, zip_size,
331 undo_page, page_no, offset,
341 trx_undo_page_init_log(
352 # define trx_undo_page_init_log(undo_page,type,mtr) ((void) 0)
377 trx_undo_page_init(page, type, mtr);
406 trx_undo_page_init_log(undo_page, type, mtr);
409 #ifndef UNIV_HOTBACKUP
436 ulint err = DB_SUCCESS;
438 ut_ad(mtr &&
id && rseg_hdr);
439 ut_ad(mutex_own(&(rseg->mutex)));
446 if (slot_no == ULINT_UNDEFINED) {
449 " InnoDB: Warning: cannot find a free slot for"
450 " an undo log. Do you have too\n"
451 "InnoDB: many active transactions"
452 " running concurrently?\n");
454 return(DB_TOO_MANY_CONCURRENT_TRXS);
463 return(DB_OUT_OF_FILE_SPACE);
476 return(DB_OUT_OF_FILE_SPACE);
479 buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
481 *undo_page = buf_block_get_frame(block);
486 trx_undo_page_init(*undo_page, type, mtr);
510 trx_undo_header_create_log(
521 # define trx_undo_header_create_log(undo_page,trx_id,mtr) ((void) 0)
531 trx_undo_header_create(
549 ut_ad(mtr && undo_page);
556 log_hdr = undo_page + free;
571 prev_log_hdr = undo_page + prev_log;
578 log_hdr = undo_page + free;
592 trx_undo_header_create_log(undo_page, trx_id, mtr);
597 #ifndef UNIV_HOTBACKUP
644 trx_undo_header_add_space_for_xid(
660 ut_a(free == (ulint)(log_hdr - undo_page) + TRX_UNDO_LOG_OLD_HDR_SIZE);
682 trx_undo_insert_header_reuse_log(
693 # define trx_undo_insert_header_reuse_log(undo_page,trx_id,mtr) ((void) 0)
715 UNIV_MEM_INVALID(&trx_id,
sizeof trx_id);
726 trx_undo_header_create(page, trx_id, mtr);
729 trx_undo_insert_header_reuse(page, trx_id, mtr);
743 trx_undo_insert_header_reuse(
756 ut_ad(mtr && undo_page);
765 log_hdr = undo_page + free;
782 log_hdr = undo_page + free;
791 trx_undo_insert_header_reuse_log(undo_page, trx_id, mtr);
796 #ifndef UNIV_HOTBACKUP
801 trx_undo_discard_latest_log(
809 # define trx_undo_discard_latest_log(undo_page, mtr) ((void) 0)
827 trx_undo_discard_latest_update_undo(page, mtr);
838 trx_undo_discard_latest_update_undo(
848 ulint prev_hdr_offset;
854 log_hdr = undo_page + free;
858 if (prev_hdr_offset != 0) {
859 prev_log_hdr = undo_page + prev_hdr_offset;
872 trx_undo_discard_latest_log(undo_page, mtr);
875 #ifndef UNIV_HOTBACKUP
897 ut_ad(!mutex_own(&kernel_mutex));
902 if (rseg->curr_size == rseg->max_size) {
936 trx_undo_page_init(new_page, undo->
type, mtr);
971 ut_a(hdr_page_no != page_no);
972 ut_ad(!mutex_own(&kernel_mutex));
975 zip_size = rseg->zip_size;
985 space, page_no, mtr);
997 ut_ad(hist_size > 0);
1002 return(last_addr.
page);
1010 trx_undo_free_page_in_rollback(
1023 ut_ad(mutex_own(&(trx->undo_mutex)));
1025 last_page_no = trx_undo_free_page(undo->
rseg, FALSE, undo->
space,
1037 trx_undo_empty_header_page(
1052 log_hdr = header_page + hdr_offset;
1054 end = trx_undo_page_get_end(header_page, hdr_page_no, hdr_offset);
1088 last_page_no, &mtr);
1099 trx_undo_free_page_in_rollback(
1100 trx, undo, last_page_no, &mtr);
1165 hdr_page_no, hdr_offset,
1188 if (page_no == hdr_page_no) {
1189 trx_undo_empty_header_page(space, rseg->zip_size,
1190 hdr_page_no, hdr_offset,
1193 trx_undo_free_page(rseg, TRUE, space, hdr_page_no,
1211 fseg_header_t* file_seg;
1223 ut_ad(!mutex_own(&kernel_mutex));
1225 mutex_enter(&(rseg->
mutex));
1238 rseg->
space, rseg->zip_size, rseg->page_no,
1244 mutex_exit(&(rseg->
mutex));
1246 }
while (!finished);
1258 trx_undo_mem_create_at_db_start(
1278 ibool xid_exists = FALSE;
1280 if (
id >= TRX_RSEG_N_SLOTS) {
1282 "InnoDB: Error: undo->id is %lu\n", (ulong)
id);
1299 undo_header = undo_page + offset;
1309 memset(&xid, 0,
sizeof(xid));
1312 if (xid_exists == TRUE) {
1313 trx_undo_read_xid(undo_header, &xid);
1316 mutex_enter(&(rseg->
mutex));
1318 undo = trx_undo_mem_create(rseg,
id, type, trx_id, &xid,
1320 mutex_exit(&(rseg->
mutex));
1326 undo->
state = state;
1330 if (state == TRX_UNDO_TO_FREE) {
1348 undo->
empty = FALSE;
1353 if (type == TRX_UNDO_INSERT) {
1354 if (state != TRX_UNDO_CACHED) {
1362 ut_ad(type == TRX_UNDO_UPDATE);
1363 if (state != TRX_UNDO_CACHED) {
1401 rseg->page_no, &mtr);
1403 for (i = 0; i < TRX_RSEG_N_SLOTS; i++) {
1414 undo = trx_undo_mem_create_at_db_start(rseg, i,
1423 rseg->
space, rseg->zip_size, rseg->page_no,
1438 trx_undo_mem_create(
1454 if (
id >= TRX_RSEG_N_SLOTS) {
1456 "InnoDB: Error: undo->id is %lu\n", (ulong)
id);
1469 undo->
state = TRX_UNDO_ACTIVE;
1496 trx_undo_mem_init_for_reuse(
1504 ut_ad(mutex_own(&((undo->
rseg)->mutex)));
1506 if (UNIV_UNLIKELY(undo->
id >= TRX_RSEG_N_SLOTS)) {
1507 fprintf(stderr,
"InnoDB: Error: undo->id is %lu\n",
1514 undo->
state = TRX_UNDO_ACTIVE;
1533 if (undo->
id >= TRX_RSEG_N_SLOTS) {
1535 "InnoDB: Error: undo->id is %lu\n", (ulong) undo->
id);
1571 if (rseg->curr_size == rseg->max_size) {
1573 return(DB_OUT_OF_FILE_SPACE);
1581 err = trx_undo_seg_create(rseg, rseg_header, type, &
id,
1584 if (err != DB_SUCCESS) {
1594 offset = trx_undo_header_create(undo_page, trx_id, mtr);
1597 trx_undo_header_add_space_for_xid(undo_page,
1598 undo_page + offset, mtr);
1601 *undo = trx_undo_mem_create(rseg,
id, type, trx_id, xid,
1603 if (*undo == NULL) {
1605 err = DB_OUT_OF_MEMORY;
1618 trx_undo_reuse_cached(
1635 if (type == TRX_UNDO_INSERT) {
1645 ut_ad(type == TRX_UNDO_UPDATE);
1658 if (undo->
id >= TRX_RSEG_N_SLOTS) {
1659 fprintf(stderr,
"InnoDB: Error: undo->id is %lu\n",
1668 if (type == TRX_UNDO_INSERT) {
1669 offset = trx_undo_insert_header_reuse(undo_page, trx_id, mtr);
1672 trx_undo_header_add_space_for_xid(
1673 undo_page, undo_page + offset, mtr);
1678 == TRX_UNDO_UPDATE);
1680 offset = trx_undo_header_create(undo_page, trx_id, mtr);
1683 trx_undo_header_add_space_for_xid(
1684 undo_page, undo_page + offset, mtr);
1688 trx_undo_mem_init_for_reuse(undo, trx_id, xid, offset);
1698 trx_undo_mark_as_dict_operation(
1747 ulint err = DB_SUCCESS;
1758 ut_ad(!mutex_own(&kernel_mutex));
1760 mutex_enter(&(rseg->
mutex));
1762 undo = trx_undo_reuse_cached(trx, rseg, type, trx->
id, &trx->
xid,
1765 err = trx_undo_create(trx, rseg, type, trx->
id, &trx->
xid,
1767 if (err != DB_SUCCESS) {
1773 if (type == TRX_UNDO_INSERT) {
1784 trx_undo_mark_as_dict_operation(trx, undo, &mtr);
1788 mutex_exit(&(rseg->
mutex));
1812 if (undo->
id >= TRX_RSEG_N_SLOTS) {
1813 fprintf(stderr,
"InnoDB: Error: undo->id is %lu\n",
1829 state = TRX_UNDO_CACHED;
1831 }
else if (undo->
type == TRX_UNDO_INSERT) {
1833 state = TRX_UNDO_TO_FREE;
1835 state = TRX_UNDO_TO_PURGE;
1838 undo->
state = state;
1861 ut_ad(trx && undo && mtr);
1863 if (undo->
id >= TRX_RSEG_N_SLOTS) {
1864 fprintf(stderr,
"InnoDB: Error: undo->id is %lu\n",
1876 undo->
state = TRX_UNDO_PREPARED;
1884 undo_header = undo_page + offset;
1889 trx_undo_write_xid(undo_header, &undo->
xid, mtr);
1921 if (undo->
state == TRX_UNDO_CACHED) {
1926 || undo->
state == TRX_UNDO_TO_FREE);
1950 mutex_enter(&(rseg->
mutex));
1955 if (undo->
state == TRX_UNDO_CACHED) {
1963 mutex_exit(&(rseg->
mutex));
1965 trx_undo_seg_free(undo);
1967 mutex_enter(&(rseg->
mutex));
1971 rseg->curr_size -= undo->
size;
1976 mutex_exit(&(rseg->
mutex));
#define TRX_UNDO_LAST_LOG
#define TRX_UNDO_PAGE_HDR
#define TRX_UNDO_TABLE_ID
buf_block_t * guess_block
UNIV_INLINE ulint page_get_space_id(const page_t *page)
UNIV_INLINE fil_addr_t flst_get_last(const flst_base_node_t *base, mtr_t *mtr)
UNIV_INLINE ulint trx_rsegf_undo_find_free(trx_rsegf_t *rsegf, mtr_t *mtr)
#define MLOG_UNDO_HDR_CREATE
#define TRX_UNDO_DICT_TRANS
UNIV_INLINE fil_addr_t flst_get_prev_addr(const flst_node_t *node, mtr_t *mtr)
UNIV_INLINE page_t * page_align(const void *ptr) __attribute__((const ))
UNIV_INLINE void mlog_catenate_ull_compressed(mtr_t *mtr, ib_uint64_t val)
UNIV_INLINE ulint page_get_page_no(const page_t *page)
UNIV_INTERN ulint fseg_alloc_free_page_general(fseg_header_t *seg_header, ulint hint, byte direction, ibool has_done_reservation, mtr_t *mtr)
UNIV_INLINE fil_addr_t flst_get_next_addr(const flst_node_t *node, mtr_t *mtr)
UNIV_INTERN void flst_add_last(flst_base_node_t *base, flst_node_t *node, mtr_t *mtr)
UNIV_INTERN ulint trx_undo_add_page(trx_t *trx, trx_undo_t *undo, mtr_t *mtr)
UNIV_INLINE ulint trx_rsegf_get_nth_undo(trx_rsegf_t *rsegf, ulint n, mtr_t *mtr)
#define TRX_UNDO_PAGE_REUSE_LIMIT
UNIV_INTERN void mlog_write_string(byte *ptr, const byte *str, ulint len, mtr_t *mtr)
UNIV_INTERN void trx_undo_update_cleanup(trx_t *trx, page_t *undo_page, mtr_t *mtr)
UNIV_INTERN void trx_undo_mem_free(trx_undo_t *undo)
UNIV_INLINE void mach_write_to_8(byte *b, ib_uint64_t n)
UNIV_INTERN void mlog_write_ulint(byte *ptr, ulint val, byte type, mtr_t *mtr)
UNIV_INLINE void flst_init(flst_base_node_t *base, mtr_t *mtr)
UNIV_INLINE byte * mach_ull_parse_compressed(byte *ptr, byte *end_ptr, ib_uint64_t *val)
UNIV_INTERN ulint fil_space_get_zip_size(ulint id)
#define TRX_UNDO_NEXT_LOG
UNIV_INTERN byte * trx_undo_parse_discard_latest(byte *ptr, byte *end_ptr, page_t *page, mtr_t *mtr)
UNIV_INTERN void trx_undo_truncate_start(trx_rseg_t *rseg, ulint space, ulint hdr_page_no, ulint hdr_offset, undo_no_t limit)
UNIV_INTERN void flst_remove(flst_base_node_t *base, flst_node_t *node2, mtr_t *mtr)
#define MLOG_UNDO_HDR_DISCARD
#define TRX_UNDO_LOG_START
UNIV_INTERN page_t * trx_undo_set_state_at_finish(trx_undo_t *undo, mtr_t *mtr)
#define TRX_UNDO_XA_BQUAL_LEN
UNIV_INTERN void fseg_free_page(fseg_header_t *seg_header, ulint space, ulint page, mtr_t *mtr)
#define TRX_UNDO_FSEG_HEADER
UNIV_INLINE trx_rsegf_t * trx_rsegf_get_new(ulint space, ulint zip_size, ulint page_no, mtr_t *mtr)
UNIV_INTERN ibool fsp_reserve_free_extents(ulint *n_reserved, ulint space, ulint n_ext, ulint alloc_type, mtr_t *mtr)
UNIV_INTERN void mtr_commit(mtr_t *mtr) __attribute__((nonnull))
#define UT_LIST_REMOVE(NAME, BASE, N)
UNIV_INTERN ulint mtr_read_ulint(const byte *ptr, ulint type, mtr_t *mtr)
UNIV_INLINE page_t * trx_undo_page_get(ulint space, ulint zip_size, ulint page_no, mtr_t *mtr)
#define TRX_UNDO_SEG_HDR_SIZE
UNIV_INTERN void mlog_write_ull(byte *ptr, ib_uint64_t val, mtr_t *mtr)
UNIV_INTERN void fil_page_set_type(byte *page, ulint type)
UNIV_INTERN byte * mach_parse_compressed(byte *ptr, byte *end_ptr, ulint *val)
UNIV_INTERN void trx_undo_insert_cleanup(trx_t *trx)
UNIV_INLINE trx_rsegf_t * trx_rsegf_get(ulint space, ulint zip_size, ulint page_no, mtr_t *mtr)
UNIV_INTERN page_t * trx_undo_set_state_at_prepare(trx_t *trx, trx_undo_t *undo, mtr_t *mtr)
UNIV_INLINE trx_undo_rec_t * trx_undo_page_get_prev_rec(trx_undo_rec_t *rec, ulint page_no, ulint offset)
#define TRX_UNDO_LOG_OLD_HDR_SIZE
UNIV_INLINE trx_undo_rec_t * trx_undo_page_get_last_rec(page_t *undo_page, ulint page_no, ulint offset)
UNIV_INLINE void mach_write_to_1(byte *b, ulint n)
UNIV_INTERN trx_undo_rec_t * trx_undo_get_next_rec(trx_undo_rec_t *rec, ulint page_no, ulint offset, mtr_t *mtr)
#define TRX_UNDO_XA_TRID_LEN
#define UT_LIST_ADD_LAST(NAME, BASE, N)
#define UT_LIST_GET_FIRST(BASE)
UNIV_INLINE trx_undo_rec_t * trx_undo_page_get_first_rec(page_t *undo_page, ulint page_no, ulint offset)
UNIV_INLINE trx_undo_rec_t * trx_undo_page_get_next_rec(trx_undo_rec_t *rec, ulint page_no, ulint offset)
UNIV_INTERN void mlog_write_initial_log_record(const byte *ptr, byte type, mtr_t *mtr)
#define TRX_UNDO_XID_EXISTS
UNIV_INLINE undo_no_t trx_undo_rec_get_undo_no(const trx_undo_rec_t *undo_rec)
UNIV_INTERN void fil_space_release_free_extents(ulint id, ulint n_reserved)
#define TRX_UNDO_PAGE_HDR_SIZE
#define UT_LIST_INIT(BASE)
#define TRX_UNDO_PAGE_NODE
UNIV_INTERN trx_undo_rec_t * trx_undo_get_first_rec(ulint space, ulint zip_size, ulint page_no, ulint offset, ulint mode, mtr_t *mtr)
#define MLOG_UNDO_HDR_REUSE
UNIV_INTERN void trx_purge_add_update_undo_to_history(trx_t *trx, page_t *undo_page, mtr_t *mtr)
UNIV_INLINE enum trx_dict_op trx_get_dict_operation(const trx_t *trx) __attribute__((pure))
#define UT_LIST_ADD_FIRST(NAME, BASE, N)
UNIV_INTERN ulint trx_undo_assign_undo(trx_t *trx, ulint type)
UNIV_INLINE ulint mach_read_from_4(const byte *b) __attribute__((nonnull
UNIV_INTERN void ut_print_timestamp(FILE *file)
#define FIL_PAGE_UNDO_LOG
UNIV_INLINE void mach_write_to_2(byte *b, ulint n)
#define TRX_UNDO_PAGE_TYPE
#define TRX_UNDO_PREV_LOG
UNIV_INTERN void mem_analyze_corruption(void *ptr)
UNIV_INLINE void mtr_start(mtr_t *mtr) __attribute__((nonnull))
UNIV_INTERN byte * trx_undo_parse_page_init(byte *ptr, byte *end_ptr, page_t *page, mtr_t *mtr)
#define TRX_UNDO_DEL_MARKS
#define TRX_UNDO_PAGE_FREE
UNIV_INLINE ulint mach_read_from_2(const byte *b) __attribute__((nonnull
#define TRX_UNDO_PAGE_START
UNIV_INTERN void trx_undo_truncate_end(trx_t *trx, trx_undo_t *undo, undo_no_t limit)
#define TRX_UNDO_XA_FORMAT
UNIV_INTERN ulint trx_undo_lists_init(trx_rseg_t *rseg)
UNIV_INTERN buf_block_t * fseg_create_general(ulint space, ulint page, ulint byte_offset, ibool has_done_reservation, mtr_t *mtr)
#define TRX_UNDO_PAGE_LIST
UNIV_INLINE ib_uint64_t mach_read_from_8(const byte *b) __attribute__((nonnull
#define TRX_UNDO_LOG_XA_HDR_SIZE
UNIV_INTERN byte * trx_undo_parse_page_header(ulint type, byte *ptr, byte *end_ptr, page_t *page, mtr_t *mtr)
UNIV_INLINE ulint flst_get_len(const flst_base_node_t *base, mtr_t *mtr)
UNIV_INLINE page_t * trx_undo_page_get_s_latched(ulint space, ulint zip_size, ulint page_no, mtr_t *mtr)
UNIV_INTERN ibool fseg_free_step(fseg_header_t *header, mtr_t *mtr)
UNIV_INLINE void trx_rsegf_set_nth_undo(trx_rsegf_t *rsegf, ulint n, ulint page_no, mtr_t *mtr)
UNIV_INLINE void mlog_catenate_ulint_compressed(mtr_t *mtr, ulint val)
UNIV_INTERN trx_undo_rec_t * trx_undo_get_prev_rec(trx_undo_rec_t *rec, ulint page_no, ulint offset, mtr_t *mtr)