29 #include "trx0undo.ic"
33 #ifndef UNIV_HOTBACKUP
110 #ifndef UNIV_HOTBACKUP
135 trx_undo_insert_header_reuse(
146 trx_undo_discard_latest_update_undo(
151 #ifndef UNIV_HOTBACKUP
157 trx_undo_get_prev_rec_from_prev_page(
186 shared ? RW_S_LATCH : RW_X_LATCH,
188 buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
190 prev_page = buf_block_get_frame(block);
220 return(trx_undo_get_prev_rec_from_prev_page(rec, page_no, offset,
229 trx_undo_get_next_rec_from_next_page(
247 log_hdr = undo_page +
offset;
264 if (mode == RW_S_LATCH) {
268 ut_ad(mode == RW_X_LATCH);
301 return(trx_undo_get_next_rec_from_next_page(space, zip_size,
325 if (mode == RW_S_LATCH) {
338 return(trx_undo_get_next_rec_from_next_page(space, zip_size,
339 undo_page, page_no, offset,
360 # define trx_undo_page_init_log(undo_page,type,mtr) ((void) 0)
385 trx_undo_page_init(page, type, mtr);
417 #ifndef UNIV_HOTBACKUP
422 static __attribute__((nonnull, warn_unused_result))
446 ut_ad(mtr &&
id && rseg_hdr);
447 ut_ad(mutex_own(&(rseg->mutex)));
454 if (slot_no == ULINT_UNDEFINED) {
457 " InnoDB: Warning: cannot find a free slot for"
458 " an undo log. Do you have too\n"
459 "InnoDB: many active transactions"
460 " running concurrently?\n");
471 return(DB_OUT_OF_FILE_SPACE);
484 return(DB_OUT_OF_FILE_SPACE);
487 buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
489 *undo_page = buf_block_get_frame(block);
494 trx_undo_page_init(*undo_page, type, mtr);
520 trx_undo_header_create_log(
531 # define trx_undo_header_create_log(undo_page,trx_id,mtr) ((void) 0)
541 trx_undo_header_create(
559 ut_ad(mtr && undo_page);
566 log_hdr = undo_page + free;
581 prev_log_hdr = undo_page + prev_log;
588 log_hdr = undo_page + free;
602 trx_undo_header_create_log(undo_page, trx_id, mtr);
607 #ifndef UNIV_HOTBACKUP
654 trx_undo_header_add_space_for_xid(
670 ut_a(free == (ulint)(log_hdr - undo_page) + TRX_UNDO_LOG_OLD_HDR_SIZE);
692 trx_undo_insert_header_reuse_log(
703 # define trx_undo_insert_header_reuse_log(undo_page,trx_id,mtr) ((void) 0)
725 UNIV_MEM_INVALID(&trx_id,
sizeof trx_id);
736 trx_undo_header_create(page, trx_id, mtr);
739 trx_undo_insert_header_reuse(page, trx_id, mtr);
753 trx_undo_insert_header_reuse(
766 ut_ad(mtr && undo_page);
775 log_hdr = undo_page + free;
792 log_hdr = undo_page + free;
801 trx_undo_insert_header_reuse_log(undo_page, trx_id, mtr);
806 #ifndef UNIV_HOTBACKUP
811 trx_undo_discard_latest_log(
819 # define trx_undo_discard_latest_log(undo_page, mtr) ((void) 0)
830 byte* end_ptr __attribute__((unused)),
837 trx_undo_discard_latest_update_undo(page, mtr);
848 trx_undo_discard_latest_update_undo(
858 ulint prev_hdr_offset;
864 log_hdr = undo_page + free;
868 if (prev_hdr_offset != 0) {
869 prev_log_hdr = undo_page + prev_hdr_offset;
882 trx_undo_discard_latest_log(undo_page, mtr);
885 #ifndef UNIV_HOTBACKUP
910 if (rseg->curr_size == rseg->max_size) {
931 if (new_block == NULL) {
939 buf_block_dbg_add_level(new_block, SYNC_TRX_UNDO_PAGE);
942 new_page = buf_block_get_frame(new_block);
944 trx_undo_page_init(new_page, undo->
type, mtr);
979 ut_a(hdr_page_no != page_no);
982 zip_size = rseg->zip_size;
992 space, page_no, mtr);
1000 rseg->page_no, mtr);
1004 ut_ad(hist_size > 0);
1009 return(last_addr.
page);
1027 ut_ad(mutex_own(&trx->undo_mutex));
1028 ut_ad(undo->hdr_page_no != undo->last_page_no);
1029 ut_ad(undo->size > 0);
1031 undo->last_page_no = trx_undo_free_page(
1032 undo->rseg, FALSE, undo->space,
1033 undo->hdr_page_no, undo->last_page_no, mtr);
1043 trx_undo_empty_header_page(
1058 log_hdr = header_page + hdr_offset;
1060 end = trx_undo_page_get_end(header_page, hdr_page_no, hdr_offset);
1085 ut_ad(mutex_own(&(trx->undo_mutex)));
1086 ut_ad(mutex_own(&(trx->rseg->mutex)));
1093 last_page_no = undo->last_page_no;
1096 last_page_no, &mtr);
1114 if (last_page_no == undo->hdr_page_no) {
1119 ut_ad(last_page_no == undo->last_page_no);
1120 trx_undo_free_last_page(trx, undo, &mtr);
1170 hdr_page_no, hdr_offset,
1193 if (page_no == hdr_page_no) {
1194 trx_undo_empty_header_page(space, rseg->zip_size,
1195 hdr_page_no, hdr_offset,
1198 trx_undo_free_page(rseg, TRUE, space, hdr_page_no,
1216 fseg_header_t* file_seg;
1228 mutex_enter(&(rseg->
mutex));
1241 rseg->
space, rseg->zip_size, rseg->page_no,
1246 MONITOR_DEC(MONITOR_NUM_UNDO_SLOT_USED);
1249 mutex_exit(&(rseg->
mutex));
1251 }
while (!finished);
1263 trx_undo_mem_create_at_db_start(
1283 ibool xid_exists = FALSE;
1285 if (
id >= TRX_RSEG_N_SLOTS) {
1287 "InnoDB: Error: undo->id is %lu\n", (ulong)
id);
1304 undo_header = undo_page +
offset;
1314 memset(&xid, 0,
sizeof(xid));
1317 if (xid_exists == TRUE) {
1318 trx_undo_read_xid(undo_header, &xid);
1321 mutex_enter(&(rseg->
mutex));
1323 undo = trx_undo_mem_create(rseg,
id, type, trx_id, &xid,
1325 mutex_exit(&(rseg->
mutex));
1331 undo->
state = state;
1335 if (state == TRX_UNDO_TO_FREE) {
1353 undo->
empty = FALSE;
1358 if (type == TRX_UNDO_INSERT) {
1359 if (state != TRX_UNDO_CACHED) {
1368 ut_ad(type == TRX_UNDO_UPDATE);
1369 if (state != TRX_UNDO_CACHED) {
1406 rseg->
space, rseg->zip_size, rseg->page_no, &mtr);
1408 for (i = 0; i < TRX_RSEG_N_SLOTS; i++) {
1423 undo = trx_undo_mem_create_at_db_start(
1424 rseg, i, page_no, &mtr);
1433 rseg->
space, rseg->zip_size, rseg->page_no,
1451 trx_undo_mem_create(
1467 if (
id >= TRX_RSEG_N_SLOTS) {
1469 "InnoDB: Error: undo->id is %lu\n", (ulong)
id);
1473 undo =
static_cast<trx_undo_t*
>(mem_alloc(
sizeof(*undo)));
1482 undo->
state = TRX_UNDO_ACTIVE;
1509 trx_undo_mem_init_for_reuse(
1517 ut_ad(mutex_own(&((undo->
rseg)->mutex)));
1519 if (UNIV_UNLIKELY(undo->
id >= TRX_RSEG_N_SLOTS)) {
1520 fprintf(stderr,
"InnoDB: Error: undo->id is %lu\n",
1527 undo->
state = TRX_UNDO_ACTIVE;
1546 if (undo->
id >= TRX_RSEG_N_SLOTS) {
1548 "InnoDB: Error: undo->id is %lu\n", (ulong) undo->
id);
1560 static __attribute__((nonnull, warn_unused_result))
1582 ut_ad(mutex_own(&(rseg->mutex)));
1584 if (rseg->curr_size == rseg->max_size) {
1586 return(DB_OUT_OF_FILE_SPACE);
1591 rseg_header =
trx_rsegf_get(rseg->space, rseg->zip_size, rseg->page_no,
1594 err = trx_undo_seg_create(rseg, rseg_header, type, &
id,
1597 if (err != DB_SUCCESS) {
1607 offset = trx_undo_header_create(undo_page, trx_id, mtr);
1609 if (trx->support_xa) {
1610 trx_undo_header_add_space_for_xid(undo_page,
1611 undo_page + offset, mtr);
1614 *undo = trx_undo_mem_create(rseg,
id, type, trx_id, xid,
1616 if (*undo == NULL) {
1618 err = DB_OUT_OF_MEMORY;
1631 trx_undo_reuse_cached(
1648 if (type == TRX_UNDO_INSERT) {
1658 MONITOR_DEC(MONITOR_NUM_UNDO_SLOT_CACHED);
1660 ut_ad(type == TRX_UNDO_UPDATE);
1670 MONITOR_DEC(MONITOR_NUM_UNDO_SLOT_CACHED);
1675 if (undo->
id >= TRX_RSEG_N_SLOTS) {
1676 fprintf(stderr,
"InnoDB: Error: undo->id is %lu\n",
1685 if (type == TRX_UNDO_INSERT) {
1686 offset = trx_undo_insert_header_reuse(undo_page, trx_id, mtr);
1689 trx_undo_header_add_space_for_xid(
1690 undo_page, undo_page + offset, mtr);
1695 == TRX_UNDO_UPDATE);
1697 offset = trx_undo_header_create(undo_page, trx_id, mtr);
1700 trx_undo_header_add_space_for_xid(
1701 undo_page, undo_page + offset, mtr);
1705 trx_undo_mem_init_for_reuse(undo, trx_id, xid, offset);
1715 trx_undo_mark_as_dict_operation(
1768 if (trx->
rseg == NULL) {
1778 mutex_enter(&rseg->
mutex);
1781 "ib_create_table_fail_too_many_trx",
1786 undo = trx_undo_reuse_cached(trx, rseg, type, trx->
id, &trx->
xid,
1789 err = trx_undo_create(trx, rseg, type, trx->
id, &trx->
xid,
1791 if (err != DB_SUCCESS) {
1797 if (type == TRX_UNDO_INSERT) {
1808 trx_undo_mark_as_dict_operation(trx, undo, &mtr);
1812 mutex_exit(&(rseg->
mutex));
1833 if (undo->
id >= TRX_RSEG_N_SLOTS) {
1834 fprintf(stderr,
"InnoDB: Error: undo->id is %lu\n",
1850 state = TRX_UNDO_CACHED;
1852 }
else if (undo->
type == TRX_UNDO_INSERT) {
1854 state = TRX_UNDO_TO_FREE;
1856 state = TRX_UNDO_TO_PURGE;
1859 undo->
state = state;
1882 ut_ad(trx && undo && mtr);
1884 if (undo->
id >= TRX_RSEG_N_SLOTS) {
1885 fprintf(stderr,
"InnoDB: Error: undo->id is %lu\n",
1897 undo->
state = TRX_UNDO_PREPARED;
1905 undo_header = undo_page +
offset;
1910 trx_undo_write_xid(undo_header, &undo->
xid, mtr);
1942 if (undo->
state == TRX_UNDO_CACHED) {
1950 trx_undo_mem_free(undo);
1972 mutex_enter(&(rseg->
mutex));
1977 if (undo->
state == TRX_UNDO_CACHED) {
1987 mutex_exit(&(rseg->
mutex));
1989 trx_undo_seg_free(undo);
1991 mutex_enter(&(rseg->
mutex));
1995 rseg->curr_size -= undo->
size;
1997 trx_undo_mem_free(undo);
2000 mutex_exit(&(rseg->
mutex));