1
/*****************************************************************************
3
Copyright (C) 1997, 2010, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/**************************************************//**
23
Created 2/25/1997 Heikki Tuuri
24
*******************************************************/
29
#include "row0uins.ic"
32
#include "dict0dict.h"
33
#include "dict0boot.h"
34
#include "dict0crea.h"
38
#include "mach0data.h"
46
#include "ibuf0ibuf.h"
49
/*************************************************************************
50
IMPORTANT NOTE: Any operation that generates redo MUST check that there
51
is enough space in the redo log before for that operation. This is
52
done by calling log_free_check(). The reason for checking the
53
availability of the redo log space before the start of the operation is
54
that we MUST not hold any synchonization objects when performing the
56
If you make a change in this module make sure that no codepath is
57
introduced where a call to log_free_check() is bypassed. */
59
/*************************************************************************
60
IMPORTANT NOTE: Any operation that generates redo MUST check that there
61
is enough space in the redo log before for that operation. This is
62
done by calling log_free_check(). The reason for checking the
63
availability of the redo log space before the start of the operation is
64
that we MUST not hold any synchonization objects when performing the
66
If you make a change in this module make sure that no codepath is
67
introduced where a call to log_free_check() is bypassed. */
69
/***************************************************************//**
70
Removes a clustered index record. The pcur in node was positioned on the
71
record, now it is detached.
72
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
75
row_undo_ins_remove_clust_rec(
76
/*==========================*/
77
undo_node_t* node) /*!< in: undo node */
87
success = btr_pcur_restore_position(BTR_MODIFY_LEAF, &(node->pcur),
91
if (node->table->id == DICT_INDEXES_ID) {
92
ut_ad(node->trx->dict_operation_lock_mode == RW_X_LATCH);
94
/* Drop the index tree associated with the row in
97
dict_drop_index_tree(btr_pcur_get_rec(&(node->pcur)), &mtr);
103
success = btr_pcur_restore_position(BTR_MODIFY_LEAF,
104
&(node->pcur), &mtr);
108
btr_cur = btr_pcur_get_btr_cur(&(node->pcur));
110
success = btr_cur_optimistic_delete(btr_cur, &mtr);
112
btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
115
trx_undo_rec_release(node->trx, node->undo_no);
120
/* If did not succeed, try pessimistic descent to tree */
123
success = btr_pcur_restore_position(BTR_MODIFY_TREE,
124
&(node->pcur), &mtr);
127
btr_cur_pessimistic_delete(&err, FALSE, btr_cur,
128
trx_is_recv(node->trx)
132
/* The delete operation may fail if we have little
133
file space left: TODO: easiest to crash the database
134
and restart with more file space */
136
if (err == DB_OUT_OF_FILE_SPACE
137
&& n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) {
139
btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
143
os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME);
148
btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
150
trx_undo_rec_release(node->trx, node->undo_no);
155
/***************************************************************//**
156
Removes a secondary index entry if found.
157
@return DB_SUCCESS, DB_FAIL, or DB_OUT_OF_FILE_SPACE */
160
row_undo_ins_remove_sec_low(
161
/*========================*/
162
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
163
depending on whether we wish optimistic or
164
pessimistic descent down the index tree */
165
dict_index_t* index, /*!< in: index */
166
dtuple_t* entry) /*!< in: index entry to remove */
172
enum row_search_result search_result;
176
btr_cur = btr_pcur_get_btr_cur(&pcur);
178
ut_ad(mode == BTR_MODIFY_TREE || mode == BTR_MODIFY_LEAF);
180
search_result = row_search_index_entry(index, entry, mode,
183
switch (search_result) {
190
case ROW_NOT_DELETED_REF:
191
/* These are invalid outcomes, because the mode passed
192
to row_search_index_entry() did not include any of the
193
flags BTR_INSERT, BTR_DELETE, or BTR_DELETE_MARK. */
197
if (mode == BTR_MODIFY_LEAF) {
198
err = btr_cur_optimistic_delete(btr_cur, &mtr)
199
? DB_SUCCESS : DB_FAIL;
201
ut_ad(mode == BTR_MODIFY_TREE);
203
/* No need to distinguish RB_RECOVERY here, because we
204
are deleting a secondary index record: the distinction
205
between RB_NORMAL and RB_RECOVERY only matters when
206
deleting a record that contains externally stored
208
ut_ad(!dict_index_is_clust(index));
209
btr_cur_pessimistic_delete(&err, FALSE, btr_cur,
213
btr_pcur_close(&pcur);
219
/***************************************************************//**
220
Removes a secondary index entry from the index if found. Tries first
221
optimistic, then pessimistic descent down the tree.
222
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
225
row_undo_ins_remove_sec(
226
/*====================*/
227
dict_index_t* index, /*!< in: index */
228
dtuple_t* entry) /*!< in: index entry to insert */
233
/* Try first optimistic descent to the B-tree */
235
err = row_undo_ins_remove_sec_low(BTR_MODIFY_LEAF, index, entry);
237
if (err == DB_SUCCESS) {
242
/* Try then pessimistic descent to the B-tree */
244
err = row_undo_ins_remove_sec_low(BTR_MODIFY_TREE, index, entry);
246
/* The delete operation may fail if we have little
247
file space left: TODO: easiest to crash the database
248
and restart with more file space */
250
if (err != DB_SUCCESS && n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) {
254
os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME);
262
/***********************************************************//**
263
Parses the row reference and other info in a fresh insert undo record. */
266
row_undo_ins_parse_undo_rec(
267
/*========================*/
268
undo_node_t* node) /*!< in/out: row undo node */
270
dict_index_t* clust_index;
280
ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &dummy,
281
&dummy_extern, &undo_no, &table_id);
282
ut_ad(type == TRX_UNDO_INSERT_REC);
283
node->rec_type = type;
286
node->table = dict_table_get_on_id(table_id, node->trx);
288
/* Skip the UNDO if we can't find the table or the .ibd file. */
289
if (UNIV_UNLIKELY(node->table == NULL)) {
290
} else if (UNIV_UNLIKELY(node->table->ibd_file_missing)) {
293
clust_index = dict_table_get_first_index(node->table);
295
if (clust_index != NULL) {
296
ptr = trx_undo_rec_get_row_ref(
297
ptr, clust_index, &node->ref, node->heap);
299
ut_print_timestamp(stderr);
300
fprintf(stderr, " InnoDB: table ");
301
ut_print_name(stderr, node->trx, TRUE,
303
fprintf(stderr, " has no indexes, "
304
"ignoring the table\n");
311
/***********************************************************//**
312
Undoes a fresh insert of a row to a table. A fresh insert means that
313
the same clustered index unique key did not have any record, even delete
314
marked, at the time of the insert. InnoDB is eager in a rollback:
315
if it figures out that an index record will be removed in the purge
316
anyway, it will remove it in the rollback.
317
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
322
undo_node_t* node) /*!< in: row undo node */
325
ut_ad(node->state == UNDO_NODE_INSERT);
327
row_undo_ins_parse_undo_rec(node);
329
if (!node->table || !row_undo_search_clust_to_pcur(node)) {
330
trx_undo_rec_release(node->trx, node->undo_no);
335
/* Iterate over all the indexes and undo the insert.*/
337
/* Skip the clustered index (the first index) */
338
node->index = dict_table_get_next_index(
339
dict_table_get_first_index(node->table));
341
while (node->index != NULL) {
345
entry = row_build_index_entry(node->row, node->ext,
346
node->index, node->heap);
347
if (UNIV_UNLIKELY(!entry)) {
348
/* The database must have crashed after
349
inserting a clustered index record but before
350
writing all the externally stored columns of
351
that record. Because secondary index entries
352
are inserted after the clustered index record,
353
we may assume that the secondary index record
354
does not exist. However, this situation may
355
only occur during the rollback of incomplete
357
ut_a(trx_is_recv(node->trx));
360
err = row_undo_ins_remove_sec(node->index, entry);
362
if (err != DB_SUCCESS) {
368
node->index = dict_table_get_next_index(node->index);
372
return(row_undo_ins_remove_clust_rec(node));