00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "row0uins.h"
00027
00028 #ifdef UNIV_NONINL
00029 #include "row0uins.ic"
00030 #endif
00031
00032 #include "dict0dict.h"
00033 #include "dict0boot.h"
00034 #include "dict0crea.h"
00035 #include "trx0undo.h"
00036 #include "trx0roll.h"
00037 #include "btr0btr.h"
00038 #include "mach0data.h"
00039 #include "row0undo.h"
00040 #include "row0vers.h"
00041 #include "trx0trx.h"
00042 #include "trx0rec.h"
00043 #include "row0row.h"
00044 #include "row0upd.h"
00045 #include "que0que.h"
00046 #include "ibuf0ibuf.h"
00047 #include "log0log.h"
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00073 static
00074 ulint
00075 row_undo_ins_remove_clust_rec(
00076
00077 undo_node_t* node)
00078 {
00079 btr_cur_t* btr_cur;
00080 ibool success;
00081 ulint err;
00082 ulint n_tries = 0;
00083 mtr_t mtr;
00084
00085 mtr_start(&mtr);
00086
00087 success = btr_pcur_restore_position(BTR_MODIFY_LEAF, &(node->pcur),
00088 &mtr);
00089 ut_a(success);
00090
00091 if (node->table->id == DICT_INDEXES_ID) {
00092 ut_ad(node->trx->dict_operation_lock_mode == RW_X_LATCH);
00093
00094
00095
00096
00097 dict_drop_index_tree(btr_pcur_get_rec(&(node->pcur)), &mtr);
00098
00099 mtr_commit(&mtr);
00100
00101 mtr_start(&mtr);
00102
00103 success = btr_pcur_restore_position(BTR_MODIFY_LEAF,
00104 &(node->pcur), &mtr);
00105 ut_a(success);
00106 }
00107
00108 btr_cur = btr_pcur_get_btr_cur(&(node->pcur));
00109
00110 success = btr_cur_optimistic_delete(btr_cur, &mtr);
00111
00112 btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
00113
00114 if (success) {
00115 trx_undo_rec_release(node->trx, node->undo_no);
00116
00117 return(DB_SUCCESS);
00118 }
00119 retry:
00120
00121 mtr_start(&mtr);
00122
00123 success = btr_pcur_restore_position(BTR_MODIFY_TREE,
00124 &(node->pcur), &mtr);
00125 ut_a(success);
00126
00127 btr_cur_pessimistic_delete(&err, FALSE, btr_cur,
00128 trx_is_recv(node->trx)
00129 ? RB_RECOVERY
00130 : RB_NORMAL, &mtr);
00131
00132
00133
00134
00135
00136 if (err == DB_OUT_OF_FILE_SPACE
00137 && n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) {
00138
00139 btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
00140
00141 n_tries++;
00142
00143 os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME);
00144
00145 goto retry;
00146 }
00147
00148 btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
00149
00150 trx_undo_rec_release(node->trx, node->undo_no);
00151
00152 return(err);
00153 }
00154
00155
00158 static
00159 ulint
00160 row_undo_ins_remove_sec_low(
00161
00162 ulint mode,
00165 dict_index_t* index,
00166 dtuple_t* entry)
00167 {
00168 btr_pcur_t pcur;
00169 btr_cur_t* btr_cur;
00170 ulint err;
00171 mtr_t mtr;
00172 enum row_search_result search_result;
00173
00174 mtr_start(&mtr);
00175
00176 btr_cur = btr_pcur_get_btr_cur(&pcur);
00177
00178 ut_ad(mode == BTR_MODIFY_TREE || mode == BTR_MODIFY_LEAF);
00179
00180 search_result = row_search_index_entry(index, entry, mode,
00181 &pcur, &mtr);
00182
00183 switch (search_result) {
00184 case ROW_NOT_FOUND:
00185 err = DB_SUCCESS;
00186 goto func_exit;
00187 case ROW_FOUND:
00188 break;
00189 case ROW_BUFFERED:
00190 case ROW_NOT_DELETED_REF:
00191
00192
00193
00194 ut_error;
00195 }
00196
00197 if (mode == BTR_MODIFY_LEAF) {
00198 err = btr_cur_optimistic_delete(btr_cur, &mtr)
00199 ? DB_SUCCESS : DB_FAIL;
00200 } else {
00201 ut_ad(mode == BTR_MODIFY_TREE);
00202
00203
00204
00205
00206
00207
00208 ut_ad(!dict_index_is_clust(index));
00209 btr_cur_pessimistic_delete(&err, FALSE, btr_cur,
00210 RB_NORMAL, &mtr);
00211 }
00212 func_exit:
00213 btr_pcur_close(&pcur);
00214 mtr_commit(&mtr);
00215
00216 return(err);
00217 }
00218
00219
00223 static
00224 ulint
00225 row_undo_ins_remove_sec(
00226
00227 dict_index_t* index,
00228 dtuple_t* entry)
00229 {
00230 ulint err;
00231 ulint n_tries = 0;
00232
00233
00234
00235 err = row_undo_ins_remove_sec_low(BTR_MODIFY_LEAF, index, entry);
00236
00237 if (err == DB_SUCCESS) {
00238
00239 return(err);
00240 }
00241
00242
00243 retry:
00244 err = row_undo_ins_remove_sec_low(BTR_MODIFY_TREE, index, entry);
00245
00246
00247
00248
00249
00250 if (err != DB_SUCCESS && n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) {
00251
00252 n_tries++;
00253
00254 os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME);
00255
00256 goto retry;
00257 }
00258
00259 return(err);
00260 }
00261
00262
00264 static
00265 void
00266 row_undo_ins_parse_undo_rec(
00267
00268 undo_node_t* node)
00269 {
00270 dict_index_t* clust_index;
00271 byte* ptr;
00272 undo_no_t undo_no;
00273 table_id_t table_id;
00274 ulint type;
00275 ulint dummy;
00276 ibool dummy_extern;
00277
00278 ut_ad(node);
00279
00280 ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &dummy,
00281 &dummy_extern, &undo_no, &table_id);
00282 ut_ad(type == TRX_UNDO_INSERT_REC);
00283 node->rec_type = type;
00284
00285 node->update = NULL;
00286 node->table = dict_table_get_on_id(table_id, node->trx);
00287
00288
00289 if (UNIV_UNLIKELY(node->table == NULL)) {
00290 } else if (UNIV_UNLIKELY(node->table->ibd_file_missing)) {
00291 node->table = NULL;
00292 } else {
00293 clust_index = dict_table_get_first_index(node->table);
00294
00295 if (clust_index != NULL) {
00296 ptr = trx_undo_rec_get_row_ref(
00297 ptr, clust_index, &node->ref, node->heap);
00298 } else {
00299 ut_print_timestamp(stderr);
00300 fprintf(stderr, " InnoDB: table ");
00301 ut_print_name(stderr, node->trx, TRUE,
00302 node->table->name);
00303 fprintf(stderr, " has no indexes, "
00304 "ignoring the table\n");
00305
00306 node->table = NULL;
00307 }
00308 }
00309 }
00310
00311
00318 UNIV_INTERN
00319 ulint
00320 row_undo_ins(
00321
00322 undo_node_t* node)
00323 {
00324 ut_ad(node);
00325 ut_ad(node->state == UNDO_NODE_INSERT);
00326
00327 row_undo_ins_parse_undo_rec(node);
00328
00329 if (!node->table || !row_undo_search_clust_to_pcur(node)) {
00330 trx_undo_rec_release(node->trx, node->undo_no);
00331
00332 return(DB_SUCCESS);
00333 }
00334
00335
00336
00337
00338 node->index = dict_table_get_next_index(
00339 dict_table_get_first_index(node->table));
00340
00341 while (node->index != NULL) {
00342 dtuple_t* entry;
00343 ulint err;
00344
00345 entry = row_build_index_entry(node->row, node->ext,
00346 node->index, node->heap);
00347 if (UNIV_UNLIKELY(!entry)) {
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 ut_a(trx_is_recv(node->trx));
00358 } else {
00359 log_free_check();
00360 err = row_undo_ins_remove_sec(node->index, entry);
00361
00362 if (err != DB_SUCCESS) {
00363
00364 return(err);
00365 }
00366 }
00367
00368 node->index = dict_table_get_next_index(node->index);
00369 }
00370
00371 log_free_check();
00372 return(row_undo_ins_remove_clust_rec(node));
00373 }