1
/******************************************************
6
Created 2/25/1997 Heikki Tuuri
7
*******************************************************/
12
#include "row0uins.ic"
15
#include "dict0dict.h"
16
#include "dict0boot.h"
17
#include "dict0crea.h"
21
#include "mach0data.h"
29
#include "ibuf0ibuf.h"
32
/*******************************************************************
33
Removes a clustered index record. The pcur in node was positioned on the
34
record, now it is detached. */
37
row_undo_ins_remove_clust_rec(
38
/*==========================*/
39
/* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
40
undo_node_t* node) /* in: undo node */
50
success = btr_pcur_restore_position(BTR_MODIFY_LEAF, &(node->pcur),
54
if (ut_dulint_cmp(node->table->id, DICT_INDEXES_ID) == 0) {
55
ut_ad(node->trx->dict_operation_lock_mode == RW_X_LATCH);
57
/* Drop the index tree associated with the row in
60
dict_drop_index_tree(btr_pcur_get_rec(&(node->pcur)), &mtr);
66
success = btr_pcur_restore_position(BTR_MODIFY_LEAF,
71
btr_cur = btr_pcur_get_btr_cur(&(node->pcur));
73
success = btr_cur_optimistic_delete(btr_cur, &mtr);
75
btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
78
trx_undo_rec_release(node->trx, node->undo_no);
83
/* If did not succeed, try pessimistic descent to tree */
86
success = btr_pcur_restore_position(BTR_MODIFY_TREE,
90
btr_cur_pessimistic_delete(&err, FALSE, btr_cur,
91
trx_is_recv(node->trx)
95
/* The delete operation may fail if we have little
96
file space left: TODO: easiest to crash the database
97
and restart with more file space */
99
if (err == DB_OUT_OF_FILE_SPACE
100
&& n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) {
102
btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
106
os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME);
111
btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
113
trx_undo_rec_release(node->trx, node->undo_no);
118
/*******************************************************************
119
Removes a secondary index entry if found. */
122
row_undo_ins_remove_sec_low(
123
/*========================*/
124
/* out: DB_SUCCESS, DB_FAIL, or
125
DB_OUT_OF_FILE_SPACE */
126
ulint mode, /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
127
depending on whether we wish optimistic or
128
pessimistic descent down the index tree */
129
dict_index_t* index, /* in: index */
130
dtuple_t* entry) /* in: index entry to remove */
142
found = row_search_index_entry(index, entry, mode, &pcur, &mtr);
144
btr_cur = btr_pcur_get_btr_cur(&pcur);
149
btr_pcur_close(&pcur);
155
if (mode == BTR_MODIFY_LEAF) {
156
success = btr_cur_optimistic_delete(btr_cur, &mtr);
164
ut_ad(mode == BTR_MODIFY_TREE);
166
/* No need to distinguish RB_RECOVERY here, because we
167
are deleting a secondary index record: the distinction
168
between RB_NORMAL and RB_RECOVERY only matters when
169
deleting a record that contains externally stored
171
ut_ad(!dict_index_is_clust(index));
172
btr_cur_pessimistic_delete(&err, FALSE, btr_cur,
176
btr_pcur_close(&pcur);
182
/*******************************************************************
183
Removes a secondary index entry from the index if found. Tries first
184
optimistic, then pessimistic descent down the tree. */
187
row_undo_ins_remove_sec(
188
/*====================*/
189
/* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
190
dict_index_t* index, /* in: index */
191
dtuple_t* entry) /* in: index entry to insert */
196
/* Try first optimistic descent to the B-tree */
198
err = row_undo_ins_remove_sec_low(BTR_MODIFY_LEAF, index, entry);
200
if (err == DB_SUCCESS) {
205
/* Try then pessimistic descent to the B-tree */
207
err = row_undo_ins_remove_sec_low(BTR_MODIFY_TREE, index, entry);
209
/* The delete operation may fail if we have little
210
file space left: TODO: easiest to crash the database
211
and restart with more file space */
213
if (err != DB_SUCCESS && n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) {
217
os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME);
225
/***************************************************************
226
Parses the row reference and other info in a fresh insert undo record. */
229
row_undo_ins_parse_undo_rec(
230
/*========================*/
231
undo_node_t* node) /* in/out: row undo node */
233
dict_index_t* clust_index;
243
ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &dummy,
244
&dummy_extern, &undo_no, &table_id);
245
ut_ad(type == TRX_UNDO_INSERT_REC);
246
node->rec_type = type;
249
node->table = dict_table_get_on_id(table_id, node->trx);
251
/* Skip the UNDO if we can't find the table or the .ibd file. */
252
if (UNIV_UNLIKELY(node->table == NULL)) {
253
} else if (UNIV_UNLIKELY(node->table->ibd_file_missing)) {
256
clust_index = dict_table_get_first_index(node->table);
258
if (clust_index != NULL) {
259
ptr = trx_undo_rec_get_row_ref(
260
ptr, clust_index, &node->ref, node->heap);
262
ut_print_timestamp(stderr);
263
fprintf(stderr, " InnoDB: table ");
264
ut_print_name(stderr, node->trx, TRUE,
266
fprintf(stderr, " has no indexes, "
267
"ignoring the table\n");
274
/***************************************************************
275
Undoes a fresh insert of a row to a table. A fresh insert means that
276
the same clustered index unique key did not have any record, even delete
277
marked, at the time of the insert. */
282
/* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
283
undo_node_t* node) /* in: row undo node */
286
ut_ad(node->state == UNDO_NODE_INSERT);
288
row_undo_ins_parse_undo_rec(node);
290
if (!node->table || !row_undo_search_clust_to_pcur(node)) {
291
trx_undo_rec_release(node->trx, node->undo_no);
296
/* Iterate over all the indexes and undo the insert.*/
298
/* Skip the clustered index (the first index) */
299
node->index = dict_table_get_next_index(
300
dict_table_get_first_index(node->table));
302
while (node->index != NULL) {
306
entry = row_build_index_entry(node->row, node->ext,
307
node->index, node->heap);
308
if (UNIV_UNLIKELY(!entry)) {
309
/* The database must have crashed after
310
inserting a clustered index record but before
311
writing all the externally stored columns of
312
that record. Because secondary index entries
313
are inserted after the clustered index record,
314
we may assume that the secondary index record
315
does not exist. However, this situation may
316
only occur during the rollback of incomplete
318
ut_a(trx_is_recv(node->trx));
320
err = row_undo_ins_remove_sec(node->index, entry);
322
if (err != DB_SUCCESS) {
328
node->index = dict_table_get_next_index(node->index);
331
return(row_undo_ins_remove_clust_rec(node));