row0uins.c
Upload User: tsgydb
Upload Date: 2007-04-14
Package Size: 10674k
Code Size: 7k
Category:

MySQL

Development Platform:

Visual C++

  1. /******************************************************
  2. Fresh insert undo
  3. (c) 1996 Innobase Oy
  4. Created 2/25/1997 Heikki Tuuri
  5. *******************************************************/
  6. #include "row0uins.h"
  7. #ifdef UNIV_NONINL
  8. #include "row0uins.ic"
  9. #endif
  10. #include "dict0dict.h"
  11. #include "dict0boot.h"
  12. #include "dict0crea.h"
  13. #include "trx0undo.h"
  14. #include "trx0roll.h"
  15. #include "btr0btr.h"
  16. #include "mach0data.h"
  17. #include "row0undo.h"
  18. #include "row0vers.h"
  19. #include "trx0trx.h"
  20. #include "trx0rec.h"
  21. #include "row0row.h"
  22. #include "row0upd.h"
  23. #include "que0que.h"
  24. #include "ibuf0ibuf.h"
  25. #include "log0log.h"
  26. /*******************************************************************
  27. Removes a clustered index record. The pcur in node was positioned on the
  28. record, now it is detached. */
  29. static
  30. ulint
  31. row_undo_ins_remove_clust_rec(
  32. /*==========================*/
  33. /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
  34. undo_node_t* node, /* in: undo node */
  35. que_thr_t* thr) /* in: query thread */
  36. {
  37. btr_cur_t* btr_cur;
  38. ibool success;
  39. ulint err;
  40. ulint n_tries = 0;
  41. mtr_t mtr;
  42. UT_NOT_USED(thr);
  43. mtr_start(&mtr);
  44. success = btr_pcur_restore_position(BTR_MODIFY_LEAF, &(node->pcur),
  45. &mtr);
  46. ut_a(success);
  47. if (ut_dulint_cmp(node->table->id, DICT_INDEXES_ID) == 0) {
  48. /* Drop the index tree associated with the row in
  49. SYS_INDEXES table: */
  50. dict_drop_index_tree(btr_pcur_get_rec(&(node->pcur)), &mtr);
  51. mtr_commit(&mtr);
  52. mtr_start(&mtr);
  53. success = btr_pcur_restore_position(BTR_MODIFY_LEAF,
  54. &(node->pcur), &mtr);
  55. ut_a(success);
  56. }
  57. btr_cur = btr_pcur_get_btr_cur(&(node->pcur));
  58. success = btr_cur_optimistic_delete(btr_cur, &mtr);
  59. btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
  60. if (success) {
  61. trx_undo_rec_release(node->trx, node->undo_no);
  62. return(DB_SUCCESS);
  63. }
  64. retry:
  65. /* If did not succeed, try pessimistic descent to tree */
  66. mtr_start(&mtr);
  67. success = btr_pcur_restore_position(BTR_MODIFY_TREE,
  68. &(node->pcur), &mtr);
  69. ut_a(success);
  70. btr_cur_pessimistic_delete(&err, FALSE, btr_cur, &mtr);
  71. /* The delete operation may fail if we have little
  72. file space left: TODO: easiest to crash the database
  73. and restart with more file space */
  74. if (err == DB_OUT_OF_FILE_SPACE
  75. && n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) {
  76. btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
  77. n_tries++;
  78. os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME);
  79. goto retry;
  80. }
  81. btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
  82. trx_undo_rec_release(node->trx, node->undo_no);
  83. return(err);
  84. }
  85. /*******************************************************************
  86. Removes a secondary index entry if found. */
  87. static
  88. ulint
  89. row_undo_ins_remove_sec_low(
  90. /*========================*/
  91. /* out: DB_SUCCESS, DB_FAIL, or
  92. DB_OUT_OF_FILE_SPACE */
  93. ulint mode, /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
  94. depending on whether we wish optimistic or
  95. pessimistic descent down the index tree */
  96. dict_index_t* index, /* in: index */
  97. dtuple_t* entry, /* in: index entry to remove */
  98. que_thr_t* thr) /* in: query thread */
  99. {
  100. btr_pcur_t pcur;
  101. btr_cur_t* btr_cur;
  102. ibool found;
  103. ibool success;
  104. ulint err;
  105. mtr_t mtr;
  106. UT_NOT_USED(thr);
  107. log_free_check();
  108. mtr_start(&mtr);
  109. found = row_search_index_entry(index, entry, mode, &pcur, &mtr);
  110. btr_cur = btr_pcur_get_btr_cur(&pcur);
  111. if (!found) {
  112. /* Not found */
  113. /* FIXME: remove printfs in the final version */
  114. /* printf(
  115. "--UNDO INS: Record not found from page %lu index %sn",
  116. buf_frame_get_page_no(btr_cur_get_rec(btr_cur)),
  117. index->name); */
  118. /* ibuf_print(); */
  119. btr_pcur_close(&pcur);
  120. mtr_commit(&mtr);
  121. return(DB_SUCCESS);
  122. }
  123. if (mode == BTR_MODIFY_LEAF) {
  124. success = btr_cur_optimistic_delete(btr_cur, &mtr);
  125. if (success) {
  126. err = DB_SUCCESS;
  127. } else {
  128. err = DB_FAIL;
  129. }
  130. } else {
  131. ut_ad(mode == BTR_MODIFY_TREE);
  132. btr_cur_pessimistic_delete(&err, FALSE, btr_cur, &mtr);
  133. }
  134. btr_pcur_close(&pcur);
  135. mtr_commit(&mtr);
  136. return(err);
  137. }
  138. /*******************************************************************
  139. Removes a secondary index entry from the index if found. Tries first
  140. optimistic, then pessimistic descent down the tree. */
  141. static
  142. ulint
  143. row_undo_ins_remove_sec(
  144. /*====================*/
  145. /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
  146. dict_index_t* index, /* in: index */
  147. dtuple_t* entry, /* in: index entry to insert */
  148. que_thr_t* thr) /* in: query thread */
  149. {
  150. ulint err;
  151. ulint n_tries = 0;
  152. /* Try first optimistic descent to the B-tree */
  153. err = row_undo_ins_remove_sec_low(BTR_MODIFY_LEAF, index, entry, thr);
  154. if (err == DB_SUCCESS) {
  155. return(err);
  156. }
  157. /* Try then pessimistic descent to the B-tree */
  158. retry:
  159. err = row_undo_ins_remove_sec_low(BTR_MODIFY_TREE, index, entry, thr);
  160. /* The delete operation may fail if we have little
  161. file space left: TODO: easiest to crash the database
  162. and restart with more file space */
  163. if (err != DB_SUCCESS && n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) {
  164. n_tries++;
  165. os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME);
  166. goto retry;
  167. }
  168. return(err);
  169. }
  170. /***************************************************************
  171. Parses the row reference and other info in a fresh insert undo record. */
  172. static
  173. void
  174. row_undo_ins_parse_undo_rec(
  175. /*========================*/
  176. undo_node_t* node, /* in: row undo node */
  177. que_thr_t* thr) /* in: query thread */
  178. {
  179. dict_index_t* clust_index;
  180. byte* ptr;
  181. dulint undo_no;
  182. dulint table_id;
  183. ulint type;
  184. ulint dummy;
  185. ut_ad(node && thr);
  186. ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &dummy, &undo_no,
  187. &table_id);
  188. ut_ad(type == TRX_UNDO_INSERT_REC);
  189. node->rec_type = type;
  190. /* NOTE that the table has to be explicitly released later */
  191. node->table = dict_table_get_on_id(table_id, node->trx);
  192. clust_index = dict_table_get_first_index(node->table);
  193. ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref),
  194. node->heap);
  195. }
  196. /***************************************************************
  197. Undoes a fresh insert of a row to a table. A fresh insert means that
  198. the same clustered index unique key did not have any record, even delete
  199. marked, at the time of the insert. */
  200. ulint
  201. row_undo_ins(
  202. /*=========*/
  203. /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
  204. undo_node_t* node, /* in: row undo node */
  205. que_thr_t* thr) /* in: query thread */
  206. {
  207. dtuple_t* entry;
  208. ibool found;
  209. ulint err;
  210. ut_ad(node && thr);
  211. ut_ad(node->state == UNDO_NODE_INSERT);
  212. row_undo_ins_parse_undo_rec(node, thr);
  213. found = row_undo_search_clust_to_pcur(node, thr);
  214. if (!found) {
  215. return(DB_SUCCESS);
  216. }
  217. node->index = dict_table_get_next_index(
  218. dict_table_get_first_index(node->table));
  219. while (node->index != NULL) {
  220. entry = row_build_index_entry(node->row, node->index,
  221. node->heap);
  222. err = row_undo_ins_remove_sec(node->index, entry, thr);
  223. if (err != DB_SUCCESS) {
  224. return(err);
  225. }
  226. node->index = dict_table_get_next_index(node->index);
  227. }
  228. err = row_undo_ins_remove_clust_rec(node, thr);
  229. return(err);
  230. }