You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

372 lines
9.8 KiB

  1. /*****************************************************************************
  2. Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
  3. This program is free software; you can redistribute it and/or modify it under
  4. the terms of the GNU General Public License as published by the Free Software
  5. Foundation; version 2 of the License.
  6. This program is distributed in the hope that it will be useful, but WITHOUT
  7. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along with
  10. this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  11. Place, Suite 330, Boston, MA 02111-1307 USA
  12. *****************************************************************************/
  13. /**************************************************//**
  14. @file include/trx0sys.ic
  15. Transaction system
  16. Created 3/26/1996 Heikki Tuuri
  17. *******************************************************/
  18. #include "trx0trx.h"
  19. #include "data0type.h"
  20. #ifndef UNIV_HOTBACKUP
  21. # include "srv0srv.h"
  22. # include "mtr0log.h"
  23. /* The typedef for rseg slot in the file copy */
  24. typedef byte trx_sysf_rseg_t;
  25. /* Rollback segment specification slot offsets */
  26. /*-------------------------------------------------------------*/
  27. #define TRX_SYS_RSEG_SPACE 0 /* space where the segment
  28. header is placed; starting with
  29. MySQL/InnoDB 5.1.7, this is
  30. UNIV_UNDEFINED if the slot is unused */
  31. #define TRX_SYS_RSEG_PAGE_NO 4 /* page number where the segment
  32. header is placed; this is FIL_NULL
  33. if the slot is unused */
  34. /*-------------------------------------------------------------*/
  35. /* Size of a rollback segment specification slot */
  36. #define TRX_SYS_RSEG_SLOT_SIZE 8
  37. /*****************************************************************//**
  38. Writes the value of max_trx_id to the file based trx system header. */
  39. UNIV_INTERN
  40. void
  41. trx_sys_flush_max_trx_id(void);
  42. /*==========================*/
  43. /***************************************************************//**
  44. Checks if a page address is the trx sys header page.
  45. @return TRUE if trx sys header page */
  46. UNIV_INLINE
  47. ibool
  48. trx_sys_hdr_page(
  49. /*=============*/
  50. ulint space, /*!< in: space */
  51. ulint page_no)/*!< in: page number */
  52. {
  53. if ((space == TRX_SYS_SPACE) && (page_no == TRX_SYS_PAGE_NO)) {
  54. return(TRUE);
  55. }
  56. return(FALSE);
  57. }
  58. /***************************************************************//**
  59. Gets the pointer in the nth slot of the rseg array.
  60. @return pointer to rseg object, NULL if slot not in use */
  61. UNIV_INLINE
  62. trx_rseg_t*
  63. trx_sys_get_nth_rseg(
  64. /*=================*/
  65. trx_sys_t* sys, /*!< in: trx system */
  66. ulint n) /*!< in: index of slot */
  67. {
  68. ut_ad(mutex_own(&(kernel_mutex)));
  69. ut_ad(n < TRX_SYS_N_RSEGS);
  70. return(sys->rseg_array[n]);
  71. }
  72. /***************************************************************//**
  73. Sets the pointer in the nth slot of the rseg array. */
  74. UNIV_INLINE
  75. void
  76. trx_sys_set_nth_rseg(
  77. /*=================*/
  78. trx_sys_t* sys, /*!< in: trx system */
  79. ulint n, /*!< in: index of slot */
  80. trx_rseg_t* rseg) /*!< in: pointer to rseg object, NULL if slot
  81. not in use */
  82. {
  83. ut_ad(n < TRX_SYS_N_RSEGS);
  84. sys->rseg_array[n] = rseg;
  85. }
  86. /**********************************************************************//**
  87. Gets a pointer to the transaction system header and x-latches its page.
  88. @return pointer to system header, page x-latched. */
  89. UNIV_INLINE
  90. trx_sysf_t*
  91. trx_sysf_get(
  92. /*=========*/
  93. mtr_t* mtr) /*!< in: mtr */
  94. {
  95. buf_block_t* block;
  96. trx_sysf_t* header;
  97. ut_ad(mtr);
  98. block = buf_page_get(TRX_SYS_SPACE, 0, TRX_SYS_PAGE_NO,
  99. RW_X_LATCH, mtr);
  100. buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER);
  101. header = TRX_SYS + buf_block_get_frame(block);
  102. return(header);
  103. }
  104. /*****************************************************************//**
  105. Gets the space of the nth rollback segment slot in the trx system
  106. file copy.
  107. @return space id */
  108. UNIV_INLINE
  109. ulint
  110. trx_sysf_rseg_get_space(
  111. /*====================*/
  112. trx_sysf_t* sys_header, /*!< in: trx sys header */
  113. ulint i, /*!< in: slot index == rseg id */
  114. mtr_t* mtr) /*!< in: mtr */
  115. {
  116. ut_ad(mutex_own(&(kernel_mutex)));
  117. ut_ad(sys_header);
  118. ut_ad(i < TRX_SYS_N_RSEGS);
  119. return(mtr_read_ulint(sys_header + TRX_SYS_RSEGS
  120. + i * TRX_SYS_RSEG_SLOT_SIZE
  121. + TRX_SYS_RSEG_SPACE, MLOG_4BYTES, mtr));
  122. }
  123. /*****************************************************************//**
  124. Gets the page number of the nth rollback segment slot in the trx system
  125. header.
  126. @return page number, FIL_NULL if slot unused */
  127. UNIV_INLINE
  128. ulint
  129. trx_sysf_rseg_get_page_no(
  130. /*======================*/
  131. trx_sysf_t* sys_header, /*!< in: trx system header */
  132. ulint i, /*!< in: slot index == rseg id */
  133. mtr_t* mtr) /*!< in: mtr */
  134. {
  135. ut_ad(sys_header);
  136. ut_ad(mutex_own(&(kernel_mutex)));
  137. ut_ad(i < TRX_SYS_N_RSEGS);
  138. return(mtr_read_ulint(sys_header + TRX_SYS_RSEGS
  139. + i * TRX_SYS_RSEG_SLOT_SIZE
  140. + TRX_SYS_RSEG_PAGE_NO, MLOG_4BYTES, mtr));
  141. }
  142. /*****************************************************************//**
  143. Sets the space id of the nth rollback segment slot in the trx system
  144. file copy. */
  145. UNIV_INLINE
  146. void
  147. trx_sysf_rseg_set_space(
  148. /*====================*/
  149. trx_sysf_t* sys_header, /*!< in: trx sys file copy */
  150. ulint i, /*!< in: slot index == rseg id */
  151. ulint space, /*!< in: space id */
  152. mtr_t* mtr) /*!< in: mtr */
  153. {
  154. ut_ad(mutex_own(&(kernel_mutex)));
  155. ut_ad(sys_header);
  156. ut_ad(i < TRX_SYS_N_RSEGS);
  157. mlog_write_ulint(sys_header + TRX_SYS_RSEGS
  158. + i * TRX_SYS_RSEG_SLOT_SIZE
  159. + TRX_SYS_RSEG_SPACE,
  160. space,
  161. MLOG_4BYTES, mtr);
  162. }
  163. /*****************************************************************//**
  164. Sets the page number of the nth rollback segment slot in the trx system
  165. header. */
  166. UNIV_INLINE
  167. void
  168. trx_sysf_rseg_set_page_no(
  169. /*======================*/
  170. trx_sysf_t* sys_header, /*!< in: trx sys header */
  171. ulint i, /*!< in: slot index == rseg id */
  172. ulint page_no, /*!< in: page number, FIL_NULL if the
  173. slot is reset to unused */
  174. mtr_t* mtr) /*!< in: mtr */
  175. {
  176. ut_ad(mutex_own(&(kernel_mutex)));
  177. ut_ad(sys_header);
  178. ut_ad(i < TRX_SYS_N_RSEGS);
  179. mlog_write_ulint(sys_header + TRX_SYS_RSEGS
  180. + i * TRX_SYS_RSEG_SLOT_SIZE
  181. + TRX_SYS_RSEG_PAGE_NO,
  182. page_no,
  183. MLOG_4BYTES, mtr);
  184. }
  185. #endif /* !UNIV_HOTBACKUP */
  186. /*****************************************************************//**
  187. Writes a trx id to an index page. In case that the id size changes in
  188. some future version, this function should be used instead of
  189. mach_write_... */
  190. UNIV_INLINE
  191. void
  192. trx_write_trx_id(
  193. /*=============*/
  194. byte* ptr, /*!< in: pointer to memory where written */
  195. trx_id_t id) /*!< in: id */
  196. {
  197. #if DATA_TRX_ID_LEN != 6
  198. # error "DATA_TRX_ID_LEN != 6"
  199. #endif
  200. mach_write_to_6(ptr, id);
  201. }
  202. #ifndef UNIV_HOTBACKUP
  203. /*****************************************************************//**
  204. Reads a trx id from an index page. In case that the id size changes in
  205. some future version, this function should be used instead of
  206. mach_read_...
  207. @return id */
  208. UNIV_INLINE
  209. trx_id_t
  210. trx_read_trx_id(
  211. /*============*/
  212. const byte* ptr) /*!< in: pointer to memory from where to read */
  213. {
  214. #if DATA_TRX_ID_LEN != 6
  215. # error "DATA_TRX_ID_LEN != 6"
  216. #endif
  217. return(mach_read_from_6(ptr));
  218. }
  219. /****************************************************************//**
  220. Looks for the trx handle with the given id in trx_list.
  221. @return the trx handle or NULL if not found */
  222. UNIV_INLINE
  223. trx_t*
  224. trx_get_on_id(
  225. /*==========*/
  226. trx_id_t trx_id) /*!< in: trx id to search for */
  227. {
  228. trx_t* trx;
  229. ut_ad(mutex_own(&(kernel_mutex)));
  230. trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
  231. while (trx != NULL) {
  232. if (trx_id == trx->id) {
  233. return(trx);
  234. }
  235. trx = UT_LIST_GET_NEXT(trx_list, trx);
  236. }
  237. return(NULL);
  238. }
  239. /****************************************************************//**
  240. Returns the minumum trx id in trx list. This is the smallest id for which
  241. the trx can possibly be active. (But, you must look at the trx->conc_state to
  242. find out if the minimum trx id transaction itself is active, or already
  243. committed.)
  244. @return the minimum trx id, or trx_sys->max_trx_id if the trx list is empty */
  245. UNIV_INLINE
  246. trx_id_t
  247. trx_list_get_min_trx_id(void)
  248. /*=========================*/
  249. {
  250. trx_t* trx;
  251. ut_ad(mutex_own(&(kernel_mutex)));
  252. trx = UT_LIST_GET_LAST(trx_sys->trx_list);
  253. if (trx == NULL) {
  254. return(trx_sys->max_trx_id);
  255. }
  256. return(trx->id);
  257. }
  258. /****************************************************************//**
  259. Checks if a transaction with the given id is active.
  260. @return TRUE if active */
  261. UNIV_INLINE
  262. ibool
  263. trx_is_active(
  264. /*==========*/
  265. trx_id_t trx_id) /*!< in: trx id of the transaction */
  266. {
  267. trx_t* trx;
  268. ut_ad(mutex_own(&(kernel_mutex)));
  269. if (trx_id < trx_list_get_min_trx_id()) {
  270. return(FALSE);
  271. }
  272. if (UNIV_UNLIKELY(trx_id >= trx_sys->max_trx_id)) {
  273. /* There must be corruption: we return TRUE because this
  274. function is only called by lock_clust_rec_some_has_impl()
  275. and row_vers_impl_x_locked_off_kernel() and they have
  276. diagnostic prints in this case */
  277. return(TRUE);
  278. }
  279. trx = trx_get_on_id(trx_id);
  280. if (trx && (trx->conc_state == TRX_ACTIVE
  281. || trx->conc_state == TRX_PREPARED)) {
  282. return(TRUE);
  283. }
  284. return(FALSE);
  285. }
  286. /*****************************************************************//**
  287. Allocates a new transaction id.
  288. @return new, allocated trx id */
  289. UNIV_INLINE
  290. trx_id_t
  291. trx_sys_get_new_trx_id(void)
  292. /*========================*/
  293. {
  294. trx_id_t id;
  295. ut_ad(mutex_own(&kernel_mutex));
  296. /* VERY important: after the database is started, max_trx_id value is
  297. divisible by TRX_SYS_TRX_ID_WRITE_MARGIN, and the following if
  298. will evaluate to TRUE when this function is first time called,
  299. and the value for trx id will be written to disk-based header!
  300. Thus trx id values will not overlap when the database is
  301. repeatedly started! */
  302. if ((ulint) trx_sys->max_trx_id % TRX_SYS_TRX_ID_WRITE_MARGIN == 0) {
  303. trx_sys_flush_max_trx_id();
  304. }
  305. id = trx_sys->max_trx_id++;
  306. return(id);
  307. }
  308. #endif /* !UNIV_HOTBACKUP */