00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "row0umod.h"
00027
00028 #ifdef UNIV_NONINL
00029 #include "row0umod.ic"
00030 #endif
00031
00032 #include "dict0dict.h"
00033 #include "dict0boot.h"
00034 #include "trx0undo.h"
00035 #include "trx0roll.h"
00036 #include "btr0btr.h"
00037 #include "mach0data.h"
00038 #include "row0undo.h"
00039 #include "row0vers.h"
00040 #include "trx0trx.h"
00041 #include "trx0rec.h"
00042 #include "row0row.h"
00043 #include "row0upd.h"
00044 #include "que0que.h"
00045 #include "log0log.h"
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00076 static
00077 ibool
00078 row_undo_mod_undo_also_prev_vers(
00079
00080 undo_node_t* node,
00081 undo_no_t* undo_no)
00082 {
00083 trx_undo_rec_t* undo_rec;
00084 trx_t* trx;
00085
00086 trx = node->trx;
00087
00088 if (node->new_trx_id != trx->id) {
00089
00090 *undo_no = 0;
00091 return(FALSE);
00092 }
00093
00094 undo_rec = trx_undo_get_undo_rec_low(node->new_roll_ptr, node->heap);
00095
00096 *undo_no = trx_undo_rec_get_undo_no(undo_rec);
00097
00098 return(trx->roll_limit <= *undo_no);
00099 }
00100
00101
00104 static
00105 ulint
00106 row_undo_mod_clust_low(
00107
00108 undo_node_t* node,
00109 que_thr_t* thr,
00110 mtr_t* mtr,
00112 ulint mode)
00113 {
00114 btr_pcur_t* pcur;
00115 btr_cur_t* btr_cur;
00116 ulint err;
00117 #ifdef UNIV_DEBUG
00118 ibool success;
00119 #endif
00120
00121 pcur = &(node->pcur);
00122 btr_cur = btr_pcur_get_btr_cur(pcur);
00123
00124 #ifdef UNIV_DEBUG
00125 success =
00126 #endif
00127 btr_pcur_restore_position(mode, pcur, mtr);
00128
00129 ut_ad(success);
00130
00131 if (mode == BTR_MODIFY_LEAF) {
00132
00133 err = btr_cur_optimistic_update(BTR_NO_LOCKING_FLAG
00134 | BTR_NO_UNDO_LOG_FLAG
00135 | BTR_KEEP_SYS_FLAG,
00136 btr_cur, node->update,
00137 node->cmpl_info, thr, mtr);
00138 } else {
00139 mem_heap_t* heap = NULL;
00140 big_rec_t* dummy_big_rec;
00141
00142 ut_ad(mode == BTR_MODIFY_TREE);
00143
00144 err = btr_cur_pessimistic_update(
00145 BTR_NO_LOCKING_FLAG
00146 | BTR_NO_UNDO_LOG_FLAG
00147 | BTR_KEEP_SYS_FLAG,
00148 btr_cur, &heap, &dummy_big_rec, node->update,
00149 node->cmpl_info, thr, mtr);
00150
00151 ut_a(!dummy_big_rec);
00152 if (UNIV_LIKELY_NULL(heap)) {
00153 mem_heap_free(heap);
00154 }
00155 }
00156
00157 return(err);
00158 }
00159
00160
00167 static
00168 ulint
00169 row_undo_mod_remove_clust_low(
00170
00171 undo_node_t* node,
00172 que_thr_t* thr,
00173 mtr_t* mtr,
00174 ulint mode)
00175 {
00176 btr_pcur_t* pcur;
00177 btr_cur_t* btr_cur;
00178 ulint err;
00179 ibool success;
00180
00181 ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC);
00182 pcur = &(node->pcur);
00183 btr_cur = btr_pcur_get_btr_cur(pcur);
00184
00185 success = btr_pcur_restore_position(mode, pcur, mtr);
00186
00187 if (!success) {
00188
00189 return(DB_SUCCESS);
00190 }
00191
00192
00193
00194 if (node->rec_type == TRX_UNDO_UPD_DEL_REC
00195 && !row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) {
00196
00197
00198 } else {
00199 return(DB_SUCCESS);
00200 }
00201
00202 if (mode == BTR_MODIFY_LEAF) {
00203 success = btr_cur_optimistic_delete(btr_cur, mtr);
00204
00205 if (success) {
00206 err = DB_SUCCESS;
00207 } else {
00208 err = DB_FAIL;
00209 }
00210 } else {
00211 ut_ad(mode == BTR_MODIFY_TREE);
00212
00213
00214
00215
00216 btr_cur_pessimistic_delete(&err, FALSE, btr_cur,
00217 thr_is_recv(thr)
00218 ? RB_RECOVERY_PURGE_REC
00219 : RB_NONE, mtr);
00220
00221
00222
00223
00224 }
00225
00226 return(err);
00227 }
00228
00229
00233 static
00234 ulint
00235 row_undo_mod_clust(
00236
00237 undo_node_t* node,
00238 que_thr_t* thr)
00239 {
00240 btr_pcur_t* pcur;
00241 mtr_t mtr;
00242 ulint err;
00243 ibool success;
00244 ibool more_vers;
00245 undo_no_t new_undo_no;
00246
00247 ut_ad(node && thr);
00248
00249 log_free_check();
00250
00251
00252
00253
00254 more_vers = row_undo_mod_undo_also_prev_vers(node, &new_undo_no);
00255
00256 pcur = &(node->pcur);
00257
00258 mtr_start(&mtr);
00259
00260
00261
00262
00263 err = row_undo_mod_clust_low(node, thr, &mtr, BTR_MODIFY_LEAF);
00264
00265 if (err != DB_SUCCESS) {
00266 btr_pcur_commit_specify_mtr(pcur, &mtr);
00267
00268
00269
00270
00271 mtr_start(&mtr);
00272
00273 err = row_undo_mod_clust_low(node, thr, &mtr, BTR_MODIFY_TREE);
00274 }
00275
00276 btr_pcur_commit_specify_mtr(pcur, &mtr);
00277
00278 if (err == DB_SUCCESS && node->rec_type == TRX_UNDO_UPD_DEL_REC) {
00279
00280 mtr_start(&mtr);
00281
00282 err = row_undo_mod_remove_clust_low(node, thr, &mtr,
00283 BTR_MODIFY_LEAF);
00284 if (err != DB_SUCCESS) {
00285 btr_pcur_commit_specify_mtr(pcur, &mtr);
00286
00287
00288
00289
00290 mtr_start(&mtr);
00291
00292 err = row_undo_mod_remove_clust_low(node, thr, &mtr,
00293 BTR_MODIFY_TREE);
00294 }
00295
00296 btr_pcur_commit_specify_mtr(pcur, &mtr);
00297 }
00298
00299 node->state = UNDO_NODE_FETCH_NEXT;
00300
00301 trx_undo_rec_release(node->trx, node->undo_no);
00302
00303 if (more_vers && err == DB_SUCCESS) {
00304
00305
00306
00307
00308
00309
00310 success = trx_undo_rec_reserve(node->trx, new_undo_no);
00311
00312 if (success) {
00313 node->state = UNDO_NODE_PREV_VERS;
00314 }
00315 }
00316
00317 return(err);
00318 }
00319
00320
00323 static
00324 ulint
00325 row_undo_mod_del_mark_or_remove_sec_low(
00326
00327 undo_node_t* node,
00328 que_thr_t* thr,
00329 dict_index_t* index,
00330 dtuple_t* entry,
00331 ulint mode)
00333 {
00334 btr_pcur_t pcur;
00335 btr_cur_t* btr_cur;
00336 ibool success;
00337 ibool old_has;
00338 ulint err;
00339 mtr_t mtr;
00340 mtr_t mtr_vers;
00341 enum row_search_result search_result;
00342
00343 log_free_check();
00344 mtr_start(&mtr);
00345
00346 btr_cur = btr_pcur_get_btr_cur(&pcur);
00347
00348 ut_ad(mode == BTR_MODIFY_TREE || mode == BTR_MODIFY_LEAF);
00349
00350 search_result = row_search_index_entry(index, entry, mode,
00351 &pcur, &mtr);
00352
00353 switch (UNIV_EXPECT(search_result, ROW_FOUND)) {
00354 case ROW_NOT_FOUND:
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 err = DB_SUCCESS;
00366 goto func_exit;
00367 case ROW_FOUND:
00368 break;
00369 case ROW_BUFFERED:
00370 case ROW_NOT_DELETED_REF:
00371
00372
00373
00374 ut_error;
00375 }
00376
00377
00378
00379
00380
00381 mtr_start(&mtr_vers);
00382
00383 success = btr_pcur_restore_position(BTR_SEARCH_LEAF, &(node->pcur),
00384 &mtr_vers);
00385 ut_a(success);
00386
00387 old_has = row_vers_old_has_index_entry(FALSE,
00388 btr_pcur_get_rec(&(node->pcur)),
00389 &mtr_vers, index, entry);
00390 if (old_has) {
00391 err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG,
00392 btr_cur, TRUE, thr, &mtr);
00393 ut_ad(err == DB_SUCCESS);
00394 } else {
00395
00396
00397 if (mode == BTR_MODIFY_LEAF) {
00398 success = btr_cur_optimistic_delete(btr_cur, &mtr);
00399 if (success) {
00400 err = DB_SUCCESS;
00401 } else {
00402 err = DB_FAIL;
00403 }
00404 } else {
00405 ut_ad(mode == BTR_MODIFY_TREE);
00406
00407
00408
00409
00410
00411
00412
00413 ut_ad(!dict_index_is_clust(index));
00414 btr_cur_pessimistic_delete(&err, FALSE, btr_cur,
00415 RB_NORMAL, &mtr);
00416
00417
00418
00419
00420 }
00421 }
00422
00423 btr_pcur_commit_specify_mtr(&(node->pcur), &mtr_vers);
00424
00425 func_exit:
00426 btr_pcur_close(&pcur);
00427 mtr_commit(&mtr);
00428
00429 return(err);
00430 }
00431
00432
00441 static
00442 ulint
00443 row_undo_mod_del_mark_or_remove_sec(
00444
00445 undo_node_t* node,
00446 que_thr_t* thr,
00447 dict_index_t* index,
00448 dtuple_t* entry)
00449 {
00450 ulint err;
00451
00452 err = row_undo_mod_del_mark_or_remove_sec_low(node, thr, index,
00453 entry, BTR_MODIFY_LEAF);
00454 if (err == DB_SUCCESS) {
00455
00456 return(err);
00457 }
00458
00459 err = row_undo_mod_del_mark_or_remove_sec_low(node, thr, index,
00460 entry, BTR_MODIFY_TREE);
00461 return(err);
00462 }
00463
00464
00470 static
00471 ulint
00472 row_undo_mod_del_unmark_sec_and_undo_update(
00473
00474 ulint mode,
00476 que_thr_t* thr,
00477 dict_index_t* index,
00478 const dtuple_t* entry)
00479 {
00480 mem_heap_t* heap;
00481 btr_pcur_t pcur;
00482 btr_cur_t* btr_cur;
00483 upd_t* update;
00484 ulint err = DB_SUCCESS;
00485 big_rec_t* dummy_big_rec;
00486 mtr_t mtr;
00487 trx_t* trx = thr_get_trx(thr);
00488 enum row_search_result search_result;
00489
00490
00491 if (UNIV_UNLIKELY(*index->name == TEMP_INDEX_PREFIX)) {
00492
00493 return(DB_SUCCESS);
00494 }
00495
00496 log_free_check();
00497 mtr_start(&mtr);
00498
00499 ut_ad(mode == BTR_MODIFY_TREE || mode == BTR_MODIFY_LEAF);
00500
00501 search_result = row_search_index_entry(index, entry, mode,
00502 &pcur, &mtr);
00503
00504 switch (search_result) {
00505 case ROW_BUFFERED:
00506 case ROW_NOT_DELETED_REF:
00507
00508
00509
00510 ut_error;
00511 case ROW_NOT_FOUND:
00512 fputs("InnoDB: error in sec index entry del undo in\n"
00513 "InnoDB: ", stderr);
00514 dict_index_name_print(stderr, trx, index);
00515 fputs("\n"
00516 "InnoDB: tuple ", stderr);
00517 dtuple_print(stderr, entry);
00518 fputs("\n"
00519 "InnoDB: record ", stderr);
00520 rec_print(stderr, btr_pcur_get_rec(&pcur), index);
00521 putc('\n', stderr);
00522 trx_print(stderr, trx, 0);
00523 fputs("\n"
00524 "InnoDB: Submit a detailed bug report"
00525 " to http://bugs.mysql.com\n", stderr);
00526 break;
00527 case ROW_FOUND:
00528 btr_cur = btr_pcur_get_btr_cur(&pcur);
00529 err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG,
00530 btr_cur, FALSE, thr, &mtr);
00531 ut_a(err == DB_SUCCESS);
00532 heap = mem_heap_create(100);
00533
00534 update = row_upd_build_sec_rec_difference_binary(
00535 index, entry, btr_cur_get_rec(btr_cur), trx, heap);
00536 if (upd_get_n_fields(update) == 0) {
00537
00538
00539
00540 } else if (mode == BTR_MODIFY_LEAF) {
00541
00542
00543
00544 err = btr_cur_optimistic_update(
00545 BTR_KEEP_SYS_FLAG | BTR_NO_LOCKING_FLAG,
00546 btr_cur, update, 0, thr, &mtr);
00547 switch (err) {
00548 case DB_OVERFLOW:
00549 case DB_UNDERFLOW:
00550 case DB_ZIP_OVERFLOW:
00551 err = DB_FAIL;
00552 }
00553 } else {
00554 ut_a(mode == BTR_MODIFY_TREE);
00555 err = btr_cur_pessimistic_update(
00556 BTR_KEEP_SYS_FLAG | BTR_NO_LOCKING_FLAG,
00557 btr_cur, &heap, &dummy_big_rec,
00558 update, 0, thr, &mtr);
00559 ut_a(!dummy_big_rec);
00560 }
00561
00562 mem_heap_free(heap);
00563 }
00564
00565 btr_pcur_close(&pcur);
00566 mtr_commit(&mtr);
00567
00568 return(err);
00569 }
00570
00571
00574 static
00575 ulint
00576 row_undo_mod_upd_del_sec(
00577
00578 undo_node_t* node,
00579 que_thr_t* thr)
00580 {
00581 mem_heap_t* heap;
00582 dtuple_t* entry;
00583 dict_index_t* index;
00584 ulint err = DB_SUCCESS;
00585
00586 ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC);
00587 heap = mem_heap_create(1024);
00588
00589 while (node->index != NULL) {
00590 index = node->index;
00591
00592 entry = row_build_index_entry(node->row, node->ext,
00593 index, heap);
00594 if (UNIV_UNLIKELY(!entry)) {
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 ut_a(thr_is_recv(thr));
00605 } else {
00606 err = row_undo_mod_del_mark_or_remove_sec(
00607 node, thr, index, entry);
00608
00609 if (err != DB_SUCCESS) {
00610
00611 break;
00612 }
00613 }
00614
00615 mem_heap_empty(heap);
00616
00617 node->index = dict_table_get_next_index(node->index);
00618 }
00619
00620 mem_heap_free(heap);
00621
00622 return(err);
00623 }
00624
00625
00628 static
00629 ulint
00630 row_undo_mod_del_mark_sec(
00631
00632 undo_node_t* node,
00633 que_thr_t* thr)
00634 {
00635 mem_heap_t* heap;
00636 dtuple_t* entry;
00637 dict_index_t* index;
00638 ulint err;
00639
00640 heap = mem_heap_create(1024);
00641
00642 while (node->index != NULL) {
00643 index = node->index;
00644
00645 entry = row_build_index_entry(node->row, node->ext,
00646 index, heap);
00647 ut_a(entry);
00648 err = row_undo_mod_del_unmark_sec_and_undo_update(
00649 BTR_MODIFY_LEAF, thr, index, entry);
00650 if (err == DB_FAIL) {
00651 err = row_undo_mod_del_unmark_sec_and_undo_update(
00652 BTR_MODIFY_TREE, thr, index, entry);
00653 }
00654
00655 if (err != DB_SUCCESS) {
00656
00657 mem_heap_free(heap);
00658
00659 return(err);
00660 }
00661
00662 node->index = dict_table_get_next_index(node->index);
00663 }
00664
00665 mem_heap_free(heap);
00666
00667 return(DB_SUCCESS);
00668 }
00669
00670
00673 static
00674 ulint
00675 row_undo_mod_upd_exist_sec(
00676
00677 undo_node_t* node,
00678 que_thr_t* thr)
00679 {
00680 mem_heap_t* heap;
00681 dtuple_t* entry;
00682 dict_index_t* index;
00683 ulint err;
00684
00685 if (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE) {
00686
00687
00688 return(DB_SUCCESS);
00689 }
00690
00691 heap = mem_heap_create(1024);
00692
00693 while (node->index != NULL) {
00694 index = node->index;
00695
00696 if (row_upd_changes_ord_field_binary(node->row, node->index,
00697 node->update)) {
00698
00699
00700 entry = row_build_index_entry(node->row, node->ext,
00701 index, heap);
00702 if (UNIV_UNLIKELY(!entry)) {
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 ut_a(dict_table_get_format(index->table)
00715 >= DICT_TF_FORMAT_ZIP);
00716
00717
00718
00719
00720 ut_a(thr_get_trx(thr)->is_recovered);
00721
00722
00723
00724
00725
00726
00727
00728
00729 } else {
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742 err = row_undo_mod_del_mark_or_remove_sec(
00743 node, thr, index, entry);
00744 if (err != DB_SUCCESS) {
00745 mem_heap_free(heap);
00746
00747 return(err);
00748 }
00749
00750 mem_heap_empty(heap);
00751 }
00752
00753
00754
00755
00756
00757
00758
00759 entry = row_build_index_entry(node->undo_row,
00760 node->undo_ext,
00761 index, heap);
00762 ut_a(entry);
00763
00764 err = row_undo_mod_del_unmark_sec_and_undo_update(
00765 BTR_MODIFY_LEAF, thr, index, entry);
00766 if (err == DB_FAIL) {
00767 err = row_undo_mod_del_unmark_sec_and_undo_update(
00768 BTR_MODIFY_TREE, thr, index, entry);
00769 }
00770
00771 if (err != DB_SUCCESS) {
00772 mem_heap_free(heap);
00773
00774 return(err);
00775 }
00776 }
00777
00778 node->index = dict_table_get_next_index(node->index);
00779 }
00780
00781 mem_heap_free(heap);
00782
00783 return(DB_SUCCESS);
00784 }
00785
00786
00788 static
00789 void
00790 row_undo_mod_parse_undo_rec(
00791
00792 undo_node_t* node,
00793 que_thr_t* thr)
00794 {
00795 dict_index_t* clust_index;
00796 byte* ptr;
00797 undo_no_t undo_no;
00798 table_id_t table_id;
00799 trx_id_t trx_id;
00800 roll_ptr_t roll_ptr;
00801 ulint info_bits;
00802 ulint type;
00803 ulint cmpl_info;
00804 ibool dummy_extern;
00805 trx_t* trx;
00806
00807 ut_ad(node && thr);
00808 trx = thr_get_trx(thr);
00809 ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info,
00810 &dummy_extern, &undo_no, &table_id);
00811 node->rec_type = type;
00812
00813 node->table = dict_table_get_on_id(table_id, trx);
00814
00815
00816
00817
00818 if (node->table == NULL) {
00819
00820 return;
00821 }
00822
00823 if (node->table->ibd_file_missing) {
00824
00825 node->table = NULL;
00826
00827 return;
00828 }
00829
00830 clust_index = dict_table_get_first_index(node->table);
00831
00832 ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr,
00833 &info_bits);
00834
00835 ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref),
00836 node->heap);
00837
00838 trx_undo_update_rec_get_update(ptr, clust_index, type, trx_id,
00839 roll_ptr, info_bits, trx,
00840 node->heap, &(node->update));
00841 node->new_roll_ptr = roll_ptr;
00842 node->new_trx_id = trx_id;
00843 node->cmpl_info = cmpl_info;
00844 }
00845
00846
00849 UNIV_INTERN
00850 ulint
00851 row_undo_mod(
00852
00853 undo_node_t* node,
00854 que_thr_t* thr)
00855 {
00856 ulint err;
00857
00858 ut_ad(node && thr);
00859 ut_ad(node->state == UNDO_NODE_MODIFY);
00860
00861 row_undo_mod_parse_undo_rec(node, thr);
00862
00863 if (!node->table || !row_undo_search_clust_to_pcur(node)) {
00864
00865
00866
00867 trx_undo_rec_release(node->trx, node->undo_no);
00868 node->state = UNDO_NODE_FETCH_NEXT;
00869
00870 return(DB_SUCCESS);
00871 }
00872
00873 node->index = dict_table_get_next_index(
00874 dict_table_get_first_index(node->table));
00875
00876 if (node->rec_type == TRX_UNDO_UPD_EXIST_REC) {
00877
00878 err = row_undo_mod_upd_exist_sec(node, thr);
00879
00880 } else if (node->rec_type == TRX_UNDO_DEL_MARK_REC) {
00881
00882 err = row_undo_mod_del_mark_sec(node, thr);
00883 } else {
00884 ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC);
00885 err = row_undo_mod_upd_del_sec(node, thr);
00886 }
00887
00888 if (err != DB_SUCCESS) {
00889
00890 return(err);
00891 }
00892
00893 err = row_undo_mod_clust(node, thr);
00894
00895 return(err);
00896 }