lock0lock.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:131k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /******************************************************
  2. The transaction lock system
  3. (c) 1996 Innobase Oy
  4. Created 5/7/1996 Heikki Tuuri
  5. *******************************************************/
  6. #include "lock0lock.h"
  7. #ifdef UNIV_NONINL
  8. #include "lock0lock.ic"
  9. #endif
  10. #include "usr0sess.h"
  11. #include "trx0purge.h"
  12. #include "dict0mem.h"
  13. #include "trx0sys.h"
  14. /* 2 function prototypes copied from ha_innodb.cc: */
  15. /*****************************************************************
  16. If you want to print a thd that is not associated with the current thread,
  17. you must call this function before reserving the InnoDB kernel_mutex, to
  18. protect MySQL from setting thd->query NULL. If you print a thd of the current
  19. thread, we know that MySQL cannot modify thd->query, and it is not necessary
  20. to call this. Call innobase_mysql_end_print_arbitrary_thd() after you release
  21. the kernel_mutex.
  22. NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
  23. function! */
  24. void
  25. innobase_mysql_prepare_print_arbitrary_thd(void);
  26. /*============================================*/
  27. /*****************************************************************
  28. Relases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
  29. NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
  30. function! */
  31. void
  32. innobase_mysql_end_print_arbitrary_thd(void);
  33. /*========================================*/
  34. /* Restricts the length of search we will do in the waits-for
  35. graph of transactions */
  36. #define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000
  37. /* When releasing transaction locks, this specifies how often we release
  38. the kernel mutex for a moment to give also others access to it */
  39. #define LOCK_RELEASE_KERNEL_INTERVAL 1000
  40. /* Safety margin when creating a new record lock: this many extra records
  41. can be inserted to the page without need to create a lock with a bigger
  42. bitmap */
  43. #define LOCK_PAGE_BITMAP_MARGIN 64
  44. /* An explicit record lock affects both the record and the gap before it.
  45. An implicit x-lock does not affect the gap, it only locks the index
  46. record from read or update. 
  47. If a transaction has modified or inserted an index record, then
  48. it owns an implicit x-lock on the record. On a secondary index record,
  49. a transaction has an implicit x-lock also if it has modified the
  50. clustered index record, the max trx id of the page where the secondary
  51. index record resides is >= trx id of the transaction (or database recovery
  52. is running), and there are no explicit non-gap lock requests on the
  53. secondary index record.
  54. This complicated definition for a secondary index comes from the
  55. implementation: we want to be able to determine if a secondary index
  56. record has an implicit x-lock, just by looking at the present clustered
  57. index record, not at the historical versions of the record. The
  58. complicated definition can be explained to the user so that there is
  59. nondeterminism in the access path when a query is answered: we may,
  60. or may not, access the clustered index record and thus may, or may not,
  61. bump into an x-lock set there.
  62. Different transaction can have conflicting locks set on the gap at the
  63. same time. The locks on the gap are purely inhibitive: an insert cannot
  64. be made, or a select cursor may have to wait if a different transaction
  65. has a conflicting lock on the gap. An x-lock on the gap does not give
  66. the right to insert into the gap.
  67. An explicit lock can be placed on a user record or the supremum record of
  68. a page. The locks on the supremum record are always thought to be of the gap
  69. type, though the gap bit is not set. When we perform an update of a record
  70. where the size of the record changes, we may temporarily store its explicit
  71. locks on the infimum record of the page, though the infimum otherwise never
  72. carries locks.
  73. A waiting record lock can also be of the gap type. A waiting lock request
  74. can be granted when there is no conflicting mode lock request by another
  75. transaction ahead of it in the explicit lock queue.
  76. In version 4.0.5 we added yet another explicit lock type: LOCK_REC_NOT_GAP.
  77. It only locks the record it is placed on, not the gap before the record.
  78. This lock type is necessary to emulate an Oracle-like READ COMMITTED isolation
  79. level.
  80. -------------------------------------------------------------------------
  81. RULE 1: If there is an implicit x-lock on a record, and there are non-gap
  82. -------
  83. lock requests waiting in the queue, then the transaction holding the implicit
  84. x-lock also has an explicit non-gap record x-lock. Therefore, as locks are
  85. released, we can grant locks to waiting lock requests purely by looking at
  86. the explicit lock requests in the queue.
  87. RULE 3: Different transactions cannot have conflicting granted non-gap locks
  88. -------
  89. on a record at the same time. However, they can have conflicting granted gap
  90. locks.
  91. RULE 4: If a there is a waiting lock request in a queue, no lock request,
  92. -------
  93. gap or not, can be inserted ahead of it in the queue. In record deletes
  94. and page splits new gap type locks can be created by the database manager
  95. for a transaction, and without rule 4, the waits-for graph of transactions
  96. might become cyclic without the database noticing it, as the deadlock check
  97. is only performed when a transaction itself requests a lock!
  98. -------------------------------------------------------------------------
  99. An insert is allowed to a gap if there are no explicit lock requests by
  100. other transactions on the next record. It does not matter if these lock
  101. requests are granted or waiting, gap bit set or not, with the exception
  102. that a gap type request set by another transaction to wait for
  103. its turn to do an insert is ignored. On the other hand, an
  104. implicit x-lock by another transaction does not prevent an insert, which
  105. allows for more concurrency when using an Oracle-style sequence number
  106. generator for the primary key with many transactions doing inserts
  107. concurrently.
  108. A modify of a record is allowed if the transaction has an x-lock on the
  109. record, or if other transactions do not have any non-gap lock requests on the
  110. record.
  111. A read of a single user record with a cursor is allowed if the transaction
  112. has a non-gap explicit, or an implicit lock on the record, or if the other
  113. transactions have no x-lock requests on the record. At a page supremum a
  114. read is always allowed.
  115. In summary, an implicit lock is seen as a granted x-lock only on the
  116. record, not on the gap. An explicit lock with no gap bit set is a lock
  117. both on the record and the gap. If the gap bit is set, the lock is only
  118. on the gap. Different transaction cannot own conflicting locks on the
  119. record at the same time, but they may own conflicting locks on the gap.
  120. Granted locks on a record give an access right to the record, but gap type
  121. locks just inhibit operations.
  122. NOTE: Finding out if some transaction has an implicit x-lock on a secondary
  123. index record can be cumbersome. We may have to look at previous versions of
  124. the corresponding clustered index record to find out if a delete marked
  125. secondary index record was delete marked by an active transaction, not by
  126. a committed one.
  127. FACT A: If a transaction has inserted a row, it can delete it any time
  128. without need to wait for locks.
  129. PROOF: The transaction has an implicit x-lock on every index record inserted
  130. for the row, and can thus modify each record without the need to wait. Q.E.D.
  131. FACT B: If a transaction has read some result set with a cursor, it can read
  132. it again, and retrieves the same result set, if it has not modified the
  133. result set in the meantime. Hence, there is no phantom problem. If the
  134. biggest record, in the alphabetical order, touched by the cursor is removed,
  135. a lock wait may occur, otherwise not.
  136. PROOF: When a read cursor proceeds, it sets an s-lock on each user record
  137. it passes, and a gap type s-lock on each page supremum. The cursor must
  138. wait until it has these locks granted. Then no other transaction can
  139. have a granted x-lock on any of the user records, and therefore cannot
  140. modify the user records. Neither can any other transaction insert into
  141. the gaps which were passed over by the cursor. Page splits and merges,
  142. and removal of obsolete versions of records do not affect this, because
  143. when a user record or a page supremum is removed, the next record inherits
  144. its locks as gap type locks, and therefore blocks inserts to the same gap.
  145. Also, if a page supremum is inserted, it inherits its locks from the successor
  146. record. When the cursor is positioned again at the start of the result set,
  147. the records it will touch on its course are either records it touched
  148. during the last pass or new inserted page supremums. It can immediately
  149. access all these records, and when it arrives at the biggest record, it
  150. notices that the result set is complete. If the biggest record was removed,
  151. lock wait can occur because the next record only inherits a gap type lock,
  152. and a wait may be needed. Q.E.D. */
  153. /* If an index record should be changed or a new inserted, we must check
  154. the lock on the record or the next. When a read cursor starts reading,
  155. we will set a record level s-lock on each record it passes, except on the
  156. initial record on which the cursor is positioned before we start to fetch
  157. records. Our index tree search has the convention that the B-tree
  158. cursor is positioned BEFORE the first possibly matching record in
  159. the search. Optimizations are possible here: if the record is searched
  160. on an equality condition to a unique key, we could actually set a special
  161. lock on the record, a lock which would not prevent any insert before
  162. this record. In the next key locking an x-lock set on a record also
  163. prevents inserts just before that record.
  164. There are special infimum and supremum records on each page.
  165. A supremum record can be locked by a read cursor. This records cannot be
  166. updated but the lock prevents insert of a user record to the end of
  167. the page.
  168. Next key locks will prevent the phantom problem where new rows
  169. could appear to SELECT result sets after the select operation has been
  170. performed. Prevention of phantoms ensures the serilizability of
  171. transactions.
  172. What should we check if an insert of a new record is wanted?
  173. Only the lock on the next record on the same page, because also the
  174. supremum record can carry a lock. An s-lock prevents insertion, but
  175. what about an x-lock? If it was set by a searched update, then there
  176. is implicitly an s-lock, too, and the insert should be prevented.
  177. What if our transaction owns an x-lock to the next record, but there is
  178. a waiting s-lock request on the next record? If this s-lock was placed
  179. by a read cursor moving in the ascending order in the index, we cannot
  180. do the insert immediately, because when we finally commit our transaction,
  181. the read cursor should see also the new inserted record. So we should
  182. move the read cursor backward from the the next record for it to pass over
  183. the new inserted record. This move backward may be too cumbersome to
  184. implement. If we in this situation just enqueue a second x-lock request
  185. for our transaction on the next record, then the deadlock mechanism
  186. notices a deadlock between our transaction and the s-lock request
  187. transaction. This seems to be an ok solution.
  188. We could have the convention that granted explicit record locks,
  189. lock the corresponding records from changing, and also lock the gaps
  190. before them from inserting. A waiting explicit lock request locks the gap
  191. before from inserting. Implicit record x-locks, which we derive from the
  192. transaction id in the clustered index record, only lock the record itself
  193. from modification, not the gap before it from inserting.
  194. How should we store update locks? If the search is done by a unique
  195. key, we could just modify the record trx id. Otherwise, we could put a record
  196. x-lock on the record. If the update changes ordering fields of the
  197. clustered index record, the inserted new record needs no record lock in
  198. lock table, the trx id is enough. The same holds for a secondary index
  199. record. Searched delete is similar to update.
  200. PROBLEM:
  201. What about waiting lock requests? If a transaction is waiting to make an
  202. update to a record which another modified, how does the other transaction
  203. know to send the end-lock-wait signal to the waiting transaction? If we have
  204. the convention that a transaction may wait for just one lock at a time, how
  205. do we preserve it if lock wait ends?
  206. PROBLEM:
  207. Checking the trx id label of a secondary index record. In the case of a
  208. modification, not an insert, is this necessary? A secondary index record
  209. is modified only by setting or resetting its deleted flag. A secondary index
  210. record contains fields to uniquely determine the corresponding clustered
  211. index record. A secondary index record is therefore only modified if we
  212. also modify the clustered index record, and the trx id checking is done
  213. on the clustered index record, before we come to modify the secondary index
  214. record. So, in the case of delete marking or unmarking a secondary index
  215. record, we do not have to care about trx ids, only the locks in the lock
  216. table must be checked. In the case of a select from a secondary index, the
  217. trx id is relevant, and in this case we may have to search the clustered
  218. index record.
  219. PROBLEM: How to update record locks when page is split or merged, or
  220. --------------------------------------------------------------------
  221. a record is deleted or updated?
  222. If the size of fields in a record changes, we perform the update by
  223. a delete followed by an insert. How can we retain the locks set or
  224. waiting on the record? Because a record lock is indexed in the bitmap
  225. by the heap number of the record, when we remove the record from the
  226. record list, it is possible still to keep the lock bits. If the page
  227. is reorganized, we could make a table of old and new heap numbers,
  228. and permute the bitmaps in the locks accordingly. We can add to the
  229. table a row telling where the updated record ended. If the update does
  230. not require a reorganization of the page, we can simply move the lock
  231. bits for the updated record to the position determined by its new heap
  232. number (we may have to allocate a new lock, if we run out of the bitmap
  233. in the old one).
  234. A more complicated case is the one where the reinsertion of the
  235. updated record is done pessimistically, because the structure of the
  236. tree may change.
  237. PROBLEM: If a supremum record is removed in a page merge, or a record
  238. ---------------------------------------------------------------------
  239. removed in a purge, what to do to the waiting lock requests? In a split to
  240. the right, we just move the lock requests to the new supremum. If a record
  241. is removed, we could move the waiting lock request to its inheritor, the
  242. next record in the index. But, the next record may already have lock
  243. requests on its own queue. A new deadlock check should be made then. Maybe
  244. it is easier just to release the waiting transactions. They can then enqueue
  245. new lock requests on appropriate records.
  246. PROBLEM: When a record is inserted, what locks should it inherit from the
  247. -------------------------------------------------------------------------
  248. upper neighbor? An insert of a new supremum record in a page split is
  249. always possible, but an insert of a new user record requires that the upper
  250. neighbor does not have any lock requests by other transactions, granted or
  251. waiting, in its lock queue. Solution: We can copy the locks as gap type
  252. locks, so that also the waiting locks are transformed to granted gap type
  253. locks on the inserted record. */
  254. ibool lock_print_waits = FALSE;
  255. /* The lock system */
  256. lock_sys_t* lock_sys = NULL;
  257. /* A table lock */
  258. typedef struct lock_table_struct lock_table_t;
  259. struct lock_table_struct{
  260. dict_table_t* table; /* database table in dictionary cache */
  261. UT_LIST_NODE_T(lock_t)
  262. locks;  /* list of locks on the same table */
  263. };
  264. /* Record lock for a page */
  265. typedef struct lock_rec_struct lock_rec_t;
  266. struct lock_rec_struct{
  267. ulint space; /* space id */
  268. ulint page_no; /* page number */
  269. ulint n_bits; /* number of bits in the lock bitmap */
  270. /* NOTE: the lock bitmap is placed immediately
  271. after the lock struct */
  272. };
  273. /* Lock struct */
  274. struct lock_struct{
  275. trx_t* trx; /* transaction owning the lock */
  276. UT_LIST_NODE_T(lock_t)
  277. trx_locks; /* list of the locks of the
  278. transaction */
  279. ulint type_mode; /* lock type, mode, LOCK_GAP or
  280. LOCK_REC_NOT_GAP,
  281. LOCK_INSERT_INTENTION,
  282. wait flag, ORed */
  283. hash_node_t hash; /* hash chain node for a record lock */
  284. dict_index_t* index; /* index for a record lock */
  285. union {
  286. lock_table_t tab_lock;/* table lock */
  287. lock_rec_t rec_lock;/* record lock */
  288. } un_member;
  289. };
  290. /* We store info on the latest deadlock error to this buffer. InnoDB
  291. Monitor will then fetch it and print */
  292. ibool lock_deadlock_found = FALSE;
  293. FILE* lock_latest_err_file;
  294. /* Flags for recursive deadlock search */
  295. #define LOCK_VICTIM_IS_START 1
  296. #define LOCK_VICTIM_IS_OTHER 2
  297. /************************************************************************
  298. Checks if a lock request results in a deadlock. */
  299. static
  300. ibool
  301. lock_deadlock_occurs(
  302. /*=================*/
  303. /* out: TRUE if a deadlock was detected */
  304. lock_t* lock, /* in: lock the transaction is requesting */
  305. trx_t* trx); /* in: transaction */
  306. /************************************************************************
  307. Looks recursively for a deadlock. */
  308. static
  309. ibool
  310. lock_deadlock_recursive(
  311. /*====================*/
  312. /* out: TRUE if a deadlock was detected
  313. or the calculation took too long */
  314. trx_t* start, /* in: recursion starting point */
  315. trx_t* trx, /* in: a transaction waiting for a lock */
  316. lock_t* wait_lock, /* in: the lock trx is waiting to be granted */
  317. ulint* cost); /* in/out: number of calculation steps thus
  318. far: if this exceeds LOCK_MAX_N_STEPS_...
  319. we return TRUE */
  320. /*************************************************************************
  321. Gets the type of a lock. */
  322. UNIV_INLINE
  323. ulint
  324. lock_get_type(
  325. /*==========*/
  326. /* out: LOCK_TABLE or LOCK_REC */
  327. lock_t* lock) /* in: lock */
  328. {
  329. ut_ad(lock);
  330. return(lock->type_mode & LOCK_TYPE_MASK);
  331. }
  332. /*************************************************************************
  333. Gets the nth bit of a record lock. */
  334. UNIV_INLINE
  335. ibool
  336. lock_rec_get_nth_bit(
  337. /*=================*/
  338. /* out: TRUE if bit set */
  339. lock_t* lock, /* in: record lock */
  340. ulint i) /* in: index of the bit */
  341. {
  342. ulint byte_index;
  343. ulint bit_index;
  344. ulint b;
  345. ut_ad(lock);
  346. ut_ad(lock_get_type(lock) == LOCK_REC);
  347. if (i >= lock->un_member.rec_lock.n_bits) {
  348. return(FALSE);
  349. }
  350. byte_index = i / 8;
  351. bit_index = i % 8;
  352. b = (ulint)*((byte*)lock + sizeof(lock_t) + byte_index);
  353. return(ut_bit_get_nth(b, bit_index));
  354. }
  355. /*************************************************************************/
  356. #define lock_mutex_enter_kernel() mutex_enter(&kernel_mutex)
  357. #define lock_mutex_exit_kernel() mutex_exit(&kernel_mutex)
  358. /*************************************************************************
  359. Checks that a transaction id is sensible, i.e., not in the future. */
  360. ibool
  361. lock_check_trx_id_sanity(
  362. /*=====================*/
  363. /* out: TRUE if ok */
  364. dulint trx_id, /* in: trx id */
  365. rec_t* rec, /* in: user record */
  366. dict_index_t* index, /* in: clustered index */
  367. ibool has_kernel_mutex)/* in: TRUE if the caller owns the
  368. kernel mutex */
  369. {
  370. ibool is_ok = TRUE;
  371. if (!has_kernel_mutex) {
  372. mutex_enter(&kernel_mutex);
  373. }
  374. /* A sanity check: the trx_id in rec must be smaller than the global
  375. trx id counter */
  376. if (ut_dulint_cmp(trx_id, trx_sys->max_trx_id) >= 0) {
  377. ut_print_timestamp(stderr);
  378. fputs("  InnoDB: Error: transaction id associated"
  379. " with recordn",
  380. stderr);
  381. rec_print(stderr, rec);
  382. fputs("InnoDB: in ", stderr);
  383. dict_index_name_print(stderr, NULL, index);
  384. fprintf(stderr, "n"
  385. "InnoDB: is %lu %lu which is higher than the global trx id counter %lu %lu!n"
  386. "InnoDB: The table is corrupt. You have to do dump + drop + reimport.n",
  387.        (ulong) ut_dulint_get_high(trx_id),
  388.        (ulong) ut_dulint_get_low(trx_id),
  389.        (ulong) ut_dulint_get_high(trx_sys->max_trx_id),
  390.        (ulong) ut_dulint_get_low(trx_sys->max_trx_id));
  391. is_ok = FALSE;
  392. }
  393. if (!has_kernel_mutex) {
  394. mutex_exit(&kernel_mutex);
  395. }
  396. return(is_ok);
  397. }
  398. /*************************************************************************
  399. Checks that a record is seen in a consistent read. */
  400. ibool
  401. lock_clust_rec_cons_read_sees(
  402. /*==========================*/
  403. /* out: TRUE if sees, or FALSE if an earlier
  404. version of the record should be retrieved */
  405. rec_t* rec, /* in: user record which should be read or
  406. passed over by a read cursor */
  407. dict_index_t* index, /* in: clustered index */
  408. read_view_t* view) /* in: consistent read view */
  409. {
  410. dulint trx_id;
  411. ut_ad(index->type & DICT_CLUSTERED);
  412. ut_ad(page_rec_is_user_rec(rec));
  413. /* NOTE that we call this function while holding the search
  414. system latch. To obey the latching order we must NOT reserve the
  415. kernel mutex here! */
  416. trx_id = row_get_rec_trx_id(rec, index);
  417. if (read_view_sees_trx_id(view, trx_id)) {
  418. return(TRUE);
  419. }
  420. return(FALSE);
  421. }
  422. /*************************************************************************
  423. Checks that a non-clustered index record is seen in a consistent read. */
  424. ulint
  425. lock_sec_rec_cons_read_sees(
  426. /*========================*/
  427. /* out: TRUE if certainly sees, or FALSE if an
  428. earlier version of the clustered index record
  429. might be needed: NOTE that a non-clustered
  430. index page contains so little information on
  431. its modifications that also in the case FALSE,
  432. the present version of rec may be the right,
  433. but we must check this from the clustered
  434. index record */
  435. rec_t* rec, /* in: user record which should be read or
  436. passed over by a read cursor */
  437. dict_index_t* index, /* in: non-clustered index */
  438. read_view_t* view) /* in: consistent read view */
  439. {
  440. dulint max_trx_id;
  441. UT_NOT_USED(index);
  442. ut_ad(!(index->type & DICT_CLUSTERED));
  443. ut_ad(page_rec_is_user_rec(rec));
  444. /* NOTE that we might call this function while holding the search
  445. system latch. To obey the latching order we must NOT reserve the
  446. kernel mutex here! */
  447. if (recv_recovery_is_on()) {
  448. return(FALSE);
  449. }
  450. max_trx_id = page_get_max_trx_id(buf_frame_align(rec));
  451. if (ut_dulint_cmp(max_trx_id, view->up_limit_id) >= 0) {
  452. return(FALSE);
  453. }
  454. return(TRUE);
  455. }
  456. /*************************************************************************
  457. Creates the lock system at database start. */
  458. void
  459. lock_sys_create(
  460. /*============*/
  461. ulint n_cells) /* in: number of slots in lock hash table */
  462. {
  463. lock_sys = mem_alloc(sizeof(lock_sys_t));
  464. lock_sys->rec_hash = hash_create(n_cells);
  465. /* hash_create_mutexes(lock_sys->rec_hash, 2, SYNC_REC_LOCK); */
  466. lock_latest_err_file = os_file_create_tmpfile();
  467. ut_a(lock_latest_err_file);
  468. }
  469. /*************************************************************************
  470. Gets the size of a lock struct. */
  471. ulint
  472. lock_get_size(void)
  473. /*===============*/
  474. /* out: size in bytes */
  475. {
  476. return((ulint)sizeof(lock_t));
  477. }
  478. /*************************************************************************
  479. Gets the mode of a lock. */
  480. UNIV_INLINE
  481. ulint
  482. lock_get_mode(
  483. /*==========*/
  484. /* out: mode */
  485. lock_t* lock) /* in: lock */
  486. {
  487. ut_ad(lock);
  488. return(lock->type_mode & LOCK_MODE_MASK);
  489. }
  490. /*************************************************************************
  491. Gets the wait flag of a lock. */
  492. UNIV_INLINE
  493. ibool
  494. lock_get_wait(
  495. /*==========*/
  496. /* out: TRUE if waiting */
  497. lock_t* lock) /* in: lock */
  498. {
  499. ut_ad(lock);
  500. if (lock->type_mode & LOCK_WAIT) {
  501. return(TRUE);
  502. }
  503. return(FALSE);
  504. }
  505. /*************************************************************************
  506. Gets the source table of an ALTER TABLE transaction.  The table must be
  507. covered by an IX or IS table lock. */
  508. dict_table_t*
  509. lock_get_src_table(
  510. /*===============*/
  511. /* out: the source table of transaction,
  512. if it is covered by an IX or IS table lock;
  513. dest if there is no source table, and
  514. NULL if the transaction is locking more than
  515. two tables or an inconsistency is found */
  516. trx_t* trx, /* in: transaction */
  517. dict_table_t* dest, /* in: destination of ALTER TABLE */
  518. ulint* mode) /* out: lock mode of the source table */
  519. {
  520. dict_table_t* src;
  521. lock_t* lock;
  522. src = NULL;
  523. *mode = LOCK_NONE;
  524. for (lock = UT_LIST_GET_FIRST(trx->trx_locks);
  525.      lock;
  526.      lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
  527. lock_table_t* tab_lock;
  528. ulint lock_mode;
  529. if (!(lock_get_type(lock) & LOCK_TABLE)) {
  530. /* We are only interested in table locks. */
  531. continue;
  532. }
  533. tab_lock = &lock->un_member.tab_lock;
  534. if (dest == tab_lock->table) {
  535. /* We are not interested in the destination table. */
  536. continue;
  537. } else if (!src) {
  538. /* This presumably is the source table. */
  539. src = tab_lock->table;
  540. if (UT_LIST_GET_LEN(src->locks) != 1 ||
  541.     UT_LIST_GET_FIRST(src->locks) != lock) {
  542. /* We only support the case when
  543. there is only one lock on this table. */
  544. return(NULL);
  545. }
  546. } else if (src != tab_lock->table) {
  547. /* The transaction is locking more than
  548. two tables (src and dest): abort */
  549. return(NULL);
  550. }
  551. /* Check that the source table is locked by
  552. LOCK_IX or LOCK_IS. */
  553. lock_mode = lock_get_mode(lock);
  554. switch (lock_mode) {
  555. case LOCK_IX:
  556. case LOCK_IS:
  557. if (*mode != LOCK_NONE && *mode != lock_mode) {
  558. /* There are multiple locks on src. */
  559. return(NULL);
  560. }
  561. *mode = lock_mode;
  562. break;
  563. }
  564. }
  565. if (!src) {
  566. /* No source table lock found: flag the situation to caller */
  567. src = dest;
  568. }
  569. return(src);
  570. }
  571. /*************************************************************************
  572. Determine if the given table is exclusively "owned" by the given
  573. transaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INC
  574. on the table. */
  575. ibool
  576. lock_is_table_exclusive(
  577. /*====================*/
  578. /* out: TRUE if table is only locked by trx,
  579. with LOCK_IX, and possibly LOCK_AUTO_INC */
  580. dict_table_t* table, /* in: table */
  581. trx_t* trx) /* in: transaction */
  582. {
  583. lock_t* lock;
  584. bool ok = FALSE;
  585. ut_ad(table && trx);
  586. for (lock = UT_LIST_GET_FIRST(table->locks);
  587.      lock;
  588.      lock = UT_LIST_GET_NEXT(locks, &lock->un_member.tab_lock)) {
  589. if (lock->trx != trx) {
  590. /* A lock on the table is held
  591. by some other transaction. */
  592. return(FALSE);
  593. }
  594. if (!(lock_get_type(lock) & LOCK_TABLE)) {
  595. /* We are interested in table locks only. */
  596. continue;
  597. }
  598. switch (lock_get_mode(lock)) {
  599. case LOCK_IX:
  600. ok = TRUE;
  601. break;
  602. case LOCK_AUTO_INC:
  603. /* It is allowed for trx to hold an
  604. auto_increment lock. */
  605. break;
  606. default:
  607. /* Other table locks than LOCK_IX are not allowed. */
  608. return(FALSE);
  609. }
  610. }
  611. return(ok);
  612. }
  613. /*************************************************************************
  614. Sets the wait flag of a lock and the back pointer in trx to lock. */
  615. UNIV_INLINE
  616. void
  617. lock_set_lock_and_trx_wait(
  618. /*=======================*/
  619. lock_t* lock, /* in: lock */
  620. trx_t* trx) /* in: trx */
  621. {
  622. ut_ad(lock);
  623. ut_ad(trx->wait_lock == NULL);
  624. trx->wait_lock = lock;
  625.   lock->type_mode = lock->type_mode | LOCK_WAIT;
  626. }
  627. /**************************************************************************
  628. The back pointer to a waiting lock request in the transaction is set to NULL
  629. and the wait bit in lock type_mode is reset. */
  630. UNIV_INLINE
  631. void
  632. lock_reset_lock_and_trx_wait(
  633. /*=========================*/
  634. lock_t* lock) /* in: record lock */
  635. {
  636. ut_ad((lock->trx)->wait_lock == lock);
  637. ut_ad(lock_get_wait(lock));
  638. /* Reset the back pointer in trx to this waiting lock request */
  639. (lock->trx)->wait_lock = NULL;
  640.   lock->type_mode = lock->type_mode & ~LOCK_WAIT;
  641. }
  642. /*************************************************************************
  643. Gets the gap flag of a record lock. */
  644. UNIV_INLINE
  645. ibool
  646. lock_rec_get_gap(
  647. /*=============*/
  648. /* out: TRUE if gap flag set */
  649. lock_t* lock) /* in: record lock */
  650. {
  651. ut_ad(lock);
  652. ut_ad(lock_get_type(lock) == LOCK_REC);
  653. if (lock->type_mode & LOCK_GAP) {
  654. return(TRUE);
  655. }
  656. return(FALSE);
  657. }
  658. /*************************************************************************
  659. Gets the LOCK_REC_NOT_GAP flag of a record lock. */
  660. UNIV_INLINE
  661. ibool
  662. lock_rec_get_rec_not_gap(
  663. /*=====================*/
  664. /* out: TRUE if LOCK_REC_NOT_GAP flag set */
  665. lock_t* lock) /* in: record lock */
  666. {
  667. ut_ad(lock);
  668. ut_ad(lock_get_type(lock) == LOCK_REC);
  669. if (lock->type_mode & LOCK_REC_NOT_GAP) {
  670. return(TRUE);
  671. }
  672. return(FALSE);
  673. }
  674. /*************************************************************************
  675. Gets the waiting insert flag of a record lock. */
  676. UNIV_INLINE
  677. ibool
  678. lock_rec_get_insert_intention(
  679. /*==========================*/
  680. /* out: TRUE if gap flag set */
  681. lock_t* lock) /* in: record lock */
  682. {
  683. ut_ad(lock);
  684. ut_ad(lock_get_type(lock) == LOCK_REC);
  685. if (lock->type_mode & LOCK_INSERT_INTENTION) {
  686. return(TRUE);
  687. }
  688. return(FALSE);
  689. }
  690. /*************************************************************************
  691. Calculates if lock mode 1 is stronger or equal to lock mode 2. */
  692. UNIV_INLINE
  693. ibool
  694. lock_mode_stronger_or_eq(
  695. /*=====================*/
  696. /* out: TRUE if mode1 stronger or equal to mode2 */
  697. ulint mode1, /* in: lock mode */
  698. ulint mode2) /* in: lock mode */
  699. {
  700. ut_ad(mode1 == LOCK_X || mode1 == LOCK_S || mode1 == LOCK_IX
  701. || mode1 == LOCK_IS || mode1 == LOCK_AUTO_INC);
  702. ut_ad(mode2 == LOCK_X || mode2 == LOCK_S || mode2 == LOCK_IX
  703. || mode2 == LOCK_IS || mode2 == LOCK_AUTO_INC);
  704. if (mode1 == LOCK_X) {
  705. return(TRUE);
  706. } else if (mode1 == LOCK_AUTO_INC && mode2 == LOCK_AUTO_INC) {
  707. return(TRUE);
  708. } else if (mode1 == LOCK_S
  709. && (mode2 == LOCK_S || mode2 == LOCK_IS)) {
  710. return(TRUE);
  711. } else if (mode1 == LOCK_IS && mode2 == LOCK_IS) {
  712. return(TRUE);
  713. } else if (mode1 == LOCK_IX && (mode2 == LOCK_IX
  714. || mode2 == LOCK_IS)) {
  715. return(TRUE);
  716. }
  717. return(FALSE);
  718. }
  719. /*************************************************************************
  720. Calculates if lock mode 1 is compatible with lock mode 2. */
  721. UNIV_INLINE
  722. ibool
  723. lock_mode_compatible(
  724. /*=================*/
  725. /* out: TRUE if mode1 compatible with mode2 */
  726. ulint mode1, /* in: lock mode */
  727. ulint mode2) /* in: lock mode */
  728. {
  729. ut_ad(mode1 == LOCK_X || mode1 == LOCK_S || mode1 == LOCK_IX
  730. || mode1 == LOCK_IS || mode1 == LOCK_AUTO_INC);
  731. ut_ad(mode2 == LOCK_X || mode2 == LOCK_S || mode2 == LOCK_IX
  732. || mode2 == LOCK_IS || mode2 == LOCK_AUTO_INC);
  733. if (mode1 == LOCK_S && (mode2 == LOCK_IS || mode2 == LOCK_S)) {
  734. return(TRUE);
  735. } else if (mode1 == LOCK_X) {
  736. return(FALSE);
  737. } else if (mode1 == LOCK_AUTO_INC && (mode2 == LOCK_IS
  738.    || mode2 == LOCK_IX)) {
  739. return(TRUE);
  740. } else if (mode1 == LOCK_IS && (mode2 == LOCK_IS
  741.    || mode2 == LOCK_IX
  742.    || mode2 == LOCK_AUTO_INC
  743.    || mode2 == LOCK_S)) {
  744. return(TRUE);
  745. } else if (mode1 == LOCK_IX && (mode2 == LOCK_IS
  746.    || mode2 == LOCK_AUTO_INC
  747.    || mode2 == LOCK_IX)) {
  748. return(TRUE);
  749. }
  750. return(FALSE);
  751. }
  752. /*************************************************************************
  753. Checks if a lock request for a new lock has to wait for request lock2. */
  754. UNIV_INLINE
  755. ibool
  756. lock_rec_has_to_wait(
  757. /*=================*/
  758. /* out: TRUE if new lock has to wait for lock2 to be
  759. removed */
  760. trx_t* trx, /* in: trx of new lock */
  761. ulint type_mode,/* in: precise mode of the new lock to set:
  762. LOCK_S or LOCK_X, possibly ORed to
  763. LOCK_GAP or LOCK_REC_NOT_GAP, LOCK_INSERT_INTENTION */
  764. lock_t* lock2, /* in: another record lock; NOTE that it is assumed
  765. that this has a lock bit set on the same record as
  766. in the new lock we are setting */
  767. ibool lock_is_on_supremum)  /* in: TRUE if we are setting the lock
  768. on the 'supremum' record of an index
  769. page: we know then that the lock request
  770. is really for a 'gap' type lock */
  771. {
  772. ut_ad(trx && lock2);
  773. ut_ad(lock_get_type(lock2) == LOCK_REC);
  774. if (trx != lock2->trx
  775.     && !lock_mode_compatible(LOCK_MODE_MASK & type_mode,
  776.       lock_get_mode(lock2))) {
  777. /* We have somewhat complex rules when gap type record locks
  778. cause waits */
  779. if ((lock_is_on_supremum || (type_mode & LOCK_GAP))
  780. && !(type_mode & LOCK_INSERT_INTENTION)) {
  781. /* Gap type locks without LOCK_INSERT_INTENTION flag
  782. do not need to wait for anything. This is because 
  783. different users can have conflicting lock types 
  784. on gaps. */
  785.   
  786. return(FALSE);
  787. }
  788. if (!(type_mode & LOCK_INSERT_INTENTION)
  789. && lock_rec_get_gap(lock2)) {
  790. /* Record lock (LOCK_ORDINARY or LOCK_REC_NOT_GAP
  791. does not need to wait for a gap type lock */
  792. return(FALSE);
  793. }
  794. if ((type_mode & LOCK_GAP)
  795. && lock_rec_get_rec_not_gap(lock2)) {
  796. /* Lock on gap does not need to wait for
  797. a LOCK_REC_NOT_GAP type lock */
  798. return(FALSE);
  799. }
  800. if (lock_rec_get_insert_intention(lock2)) {
  801. /* No lock request needs to wait for an insert
  802. intention lock to be removed. This is ok since our
  803. rules allow conflicting locks on gaps. This eliminates
  804. a spurious deadlock caused by a next-key lock waiting
  805. for an insert intention lock; when the insert
  806. intention lock was granted, the insert deadlocked on
  807. the waiting next-key lock.
  808. Also, insert intention locks do not disturb each
  809. other. */
  810. return(FALSE);
  811. }
  812. return(TRUE);
  813. }
  814. return(FALSE);
  815. }
  816. /*************************************************************************
  817. Checks if a lock request lock1 has to wait for request lock2. */
  818. static
  819. ibool
  820. lock_has_to_wait(
  821. /*=============*/
  822. /* out: TRUE if lock1 has to wait for lock2 to be
  823. removed */
  824. lock_t* lock1, /* in: waiting lock */
  825. lock_t* lock2) /* in: another lock; NOTE that it is assumed that this
  826. has a lock bit set on the same record as in lock1 if
  827. the locks are record locks */
  828. {
  829. ut_ad(lock1 && lock2);
  830. if (lock1->trx != lock2->trx
  831. && !lock_mode_compatible(lock_get_mode(lock1),
  832.       lock_get_mode(lock2))) {
  833. if (lock_get_type(lock1) == LOCK_REC) {
  834. ut_ad(lock_get_type(lock2) == LOCK_REC);
  835. /* If this lock request is for a supremum record
  836. then the second bit on the lock bitmap is set */
  837. return(lock_rec_has_to_wait(lock1->trx,
  838. lock1->type_mode, lock2,
  839. lock_rec_get_nth_bit(lock1,1)));
  840. }
  841. return(TRUE);
  842. }
  843. return(FALSE);
  844. }
  845. /*============== RECORD LOCK BASIC FUNCTIONS ============================*/
  846. /*************************************************************************
  847. Gets the number of bits in a record lock bitmap. */
  848. UNIV_INLINE
  849. ulint
  850. lock_rec_get_n_bits(
  851. /*================*/
  852. /* out: number of bits */
  853. lock_t* lock) /* in: record lock */
  854. {
  855. return(lock->un_member.rec_lock.n_bits);
  856. }
  857. /**************************************************************************
  858. Sets the nth bit of a record lock to TRUE. */
  859. UNIV_INLINE
  860. void
  861. lock_rec_set_nth_bit(
  862. /*==================*/
  863. lock_t* lock, /* in: record lock */
  864. ulint i) /* in: index of the bit */
  865. {
  866. ulint byte_index;
  867. ulint bit_index;
  868. byte* ptr;
  869. ulint b;
  870. ut_ad(lock);
  871. ut_ad(lock_get_type(lock) == LOCK_REC);
  872. ut_ad(i < lock->un_member.rec_lock.n_bits);
  873. byte_index = i / 8;
  874. bit_index = i % 8;
  875. ptr = (byte*)lock + sizeof(lock_t) + byte_index;
  876. b = (ulint)*ptr;
  877. b = ut_bit_set_nth(b, bit_index, TRUE);
  878. *ptr = (byte)b;
  879. }
  880. /**************************************************************************
  881. Looks for a set bit in a record lock bitmap. Returns ULINT_UNDEFINED,
  882. if none found. */
  883. static
  884. ulint
  885. lock_rec_find_set_bit(
  886. /*==================*/
  887. /* out: bit index == heap number of the record, or
  888. ULINT_UNDEFINED if none found */
  889. lock_t* lock) /* in: record lock with at least one bit set */
  890. {
  891. ulint i;
  892. for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
  893. if (lock_rec_get_nth_bit(lock, i)) {
  894. return(i);
  895. }
  896. }
  897. return(ULINT_UNDEFINED);
  898. }
  899. /**************************************************************************
  900. Resets the nth bit of a record lock. */
  901. UNIV_INLINE
  902. void
  903. lock_rec_reset_nth_bit(
  904. /*===================*/
  905. lock_t* lock, /* in: record lock */
  906. ulint i) /* in: index of the bit which must be set to TRUE
  907. when this function is called */
  908. {
  909. ulint byte_index;
  910. ulint bit_index;
  911. byte* ptr;
  912. ulint b;
  913. ut_ad(lock);
  914. ut_ad(lock_get_type(lock) == LOCK_REC);
  915. ut_ad(i < lock->un_member.rec_lock.n_bits);
  916. byte_index = i / 8;
  917. bit_index = i % 8;
  918. ptr = (byte*)lock + sizeof(lock_t) + byte_index;
  919. b = (ulint)*ptr;
  920. b = ut_bit_set_nth(b, bit_index, FALSE);
  921. *ptr = (byte)b;
  922. }
  923. /*************************************************************************
  924. Gets the first or next record lock on a page. */
  925. UNIV_INLINE
  926. lock_t*
  927. lock_rec_get_next_on_page(
  928. /*======================*/
  929. /* out: next lock, NULL if none exists */
  930. lock_t* lock) /* in: a record lock */
  931. {
  932. ulint space;
  933. ulint page_no;
  934. #ifdef UNIV_SYNC_DEBUG
  935. ut_ad(mutex_own(&kernel_mutex));
  936. #endif /* UNIV_SYNC_DEBUG */
  937. ut_ad(lock_get_type(lock) == LOCK_REC);
  938. space = lock->un_member.rec_lock.space;
  939. page_no = lock->un_member.rec_lock.page_no;
  940. for (;;) {
  941. lock = HASH_GET_NEXT(hash, lock);
  942. if (!lock) {
  943. break;
  944. }
  945. if ((lock->un_member.rec_lock.space == space) 
  946.          && (lock->un_member.rec_lock.page_no == page_no)) {
  947. break;
  948. }
  949. }
  950. return(lock);
  951. }
  952. /*************************************************************************
  953. Gets the first record lock on a page, where the page is identified by its
  954. file address. */
  955. UNIV_INLINE
  956. lock_t*
  957. lock_rec_get_first_on_page_addr(
  958. /*============================*/
  959. /* out: first lock, NULL if none exists */
  960. ulint space, /* in: space */
  961. ulint page_no)/* in: page number */
  962. {
  963. lock_t* lock;
  964. #ifdef UNIV_SYNC_DEBUG
  965. ut_ad(mutex_own(&kernel_mutex));
  966. #endif /* UNIV_SYNC_DEBUG */
  967. lock = HASH_GET_FIRST(lock_sys->rec_hash,
  968. lock_rec_hash(space, page_no));
  969. while (lock) {
  970. if ((lock->un_member.rec_lock.space == space) 
  971.          && (lock->un_member.rec_lock.page_no == page_no)) {
  972. break;
  973. }
  974. lock = HASH_GET_NEXT(hash, lock);
  975. }
  976. return(lock);
  977. }
  978. /*************************************************************************
  979. Returns TRUE if there are explicit record locks on a page. */
  980. ibool
  981. lock_rec_expl_exist_on_page(
  982. /*========================*/
  983. /* out: TRUE if there are explicit record locks on
  984. the page */
  985. ulint space, /* in: space id */
  986. ulint page_no)/* in: page number */
  987. {
  988. ibool ret;
  989. mutex_enter(&kernel_mutex);
  990. if (lock_rec_get_first_on_page_addr(space, page_no)) {
  991. ret = TRUE;
  992. } else {
  993. ret = FALSE;
  994. }
  995. mutex_exit(&kernel_mutex);
  996. return(ret);
  997. }
  998. /*************************************************************************
  999. Gets the first record lock on a page, where the page is identified by a
  1000. pointer to it. */
  1001. UNIV_INLINE
  1002. lock_t*
  1003. lock_rec_get_first_on_page(
  1004. /*=======================*/
  1005. /* out: first lock, NULL if none exists */
  1006. byte* ptr) /* in: pointer to somewhere on the page */
  1007. {
  1008. ulint hash;
  1009. lock_t* lock;
  1010. ulint space;
  1011. ulint page_no;
  1012. #ifdef UNIV_SYNC_DEBUG
  1013. ut_ad(mutex_own(&kernel_mutex));
  1014. #endif /* UNIV_SYNC_DEBUG */
  1015. hash = buf_frame_get_lock_hash_val(ptr);
  1016. lock = HASH_GET_FIRST(lock_sys->rec_hash, hash);
  1017. while (lock) {
  1018. space = buf_frame_get_space_id(ptr);
  1019. page_no = buf_frame_get_page_no(ptr);
  1020. if ((lock->un_member.rec_lock.space == space) 
  1021.      && (lock->un_member.rec_lock.page_no == page_no)) {
  1022. break;
  1023. }
  1024. lock = HASH_GET_NEXT(hash, lock);
  1025. }
  1026. return(lock);
  1027. }
  1028. /*************************************************************************
  1029. Gets the next explicit lock request on a record. */
  1030. UNIV_INLINE
  1031. lock_t*
  1032. lock_rec_get_next(
  1033. /*==============*/
  1034. /* out: next lock, NULL if none exists */
  1035. rec_t* rec, /* in: record on a page */
  1036. lock_t* lock) /* in: lock */
  1037. {
  1038. #ifdef UNIV_SYNC_DEBUG
  1039. ut_ad(mutex_own(&kernel_mutex));
  1040. #endif /* UNIV_SYNC_DEBUG */
  1041. ut_ad(lock_get_type(lock) == LOCK_REC);
  1042. for (;;) {
  1043. lock = lock_rec_get_next_on_page(lock);
  1044. if (lock == NULL) {
  1045. return(NULL);
  1046. }
  1047. if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec))) {
  1048. return(lock);
  1049. }
  1050. }
  1051. }
  1052. /*************************************************************************
  1053. Gets the first explicit lock request on a record. */
  1054. UNIV_INLINE
  1055. lock_t*
  1056. lock_rec_get_first(
  1057. /*===============*/
  1058. /* out: first lock, NULL if none exists */
  1059. rec_t* rec) /* in: record on a page */
  1060. {
  1061. lock_t* lock;
  1062. #ifdef UNIV_SYNC_DEBUG
  1063. ut_ad(mutex_own(&kernel_mutex));
  1064. #endif /* UNIV_SYNC_DEBUG */
  1065. lock = lock_rec_get_first_on_page(rec);
  1066. while (lock) {
  1067. if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec))) {
  1068. break;
  1069. }
  1070. lock = lock_rec_get_next_on_page(lock);
  1071. }
  1072. return(lock);
  1073. }
  1074. /*************************************************************************
  1075. Resets the record lock bitmap to zero. NOTE: does not touch the wait_lock
  1076. pointer in the transaction! This function is used in lock object creation
  1077. and resetting. */
  1078. static
  1079. void
  1080. lock_rec_bitmap_reset(
  1081. /*==================*/
  1082. lock_t* lock) /* in: record lock */
  1083. {
  1084. byte* ptr;
  1085. ulint n_bytes;
  1086. ulint i;
  1087. ut_ad(lock_get_type(lock) == LOCK_REC);
  1088. /* Reset to zero the bitmap which resides immediately after the lock
  1089. struct */
  1090. ptr = (byte*)lock + sizeof(lock_t);
  1091. n_bytes = lock_rec_get_n_bits(lock) / 8;
  1092. ut_ad((lock_rec_get_n_bits(lock) % 8) == 0);
  1093. for (i = 0; i < n_bytes; i++) {
  1094. *ptr = 0;
  1095. ptr++;
  1096. }
  1097. }
  1098. /*************************************************************************
  1099. Copies a record lock to heap. */
  1100. static
  1101. lock_t*
  1102. lock_rec_copy(
  1103. /*==========*/
  1104. /* out: copy of lock */
  1105. lock_t* lock, /* in: record lock */
  1106. mem_heap_t* heap) /* in: memory heap */
  1107. {
  1108. lock_t* dupl_lock;
  1109. ulint size;
  1110. ut_ad(lock_get_type(lock) == LOCK_REC);
  1111. size = sizeof(lock_t) + lock_rec_get_n_bits(lock) / 8;
  1112. dupl_lock = mem_heap_alloc(heap, size);
  1113. ut_memcpy(dupl_lock, lock, size);
  1114. return(dupl_lock);
  1115. }
  1116. /*************************************************************************
  1117. Gets the previous record lock set on a record. */
  1118. static
  1119. lock_t*
  1120. lock_rec_get_prev(
  1121. /*==============*/
  1122. /* out: previous lock on the same record, NULL if
  1123. none exists */
  1124. lock_t* in_lock,/* in: record lock */
  1125. ulint heap_no)/* in: heap number of the record */
  1126. {
  1127. lock_t* lock;
  1128. ulint space;
  1129. ulint page_no;
  1130. lock_t* found_lock  = NULL;
  1131. #ifdef UNIV_SYNC_DEBUG
  1132. ut_ad(mutex_own(&kernel_mutex));
  1133. #endif /* UNIV_SYNC_DEBUG */
  1134. ut_ad(lock_get_type(in_lock) == LOCK_REC);
  1135. space = in_lock->un_member.rec_lock.space;
  1136. page_no = in_lock->un_member.rec_lock.page_no;
  1137. lock = lock_rec_get_first_on_page_addr(space, page_no);
  1138. for (;;) {
  1139. ut_ad(lock);
  1140. if (lock == in_lock) {
  1141. return(found_lock);
  1142. }
  1143. if (lock_rec_get_nth_bit(lock, heap_no)) {
  1144. found_lock = lock;
  1145. }
  1146. lock = lock_rec_get_next_on_page(lock);
  1147. }
  1148. }
  1149. /*============= FUNCTIONS FOR ANALYZING TABLE LOCK QUEUE ================*/
  1150. /*************************************************************************
  1151. Checks if a transaction has the specified table lock, or stronger. */
  1152. UNIV_INLINE
  1153. lock_t*
  1154. lock_table_has(
  1155. /*===========*/
  1156. /* out: lock or NULL */
  1157. trx_t* trx, /* in: transaction */
  1158. dict_table_t* table, /* in: table */
  1159. ulint mode) /* in: lock mode */
  1160. {
  1161. lock_t* lock;
  1162. #ifdef UNIV_SYNC_DEBUG
  1163. ut_ad(mutex_own(&kernel_mutex));
  1164. #endif /* UNIV_SYNC_DEBUG */
  1165. /* Look for stronger locks the same trx already has on the table */
  1166. lock = UT_LIST_GET_LAST(table->locks);
  1167. while (lock != NULL) {
  1168. if (lock->trx == trx
  1169.     && lock_mode_stronger_or_eq(lock_get_mode(lock), mode)) {
  1170. /* The same trx already has locked the table in 
  1171. a mode stronger or equal to the mode given */
  1172. ut_ad(!lock_get_wait(lock)); 
  1173. return(lock);
  1174. }
  1175. lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock);
  1176. }
  1177. return(NULL);
  1178. }
  1179. /*============= FUNCTIONS FOR ANALYZING RECORD LOCK QUEUE ================*/
  1180. /*************************************************************************
  1181. Checks if a transaction has a GRANTED explicit lock on rec stronger or equal
  1182. to precise_mode. */
  1183. UNIV_INLINE
  1184. lock_t*
  1185. lock_rec_has_expl(
  1186. /*==============*/
  1187. /* out: lock or NULL */
  1188. ulint precise_mode,/* in: LOCK_S or LOCK_X possibly ORed to
  1189. LOCK_GAP or LOCK_REC_NOT_GAP,
  1190. for a supremum record we regard this always a gap
  1191. type request */
  1192. rec_t* rec, /* in: record */
  1193. trx_t* trx) /* in: transaction */
  1194. {
  1195. lock_t* lock;
  1196. #ifdef UNIV_SYNC_DEBUG
  1197. ut_ad(mutex_own(&kernel_mutex));
  1198. #endif /* UNIV_SYNC_DEBUG */
  1199. ut_ad((precise_mode & LOCK_MODE_MASK) == LOCK_S
  1200.       || (precise_mode & LOCK_MODE_MASK) == LOCK_X);
  1201. ut_ad(!(precise_mode & LOCK_INSERT_INTENTION));
  1202. lock = lock_rec_get_first(rec);
  1203. while (lock) {
  1204. if (lock->trx == trx
  1205.     && lock_mode_stronger_or_eq(lock_get_mode(lock),
  1206.      precise_mode & LOCK_MODE_MASK)
  1207.     && !lock_get_wait(lock)
  1208.     && (!lock_rec_get_rec_not_gap(lock)
  1209.      || (precise_mode & LOCK_REC_NOT_GAP)
  1210.      || page_rec_is_supremum(rec))
  1211.     && (!lock_rec_get_gap(lock)
  1212. || (precise_mode & LOCK_GAP)
  1213. || page_rec_is_supremum(rec))
  1214.     && (!lock_rec_get_insert_intention(lock))) {
  1215.      return(lock);
  1216. }
  1217. lock = lock_rec_get_next(rec, lock);
  1218. }
  1219. return(NULL);
  1220. }
  1221. /*************************************************************************
  1222. Checks if some other transaction has a lock request in the queue. */
  1223. static
  1224. lock_t*
  1225. lock_rec_other_has_expl_req(
  1226. /*========================*/
  1227. /* out: lock or NULL */
  1228. ulint mode, /* in: LOCK_S or LOCK_X */
  1229. ulint gap, /* in: LOCK_GAP if also gap locks are taken
  1230. into account, or 0 if not */
  1231. ulint wait, /* in: LOCK_WAIT if also waiting locks are
  1232. taken into account, or 0 if not */
  1233. rec_t* rec, /* in: record to look at */
  1234. trx_t* trx) /* in: transaction, or NULL if requests by all
  1235. transactions are taken into account */
  1236. {
  1237. lock_t* lock;
  1238. #ifdef UNIV_SYNC_DEBUG
  1239. ut_ad(mutex_own(&kernel_mutex));
  1240. #endif /* UNIV_SYNC_DEBUG */
  1241. ut_ad(mode == LOCK_X || mode == LOCK_S);
  1242. ut_ad(gap == 0 || gap == LOCK_GAP);
  1243. ut_ad(wait == 0 || wait == LOCK_WAIT);
  1244. lock = lock_rec_get_first(rec);
  1245. while (lock) {
  1246. if (lock->trx != trx
  1247.     && (gap ||
  1248. !(lock_rec_get_gap(lock) || page_rec_is_supremum(rec)))
  1249.     && (wait || !lock_get_wait(lock))
  1250.     && lock_mode_stronger_or_eq(lock_get_mode(lock), mode)) {
  1251.      return(lock);
  1252. }
  1253. lock = lock_rec_get_next(rec, lock);
  1254. }
  1255. return(NULL);
  1256. }
  1257. /*************************************************************************
  1258. Checks if some other transaction has a conflicting explicit lock request
  1259. in the queue, so that we have to wait. */
  1260. static
  1261. lock_t*
  1262. lock_rec_other_has_conflicting(
  1263. /*===========================*/
  1264. /* out: lock or NULL */
  1265. ulint mode, /* in: LOCK_S or LOCK_X,
  1266. possibly ORed to LOCK_GAP or LOC_REC_NOT_GAP,
  1267. LOCK_INSERT_INTENTION */
  1268. rec_t* rec, /* in: record to look at */
  1269. trx_t* trx) /* in: our transaction */
  1270. {
  1271. lock_t* lock;
  1272. #ifdef UNIV_SYNC_DEBUG
  1273. ut_ad(mutex_own(&kernel_mutex));
  1274. #endif /* UNIV_SYNC_DEBUG */
  1275. lock = lock_rec_get_first(rec);
  1276. while (lock) {
  1277. if (lock_rec_has_to_wait(trx, mode, lock,
  1278. page_rec_is_supremum(rec))) {
  1279. return(lock);
  1280. }
  1281. lock = lock_rec_get_next(rec, lock);
  1282. }
  1283. return(NULL);
  1284. }
  1285. /*************************************************************************
  1286. Looks for a suitable type record lock struct by the same trx on the same page.
  1287. This can be used to save space when a new record lock should be set on a page:
  1288. no new struct is needed, if a suitable old is found. */
  1289. UNIV_INLINE
  1290. lock_t*
  1291. lock_rec_find_similar_on_page(
  1292. /*==========================*/
  1293. /* out: lock or NULL */
  1294. ulint type_mode, /* in: lock type_mode field */
  1295. rec_t* rec, /* in: record */
  1296. trx_t* trx) /* in: transaction */
  1297. {
  1298. lock_t* lock;
  1299. ulint heap_no;
  1300. #ifdef UNIV_SYNC_DEBUG
  1301. ut_ad(mutex_own(&kernel_mutex));
  1302. #endif /* UNIV_SYNC_DEBUG */
  1303. heap_no = rec_get_heap_no(rec);
  1304. lock = lock_rec_get_first_on_page(rec);
  1305. while (lock != NULL) {
  1306. if (lock->trx == trx
  1307.     && lock->type_mode == type_mode
  1308.     && lock_rec_get_n_bits(lock) > heap_no) {
  1309.     
  1310. return(lock);
  1311. }
  1312. lock = lock_rec_get_next_on_page(lock);
  1313. }
  1314. return(NULL);
  1315. }
  1316. /*************************************************************************
  1317. Checks if some transaction has an implicit x-lock on a record in a secondary
  1318. index. */
  1319. trx_t*
  1320. lock_sec_rec_some_has_impl_off_kernel(
  1321. /*==================================*/
  1322. /* out: transaction which has the x-lock, or
  1323. NULL */
  1324. rec_t* rec, /* in: user record */
  1325. dict_index_t* index) /* in: secondary index */
  1326. {
  1327. page_t* page;
  1328. #ifdef UNIV_SYNC_DEBUG
  1329. ut_ad(mutex_own(&kernel_mutex));
  1330. #endif /* UNIV_SYNC_DEBUG */
  1331. ut_ad(!(index->type & DICT_CLUSTERED));
  1332. ut_ad(page_rec_is_user_rec(rec));
  1333. page = buf_frame_align(rec);
  1334. /* Some transaction may have an implicit x-lock on the record only
  1335. if the max trx id for the page >= min trx id for the trx list, or
  1336. database recovery is running. We do not write the changes of a page
  1337. max trx id to the log, and therefore during recovery, this value
  1338. for a page may be incorrect. */
  1339. if (!(ut_dulint_cmp(page_get_max_trx_id(page),
  1340. trx_list_get_min_trx_id()) >= 0)
  1341.     && !recv_recovery_is_on()) {
  1342. return(NULL);
  1343. }
  1344. /* Ok, in this case it is possible that some transaction has an
  1345. implicit x-lock. We have to look in the clustered index. */
  1346. if (!lock_check_trx_id_sanity(page_get_max_trx_id(page), rec, index,
  1347.      TRUE)) {
  1348. buf_page_print(page);
  1349. /* The page is corrupt: try to avoid a crash by returning
  1350. NULL */
  1351. return(NULL);
  1352. }
  1353. return(row_vers_impl_x_locked_off_kernel(rec, index));
  1354. }
  1355. /*============== RECORD LOCK CREATION AND QUEUE MANAGEMENT =============*/
  1356. /*************************************************************************
  1357. Creates a new record lock and inserts it to the lock queue. Does NOT check
  1358. for deadlocks or lock compatibility! */
  1359. static
  1360. lock_t*
  1361. lock_rec_create(
  1362. /*============*/
  1363. /* out: created lock, NULL if out of memory */
  1364. ulint type_mode,/* in: lock mode and wait flag, type is
  1365. ignored and replaced by LOCK_REC */
  1366. rec_t* rec, /* in: record on page */
  1367. dict_index_t* index, /* in: index of record */
  1368. trx_t* trx) /* in: transaction */
  1369. {
  1370. page_t* page;
  1371. lock_t* lock;
  1372. ulint page_no;
  1373. ulint heap_no;
  1374. ulint space;
  1375. ulint n_bits;
  1376. ulint n_bytes;
  1377. #ifdef UNIV_SYNC_DEBUG
  1378. ut_ad(mutex_own(&kernel_mutex));
  1379. #endif /* UNIV_SYNC_DEBUG */
  1380. page = buf_frame_align(rec);
  1381. space = buf_frame_get_space_id(page);
  1382. page_no = buf_frame_get_page_no(page);
  1383. heap_no = rec_get_heap_no(rec);
  1384. /* If rec is the supremum record, then we reset the gap and
  1385. LOCK_REC_NOT_GAP bits, as all locks on the supremum are
  1386. automatically of the gap type */
  1387. if (rec == page_get_supremum_rec(page)) {
  1388. ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
  1389. type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP);
  1390. }
  1391. /* Make lock bitmap bigger by a safety margin */
  1392. n_bits = page_header_get_field(page, PAGE_N_HEAP)
  1393. + LOCK_PAGE_BITMAP_MARGIN;
  1394. n_bytes = 1 + n_bits / 8;
  1395. lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t) + n_bytes);
  1396. if (lock == NULL) {
  1397. return(NULL);
  1398. }
  1399. UT_LIST_ADD_LAST(trx_locks, trx->trx_locks, lock);
  1400. lock->trx = trx;
  1401. lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC;
  1402. lock->index = index;
  1403. lock->un_member.rec_lock.space = space;
  1404. lock->un_member.rec_lock.page_no = page_no;
  1405. lock->un_member.rec_lock.n_bits = n_bytes * 8;
  1406. /* Reset to zero the bitmap which resides immediately after the
  1407. lock struct */
  1408. lock_rec_bitmap_reset(lock);
  1409. /* Set the bit corresponding to rec */
  1410. lock_rec_set_nth_bit(lock, heap_no);
  1411. HASH_INSERT(lock_t, hash, lock_sys->rec_hash,
  1412. lock_rec_fold(space, page_no), lock); 
  1413. if (type_mode & LOCK_WAIT) {
  1414. lock_set_lock_and_trx_wait(lock, trx);
  1415. }
  1416. return(lock);
  1417. }
  1418. /*************************************************************************
  1419. Enqueues a waiting request for a lock which cannot be granted immediately.
  1420. Checks for deadlocks. */
  1421. static
  1422. ulint
  1423. lock_rec_enqueue_waiting(
  1424. /*=====================*/
  1425. /* out: DB_LOCK_WAIT, DB_DEADLOCK, or
  1426. DB_QUE_THR_SUSPENDED, or DB_SUCCESS;
  1427. DB_SUCCESS means that there was a deadlock,
  1428. but another transaction was chosen as a
  1429. victim, and we got the lock immediately:
  1430. no need to wait then */
  1431. ulint type_mode,/* in: lock mode this transaction is
  1432. requesting: LOCK_S or LOCK_X, possibly ORed
  1433. with LOCK_GAP or LOCK_REC_NOT_GAP, ORed
  1434. with LOCK_INSERT_INTENTION if this waiting
  1435. lock request is set when performing an
  1436. insert of an index record */
  1437. rec_t* rec, /* in: record */
  1438. dict_index_t* index, /* in: index of record */
  1439. que_thr_t* thr) /* in: query thread */
  1440. {
  1441. lock_t* lock;
  1442. trx_t* trx;
  1443. #ifdef UNIV_SYNC_DEBUG
  1444. ut_ad(mutex_own(&kernel_mutex));
  1445. #endif /* UNIV_SYNC_DEBUG */
  1446. /* Test if there already is some other reason to suspend thread:
  1447. we do not enqueue a lock request if the query thread should be
  1448. stopped anyway */
  1449. if (que_thr_stop(thr)) {
  1450. ut_error;
  1451. return(DB_QUE_THR_SUSPENDED);
  1452. }
  1453. trx = thr_get_trx(thr);
  1454. if (trx->dict_operation) {
  1455. ut_print_timestamp(stderr);
  1456. fputs(
  1457. "  InnoDB: Error: a record lock wait happens in a dictionary operation!n"
  1458. "InnoDB: Table name ", stderr);
  1459. ut_print_name(stderr, trx, index->table_name);
  1460. fputs(".n"
  1461. "InnoDB: Submit a detailed bug report to http://bugs.mysql.comn",
  1462. stderr);
  1463. }
  1464. /* Enqueue the lock request that will wait to be granted */
  1465. lock = lock_rec_create(type_mode | LOCK_WAIT, rec, index, trx);
  1466. /* Check if a deadlock occurs: if yes, remove the lock request and
  1467. return an error code */
  1468. if (lock_deadlock_occurs(lock, trx)) {
  1469. lock_reset_lock_and_trx_wait(lock);
  1470. lock_rec_reset_nth_bit(lock, rec_get_heap_no(rec));
  1471. return(DB_DEADLOCK);
  1472. }
  1473. /* If there was a deadlock but we chose another transaction as a
  1474. victim, it is possible that we already have the lock now granted! */
  1475. if (trx->wait_lock == NULL) {
  1476. return(DB_SUCCESS);
  1477. }
  1478. trx->que_state = TRX_QUE_LOCK_WAIT;
  1479. trx->was_chosen_as_deadlock_victim = FALSE;
  1480. trx->wait_started = time(NULL);
  1481. ut_a(que_thr_stop(thr));
  1482. if (lock_print_waits) {
  1483. fprintf(stderr, "Lock wait for trx %lu in index ",
  1484. (ulong) ut_dulint_get_low(trx->id));
  1485. ut_print_name(stderr, trx, index->name);
  1486. }
  1487. return(DB_LOCK_WAIT);
  1488. }
  1489. /*************************************************************************
  1490. Adds a record lock request in the record queue. The request is normally
  1491. added as the last in the queue, but if there are no waiting lock requests
  1492. on the record, and the request to be added is not a waiting request, we
  1493. can reuse a suitable record lock object already existing on the same page,
  1494. just setting the appropriate bit in its bitmap. This is a low-level function
  1495. which does NOT check for deadlocks or lock compatibility! */
  1496. static
  1497. lock_t*
  1498. lock_rec_add_to_queue(
  1499. /*==================*/
  1500. /* out: lock where the bit was set, NULL if out
  1501. of memory */
  1502. ulint type_mode,/* in: lock mode, wait, gap etc. flags;
  1503. type is ignored and replaced by LOCK_REC */
  1504. rec_t* rec, /* in: record on page */
  1505. dict_index_t* index, /* in: index of record */
  1506. trx_t* trx) /* in: transaction */
  1507. {
  1508. lock_t* lock;
  1509. lock_t* similar_lock = NULL;
  1510. ulint heap_no;
  1511. page_t* page;
  1512. ibool somebody_waits = FALSE;
  1513. #ifdef UNIV_SYNC_DEBUG
  1514. ut_ad(mutex_own(&kernel_mutex));
  1515. #endif /* UNIV_SYNC_DEBUG */
  1516. ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
  1517.       || ((type_mode & LOCK_MODE_MASK) != LOCK_S)
  1518.       || !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT, rec, trx));
  1519. ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
  1520.       || ((type_mode & LOCK_MODE_MASK) != LOCK_X)
  1521.       || !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT, rec, trx));
  1522. type_mode = type_mode | LOCK_REC;
  1523. page = buf_frame_align(rec);
  1524. /* If rec is the supremum record, then we can reset the gap bit, as
  1525. all locks on the supremum are automatically of the gap type, and we
  1526. try to avoid unnecessary memory consumption of a new record lock
  1527. struct for a gap type lock */
  1528. if (rec == page_get_supremum_rec(page)) {
  1529. ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
  1530. /* There should never be LOCK_REC_NOT_GAP on a supremum
  1531. record, but let us play safe */
  1532. type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP);
  1533. }
  1534. /* Look for a waiting lock request on the same record or on a gap */
  1535. heap_no = rec_get_heap_no(rec);
  1536. lock = lock_rec_get_first_on_page(rec);
  1537. while (lock != NULL) {
  1538. if (lock_get_wait(lock)
  1539. && (lock_rec_get_nth_bit(lock, heap_no))) {
  1540. somebody_waits = TRUE;
  1541. }
  1542. lock = lock_rec_get_next_on_page(lock);
  1543. }
  1544. /* Look for a similar record lock on the same page: if one is found
  1545. and there are no waiting lock requests, we can just set the bit */
  1546. similar_lock = lock_rec_find_similar_on_page(type_mode, rec, trx);
  1547. if (similar_lock && !somebody_waits && !(type_mode & LOCK_WAIT)) {
  1548. lock_rec_set_nth_bit(similar_lock, heap_no);
  1549. return(similar_lock);
  1550. }
  1551. return(lock_rec_create(type_mode, rec, index, trx));
  1552. }
  1553. /*************************************************************************
  1554. This is a fast routine for locking a record in the most common cases:
  1555. there are no explicit locks on the page, or there is just one lock, owned
  1556. by this transaction, and of the right type_mode. This is a low-level function
  1557. which does NOT look at implicit locks! Checks lock compatibility within
  1558. explicit locks. This function sets a normal next-key lock, or in the case of
  1559. a page supremum record, a gap type lock. */
  1560. UNIV_INLINE
  1561. ibool
  1562. lock_rec_lock_fast(
  1563. /*===============*/
  1564. /* out: TRUE if locking succeeded */
  1565. ibool impl, /* in: if TRUE, no lock is set if no wait
  1566. is necessary: we assume that the caller will
  1567. set an implicit lock */
  1568. ulint mode, /* in: lock mode: LOCK_X or LOCK_S possibly
  1569. ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */
  1570. rec_t* rec, /* in: record */
  1571. dict_index_t* index, /* in: index of record */
  1572. que_thr_t*  thr) /* in: query thread */
  1573. {
  1574. lock_t* lock;
  1575. ulint heap_no;
  1576. #ifdef UNIV_SYNC_DEBUG
  1577. ut_ad(mutex_own(&kernel_mutex));
  1578. #endif /* UNIV_SYNC_DEBUG */
  1579. ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
  1580. || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
  1581. ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
  1582. || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
  1583. ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
  1584. || (LOCK_MODE_MASK & mode) == LOCK_X);
  1585. ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
  1586. || mode - (LOCK_MODE_MASK & mode) == 0
  1587. || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
  1588. heap_no = rec_get_heap_no(rec);
  1589. lock = lock_rec_get_first_on_page(rec);
  1590. if (lock == NULL) {
  1591. if (!impl) {
  1592. lock_rec_create(mode, rec, index, thr_get_trx(thr));
  1593. }
  1594. return(TRUE);
  1595. }
  1596. if (lock_rec_get_next_on_page(lock)) {
  1597. return(FALSE);
  1598. }
  1599. if (lock->trx != thr_get_trx(thr)
  1600. || lock->type_mode != (mode | LOCK_REC)
  1601. || lock_rec_get_n_bits(lock) <= heap_no) {
  1602.      return(FALSE);
  1603. }
  1604. if (!impl) {
  1605. lock_rec_set_nth_bit(lock, heap_no);
  1606. }
  1607. return(TRUE);
  1608. }
  1609. /*************************************************************************
  1610. This is the general, and slower, routine for locking a record. This is a
  1611. low-level function which does NOT look at implicit locks! Checks lock
  1612. compatibility within explicit locks. This function sets a normal next-key
  1613. lock, or in the case of a page supremum record, a gap type lock. */
  1614. static
  1615. ulint
  1616. lock_rec_lock_slow(
  1617. /*===============*/
  1618. /* out: DB_SUCCESS, DB_LOCK_WAIT, or error
  1619. code */
  1620. ibool impl, /* in: if TRUE, no lock is set if no wait is
  1621. necessary: we assume that the caller will set
  1622. an implicit lock */
  1623. ulint mode, /* in: lock mode: LOCK_X or LOCK_S possibly
  1624. ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */
  1625. rec_t* rec, /* in: record */
  1626. dict_index_t* index, /* in: index of record */
  1627. que_thr_t*  thr) /* in: query thread */
  1628. {
  1629. trx_t* trx;
  1630. ulint err;
  1631. #ifdef UNIV_SYNC_DEBUG
  1632. ut_ad(mutex_own(&kernel_mutex));
  1633. #endif /* UNIV_SYNC_DEBUG */
  1634. ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
  1635. || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
  1636. ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
  1637. || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
  1638. ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
  1639. || (LOCK_MODE_MASK & mode) == LOCK_X);
  1640. ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
  1641. || mode - (LOCK_MODE_MASK & mode) == 0
  1642. || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
  1643. trx = thr_get_trx(thr);
  1644. if (lock_rec_has_expl(mode, rec, trx)) {
  1645. /* The trx already has a strong enough lock on rec: do
  1646. nothing */
  1647. err = DB_SUCCESS;
  1648. } else if (lock_rec_other_has_conflicting(mode, rec, trx)) {
  1649. /* If another transaction has a non-gap conflicting request in
  1650. the queue, as this transaction does not have a lock strong
  1651. enough already granted on the record, we have to wait. */
  1652.     
  1653. err = lock_rec_enqueue_waiting(mode, rec, index, thr);
  1654. } else {
  1655. if (!impl) {
  1656. /* Set the requested lock on the record */
  1657. lock_rec_add_to_queue(LOCK_REC | mode, rec, index,
  1658. trx);
  1659. }
  1660. err = DB_SUCCESS;
  1661. }
  1662. return(err);
  1663. }
  1664. /*************************************************************************
  1665. Tries to lock the specified record in the mode requested. If not immediately
  1666. possible, enqueues a waiting lock request. This is a low-level function
  1667. which does NOT look at implicit locks! Checks lock compatibility within
  1668. explicit locks. This function sets a normal next-key lock, or in the case
  1669. of a page supremum record, a gap type lock. */
  1670. static
  1671. ulint
  1672. lock_rec_lock(
  1673. /*==========*/
  1674. /* out: DB_SUCCESS, DB_LOCK_WAIT, or error
  1675. code */
  1676. ibool impl, /* in: if TRUE, no lock is set if no wait is
  1677. necessary: we assume that the caller will set
  1678. an implicit lock */
  1679. ulint mode, /* in: lock mode: LOCK_X or LOCK_S possibly
  1680. ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */
  1681. rec_t* rec, /* in: record */
  1682. dict_index_t* index, /* in: index of record */
  1683. que_thr_t*  thr) /* in: query thread */
  1684. {
  1685. ulint err;
  1686. #ifdef UNIV_SYNC_DEBUG
  1687. ut_ad(mutex_own(&kernel_mutex));
  1688. #endif /* UNIV_SYNC_DEBUG */
  1689. ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
  1690. || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
  1691. ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
  1692. || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
  1693. ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
  1694. || (LOCK_MODE_MASK & mode) == LOCK_X);
  1695. ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
  1696. || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
  1697. || mode - (LOCK_MODE_MASK & mode) == 0);
  1698. if (lock_rec_lock_fast(impl, mode, rec, index, thr)) {
  1699. /* We try a simplified and faster subroutine for the most
  1700. common cases */
  1701. err = DB_SUCCESS;
  1702. } else {
  1703. err = lock_rec_lock_slow(impl, mode, rec, index, thr);
  1704. }
  1705. return(err);
  1706. }
  1707. /*************************************************************************
  1708. Checks if a waiting record lock request still has to wait in a queue. */
  1709. static
  1710. ibool
  1711. lock_rec_has_to_wait_in_queue(
  1712. /*==========================*/
  1713. /* out: TRUE if still has to wait */
  1714. lock_t* wait_lock) /* in: waiting record lock */
  1715. {
  1716. lock_t* lock;
  1717. ulint space;
  1718. ulint page_no;
  1719. ulint heap_no;
  1720. #ifdef UNIV_SYNC_DEBUG
  1721. ut_ad(mutex_own(&kernel_mutex));
  1722. #endif /* UNIV_SYNC_DEBUG */
  1723.   ut_ad(lock_get_wait(wait_lock));
  1724. ut_ad(lock_get_type(wait_lock) == LOCK_REC);
  1725.  
  1726. space = wait_lock->un_member.rec_lock.space;
  1727. page_no = wait_lock->un_member.rec_lock.page_no;
  1728. heap_no = lock_rec_find_set_bit(wait_lock);
  1729. lock = lock_rec_get_first_on_page_addr(space, page_no);
  1730. while (lock != wait_lock) {
  1731. if (lock_rec_get_nth_bit(lock, heap_no)
  1732.     && lock_has_to_wait(wait_lock, lock)) {
  1733.      return(TRUE);
  1734. }
  1735. lock = lock_rec_get_next_on_page(lock);
  1736. }
  1737. return(FALSE);
  1738. }
  1739. /*****************************************************************
  1740. Grants a lock to a waiting lock request and releases the waiting
  1741. transaction. */
  1742. static
  1743. void
  1744. lock_grant(
  1745. /*=======*/
  1746. lock_t* lock) /* in: waiting lock request */
  1747. {
  1748. #ifdef UNIV_SYNC_DEBUG
  1749. ut_ad(mutex_own(&kernel_mutex));
  1750. #endif /* UNIV_SYNC_DEBUG */
  1751. lock_reset_lock_and_trx_wait(lock);
  1752.         if (lock_get_mode(lock) == LOCK_AUTO_INC) {
  1753.                 if (lock->trx->auto_inc_lock != NULL) {
  1754.                         fprintf(stderr,
  1755.                    "InnoDB: Error: trx already had an AUTO-INC lock!n");
  1756.                 }
  1757.                 /* Store pointer to lock to trx so that we know to
  1758.                 release it at the end of the SQL statement */
  1759.                 lock->trx->auto_inc_lock = lock;
  1760.         } else if (lock_get_type(lock) == LOCK_TABLE_EXP) {
  1761. ut_a(lock_get_mode(lock) == LOCK_S
  1762. || lock_get_mode(lock) == LOCK_X);
  1763. }
  1764. if (lock_print_waits) {
  1765. fprintf(stderr, "Lock wait for trx %lu endsn",
  1766.        (ulong) ut_dulint_get_low(lock->trx->id));
  1767. }
  1768. /* If we are resolving a deadlock by choosing another transaction
  1769. as a victim, then our original transaction may not be in the
  1770. TRX_QUE_LOCK_WAIT state, and there is no need to end the lock wait
  1771. for it */
  1772. if (lock->trx->que_state == TRX_QUE_LOCK_WAIT) {
  1773. trx_end_lock_wait(lock->trx);
  1774. }
  1775. }
  1776. /*****************************************************************
  1777. Cancels a waiting record lock request and releases the waiting transaction
  1778. that requested it. NOTE: does NOT check if waiting lock requests behind this
  1779. one can now be granted! */
  1780. static
  1781. void
  1782. lock_rec_cancel(
  1783. /*============*/
  1784. lock_t* lock) /* in: waiting record lock request */
  1785. {
  1786. #ifdef UNIV_SYNC_DEBUG
  1787. ut_ad(mutex_own(&kernel_mutex));
  1788. #endif /* UNIV_SYNC_DEBUG */
  1789. ut_ad(lock_get_type(lock) == LOCK_REC);
  1790. /* Reset the bit (there can be only one set bit) in the lock bitmap */
  1791. lock_rec_reset_nth_bit(lock, lock_rec_find_set_bit(lock));
  1792. /* Reset the wait flag and the back pointer to lock in trx */
  1793. lock_reset_lock_and_trx_wait(lock);
  1794. /* The following function releases the trx from lock wait */
  1795. trx_end_lock_wait(lock->trx);
  1796. }
  1797. /*****************************************************************
  1798. Removes a record lock request, waiting or granted, from the queue and
  1799. grants locks to other transactions in the queue if they now are entitled
  1800. to a lock. NOTE: all record locks contained in in_lock are removed. */
  1801. static
  1802. void
  1803. lock_rec_dequeue_from_page(
  1804. /*=======================*/
  1805. lock_t* in_lock)/* in: record lock object: all record locks which
  1806. are contained in this lock object are removed;
  1807. transactions waiting behind will get their lock
  1808. requests granted, if they are now qualified to it */
  1809. {
  1810. ulint space;
  1811. ulint page_no;
  1812. lock_t* lock;
  1813. trx_t* trx;
  1814. #ifdef UNIV_SYNC_DEBUG
  1815. ut_ad(mutex_own(&kernel_mutex));
  1816. #endif /* UNIV_SYNC_DEBUG */
  1817. ut_ad(lock_get_type(in_lock) == LOCK_REC);
  1818. trx = in_lock->trx;
  1819. space = in_lock->un_member.rec_lock.space;
  1820. page_no = in_lock->un_member.rec_lock.page_no;
  1821. HASH_DELETE(lock_t, hash, lock_sys->rec_hash,
  1822. lock_rec_fold(space, page_no), in_lock);
  1823. UT_LIST_REMOVE(trx_locks, trx->trx_locks, in_lock);
  1824. /* Check if waiting locks in the queue can now be granted: grant
  1825. locks if there are no conflicting locks ahead. */
  1826. lock = lock_rec_get_first_on_page_addr(space, page_no);
  1827. while (lock != NULL) {
  1828. if (lock_get_wait(lock)
  1829. && !lock_rec_has_to_wait_in_queue(lock)) {
  1830. /* Grant the lock */
  1831. lock_grant(lock);
  1832. }
  1833. lock = lock_rec_get_next_on_page(lock);
  1834. }
  1835. }
  1836. /*****************************************************************
  1837. Removes a record lock request, waiting or granted, from the queue. */
  1838. static
  1839. void
  1840. lock_rec_discard(
  1841. /*=============*/
  1842. lock_t* in_lock)/* in: record lock object: all record locks which
  1843. are contained in this lock object are removed */
  1844. {
  1845. ulint space;
  1846. ulint page_no;
  1847. trx_t* trx;
  1848. #ifdef UNIV_SYNC_DEBUG
  1849. ut_ad(mutex_own(&kernel_mutex));
  1850. #endif /* UNIV_SYNC_DEBUG */
  1851. ut_ad(lock_get_type(in_lock) == LOCK_REC);
  1852. trx = in_lock->trx;
  1853. space = in_lock->un_member.rec_lock.space;
  1854. page_no = in_lock->un_member.rec_lock.page_no;
  1855. HASH_DELETE(lock_t, hash, lock_sys->rec_hash,
  1856. lock_rec_fold(space, page_no), in_lock);
  1857. UT_LIST_REMOVE(trx_locks, trx->trx_locks, in_lock);
  1858. }
  1859. /*****************************************************************
  1860. Removes record lock objects set on an index page which is discarded. This
  1861. function does not move locks, or check for waiting locks, therefore the
  1862. lock bitmaps must already be reset when this function is called. */
  1863. static
  1864. void
  1865. lock_rec_free_all_from_discard_page(
  1866. /*================================*/
  1867. page_t* page) /* in: page to be discarded */
  1868. {
  1869. ulint space;
  1870. ulint page_no;
  1871. lock_t* lock;
  1872. lock_t* next_lock;
  1873. #ifdef UNIV_SYNC_DEBUG
  1874. ut_ad(mutex_own(&kernel_mutex));
  1875. #endif /* UNIV_SYNC_DEBUG */
  1876. space = buf_frame_get_space_id(page);
  1877. page_no = buf_frame_get_page_no(page);
  1878. lock = lock_rec_get_first_on_page_addr(space, page_no);
  1879. while (lock != NULL) {
  1880. ut_ad(lock_rec_find_set_bit(lock) == ULINT_UNDEFINED);
  1881. ut_ad(!lock_get_wait(lock));
  1882. next_lock = lock_rec_get_next_on_page(lock);
  1883. lock_rec_discard(lock);
  1884. lock = next_lock;
  1885. }
  1886. }
  1887. /*============= RECORD LOCK MOVING AND INHERITING ===================*/
  1888. /*****************************************************************
  1889. Resets the lock bits for a single record. Releases transactions waiting for
  1890. lock requests here. */
  1891. void
  1892. lock_rec_reset_and_release_wait(
  1893. /*============================*/
  1894. rec_t* rec) /* in: record whose locks bits should be reset */
  1895. {
  1896. lock_t* lock;
  1897. ulint heap_no;
  1898. #ifdef UNIV_SYNC_DEBUG
  1899. ut_ad(mutex_own(&kernel_mutex));
  1900. #endif /* UNIV_SYNC_DEBUG */
  1901. heap_no = rec_get_heap_no(rec);
  1902. lock = lock_rec_get_first(rec);
  1903. while (lock != NULL) {
  1904. if (lock_get_wait(lock)) {
  1905. lock_rec_cancel(lock);
  1906. } else {
  1907. lock_rec_reset_nth_bit(lock, heap_no);
  1908. }
  1909. lock = lock_rec_get_next(rec, lock);
  1910. }
  1911. }
  1912. /*****************************************************************
  1913. Makes a record to inherit the locks (except LOCK_INSERT_INTENTION type)
  1914. of another record as gap type locks, but does not reset the lock bits of
  1915. the other record. Also waiting lock requests on rec are inherited as
  1916. GRANTED gap locks. */
  1917. void
  1918. lock_rec_inherit_to_gap(
  1919. /*====================*/
  1920. rec_t* heir, /* in: record which inherits */
  1921. rec_t* rec) /* in: record from which inherited; does NOT reset
  1922. the locks on this record */
  1923. {
  1924. lock_t* lock;
  1925. #ifdef UNIV_SYNC_DEBUG
  1926. ut_ad(mutex_own(&kernel_mutex));
  1927. #endif /* UNIV_SYNC_DEBUG */
  1928. lock = lock_rec_get_first(rec);
  1929. while (lock != NULL) {
  1930. if (!lock_rec_get_insert_intention(lock)) {
  1931. lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock)
  1932. | LOCK_GAP,
  1933.         heir, lock->index, lock->trx);
  1934.   }
  1935.  
  1936. lock = lock_rec_get_next(rec, lock);
  1937. }
  1938. }
  1939. /*****************************************************************
  1940. Makes a record to inherit the gap locks (except LOCK_INSERT_INTENTION type)
  1941. of another record as gap type locks, but does not reset the lock bits of the
  1942. other record. Also waiting lock requests are inherited as GRANTED gap locks. */
  1943. static
  1944. void
  1945. lock_rec_inherit_to_gap_if_gap_lock(
  1946. /*================================*/
  1947. rec_t* heir, /* in: record which inherits */
  1948. rec_t* rec) /* in: record from which inherited; does NOT reset
  1949. the locks on this record */
  1950. {
  1951. lock_t* lock;
  1952. #ifdef UNIV_SYNC_DEBUG
  1953. ut_ad(mutex_own(&kernel_mutex));
  1954. #endif /* UNIV_SYNC_DEBUG */
  1955. lock = lock_rec_get_first(rec);
  1956. while (lock != NULL) {
  1957. if (!lock_rec_get_insert_intention(lock)
  1958.     && (page_rec_is_supremum(rec)
  1959. || !lock_rec_get_rec_not_gap(lock))) {
  1960. lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock)
  1961. | LOCK_GAP,
  1962.         heir, lock->index, lock->trx);
  1963.   }
  1964. lock = lock_rec_get_next(rec, lock);
  1965. }
  1966. }
  1967. /*****************************************************************
  1968. Moves the locks of a record to another record and resets the lock bits of
  1969. the donating record. */
  1970. static
  1971. void
  1972. lock_rec_move(
  1973. /*==========*/
  1974. rec_t* receiver, /* in: record which gets locks; this record
  1975. must have no lock requests on it! */
  1976. rec_t* donator) /* in: record which gives locks */
  1977. {
  1978. lock_t* lock;
  1979. ulint heap_no;
  1980. ulint type_mode;
  1981. #ifdef UNIV_SYNC_DEBUG
  1982. ut_ad(mutex_own(&kernel_mutex));
  1983. #endif /* UNIV_SYNC_DEBUG */
  1984. heap_no = rec_get_heap_no(donator);
  1985. lock = lock_rec_get_first(donator);
  1986. ut_ad(lock_rec_get_first(receiver) == NULL);
  1987. while (lock != NULL) {
  1988. type_mode = lock->type_mode;
  1989. lock_rec_reset_nth_bit(lock, heap_no);
  1990. if (lock_get_wait(lock)) {
  1991. lock_reset_lock_and_trx_wait(lock);
  1992. }
  1993. /* Note that we FIRST reset the bit, and then set the lock:
  1994. the function works also if donator == receiver */
  1995. lock_rec_add_to_queue(type_mode, receiver, lock->index,
  1996. lock->trx);
  1997. lock = lock_rec_get_next(donator, lock);
  1998. }
  1999. ut_ad(lock_rec_get_first(donator) == NULL);
  2000. }
  2001. /*****************************************************************
  2002. Updates the lock table when we have reorganized a page. NOTE: we copy
  2003. also the locks set on the infimum of the page; the infimum may carry
  2004. locks if an update of a record is occurring on the page, and its locks
  2005. were temporarily stored on the infimum. */
  2006. void
  2007. lock_move_reorganize_page(
  2008. /*======================*/
  2009. page_t* page, /* in: old index page, now reorganized */
  2010. page_t* old_page) /* in: copy of the old, not reorganized page */
  2011. {
  2012. lock_t* lock;
  2013. lock_t* old_lock;
  2014. page_cur_t cur1;
  2015. page_cur_t cur2;
  2016. ulint old_heap_no;
  2017. UT_LIST_BASE_NODE_T(lock_t) old_locks;
  2018. mem_heap_t* heap = NULL;