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.

7205 lines
196 KiB

17 years ago
17 years ago
17 years ago
16 years ago
MDEV-5262, MDEV-5914, MDEV-5941, MDEV-6020: Deadlocks during parallel replication causing replication to fail. In parallel replication, we run transactions from the master in parallel, but force them to commit in the same order they did on the master. If we force T1 to commit before T2, but T2 holds eg. a row lock that is needed by T1, we get a deadlock when T2 waits until T1 has committed. Usually, we do not run T1 and T2 in parallel if there is a chance that they can have conflicting locks like this, but there are certain edge cases where it can occasionally happen (eg. MDEV-5914, MDEV-5941, MDEV-6020). The bug was that this would cause replication to hang, eventually getting a lock timeout and causing the slave to stop with error. With this patch, InnoDB will report back to the upper layer whenever a transactions T1 is about to do a lock wait on T2. If T1 and T2 are parallel replication transactions, and T2 needs to commit later than T1, we can thus detect the deadlock; we then kill T2, setting a flag that causes it to catch the kill and convert it to a deadlock error; this error will then cause T2 to roll back and release its locks (so that T1 can commit), and later T2 will be re-tried and eventually also committed. The kill happens asynchroneously in a slave background thread; this is necessary, as the reporting from InnoDB about lock waits happen deep inside the locking code, at a point where it is not possible to directly call THD::awake() due to mutexes held. Deadlock is assumed to be (very) rarely occuring, so this patch tries to minimise the performance impact on the normal case where no deadlocks occur, rather than optimise the handling of the occasional deadlock. Also fix transaction retry due to deadlock when it happens after a transaction already signalled to later transactions that it started to commit. In this case we need to undo this signalling (and later redo it when we commit again during retry), so following transactions will not start too early. Also add a missing thd->send_kill_message() that got triggered during testing (this corrects an incorrect fix for MySQL Bug#58933).
12 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
14 years ago
14 years ago
16 years ago
16 years ago
14 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
14 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
14 years ago
16 years ago
16 years ago
16 years ago
14 years ago
16 years ago
14 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
MDEV-5262, MDEV-5914, MDEV-5941, MDEV-6020: Deadlocks during parallel replication causing replication to fail. In parallel replication, we run transactions from the master in parallel, but force them to commit in the same order they did on the master. If we force T1 to commit before T2, but T2 holds eg. a row lock that is needed by T1, we get a deadlock when T2 waits until T1 has committed. Usually, we do not run T1 and T2 in parallel if there is a chance that they can have conflicting locks like this, but there are certain edge cases where it can occasionally happen (eg. MDEV-5914, MDEV-5941, MDEV-6020). The bug was that this would cause replication to hang, eventually getting a lock timeout and causing the slave to stop with error. With this patch, InnoDB will report back to the upper layer whenever a transactions T1 is about to do a lock wait on T2. If T1 and T2 are parallel replication transactions, and T2 needs to commit later than T1, we can thus detect the deadlock; we then kill T2, setting a flag that causes it to catch the kill and convert it to a deadlock error; this error will then cause T2 to roll back and release its locks (so that T1 can commit), and later T2 will be re-tried and eventually also committed. The kill happens asynchroneously in a slave background thread; this is necessary, as the reporting from InnoDB about lock waits happen deep inside the locking code, at a point where it is not possible to directly call THD::awake() due to mutexes held. Deadlock is assumed to be (very) rarely occuring, so this patch tries to minimise the performance impact on the normal case where no deadlocks occur, rather than optimise the handling of the occasional deadlock. Also fix transaction retry due to deadlock when it happens after a transaction already signalled to later transactions that it started to commit. In this case we need to undo this signalling (and later redo it when we commit again during retry), so following transactions will not start too early. Also add a missing thd->send_kill_message() that got triggered during testing (this corrects an incorrect fix for MySQL Bug#58933).
12 years ago
MDEV-5262, MDEV-5914, MDEV-5941, MDEV-6020: Deadlocks during parallel replication causing replication to fail. In parallel replication, we run transactions from the master in parallel, but force them to commit in the same order they did on the master. If we force T1 to commit before T2, but T2 holds eg. a row lock that is needed by T1, we get a deadlock when T2 waits until T1 has committed. Usually, we do not run T1 and T2 in parallel if there is a chance that they can have conflicting locks like this, but there are certain edge cases where it can occasionally happen (eg. MDEV-5914, MDEV-5941, MDEV-6020). The bug was that this would cause replication to hang, eventually getting a lock timeout and causing the slave to stop with error. With this patch, InnoDB will report back to the upper layer whenever a transactions T1 is about to do a lock wait on T2. If T1 and T2 are parallel replication transactions, and T2 needs to commit later than T1, we can thus detect the deadlock; we then kill T2, setting a flag that causes it to catch the kill and convert it to a deadlock error; this error will then cause T2 to roll back and release its locks (so that T1 can commit), and later T2 will be re-tried and eventually also committed. The kill happens asynchroneously in a slave background thread; this is necessary, as the reporting from InnoDB about lock waits happen deep inside the locking code, at a point where it is not possible to directly call THD::awake() due to mutexes held. Deadlock is assumed to be (very) rarely occuring, so this patch tries to minimise the performance impact on the normal case where no deadlocks occur, rather than optimise the handling of the occasional deadlock. Also fix transaction retry due to deadlock when it happens after a transaction already signalled to later transactions that it started to commit. In this case we need to undo this signalling (and later redo it when we commit again during retry), so following transactions will not start too early. Also add a missing thd->send_kill_message() that got triggered during testing (this corrects an incorrect fix for MySQL Bug#58933).
12 years ago
MDEV-5262, MDEV-5914, MDEV-5941, MDEV-6020: Deadlocks during parallel replication causing replication to fail. In parallel replication, we run transactions from the master in parallel, but force them to commit in the same order they did on the master. If we force T1 to commit before T2, but T2 holds eg. a row lock that is needed by T1, we get a deadlock when T2 waits until T1 has committed. Usually, we do not run T1 and T2 in parallel if there is a chance that they can have conflicting locks like this, but there are certain edge cases where it can occasionally happen (eg. MDEV-5914, MDEV-5941, MDEV-6020). The bug was that this would cause replication to hang, eventually getting a lock timeout and causing the slave to stop with error. With this patch, InnoDB will report back to the upper layer whenever a transactions T1 is about to do a lock wait on T2. If T1 and T2 are parallel replication transactions, and T2 needs to commit later than T1, we can thus detect the deadlock; we then kill T2, setting a flag that causes it to catch the kill and convert it to a deadlock error; this error will then cause T2 to roll back and release its locks (so that T1 can commit), and later T2 will be re-tried and eventually also committed. The kill happens asynchroneously in a slave background thread; this is necessary, as the reporting from InnoDB about lock waits happen deep inside the locking code, at a point where it is not possible to directly call THD::awake() due to mutexes held. Deadlock is assumed to be (very) rarely occuring, so this patch tries to minimise the performance impact on the normal case where no deadlocks occur, rather than optimise the handling of the occasional deadlock. Also fix transaction retry due to deadlock when it happens after a transaction already signalled to later transactions that it started to commit. In this case we need to undo this signalling (and later redo it when we commit again during retry), so following transactions will not start too early. Also add a missing thd->send_kill_message() that got triggered during testing (this corrects an incorrect fix for MySQL Bug#58933).
12 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
14 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
14 years ago
14 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
14 years ago
16 years ago
14 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
14 years ago
16 years ago
14 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
  1. /*****************************************************************************
  2. Copyright (c) 1996, 2014, Oracle and/or its affiliates. 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.,
  11. 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
  12. *****************************************************************************/
  13. /**************************************************//**
  14. @file lock/lock0lock.cc
  15. The transaction lock system
  16. Created 5/7/1996 Heikki Tuuri
  17. *******************************************************/
  18. #define LOCK_MODULE_IMPLEMENTATION
  19. #include "lock0lock.h"
  20. #include "lock0priv.h"
  21. #ifdef UNIV_NONINL
  22. #include "lock0lock.ic"
  23. #include "lock0priv.ic"
  24. #endif
  25. #include "ha_prototypes.h"
  26. #include "usr0sess.h"
  27. #include "trx0purge.h"
  28. #include "dict0mem.h"
  29. #include "dict0boot.h"
  30. #include "trx0sys.h"
  31. #include "pars0pars.h" /* pars_complete_graph_for_exec() */
  32. #include "que0que.h" /* que_node_get_parent() */
  33. #include "row0mysql.h" /* row_mysql_handle_errors() */
  34. #include "row0sel.h" /* sel_node_create(), sel_node_t */
  35. #include "row0types.h" /* sel_node_t */
  36. #include "srv0mon.h"
  37. #include "ut0vec.h"
  38. #include "btr0btr.h"
  39. #include "dict0boot.h"
  40. #include <set>
  41. #include "mysql/plugin.h"
  42. /* Restricts the length of search we will do in the waits-for
  43. graph of transactions */
  44. #define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000
  45. /* Restricts the search depth we will do in the waits-for graph of
  46. transactions */
  47. #define LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK 200
  48. /* When releasing transaction locks, this specifies how often we release
  49. the lock mutex for a moment to give also others access to it */
  50. #define LOCK_RELEASE_INTERVAL 1000
  51. /* Safety margin when creating a new record lock: this many extra records
  52. can be inserted to the page without need to create a lock with a bigger
  53. bitmap */
  54. #define LOCK_PAGE_BITMAP_MARGIN 64
  55. /* An explicit record lock affects both the record and the gap before it.
  56. An implicit x-lock does not affect the gap, it only locks the index
  57. record from read or update.
  58. If a transaction has modified or inserted an index record, then
  59. it owns an implicit x-lock on the record. On a secondary index record,
  60. a transaction has an implicit x-lock also if it has modified the
  61. clustered index record, the max trx id of the page where the secondary
  62. index record resides is >= trx id of the transaction (or database recovery
  63. is running), and there are no explicit non-gap lock requests on the
  64. secondary index record.
  65. This complicated definition for a secondary index comes from the
  66. implementation: we want to be able to determine if a secondary index
  67. record has an implicit x-lock, just by looking at the present clustered
  68. index record, not at the historical versions of the record. The
  69. complicated definition can be explained to the user so that there is
  70. nondeterminism in the access path when a query is answered: we may,
  71. or may not, access the clustered index record and thus may, or may not,
  72. bump into an x-lock set there.
  73. Different transaction can have conflicting locks set on the gap at the
  74. same time. The locks on the gap are purely inhibitive: an insert cannot
  75. be made, or a select cursor may have to wait if a different transaction
  76. has a conflicting lock on the gap. An x-lock on the gap does not give
  77. the right to insert into the gap.
  78. An explicit lock can be placed on a user record or the supremum record of
  79. a page. The locks on the supremum record are always thought to be of the gap
  80. type, though the gap bit is not set. When we perform an update of a record
  81. where the size of the record changes, we may temporarily store its explicit
  82. locks on the infimum record of the page, though the infimum otherwise never
  83. carries locks.
  84. A waiting record lock can also be of the gap type. A waiting lock request
  85. can be granted when there is no conflicting mode lock request by another
  86. transaction ahead of it in the explicit lock queue.
  87. In version 4.0.5 we added yet another explicit lock type: LOCK_REC_NOT_GAP.
  88. It only locks the record it is placed on, not the gap before the record.
  89. This lock type is necessary to emulate an Oracle-like READ COMMITTED isolation
  90. level.
  91. -------------------------------------------------------------------------
  92. RULE 1: If there is an implicit x-lock on a record, and there are non-gap
  93. -------
  94. lock requests waiting in the queue, then the transaction holding the implicit
  95. x-lock also has an explicit non-gap record x-lock. Therefore, as locks are
  96. released, we can grant locks to waiting lock requests purely by looking at
  97. the explicit lock requests in the queue.
  98. RULE 3: Different transactions cannot have conflicting granted non-gap locks
  99. -------
  100. on a record at the same time. However, they can have conflicting granted gap
  101. locks.
  102. RULE 4: If a there is a waiting lock request in a queue, no lock request,
  103. -------
  104. gap or not, can be inserted ahead of it in the queue. In record deletes
  105. and page splits new gap type locks can be created by the database manager
  106. for a transaction, and without rule 4, the waits-for graph of transactions
  107. might become cyclic without the database noticing it, as the deadlock check
  108. is only performed when a transaction itself requests a lock!
  109. -------------------------------------------------------------------------
  110. An insert is allowed to a gap if there are no explicit lock requests by
  111. other transactions on the next record. It does not matter if these lock
  112. requests are granted or waiting, gap bit set or not, with the exception
  113. that a gap type request set by another transaction to wait for
  114. its turn to do an insert is ignored. On the other hand, an
  115. implicit x-lock by another transaction does not prevent an insert, which
  116. allows for more concurrency when using an Oracle-style sequence number
  117. generator for the primary key with many transactions doing inserts
  118. concurrently.
  119. A modify of a record is allowed if the transaction has an x-lock on the
  120. record, or if other transactions do not have any non-gap lock requests on the
  121. record.
  122. A read of a single user record with a cursor is allowed if the transaction
  123. has a non-gap explicit, or an implicit lock on the record, or if the other
  124. transactions have no x-lock requests on the record. At a page supremum a
  125. read is always allowed.
  126. In summary, an implicit lock is seen as a granted x-lock only on the
  127. record, not on the gap. An explicit lock with no gap bit set is a lock
  128. both on the record and the gap. If the gap bit is set, the lock is only
  129. on the gap. Different transaction cannot own conflicting locks on the
  130. record at the same time, but they may own conflicting locks on the gap.
  131. Granted locks on a record give an access right to the record, but gap type
  132. locks just inhibit operations.
  133. NOTE: Finding out if some transaction has an implicit x-lock on a secondary
  134. index record can be cumbersome. We may have to look at previous versions of
  135. the corresponding clustered index record to find out if a delete marked
  136. secondary index record was delete marked by an active transaction, not by
  137. a committed one.
  138. FACT A: If a transaction has inserted a row, it can delete it any time
  139. without need to wait for locks.
  140. PROOF: The transaction has an implicit x-lock on every index record inserted
  141. for the row, and can thus modify each record without the need to wait. Q.E.D.
  142. FACT B: If a transaction has read some result set with a cursor, it can read
  143. it again, and retrieves the same result set, if it has not modified the
  144. result set in the meantime. Hence, there is no phantom problem. If the
  145. biggest record, in the alphabetical order, touched by the cursor is removed,
  146. a lock wait may occur, otherwise not.
  147. PROOF: When a read cursor proceeds, it sets an s-lock on each user record
  148. it passes, and a gap type s-lock on each page supremum. The cursor must
  149. wait until it has these locks granted. Then no other transaction can
  150. have a granted x-lock on any of the user records, and therefore cannot
  151. modify the user records. Neither can any other transaction insert into
  152. the gaps which were passed over by the cursor. Page splits and merges,
  153. and removal of obsolete versions of records do not affect this, because
  154. when a user record or a page supremum is removed, the next record inherits
  155. its locks as gap type locks, and therefore blocks inserts to the same gap.
  156. Also, if a page supremum is inserted, it inherits its locks from the successor
  157. record. When the cursor is positioned again at the start of the result set,
  158. the records it will touch on its course are either records it touched
  159. during the last pass or new inserted page supremums. It can immediately
  160. access all these records, and when it arrives at the biggest record, it
  161. notices that the result set is complete. If the biggest record was removed,
  162. lock wait can occur because the next record only inherits a gap type lock,
  163. and a wait may be needed. Q.E.D. */
  164. /* If an index record should be changed or a new inserted, we must check
  165. the lock on the record or the next. When a read cursor starts reading,
  166. we will set a record level s-lock on each record it passes, except on the
  167. initial record on which the cursor is positioned before we start to fetch
  168. records. Our index tree search has the convention that the B-tree
  169. cursor is positioned BEFORE the first possibly matching record in
  170. the search. Optimizations are possible here: if the record is searched
  171. on an equality condition to a unique key, we could actually set a special
  172. lock on the record, a lock which would not prevent any insert before
  173. this record. In the next key locking an x-lock set on a record also
  174. prevents inserts just before that record.
  175. There are special infimum and supremum records on each page.
  176. A supremum record can be locked by a read cursor. This records cannot be
  177. updated but the lock prevents insert of a user record to the end of
  178. the page.
  179. Next key locks will prevent the phantom problem where new rows
  180. could appear to SELECT result sets after the select operation has been
  181. performed. Prevention of phantoms ensures the serilizability of
  182. transactions.
  183. What should we check if an insert of a new record is wanted?
  184. Only the lock on the next record on the same page, because also the
  185. supremum record can carry a lock. An s-lock prevents insertion, but
  186. what about an x-lock? If it was set by a searched update, then there
  187. is implicitly an s-lock, too, and the insert should be prevented.
  188. What if our transaction owns an x-lock to the next record, but there is
  189. a waiting s-lock request on the next record? If this s-lock was placed
  190. by a read cursor moving in the ascending order in the index, we cannot
  191. do the insert immediately, because when we finally commit our transaction,
  192. the read cursor should see also the new inserted record. So we should
  193. move the read cursor backward from the next record for it to pass over
  194. the new inserted record. This move backward may be too cumbersome to
  195. implement. If we in this situation just enqueue a second x-lock request
  196. for our transaction on the next record, then the deadlock mechanism
  197. notices a deadlock between our transaction and the s-lock request
  198. transaction. This seems to be an ok solution.
  199. We could have the convention that granted explicit record locks,
  200. lock the corresponding records from changing, and also lock the gaps
  201. before them from inserting. A waiting explicit lock request locks the gap
  202. before from inserting. Implicit record x-locks, which we derive from the
  203. transaction id in the clustered index record, only lock the record itself
  204. from modification, not the gap before it from inserting.
  205. How should we store update locks? If the search is done by a unique
  206. key, we could just modify the record trx id. Otherwise, we could put a record
  207. x-lock on the record. If the update changes ordering fields of the
  208. clustered index record, the inserted new record needs no record lock in
  209. lock table, the trx id is enough. The same holds for a secondary index
  210. record. Searched delete is similar to update.
  211. PROBLEM:
  212. What about waiting lock requests? If a transaction is waiting to make an
  213. update to a record which another modified, how does the other transaction
  214. know to send the end-lock-wait signal to the waiting transaction? If we have
  215. the convention that a transaction may wait for just one lock at a time, how
  216. do we preserve it if lock wait ends?
  217. PROBLEM:
  218. Checking the trx id label of a secondary index record. In the case of a
  219. modification, not an insert, is this necessary? A secondary index record
  220. is modified only by setting or resetting its deleted flag. A secondary index
  221. record contains fields to uniquely determine the corresponding clustered
  222. index record. A secondary index record is therefore only modified if we
  223. also modify the clustered index record, and the trx id checking is done
  224. on the clustered index record, before we come to modify the secondary index
  225. record. So, in the case of delete marking or unmarking a secondary index
  226. record, we do not have to care about trx ids, only the locks in the lock
  227. table must be checked. In the case of a select from a secondary index, the
  228. trx id is relevant, and in this case we may have to search the clustered
  229. index record.
  230. PROBLEM: How to update record locks when page is split or merged, or
  231. --------------------------------------------------------------------
  232. a record is deleted or updated?
  233. If the size of fields in a record changes, we perform the update by
  234. a delete followed by an insert. How can we retain the locks set or
  235. waiting on the record? Because a record lock is indexed in the bitmap
  236. by the heap number of the record, when we remove the record from the
  237. record list, it is possible still to keep the lock bits. If the page
  238. is reorganized, we could make a table of old and new heap numbers,
  239. and permute the bitmaps in the locks accordingly. We can add to the
  240. table a row telling where the updated record ended. If the update does
  241. not require a reorganization of the page, we can simply move the lock
  242. bits for the updated record to the position determined by its new heap
  243. number (we may have to allocate a new lock, if we run out of the bitmap
  244. in the old one).
  245. A more complicated case is the one where the reinsertion of the
  246. updated record is done pessimistically, because the structure of the
  247. tree may change.
  248. PROBLEM: If a supremum record is removed in a page merge, or a record
  249. ---------------------------------------------------------------------
  250. removed in a purge, what to do to the waiting lock requests? In a split to
  251. the right, we just move the lock requests to the new supremum. If a record
  252. is removed, we could move the waiting lock request to its inheritor, the
  253. next record in the index. But, the next record may already have lock
  254. requests on its own queue. A new deadlock check should be made then. Maybe
  255. it is easier just to release the waiting transactions. They can then enqueue
  256. new lock requests on appropriate records.
  257. PROBLEM: When a record is inserted, what locks should it inherit from the
  258. -------------------------------------------------------------------------
  259. upper neighbor? An insert of a new supremum record in a page split is
  260. always possible, but an insert of a new user record requires that the upper
  261. neighbor does not have any lock requests by other transactions, granted or
  262. waiting, in its lock queue. Solution: We can copy the locks as gap type
  263. locks, so that also the waiting locks are transformed to granted gap type
  264. locks on the inserted record. */
  265. #define LOCK_STACK_SIZE OS_THREAD_MAX_N
  266. /* LOCK COMPATIBILITY MATRIX
  267. * IS IX S X AI
  268. * IS + + + - +
  269. * IX + + - - +
  270. * S + - + - -
  271. * X - - - - -
  272. * AI + + - - -
  273. *
  274. * Note that for rows, InnoDB only acquires S or X locks.
  275. * For tables, InnoDB normally acquires IS or IX locks.
  276. * S or X table locks are only acquired for LOCK TABLES.
  277. * Auto-increment (AI) locks are needed because of
  278. * statement-level MySQL binlog.
  279. * See also lock_mode_compatible().
  280. */
  281. static const byte lock_compatibility_matrix[5][5] = {
  282. /** IS IX S X AI */
  283. /* IS */ { TRUE, TRUE, TRUE, FALSE, TRUE},
  284. /* IX */ { TRUE, TRUE, FALSE, FALSE, TRUE},
  285. /* S */ { TRUE, FALSE, TRUE, FALSE, FALSE},
  286. /* X */ { FALSE, FALSE, FALSE, FALSE, FALSE},
  287. /* AI */ { TRUE, TRUE, FALSE, FALSE, FALSE}
  288. };
  289. /* STRONGER-OR-EQUAL RELATION (mode1=row, mode2=column)
  290. * IS IX S X AI
  291. * IS + - - - -
  292. * IX + + - - -
  293. * S + - + - -
  294. * X + + + + +
  295. * AI - - - - +
  296. * See lock_mode_stronger_or_eq().
  297. */
  298. static const byte lock_strength_matrix[5][5] = {
  299. /** IS IX S X AI */
  300. /* IS */ { TRUE, FALSE, FALSE, FALSE, FALSE},
  301. /* IX */ { TRUE, TRUE, FALSE, FALSE, FALSE},
  302. /* S */ { TRUE, FALSE, TRUE, FALSE, FALSE},
  303. /* X */ { TRUE, TRUE, TRUE, TRUE, TRUE},
  304. /* AI */ { FALSE, FALSE, FALSE, FALSE, TRUE}
  305. };
  306. /** Deadlock check context. */
  307. struct lock_deadlock_ctx_t {
  308. const trx_t* start; /*!< Joining transaction that is
  309. requesting a lock in an incompatible
  310. mode */
  311. const lock_t* wait_lock; /*!< Lock that trx wants */
  312. ib_uint64_t mark_start; /*!< Value of lock_mark_count at
  313. the start of the deadlock check. */
  314. ulint depth; /*!< Stack depth */
  315. ulint cost; /*!< Calculation steps thus far */
  316. ibool too_deep; /*!< TRUE if search was too deep and
  317. was aborted */
  318. };
  319. /** DFS visited node information used during deadlock checking. */
  320. struct lock_stack_t {
  321. const lock_t* lock; /*!< Current lock */
  322. const lock_t* wait_lock; /*!< Waiting for lock */
  323. ulint heap_no; /*!< heap number if rec lock */
  324. };
  325. /** Stack to use during DFS search. Currently only a single stack is required
  326. because there is no parallel deadlock check. This stack is protected by
  327. the lock_sys_t::mutex. */
  328. static lock_stack_t* lock_stack;
  329. /** The count of the types of locks. */
  330. static const ulint lock_types = UT_ARR_SIZE(lock_compatibility_matrix);
  331. #ifdef UNIV_PFS_MUTEX
  332. /* Key to register mutex with performance schema */
  333. UNIV_INTERN mysql_pfs_key_t lock_sys_mutex_key;
  334. /* Key to register mutex with performance schema */
  335. UNIV_INTERN mysql_pfs_key_t lock_sys_wait_mutex_key;
  336. #endif /* UNIV_PFS_MUTEX */
  337. #ifdef UNIV_DEBUG
  338. UNIV_INTERN ibool lock_print_waits = FALSE;
  339. /*********************************************************************//**
  340. Validates the lock system.
  341. @return TRUE if ok */
  342. static
  343. bool
  344. lock_validate();
  345. /*============*/
  346. /*********************************************************************//**
  347. Validates the record lock queues on a page.
  348. @return TRUE if ok */
  349. static
  350. ibool
  351. lock_rec_validate_page(
  352. /*===================*/
  353. const buf_block_t* block) /*!< in: buffer block */
  354. __attribute__((nonnull, warn_unused_result));
  355. #endif /* UNIV_DEBUG */
  356. /* The lock system */
  357. UNIV_INTERN lock_sys_t* lock_sys = NULL;
  358. /** We store info on the latest deadlock error to this buffer. InnoDB
  359. Monitor will then fetch it and print */
  360. UNIV_INTERN ibool lock_deadlock_found = FALSE;
  361. /** Only created if !srv_read_only_mode */
  362. static FILE* lock_latest_err_file;
  363. /********************************************************************//**
  364. Checks if a joining lock request results in a deadlock. If a deadlock is
  365. found this function will resolve the dadlock by choosing a victim transaction
  366. and rolling it back. It will attempt to resolve all deadlocks. The returned
  367. transaction id will be the joining transaction id or 0 if some other
  368. transaction was chosen as a victim and rolled back or no deadlock found.
  369. @return id of transaction chosen as victim or 0 */
  370. static
  371. trx_id_t
  372. lock_deadlock_check_and_resolve(
  373. /*===========================*/
  374. const lock_t* lock, /*!< in: lock the transaction is requesting */
  375. const trx_t* trx); /*!< in: transaction */
  376. /*********************************************************************//**
  377. Gets the nth bit of a record lock.
  378. @return TRUE if bit set also if i == ULINT_UNDEFINED return FALSE*/
  379. UNIV_INLINE
  380. ibool
  381. lock_rec_get_nth_bit(
  382. /*=================*/
  383. const lock_t* lock, /*!< in: record lock */
  384. ulint i) /*!< in: index of the bit */
  385. {
  386. const byte* b;
  387. ut_ad(lock);
  388. ut_ad(lock_get_type_low(lock) == LOCK_REC);
  389. if (i >= lock->un_member.rec_lock.n_bits) {
  390. return(FALSE);
  391. }
  392. b = ((const byte*) &lock[1]) + (i / 8);
  393. return(1 & *b >> (i % 8));
  394. }
  395. /*********************************************************************//**
  396. Reports that a transaction id is insensible, i.e., in the future. */
  397. UNIV_INTERN
  398. void
  399. lock_report_trx_id_insanity(
  400. /*========================*/
  401. trx_id_t trx_id, /*!< in: trx id */
  402. const rec_t* rec, /*!< in: user record */
  403. dict_index_t* index, /*!< in: index */
  404. const ulint* offsets, /*!< in: rec_get_offsets(rec, index) */
  405. trx_id_t max_trx_id) /*!< in: trx_sys_get_max_trx_id() */
  406. {
  407. ut_print_timestamp(stderr);
  408. fputs(" InnoDB: Error: transaction id associated with record\n",
  409. stderr);
  410. rec_print_new(stderr, rec, offsets);
  411. fputs("InnoDB: in ", stderr);
  412. dict_index_name_print(stderr, NULL, index);
  413. fprintf(stderr, "\n"
  414. "InnoDB: is " TRX_ID_FMT " which is higher than the"
  415. " global trx id counter " TRX_ID_FMT "!\n"
  416. "InnoDB: The table is corrupt. You have to do"
  417. " dump + drop + reimport.\n",
  418. trx_id, max_trx_id);
  419. }
  420. /*********************************************************************//**
  421. Checks that a transaction id is sensible, i.e., not in the future.
  422. @return true if ok */
  423. #ifdef UNIV_DEBUG
  424. UNIV_INTERN
  425. #else
  426. static __attribute__((nonnull, warn_unused_result))
  427. #endif
  428. bool
  429. lock_check_trx_id_sanity(
  430. /*=====================*/
  431. trx_id_t trx_id, /*!< in: trx id */
  432. const rec_t* rec, /*!< in: user record */
  433. dict_index_t* index, /*!< in: index */
  434. const ulint* offsets) /*!< in: rec_get_offsets(rec, index) */
  435. {
  436. bool is_ok;
  437. trx_id_t max_trx_id;
  438. ut_ad(rec_offs_validate(rec, index, offsets));
  439. max_trx_id = trx_sys_get_max_trx_id();
  440. is_ok = trx_id < max_trx_id;
  441. if (UNIV_UNLIKELY(!is_ok)) {
  442. lock_report_trx_id_insanity(trx_id,
  443. rec, index, offsets, max_trx_id);
  444. }
  445. return(is_ok);
  446. }
  447. /*********************************************************************//**
  448. Checks that a record is seen in a consistent read.
  449. @return true if sees, or false if an earlier version of the record
  450. should be retrieved */
  451. UNIV_INTERN
  452. bool
  453. lock_clust_rec_cons_read_sees(
  454. /*==========================*/
  455. const rec_t* rec, /*!< in: user record which should be read or
  456. passed over by a read cursor */
  457. dict_index_t* index, /*!< in: clustered index */
  458. const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
  459. read_view_t* view) /*!< in: consistent read view */
  460. {
  461. trx_id_t trx_id;
  462. ut_ad(dict_index_is_clust(index));
  463. ut_ad(page_rec_is_user_rec(rec));
  464. ut_ad(rec_offs_validate(rec, index, offsets));
  465. /* NOTE that we call this function while holding the search
  466. system latch. */
  467. trx_id = row_get_rec_trx_id(rec, index, offsets);
  468. return(read_view_sees_trx_id(view, trx_id));
  469. }
  470. /*********************************************************************//**
  471. Checks that a non-clustered index record is seen in a consistent read.
  472. NOTE that a non-clustered index page contains so little information on
  473. its modifications that also in the case false, the present version of
  474. rec may be the right, but we must check this from the clustered index
  475. record.
  476. @return true if certainly sees, or false if an earlier version of the
  477. clustered index record might be needed */
  478. UNIV_INTERN
  479. bool
  480. lock_sec_rec_cons_read_sees(
  481. /*========================*/
  482. const rec_t* rec, /*!< in: user record which
  483. should be read or passed over
  484. by a read cursor */
  485. const read_view_t* view) /*!< in: consistent read view */
  486. {
  487. trx_id_t max_trx_id;
  488. ut_ad(page_rec_is_user_rec(rec));
  489. /* NOTE that we might call this function while holding the search
  490. system latch. */
  491. if (recv_recovery_is_on()) {
  492. return(false);
  493. }
  494. max_trx_id = page_get_max_trx_id(page_align(rec));
  495. ut_ad(max_trx_id);
  496. return(max_trx_id < view->up_limit_id);
  497. }
  498. /*********************************************************************//**
  499. Creates the lock system at database start. */
  500. UNIV_INTERN
  501. void
  502. lock_sys_create(
  503. /*============*/
  504. ulint n_cells) /*!< in: number of slots in lock hash table */
  505. {
  506. ulint lock_sys_sz;
  507. lock_sys_sz = sizeof(*lock_sys)
  508. + OS_THREAD_MAX_N * sizeof(srv_slot_t);
  509. lock_sys = static_cast<lock_sys_t*>(mem_zalloc(lock_sys_sz));
  510. lock_stack = static_cast<lock_stack_t*>(
  511. mem_zalloc(sizeof(*lock_stack) * LOCK_STACK_SIZE));
  512. void* ptr = &lock_sys[1];
  513. lock_sys->waiting_threads = static_cast<srv_slot_t*>(ptr);
  514. lock_sys->last_slot = lock_sys->waiting_threads;
  515. mutex_create(lock_sys_mutex_key, &lock_sys->mutex, SYNC_LOCK_SYS);
  516. mutex_create(lock_sys_wait_mutex_key,
  517. &lock_sys->wait_mutex, SYNC_LOCK_WAIT_SYS);
  518. lock_sys->timeout_event = os_event_create();
  519. lock_sys->rec_hash = hash_create(n_cells);
  520. lock_sys->rec_num = 0;
  521. if (!srv_read_only_mode) {
  522. lock_latest_err_file = os_file_create_tmpfile();
  523. ut_a(lock_latest_err_file);
  524. }
  525. }
  526. /*********************************************************************//**
  527. Closes the lock system at database shutdown. */
  528. UNIV_INTERN
  529. void
  530. lock_sys_close(void)
  531. /*================*/
  532. {
  533. if (lock_latest_err_file != NULL) {
  534. fclose(lock_latest_err_file);
  535. lock_latest_err_file = NULL;
  536. }
  537. hash_table_free(lock_sys->rec_hash);
  538. mutex_free(&lock_sys->mutex);
  539. mutex_free(&lock_sys->wait_mutex);
  540. mem_free(lock_stack);
  541. mem_free(lock_sys);
  542. lock_sys = NULL;
  543. lock_stack = NULL;
  544. }
  545. /*********************************************************************//**
  546. Gets the size of a lock struct.
  547. @return size in bytes */
  548. UNIV_INTERN
  549. ulint
  550. lock_get_size(void)
  551. /*===============*/
  552. {
  553. return((ulint) sizeof(lock_t));
  554. }
  555. /*********************************************************************//**
  556. Gets the mode of a lock.
  557. @return mode */
  558. UNIV_INLINE
  559. enum lock_mode
  560. lock_get_mode(
  561. /*==========*/
  562. const lock_t* lock) /*!< in: lock */
  563. {
  564. ut_ad(lock);
  565. return(static_cast<enum lock_mode>(lock->type_mode & LOCK_MODE_MASK));
  566. }
  567. /*********************************************************************//**
  568. Gets the wait flag of a lock.
  569. @return LOCK_WAIT if waiting, 0 if not */
  570. UNIV_INLINE
  571. ulint
  572. lock_get_wait(
  573. /*==========*/
  574. const lock_t* lock) /*!< in: lock */
  575. {
  576. ut_ad(lock);
  577. return(lock->type_mode & LOCK_WAIT);
  578. }
  579. /*********************************************************************//**
  580. Gets the source table of an ALTER TABLE transaction. The table must be
  581. covered by an IX or IS table lock.
  582. @return the source table of transaction, if it is covered by an IX or
  583. IS table lock; dest if there is no source table, and NULL if the
  584. transaction is locking more than two tables or an inconsistency is
  585. found */
  586. UNIV_INTERN
  587. dict_table_t*
  588. lock_get_src_table(
  589. /*===============*/
  590. trx_t* trx, /*!< in: transaction */
  591. dict_table_t* dest, /*!< in: destination of ALTER TABLE */
  592. enum lock_mode* mode) /*!< out: lock mode of the source table */
  593. {
  594. dict_table_t* src;
  595. lock_t* lock;
  596. ut_ad(!lock_mutex_own());
  597. src = NULL;
  598. *mode = LOCK_NONE;
  599. /* The trx mutex protects the trx_locks for our purposes.
  600. Other transactions could want to convert one of our implicit
  601. record locks to an explicit one. For that, they would need our
  602. trx mutex. Waiting locks can be removed while only holding
  603. lock_sys->mutex, but this is a running transaction and cannot
  604. thus be holding any waiting locks. */
  605. trx_mutex_enter(trx);
  606. for (lock = UT_LIST_GET_FIRST(trx->lock.trx_locks);
  607. lock != NULL;
  608. lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
  609. lock_table_t* tab_lock;
  610. enum lock_mode lock_mode;
  611. if (!(lock_get_type_low(lock) & LOCK_TABLE)) {
  612. /* We are only interested in table locks. */
  613. continue;
  614. }
  615. tab_lock = &lock->un_member.tab_lock;
  616. if (dest == tab_lock->table) {
  617. /* We are not interested in the destination table. */
  618. continue;
  619. } else if (!src) {
  620. /* This presumably is the source table. */
  621. src = tab_lock->table;
  622. if (UT_LIST_GET_LEN(src->locks) != 1
  623. || UT_LIST_GET_FIRST(src->locks) != lock) {
  624. /* We only support the case when
  625. there is only one lock on this table. */
  626. src = NULL;
  627. goto func_exit;
  628. }
  629. } else if (src != tab_lock->table) {
  630. /* The transaction is locking more than
  631. two tables (src and dest): abort */
  632. src = NULL;
  633. goto func_exit;
  634. }
  635. /* Check that the source table is locked by
  636. LOCK_IX or LOCK_IS. */
  637. lock_mode = lock_get_mode(lock);
  638. if (lock_mode == LOCK_IX || lock_mode == LOCK_IS) {
  639. if (*mode != LOCK_NONE && *mode != lock_mode) {
  640. /* There are multiple locks on src. */
  641. src = NULL;
  642. goto func_exit;
  643. }
  644. *mode = lock_mode;
  645. }
  646. }
  647. if (!src) {
  648. /* No source table lock found: flag the situation to caller */
  649. src = dest;
  650. }
  651. func_exit:
  652. trx_mutex_exit(trx);
  653. return(src);
  654. }
  655. /*********************************************************************//**
  656. Determine if the given table is exclusively "owned" by the given
  657. transaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INC
  658. on the table.
  659. @return TRUE if table is only locked by trx, with LOCK_IX, and
  660. possibly LOCK_AUTO_INC */
  661. UNIV_INTERN
  662. ibool
  663. lock_is_table_exclusive(
  664. /*====================*/
  665. const dict_table_t* table, /*!< in: table */
  666. const trx_t* trx) /*!< in: transaction */
  667. {
  668. const lock_t* lock;
  669. ibool ok = FALSE;
  670. ut_ad(table);
  671. ut_ad(trx);
  672. lock_mutex_enter();
  673. for (lock = UT_LIST_GET_FIRST(table->locks);
  674. lock != NULL;
  675. lock = UT_LIST_GET_NEXT(locks, &lock->un_member.tab_lock)) {
  676. if (lock->trx != trx) {
  677. /* A lock on the table is held
  678. by some other transaction. */
  679. goto not_ok;
  680. }
  681. if (!(lock_get_type_low(lock) & LOCK_TABLE)) {
  682. /* We are interested in table locks only. */
  683. continue;
  684. }
  685. switch (lock_get_mode(lock)) {
  686. case LOCK_IX:
  687. ok = TRUE;
  688. break;
  689. case LOCK_AUTO_INC:
  690. /* It is allowed for trx to hold an
  691. auto_increment lock. */
  692. break;
  693. default:
  694. not_ok:
  695. /* Other table locks than LOCK_IX are not allowed. */
  696. ok = FALSE;
  697. goto func_exit;
  698. }
  699. }
  700. func_exit:
  701. lock_mutex_exit();
  702. return(ok);
  703. }
  704. /*********************************************************************//**
  705. Sets the wait flag of a lock and the back pointer in trx to lock. */
  706. UNIV_INLINE
  707. void
  708. lock_set_lock_and_trx_wait(
  709. /*=======================*/
  710. lock_t* lock, /*!< in: lock */
  711. trx_t* trx) /*!< in/out: trx */
  712. {
  713. ut_ad(lock);
  714. ut_ad(lock->trx == trx);
  715. ut_ad(trx->lock.wait_lock == NULL);
  716. ut_ad(lock_mutex_own());
  717. ut_ad(trx_mutex_own(trx));
  718. trx->lock.wait_lock = lock;
  719. lock->type_mode |= LOCK_WAIT;
  720. }
  721. /**********************************************************************//**
  722. The back pointer to a waiting lock request in the transaction is set to NULL
  723. and the wait bit in lock type_mode is reset. */
  724. UNIV_INLINE
  725. void
  726. lock_reset_lock_and_trx_wait(
  727. /*=========================*/
  728. lock_t* lock) /*!< in/out: record lock */
  729. {
  730. ut_ad(lock->trx->lock.wait_lock == lock);
  731. ut_ad(lock_get_wait(lock));
  732. ut_ad(lock_mutex_own());
  733. lock->trx->lock.wait_lock = NULL;
  734. lock->type_mode &= ~LOCK_WAIT;
  735. }
  736. /*********************************************************************//**
  737. Gets the gap flag of a record lock.
  738. @return LOCK_GAP or 0 */
  739. UNIV_INLINE
  740. ulint
  741. lock_rec_get_gap(
  742. /*=============*/
  743. const lock_t* lock) /*!< in: record lock */
  744. {
  745. ut_ad(lock);
  746. ut_ad(lock_get_type_low(lock) == LOCK_REC);
  747. return(lock->type_mode & LOCK_GAP);
  748. }
  749. /*********************************************************************//**
  750. Gets the LOCK_REC_NOT_GAP flag of a record lock.
  751. @return LOCK_REC_NOT_GAP or 0 */
  752. UNIV_INLINE
  753. ulint
  754. lock_rec_get_rec_not_gap(
  755. /*=====================*/
  756. const lock_t* lock) /*!< in: record lock */
  757. {
  758. ut_ad(lock);
  759. ut_ad(lock_get_type_low(lock) == LOCK_REC);
  760. return(lock->type_mode & LOCK_REC_NOT_GAP);
  761. }
  762. /*********************************************************************//**
  763. Gets the waiting insert flag of a record lock.
  764. @return LOCK_INSERT_INTENTION or 0 */
  765. UNIV_INLINE
  766. ulint
  767. lock_rec_get_insert_intention(
  768. /*==========================*/
  769. const lock_t* lock) /*!< in: record lock */
  770. {
  771. ut_ad(lock);
  772. ut_ad(lock_get_type_low(lock) == LOCK_REC);
  773. return(lock->type_mode & LOCK_INSERT_INTENTION);
  774. }
  775. /*********************************************************************//**
  776. Calculates if lock mode 1 is stronger or equal to lock mode 2.
  777. @return nonzero if mode1 stronger or equal to mode2 */
  778. UNIV_INLINE
  779. ulint
  780. lock_mode_stronger_or_eq(
  781. /*=====================*/
  782. enum lock_mode mode1, /*!< in: lock mode */
  783. enum lock_mode mode2) /*!< in: lock mode */
  784. {
  785. ut_ad((ulint) mode1 < lock_types);
  786. ut_ad((ulint) mode2 < lock_types);
  787. return(lock_strength_matrix[mode1][mode2]);
  788. }
  789. /*********************************************************************//**
  790. Calculates if lock mode 1 is compatible with lock mode 2.
  791. @return nonzero if mode1 compatible with mode2 */
  792. UNIV_INLINE
  793. ulint
  794. lock_mode_compatible(
  795. /*=================*/
  796. enum lock_mode mode1, /*!< in: lock mode */
  797. enum lock_mode mode2) /*!< in: lock mode */
  798. {
  799. ut_ad((ulint) mode1 < lock_types);
  800. ut_ad((ulint) mode2 < lock_types);
  801. return(lock_compatibility_matrix[mode1][mode2]);
  802. }
  803. /*********************************************************************//**
  804. Checks if a lock request for a new lock has to wait for request lock2.
  805. @return TRUE if new lock has to wait for lock2 to be removed */
  806. UNIV_INLINE
  807. ibool
  808. lock_rec_has_to_wait(
  809. /*=================*/
  810. const trx_t* trx, /*!< in: trx of new lock */
  811. ulint type_mode,/*!< in: precise mode of the new lock
  812. to set: LOCK_S or LOCK_X, possibly
  813. ORed to LOCK_GAP or LOCK_REC_NOT_GAP,
  814. LOCK_INSERT_INTENTION */
  815. const lock_t* lock2, /*!< in: another record lock; NOTE that
  816. it is assumed that this has a lock bit
  817. set on the same record as in the new
  818. lock we are setting */
  819. ibool lock_is_on_supremum) /*!< in: TRUE if we are setting the
  820. lock on the 'supremum' record of an
  821. index page: we know then that the lock
  822. request is really for a 'gap' type lock */
  823. {
  824. ut_ad(trx && lock2);
  825. ut_ad(lock_get_type_low(lock2) == LOCK_REC);
  826. if (trx != lock2->trx
  827. && !lock_mode_compatible(static_cast<enum lock_mode>(
  828. LOCK_MODE_MASK & type_mode),
  829. lock_get_mode(lock2))) {
  830. /* We have somewhat complex rules when gap type record locks
  831. cause waits */
  832. if ((lock_is_on_supremum || (type_mode & LOCK_GAP))
  833. && !(type_mode & LOCK_INSERT_INTENTION)) {
  834. /* Gap type locks without LOCK_INSERT_INTENTION flag
  835. do not need to wait for anything. This is because
  836. different users can have conflicting lock types
  837. on gaps. */
  838. return(FALSE);
  839. }
  840. if (!(type_mode & LOCK_INSERT_INTENTION)
  841. && lock_rec_get_gap(lock2)) {
  842. /* Record lock (LOCK_ORDINARY or LOCK_REC_NOT_GAP
  843. does not need to wait for a gap type lock */
  844. return(FALSE);
  845. }
  846. if ((type_mode & LOCK_GAP)
  847. && lock_rec_get_rec_not_gap(lock2)) {
  848. /* Lock on gap does not need to wait for
  849. a LOCK_REC_NOT_GAP type lock */
  850. return(FALSE);
  851. }
  852. if (lock_rec_get_insert_intention(lock2)) {
  853. /* No lock request needs to wait for an insert
  854. intention lock to be removed. This is ok since our
  855. rules allow conflicting locks on gaps. This eliminates
  856. a spurious deadlock caused by a next-key lock waiting
  857. for an insert intention lock; when the insert
  858. intention lock was granted, the insert deadlocked on
  859. the waiting next-key lock.
  860. Also, insert intention locks do not disturb each
  861. other. */
  862. return(FALSE);
  863. }
  864. return(TRUE);
  865. }
  866. return(FALSE);
  867. }
  868. /*********************************************************************//**
  869. Checks if a lock request lock1 has to wait for request lock2.
  870. @return TRUE if lock1 has to wait for lock2 to be removed */
  871. UNIV_INTERN
  872. ibool
  873. lock_has_to_wait(
  874. /*=============*/
  875. const lock_t* lock1, /*!< in: waiting lock */
  876. const lock_t* lock2) /*!< in: another lock; NOTE that it is
  877. assumed that this has a lock bit set
  878. on the same record as in lock1 if the
  879. locks are record locks */
  880. {
  881. ut_ad(lock1 && lock2);
  882. if (lock1->trx != lock2->trx
  883. && !lock_mode_compatible(lock_get_mode(lock1),
  884. lock_get_mode(lock2))) {
  885. if (lock_get_type_low(lock1) == LOCK_REC) {
  886. ut_ad(lock_get_type_low(lock2) == LOCK_REC);
  887. /* If this lock request is for a supremum record
  888. then the second bit on the lock bitmap is set */
  889. return(lock_rec_has_to_wait(lock1->trx,
  890. lock1->type_mode, lock2,
  891. lock_rec_get_nth_bit(
  892. lock1, 1)));
  893. }
  894. return(TRUE);
  895. }
  896. return(FALSE);
  897. }
  898. /*============== RECORD LOCK BASIC FUNCTIONS ============================*/
  899. /*********************************************************************//**
  900. Gets the number of bits in a record lock bitmap.
  901. @return number of bits */
  902. UNIV_INLINE
  903. ulint
  904. lock_rec_get_n_bits(
  905. /*================*/
  906. const lock_t* lock) /*!< in: record lock */
  907. {
  908. return(lock->un_member.rec_lock.n_bits);
  909. }
  910. /**********************************************************************//**
  911. Sets the nth bit of a record lock to TRUE. */
  912. UNIV_INLINE
  913. void
  914. lock_rec_set_nth_bit(
  915. /*=================*/
  916. lock_t* lock, /*!< in: record lock */
  917. ulint i) /*!< in: index of the bit */
  918. {
  919. ulint byte_index;
  920. ulint bit_index;
  921. ut_ad(lock);
  922. ut_ad(lock_get_type_low(lock) == LOCK_REC);
  923. ut_ad(i < lock->un_member.rec_lock.n_bits);
  924. byte_index = i / 8;
  925. bit_index = i % 8;
  926. ((byte*) &lock[1])[byte_index] |= 1 << bit_index;
  927. }
  928. /**********************************************************************//**
  929. Looks for a set bit in a record lock bitmap. Returns ULINT_UNDEFINED,
  930. if none found.
  931. @return bit index == heap number of the record, or ULINT_UNDEFINED if
  932. none found */
  933. UNIV_INTERN
  934. ulint
  935. lock_rec_find_set_bit(
  936. /*==================*/
  937. const lock_t* lock) /*!< in: record lock with at least one bit set */
  938. {
  939. ulint i;
  940. for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
  941. if (lock_rec_get_nth_bit(lock, i)) {
  942. return(i);
  943. }
  944. }
  945. return(ULINT_UNDEFINED);
  946. }
  947. /**********************************************************************//**
  948. Resets the nth bit of a record lock. */
  949. UNIV_INLINE
  950. void
  951. lock_rec_reset_nth_bit(
  952. /*===================*/
  953. lock_t* lock, /*!< in: record lock */
  954. ulint i) /*!< in: index of the bit which must be set to TRUE
  955. when this function is called */
  956. {
  957. ulint byte_index;
  958. ulint bit_index;
  959. ut_ad(lock);
  960. ut_ad(lock_get_type_low(lock) == LOCK_REC);
  961. ut_ad(i < lock->un_member.rec_lock.n_bits);
  962. byte_index = i / 8;
  963. bit_index = i % 8;
  964. ((byte*) &lock[1])[byte_index] &= ~(1 << bit_index);
  965. }
  966. /*********************************************************************//**
  967. Gets the first or next record lock on a page.
  968. @return next lock, NULL if none exists */
  969. UNIV_INLINE
  970. const lock_t*
  971. lock_rec_get_next_on_page_const(
  972. /*============================*/
  973. const lock_t* lock) /*!< in: a record lock */
  974. {
  975. ulint space;
  976. ulint page_no;
  977. ut_ad(lock_mutex_own());
  978. ut_ad(lock_get_type_low(lock) == LOCK_REC);
  979. space = lock->un_member.rec_lock.space;
  980. page_no = lock->un_member.rec_lock.page_no;
  981. for (;;) {
  982. lock = static_cast<const lock_t*>(HASH_GET_NEXT(hash, lock));
  983. if (!lock) {
  984. break;
  985. }
  986. if ((lock->un_member.rec_lock.space == space)
  987. && (lock->un_member.rec_lock.page_no == page_no)) {
  988. break;
  989. }
  990. }
  991. return(lock);
  992. }
  993. /*********************************************************************//**
  994. Gets the first or next record lock on a page.
  995. @return next lock, NULL if none exists */
  996. UNIV_INLINE
  997. lock_t*
  998. lock_rec_get_next_on_page(
  999. /*======================*/
  1000. lock_t* lock) /*!< in: a record lock */
  1001. {
  1002. return((lock_t*) lock_rec_get_next_on_page_const(lock));
  1003. }
  1004. /*********************************************************************//**
  1005. Gets the first record lock on a page, where the page is identified by its
  1006. file address.
  1007. @return first lock, NULL if none exists */
  1008. UNIV_INLINE
  1009. lock_t*
  1010. lock_rec_get_first_on_page_addr(
  1011. /*============================*/
  1012. ulint space, /*!< in: space */
  1013. ulint page_no)/*!< in: page number */
  1014. {
  1015. lock_t* lock;
  1016. ut_ad(lock_mutex_own());
  1017. for (lock = static_cast<lock_t*>(
  1018. HASH_GET_FIRST(lock_sys->rec_hash,
  1019. lock_rec_hash(space, page_no)));
  1020. lock != NULL;
  1021. lock = static_cast<lock_t*>(HASH_GET_NEXT(hash, lock))) {
  1022. if (lock->un_member.rec_lock.space == space
  1023. && lock->un_member.rec_lock.page_no == page_no) {
  1024. break;
  1025. }
  1026. }
  1027. return(lock);
  1028. }
  1029. /*********************************************************************//**
  1030. Determines if there are explicit record locks on a page.
  1031. @return an explicit record lock on the page, or NULL if there are none */
  1032. UNIV_INTERN
  1033. lock_t*
  1034. lock_rec_expl_exist_on_page(
  1035. /*========================*/
  1036. ulint space, /*!< in: space id */
  1037. ulint page_no)/*!< in: page number */
  1038. {
  1039. lock_t* lock;
  1040. lock_mutex_enter();
  1041. lock = lock_rec_get_first_on_page_addr(space, page_no);
  1042. lock_mutex_exit();
  1043. return(lock);
  1044. }
  1045. /*********************************************************************//**
  1046. Gets the first record lock on a page, where the page is identified by a
  1047. pointer to it.
  1048. @return first lock, NULL if none exists */
  1049. UNIV_INLINE
  1050. lock_t*
  1051. lock_rec_get_first_on_page(
  1052. /*=======================*/
  1053. const buf_block_t* block) /*!< in: buffer block */
  1054. {
  1055. ulint hash;
  1056. lock_t* lock;
  1057. ulint space = buf_block_get_space(block);
  1058. ulint page_no = buf_block_get_page_no(block);
  1059. ut_ad(lock_mutex_own());
  1060. hash = buf_block_get_lock_hash_val(block);
  1061. for (lock = static_cast<lock_t*>(
  1062. HASH_GET_FIRST( lock_sys->rec_hash, hash));
  1063. lock != NULL;
  1064. lock = static_cast<lock_t*>(HASH_GET_NEXT(hash, lock))) {
  1065. if ((lock->un_member.rec_lock.space == space)
  1066. && (lock->un_member.rec_lock.page_no == page_no)) {
  1067. break;
  1068. }
  1069. }
  1070. return(lock);
  1071. }
  1072. /*********************************************************************//**
  1073. Gets the next explicit lock request on a record.
  1074. @return next lock, NULL if none exists or if heap_no == ULINT_UNDEFINED */
  1075. UNIV_INLINE
  1076. lock_t*
  1077. lock_rec_get_next(
  1078. /*==============*/
  1079. ulint heap_no,/*!< in: heap number of the record */
  1080. lock_t* lock) /*!< in: lock */
  1081. {
  1082. ut_ad(lock_mutex_own());
  1083. do {
  1084. ut_ad(lock_get_type_low(lock) == LOCK_REC);
  1085. lock = lock_rec_get_next_on_page(lock);
  1086. } while (lock && !lock_rec_get_nth_bit(lock, heap_no));
  1087. return(lock);
  1088. }
  1089. /*********************************************************************//**
  1090. Gets the next explicit lock request on a record.
  1091. @return next lock, NULL if none exists or if heap_no == ULINT_UNDEFINED */
  1092. UNIV_INLINE
  1093. const lock_t*
  1094. lock_rec_get_next_const(
  1095. /*====================*/
  1096. ulint heap_no,/*!< in: heap number of the record */
  1097. const lock_t* lock) /*!< in: lock */
  1098. {
  1099. return(lock_rec_get_next(heap_no, (lock_t*) lock));
  1100. }
  1101. /*********************************************************************//**
  1102. Gets the first explicit lock request on a record.
  1103. @return first lock, NULL if none exists */
  1104. UNIV_INLINE
  1105. lock_t*
  1106. lock_rec_get_first(
  1107. /*===============*/
  1108. const buf_block_t* block, /*!< in: block containing the record */
  1109. ulint heap_no)/*!< in: heap number of the record */
  1110. {
  1111. lock_t* lock;
  1112. ut_ad(lock_mutex_own());
  1113. for (lock = lock_rec_get_first_on_page(block); lock;
  1114. lock = lock_rec_get_next_on_page(lock)) {
  1115. if (lock_rec_get_nth_bit(lock, heap_no)) {
  1116. break;
  1117. }
  1118. }
  1119. return(lock);
  1120. }
  1121. /*********************************************************************//**
  1122. Resets the record lock bitmap to zero. NOTE: does not touch the wait_lock
  1123. pointer in the transaction! This function is used in lock object creation
  1124. and resetting. */
  1125. static
  1126. void
  1127. lock_rec_bitmap_reset(
  1128. /*==================*/
  1129. lock_t* lock) /*!< in: record lock */
  1130. {
  1131. ulint n_bytes;
  1132. ut_ad(lock_get_type_low(lock) == LOCK_REC);
  1133. /* Reset to zero the bitmap which resides immediately after the lock
  1134. struct */
  1135. n_bytes = lock_rec_get_n_bits(lock) / 8;
  1136. ut_ad((lock_rec_get_n_bits(lock) % 8) == 0);
  1137. memset(&lock[1], 0, n_bytes);
  1138. }
  1139. /*********************************************************************//**
  1140. Copies a record lock to heap.
  1141. @return copy of lock */
  1142. static
  1143. lock_t*
  1144. lock_rec_copy(
  1145. /*==========*/
  1146. const lock_t* lock, /*!< in: record lock */
  1147. mem_heap_t* heap) /*!< in: memory heap */
  1148. {
  1149. ulint size;
  1150. ut_ad(lock_get_type_low(lock) == LOCK_REC);
  1151. size = sizeof(lock_t) + lock_rec_get_n_bits(lock) / 8;
  1152. return(static_cast<lock_t*>(mem_heap_dup(heap, lock, size)));
  1153. }
  1154. /*********************************************************************//**
  1155. Gets the previous record lock set on a record.
  1156. @return previous lock on the same record, NULL if none exists */
  1157. UNIV_INTERN
  1158. const lock_t*
  1159. lock_rec_get_prev(
  1160. /*==============*/
  1161. const lock_t* in_lock,/*!< in: record lock */
  1162. ulint heap_no)/*!< in: heap number of the record */
  1163. {
  1164. lock_t* lock;
  1165. ulint space;
  1166. ulint page_no;
  1167. lock_t* found_lock = NULL;
  1168. ut_ad(lock_mutex_own());
  1169. ut_ad(lock_get_type_low(in_lock) == LOCK_REC);
  1170. space = in_lock->un_member.rec_lock.space;
  1171. page_no = in_lock->un_member.rec_lock.page_no;
  1172. for (lock = lock_rec_get_first_on_page_addr(space, page_no);
  1173. /* No op */;
  1174. lock = lock_rec_get_next_on_page(lock)) {
  1175. ut_ad(lock);
  1176. if (lock == in_lock) {
  1177. return(found_lock);
  1178. }
  1179. if (lock_rec_get_nth_bit(lock, heap_no)) {
  1180. found_lock = lock;
  1181. }
  1182. }
  1183. }
  1184. /*============= FUNCTIONS FOR ANALYZING TABLE LOCK QUEUE ================*/
  1185. /*********************************************************************//**
  1186. Checks if a transaction has the specified table lock, or stronger. This
  1187. function should only be called by the thread that owns the transaction.
  1188. @return lock or NULL */
  1189. UNIV_INLINE
  1190. const lock_t*
  1191. lock_table_has(
  1192. /*===========*/
  1193. const trx_t* trx, /*!< in: transaction */
  1194. const dict_table_t* table, /*!< in: table */
  1195. enum lock_mode mode) /*!< in: lock mode */
  1196. {
  1197. lint i;
  1198. if (ib_vector_is_empty(trx->lock.table_locks)) {
  1199. return(NULL);
  1200. }
  1201. /* Look for stronger locks the same trx already has on the table */
  1202. for (i = ib_vector_size(trx->lock.table_locks) - 1; i >= 0; --i) {
  1203. const lock_t* lock;
  1204. enum lock_mode lock_mode;
  1205. lock = *static_cast<const lock_t**>(
  1206. ib_vector_get(trx->lock.table_locks, i));
  1207. if (lock == NULL) {
  1208. continue;
  1209. }
  1210. lock_mode = lock_get_mode(lock);
  1211. ut_ad(trx == lock->trx);
  1212. ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
  1213. ut_ad(lock->un_member.tab_lock.table != NULL);
  1214. if (table == lock->un_member.tab_lock.table
  1215. && lock_mode_stronger_or_eq(lock_mode, mode)) {
  1216. ut_ad(!lock_get_wait(lock));
  1217. return(lock);
  1218. }
  1219. }
  1220. return(NULL);
  1221. }
  1222. /*============= FUNCTIONS FOR ANALYZING RECORD LOCK QUEUE ================*/
  1223. /*********************************************************************//**
  1224. Checks if a transaction has a GRANTED explicit lock on rec stronger or equal
  1225. to precise_mode.
  1226. @return lock or NULL */
  1227. UNIV_INLINE
  1228. lock_t*
  1229. lock_rec_has_expl(
  1230. /*==============*/
  1231. ulint precise_mode,/*!< in: LOCK_S or LOCK_X
  1232. possibly ORed to LOCK_GAP or
  1233. LOCK_REC_NOT_GAP, for a
  1234. supremum record we regard this
  1235. always a gap type request */
  1236. const buf_block_t* block, /*!< in: buffer block containing
  1237. the record */
  1238. ulint heap_no,/*!< in: heap number of the record */
  1239. trx_id_t trx_id) /*!< in: transaction id */
  1240. {
  1241. lock_t* lock;
  1242. ut_ad(lock_mutex_own());
  1243. ut_ad((precise_mode & LOCK_MODE_MASK) == LOCK_S
  1244. || (precise_mode & LOCK_MODE_MASK) == LOCK_X);
  1245. ut_ad(!(precise_mode & LOCK_INSERT_INTENTION));
  1246. for (lock = lock_rec_get_first(block, heap_no);
  1247. lock != NULL;
  1248. lock = lock_rec_get_next(heap_no, lock)) {
  1249. if (lock->trx->id == trx_id
  1250. && !lock_rec_get_insert_intention(lock)
  1251. && lock_mode_stronger_or_eq(
  1252. lock_get_mode(lock),
  1253. static_cast<enum lock_mode>(
  1254. precise_mode & LOCK_MODE_MASK))
  1255. && !lock_get_wait(lock)
  1256. && (!lock_rec_get_rec_not_gap(lock)
  1257. || (precise_mode & LOCK_REC_NOT_GAP)
  1258. || heap_no == PAGE_HEAP_NO_SUPREMUM)
  1259. && (!lock_rec_get_gap(lock)
  1260. || (precise_mode & LOCK_GAP)
  1261. || heap_no == PAGE_HEAP_NO_SUPREMUM)) {
  1262. return(lock);
  1263. }
  1264. }
  1265. return(NULL);
  1266. }
  1267. #ifdef UNIV_DEBUG
  1268. /*********************************************************************//**
  1269. Checks if some other transaction has a lock request in the queue.
  1270. @return lock or NULL */
  1271. static __attribute__((nonnull, warn_unused_result))
  1272. const lock_t*
  1273. lock_rec_other_has_expl_req(
  1274. /*========================*/
  1275. enum lock_mode mode, /*!< in: LOCK_S or LOCK_X */
  1276. ulint gap, /*!< in: LOCK_GAP if also gap
  1277. locks are taken into account,
  1278. or 0 if not */
  1279. ulint wait, /*!< in: LOCK_WAIT if also
  1280. waiting locks are taken into
  1281. account, or 0 if not */
  1282. const buf_block_t* block, /*!< in: buffer block containing
  1283. the record */
  1284. ulint heap_no,/*!< in: heap number of the record */
  1285. trx_id_t trx_id) /*!< in: transaction */
  1286. {
  1287. const lock_t* lock;
  1288. ut_ad(lock_mutex_own());
  1289. ut_ad(mode == LOCK_X || mode == LOCK_S);
  1290. ut_ad(gap == 0 || gap == LOCK_GAP);
  1291. ut_ad(wait == 0 || wait == LOCK_WAIT);
  1292. for (lock = lock_rec_get_first(block, heap_no);
  1293. lock != NULL;
  1294. lock = lock_rec_get_next_const(heap_no, lock)) {
  1295. if (lock->trx->id != trx_id
  1296. && (gap
  1297. || !(lock_rec_get_gap(lock)
  1298. || heap_no == PAGE_HEAP_NO_SUPREMUM))
  1299. && (wait || !lock_get_wait(lock))
  1300. && lock_mode_stronger_or_eq(lock_get_mode(lock), mode)) {
  1301. return(lock);
  1302. }
  1303. }
  1304. return(NULL);
  1305. }
  1306. #endif /* UNIV_DEBUG */
  1307. /*********************************************************************//**
  1308. Checks if some other transaction has a conflicting explicit lock request
  1309. in the queue, so that we have to wait.
  1310. @return lock or NULL */
  1311. static
  1312. const lock_t*
  1313. lock_rec_other_has_conflicting(
  1314. /*===========================*/
  1315. enum lock_mode mode, /*!< in: LOCK_S or LOCK_X,
  1316. possibly ORed to LOCK_GAP or
  1317. LOC_REC_NOT_GAP,
  1318. LOCK_INSERT_INTENTION */
  1319. const buf_block_t* block, /*!< in: buffer block containing
  1320. the record */
  1321. ulint heap_no,/*!< in: heap number of the record */
  1322. const trx_t* trx) /*!< in: our transaction */
  1323. {
  1324. const lock_t* lock;
  1325. ibool is_supremum;
  1326. ut_ad(lock_mutex_own());
  1327. is_supremum = (heap_no == PAGE_HEAP_NO_SUPREMUM);
  1328. for (lock = lock_rec_get_first(block, heap_no);
  1329. lock != NULL;
  1330. lock = lock_rec_get_next_const(heap_no, lock)) {
  1331. if (lock_rec_has_to_wait(trx, mode, lock, is_supremum)) {
  1332. return(lock);
  1333. }
  1334. }
  1335. return(NULL);
  1336. }
  1337. /*********************************************************************//**
  1338. Looks for a suitable type record lock struct by the same trx on the same page.
  1339. This can be used to save space when a new record lock should be set on a page:
  1340. no new struct is needed, if a suitable old is found.
  1341. @return lock or NULL */
  1342. UNIV_INLINE
  1343. lock_t*
  1344. lock_rec_find_similar_on_page(
  1345. /*==========================*/
  1346. ulint type_mode, /*!< in: lock type_mode field */
  1347. ulint heap_no, /*!< in: heap number of the record */
  1348. lock_t* lock, /*!< in: lock_rec_get_first_on_page() */
  1349. const trx_t* trx) /*!< in: transaction */
  1350. {
  1351. ut_ad(lock_mutex_own());
  1352. for (/* No op */;
  1353. lock != NULL;
  1354. lock = lock_rec_get_next_on_page(lock)) {
  1355. if (lock->trx == trx
  1356. && lock->type_mode == type_mode
  1357. && lock_rec_get_n_bits(lock) > heap_no) {
  1358. return(lock);
  1359. }
  1360. }
  1361. return(NULL);
  1362. }
  1363. /*********************************************************************//**
  1364. Checks if some transaction has an implicit x-lock on a record in a secondary
  1365. index.
  1366. @return transaction id of the transaction which has the x-lock, or 0;
  1367. NOTE that this function can return false positives but never false
  1368. negatives. The caller must confirm all positive results by calling
  1369. trx_is_active(). */
  1370. static
  1371. trx_id_t
  1372. lock_sec_rec_some_has_impl(
  1373. /*=======================*/
  1374. const rec_t* rec, /*!< in: user record */
  1375. dict_index_t* index, /*!< in: secondary index */
  1376. const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
  1377. {
  1378. trx_id_t trx_id;
  1379. trx_id_t max_trx_id;
  1380. const page_t* page = page_align(rec);
  1381. ut_ad(!lock_mutex_own());
  1382. ut_ad(!mutex_own(&trx_sys->mutex));
  1383. ut_ad(!dict_index_is_clust(index));
  1384. ut_ad(page_rec_is_user_rec(rec));
  1385. ut_ad(rec_offs_validate(rec, index, offsets));
  1386. max_trx_id = page_get_max_trx_id(page);
  1387. /* Some transaction may have an implicit x-lock on the record only
  1388. if the max trx id for the page >= min trx id for the trx list, or
  1389. database recovery is running. We do not write the changes of a page
  1390. max trx id to the log, and therefore during recovery, this value
  1391. for a page may be incorrect. */
  1392. if (max_trx_id < trx_rw_min_trx_id() && !recv_recovery_is_on()) {
  1393. trx_id = 0;
  1394. } else if (!lock_check_trx_id_sanity(max_trx_id, rec, index, offsets)) {
  1395. buf_page_print(page, 0, 0);
  1396. /* The page is corrupt: try to avoid a crash by returning 0 */
  1397. trx_id = 0;
  1398. /* In this case it is possible that some transaction has an implicit
  1399. x-lock. We have to look in the clustered index. */
  1400. } else {
  1401. trx_id = row_vers_impl_x_locked(rec, index, offsets);
  1402. }
  1403. return(trx_id);
  1404. }
  1405. #ifdef UNIV_DEBUG
  1406. /*********************************************************************//**
  1407. Checks if some transaction, other than given trx_id, has an explicit
  1408. lock on the given rec, in the given precise_mode.
  1409. @return the transaction, whose id is not equal to trx_id, that has an
  1410. explicit lock on the given rec, in the given precise_mode or NULL.*/
  1411. static
  1412. trx_t*
  1413. lock_rec_other_trx_holds_expl(
  1414. /*==========================*/
  1415. ulint precise_mode, /*!< in: LOCK_S or LOCK_X
  1416. possibly ORed to LOCK_GAP or
  1417. LOCK_REC_NOT_GAP. */
  1418. trx_id_t trx_id, /*!< in: trx holding implicit
  1419. lock on rec */
  1420. const rec_t* rec, /*!< in: user record */
  1421. const buf_block_t* block) /*!< in: buffer block
  1422. containing the record */
  1423. {
  1424. trx_t* holds = NULL;
  1425. lock_mutex_enter();
  1426. mutex_enter(&trx_sys->mutex);
  1427. trx_id_t* impl_trx_desc = trx_find_descriptor(trx_sys->descriptors,
  1428. trx_sys->descr_n_used,
  1429. trx_id);
  1430. if (impl_trx_desc) {
  1431. ut_ad(trx_id == *impl_trx_desc);
  1432. ulint heap_no = page_rec_get_heap_no(rec);
  1433. ulint rw_trx_count = trx_sys->descr_n_used;
  1434. trx_id_t* rw_trx_snapshot = static_cast<trx_id_t *>
  1435. (ut_malloc(sizeof(trx_id_t) * rw_trx_count));
  1436. memcpy(rw_trx_snapshot, trx_sys->descriptors,
  1437. sizeof(trx_id_t) * rw_trx_count);
  1438. mutex_exit(&trx_sys->mutex);
  1439. for (ulint i = 0; i < rw_trx_count; i++) {
  1440. lock_t* expl_lock = lock_rec_has_expl(precise_mode,
  1441. block, heap_no,
  1442. rw_trx_snapshot[i]);
  1443. if (expl_lock && expl_lock->trx->id != trx_id) {
  1444. /* An explicit lock is held by trx other than
  1445. the trx holding the implicit lock. */
  1446. holds = expl_lock->trx;
  1447. break;
  1448. }
  1449. }
  1450. ut_free(rw_trx_snapshot);
  1451. } else {
  1452. mutex_exit(&trx_sys->mutex);
  1453. }
  1454. lock_mutex_exit();
  1455. return(holds);
  1456. }
  1457. #endif /* UNIV_DEBUG */
  1458. /*********************************************************************//**
  1459. Return approximate number or record locks (bits set in the bitmap) for
  1460. this transaction. Since delete-marked records may be removed, the
  1461. record count will not be precise.
  1462. The caller must be holding lock_sys->mutex. */
  1463. UNIV_INTERN
  1464. ulint
  1465. lock_number_of_rows_locked(
  1466. /*=======================*/
  1467. const trx_lock_t* trx_lock) /*!< in: transaction locks */
  1468. {
  1469. const lock_t* lock;
  1470. ulint n_records = 0;
  1471. ut_ad(lock_mutex_own());
  1472. for (lock = UT_LIST_GET_FIRST(trx_lock->trx_locks);
  1473. lock != NULL;
  1474. lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
  1475. if (lock_get_type_low(lock) == LOCK_REC) {
  1476. ulint n_bit;
  1477. ulint n_bits = lock_rec_get_n_bits(lock);
  1478. for (n_bit = 0; n_bit < n_bits; n_bit++) {
  1479. if (lock_rec_get_nth_bit(lock, n_bit)) {
  1480. n_records++;
  1481. }
  1482. }
  1483. }
  1484. }
  1485. return(n_records);
  1486. }
  1487. /*============== RECORD LOCK CREATION AND QUEUE MANAGEMENT =============*/
  1488. /*********************************************************************//**
  1489. Creates a new record lock and inserts it to the lock queue. Does NOT check
  1490. for deadlocks or lock compatibility!
  1491. @return created lock */
  1492. static
  1493. lock_t*
  1494. lock_rec_create(
  1495. /*============*/
  1496. ulint type_mode,/*!< in: lock mode and wait
  1497. flag, type is ignored and
  1498. replaced by LOCK_REC */
  1499. const buf_block_t* block, /*!< in: buffer block containing
  1500. the record */
  1501. ulint heap_no,/*!< in: heap number of the record */
  1502. dict_index_t* index, /*!< in: index of record */
  1503. trx_t* trx, /*!< in/out: transaction */
  1504. ibool caller_owns_trx_mutex)
  1505. /*!< in: TRUE if caller owns
  1506. trx mutex */
  1507. {
  1508. lock_t* lock;
  1509. ulint page_no;
  1510. ulint space;
  1511. ulint n_bits;
  1512. ulint n_bytes;
  1513. const page_t* page;
  1514. ut_ad(lock_mutex_own());
  1515. ut_ad(caller_owns_trx_mutex == trx_mutex_own(trx));
  1516. ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
  1517. /* Non-locking autocommit read-only transactions should not set
  1518. any locks. */
  1519. assert_trx_in_list(trx);
  1520. space = buf_block_get_space(block);
  1521. page_no = buf_block_get_page_no(block);
  1522. page = block->frame;
  1523. btr_assert_not_corrupted(block, index);
  1524. /* If rec is the supremum record, then we reset the gap and
  1525. LOCK_REC_NOT_GAP bits, as all locks on the supremum are
  1526. automatically of the gap type */
  1527. if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) {
  1528. ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
  1529. type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP);
  1530. }
  1531. /* Make lock bitmap bigger by a safety margin */
  1532. n_bits = page_dir_get_n_heap(page) + LOCK_PAGE_BITMAP_MARGIN;
  1533. n_bytes = 1 + n_bits / 8;
  1534. lock = static_cast<lock_t*>(
  1535. mem_heap_alloc(trx->lock.lock_heap, sizeof(lock_t) + n_bytes));
  1536. lock->trx = trx;
  1537. lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC;
  1538. lock->index = index;
  1539. lock->un_member.rec_lock.space = space;
  1540. lock->un_member.rec_lock.page_no = page_no;
  1541. lock->un_member.rec_lock.n_bits = n_bytes * 8;
  1542. /* Reset to zero the bitmap which resides immediately after the
  1543. lock struct */
  1544. lock_rec_bitmap_reset(lock);
  1545. /* Set the bit corresponding to rec */
  1546. lock_rec_set_nth_bit(lock, heap_no);
  1547. index->table->n_rec_locks++;
  1548. ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted);
  1549. HASH_INSERT(lock_t, hash, lock_sys->rec_hash,
  1550. lock_rec_fold(space, page_no), lock);
  1551. lock_sys->rec_num++;
  1552. if (!caller_owns_trx_mutex) {
  1553. trx_mutex_enter(trx);
  1554. }
  1555. ut_ad(trx_mutex_own(trx));
  1556. if (type_mode & LOCK_WAIT) {
  1557. lock_set_lock_and_trx_wait(lock, trx);
  1558. }
  1559. UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock);
  1560. if (!caller_owns_trx_mutex) {
  1561. trx_mutex_exit(trx);
  1562. }
  1563. MONITOR_INC(MONITOR_RECLOCK_CREATED);
  1564. MONITOR_INC(MONITOR_NUM_RECLOCK);
  1565. return(lock);
  1566. }
  1567. /*********************************************************************//**
  1568. Enqueues a waiting request for a lock which cannot be granted immediately.
  1569. Checks for deadlocks.
  1570. @return DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED, or
  1571. DB_SUCCESS_LOCKED_REC; DB_SUCCESS_LOCKED_REC means that
  1572. there was a deadlock, but another transaction was chosen as a victim,
  1573. and we got the lock immediately: no need to wait then */
  1574. static
  1575. dberr_t
  1576. lock_rec_enqueue_waiting(
  1577. /*=====================*/
  1578. ulint type_mode,/*!< in: lock mode this
  1579. transaction is requesting:
  1580. LOCK_S or LOCK_X, possibly
  1581. ORed with LOCK_GAP or
  1582. LOCK_REC_NOT_GAP, ORed with
  1583. LOCK_INSERT_INTENTION if this
  1584. waiting lock request is set
  1585. when performing an insert of
  1586. an index record */
  1587. const buf_block_t* block, /*!< in: buffer block containing
  1588. the record */
  1589. ulint heap_no,/*!< in: heap number of the record */
  1590. dict_index_t* index, /*!< in: index of record */
  1591. que_thr_t* thr) /*!< in: query thread */
  1592. {
  1593. trx_t* trx;
  1594. lock_t* lock;
  1595. trx_id_t victim_trx_id;
  1596. ulint sec;
  1597. ulint ms;
  1598. ut_ad(lock_mutex_own());
  1599. ut_ad(!srv_read_only_mode);
  1600. ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
  1601. trx = thr_get_trx(thr);
  1602. ut_ad(trx_mutex_own(trx));
  1603. /* Test if there already is some other reason to suspend thread:
  1604. we do not enqueue a lock request if the query thread should be
  1605. stopped anyway */
  1606. if (que_thr_stop(thr)) {
  1607. ut_error;
  1608. return(DB_QUE_THR_SUSPENDED);
  1609. }
  1610. switch (trx_get_dict_operation(trx)) {
  1611. case TRX_DICT_OP_NONE:
  1612. break;
  1613. case TRX_DICT_OP_TABLE:
  1614. case TRX_DICT_OP_INDEX:
  1615. ut_print_timestamp(stderr);
  1616. fputs(" InnoDB: Error: a record lock wait happens"
  1617. " in a dictionary operation!\n"
  1618. "InnoDB: ", stderr);
  1619. dict_index_name_print(stderr, trx, index);
  1620. fputs(".\n"
  1621. "InnoDB: Submit a detailed bug report"
  1622. " to http://bugs.mysql.com\n",
  1623. stderr);
  1624. ut_ad(0);
  1625. }
  1626. /* Enqueue the lock request that will wait to be granted, note that
  1627. we already own the trx mutex. */
  1628. lock = lock_rec_create(
  1629. type_mode | LOCK_WAIT, block, heap_no, index, trx, TRUE);
  1630. /* Release the mutex to obey the latching order.
  1631. This is safe, because lock_deadlock_check_and_resolve()
  1632. is invoked when a lock wait is enqueued for the currently
  1633. running transaction. Because trx is a running transaction
  1634. (it is not currently suspended because of a lock wait),
  1635. its state can only be changed by this thread, which is
  1636. currently associated with the transaction. */
  1637. trx_mutex_exit(trx);
  1638. victim_trx_id = lock_deadlock_check_and_resolve(lock, trx);
  1639. trx_mutex_enter(trx);
  1640. if (victim_trx_id != 0) {
  1641. ut_ad(victim_trx_id == trx->id);
  1642. lock_reset_lock_and_trx_wait(lock);
  1643. lock_rec_reset_nth_bit(lock, heap_no);
  1644. return(DB_DEADLOCK);
  1645. } else if (trx->lock.wait_lock == NULL) {
  1646. /* If there was a deadlock but we chose another
  1647. transaction as a victim, it is possible that we
  1648. already have the lock now granted! */
  1649. return(DB_SUCCESS_LOCKED_REC);
  1650. }
  1651. trx->lock.que_state = TRX_QUE_LOCK_WAIT;
  1652. trx->lock.was_chosen_as_deadlock_victim = FALSE;
  1653. trx->lock.wait_started = ut_time();
  1654. if (UNIV_UNLIKELY(trx->take_stats)) {
  1655. ut_usectime(&sec, &ms);
  1656. trx->lock_que_wait_ustarted = (ib_uint64_t)sec * 1000000 + ms;
  1657. }
  1658. ut_a(que_thr_stop(thr));
  1659. #ifdef UNIV_DEBUG
  1660. if (lock_print_waits) {
  1661. fprintf(stderr, "Lock wait for trx " TRX_ID_FMT " in index ",
  1662. trx->id);
  1663. ut_print_name(stderr, trx, FALSE, index->name);
  1664. }
  1665. #endif /* UNIV_DEBUG */
  1666. MONITOR_INC(MONITOR_LOCKREC_WAIT);
  1667. return(DB_LOCK_WAIT);
  1668. }
  1669. /*********************************************************************//**
  1670. Adds a record lock request in the record queue. The request is normally
  1671. added as the last in the queue, but if there are no waiting lock requests
  1672. on the record, and the request to be added is not a waiting request, we
  1673. can reuse a suitable record lock object already existing on the same page,
  1674. just setting the appropriate bit in its bitmap. This is a low-level function
  1675. which does NOT check for deadlocks or lock compatibility!
  1676. @return lock where the bit was set */
  1677. static
  1678. lock_t*
  1679. lock_rec_add_to_queue(
  1680. /*==================*/
  1681. ulint type_mode,/*!< in: lock mode, wait, gap
  1682. etc. flags; type is ignored
  1683. and replaced by LOCK_REC */
  1684. const buf_block_t* block, /*!< in: buffer block containing
  1685. the record */
  1686. ulint heap_no,/*!< in: heap number of the record */
  1687. dict_index_t* index, /*!< in: index of record */
  1688. trx_t* trx, /*!< in/out: transaction */
  1689. ibool caller_owns_trx_mutex)
  1690. /*!< in: TRUE if caller owns the
  1691. transaction mutex */
  1692. {
  1693. lock_t* lock;
  1694. lock_t* first_lock;
  1695. ut_ad(lock_mutex_own());
  1696. ut_ad(caller_owns_trx_mutex == trx_mutex_own(trx));
  1697. ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
  1698. #ifdef UNIV_DEBUG
  1699. switch (type_mode & LOCK_MODE_MASK) {
  1700. case LOCK_X:
  1701. case LOCK_S:
  1702. break;
  1703. default:
  1704. ut_error;
  1705. }
  1706. if (!(type_mode & (LOCK_WAIT | LOCK_GAP))) {
  1707. enum lock_mode mode = (type_mode & LOCK_MODE_MASK) == LOCK_S
  1708. ? LOCK_X
  1709. : LOCK_S;
  1710. const lock_t* other_lock
  1711. = lock_rec_other_has_expl_req(mode, 0, LOCK_WAIT,
  1712. block, heap_no, trx->id);
  1713. ut_a(!other_lock);
  1714. }
  1715. #endif /* UNIV_DEBUG */
  1716. type_mode |= LOCK_REC;
  1717. /* If rec is the supremum record, then we can reset the gap bit, as
  1718. all locks on the supremum are automatically of the gap type, and we
  1719. try to avoid unnecessary memory consumption of a new record lock
  1720. struct for a gap type lock */
  1721. if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) {
  1722. ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
  1723. /* There should never be LOCK_REC_NOT_GAP on a supremum
  1724. record, but let us play safe */
  1725. type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP);
  1726. }
  1727. /* Look for a waiting lock request on the same record or on a gap */
  1728. for (first_lock = lock = lock_rec_get_first_on_page(block);
  1729. lock != NULL;
  1730. lock = lock_rec_get_next_on_page(lock)) {
  1731. if (lock_get_wait(lock)
  1732. && lock_rec_get_nth_bit(lock, heap_no)) {
  1733. goto somebody_waits;
  1734. }
  1735. }
  1736. if (UNIV_LIKELY(!(type_mode & LOCK_WAIT))) {
  1737. /* Look for a similar record lock on the same page:
  1738. if one is found and there are no waiting lock requests,
  1739. we can just set the bit */
  1740. lock = lock_rec_find_similar_on_page(
  1741. type_mode, heap_no, first_lock, trx);
  1742. if (lock) {
  1743. lock_rec_set_nth_bit(lock, heap_no);
  1744. return(lock);
  1745. }
  1746. }
  1747. somebody_waits:
  1748. return(lock_rec_create(
  1749. type_mode, block, heap_no, index, trx,
  1750. caller_owns_trx_mutex));
  1751. }
  1752. /** Record locking request status */
  1753. enum lock_rec_req_status {
  1754. /** Failed to acquire a lock */
  1755. LOCK_REC_FAIL,
  1756. /** Succeeded in acquiring a lock (implicit or already acquired) */
  1757. LOCK_REC_SUCCESS,
  1758. /** Explicitly created a new lock */
  1759. LOCK_REC_SUCCESS_CREATED
  1760. };
  1761. /*********************************************************************//**
  1762. This is a fast routine for locking a record in the most common cases:
  1763. there are no explicit locks on the page, or there is just one lock, owned
  1764. by this transaction, and of the right type_mode. This is a low-level function
  1765. which does NOT look at implicit locks! Checks lock compatibility within
  1766. explicit locks. This function sets a normal next-key lock, or in the case of
  1767. a page supremum record, a gap type lock.
  1768. @return whether the locking succeeded */
  1769. UNIV_INLINE
  1770. enum lock_rec_req_status
  1771. lock_rec_lock_fast(
  1772. /*===============*/
  1773. ibool impl, /*!< in: if TRUE, no lock is set
  1774. if no wait is necessary: we
  1775. assume that the caller will
  1776. set an implicit lock */
  1777. ulint mode, /*!< in: lock mode: LOCK_X or
  1778. LOCK_S possibly ORed to either
  1779. LOCK_GAP or LOCK_REC_NOT_GAP */
  1780. const buf_block_t* block, /*!< in: buffer block containing
  1781. the record */
  1782. ulint heap_no,/*!< in: heap number of record */
  1783. dict_index_t* index, /*!< in: index of record */
  1784. que_thr_t* thr) /*!< in: query thread */
  1785. {
  1786. lock_t* lock;
  1787. trx_t* trx;
  1788. enum lock_rec_req_status status = LOCK_REC_SUCCESS;
  1789. ut_ad(lock_mutex_own());
  1790. ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
  1791. || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
  1792. ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
  1793. || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
  1794. ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
  1795. || (LOCK_MODE_MASK & mode) == LOCK_X);
  1796. ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
  1797. || mode - (LOCK_MODE_MASK & mode) == 0
  1798. || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
  1799. ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
  1800. DBUG_EXECUTE_IF("innodb_report_deadlock", return(LOCK_REC_FAIL););
  1801. lock = lock_rec_get_first_on_page(block);
  1802. trx = thr_get_trx(thr);
  1803. if (lock == NULL) {
  1804. if (!impl) {
  1805. /* Note that we don't own the trx mutex. */
  1806. lock = lock_rec_create(
  1807. mode, block, heap_no, index, trx, FALSE);
  1808. }
  1809. status = LOCK_REC_SUCCESS_CREATED;
  1810. } else {
  1811. trx_mutex_enter(trx);
  1812. if (lock_rec_get_next_on_page(lock)
  1813. || lock->trx != trx
  1814. || lock->type_mode != (mode | LOCK_REC)
  1815. || lock_rec_get_n_bits(lock) <= heap_no) {
  1816. status = LOCK_REC_FAIL;
  1817. } else if (!impl) {
  1818. /* If the nth bit of the record lock is already set
  1819. then we do not set a new lock bit, otherwise we do
  1820. set */
  1821. if (!lock_rec_get_nth_bit(lock, heap_no)) {
  1822. lock_rec_set_nth_bit(lock, heap_no);
  1823. status = LOCK_REC_SUCCESS_CREATED;
  1824. }
  1825. }
  1826. trx_mutex_exit(trx);
  1827. }
  1828. return(status);
  1829. }
  1830. /*********************************************************************//**
  1831. This is the general, and slower, routine for locking a record. This is a
  1832. low-level function which does NOT look at implicit locks! Checks lock
  1833. compatibility within explicit locks. This function sets a normal next-key
  1834. lock, or in the case of a page supremum record, a gap type lock.
  1835. @return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
  1836. or DB_QUE_THR_SUSPENDED */
  1837. static
  1838. dberr_t
  1839. lock_rec_lock_slow(
  1840. /*===============*/
  1841. ibool impl, /*!< in: if TRUE, no lock is set
  1842. if no wait is necessary: we
  1843. assume that the caller will
  1844. set an implicit lock */
  1845. ulint mode, /*!< in: lock mode: LOCK_X or
  1846. LOCK_S possibly ORed to either
  1847. LOCK_GAP or LOCK_REC_NOT_GAP */
  1848. const buf_block_t* block, /*!< in: buffer block containing
  1849. the record */
  1850. ulint heap_no,/*!< in: heap number of record */
  1851. dict_index_t* index, /*!< in: index of record */
  1852. que_thr_t* thr) /*!< in: query thread */
  1853. {
  1854. trx_t* trx;
  1855. dberr_t err = DB_SUCCESS;
  1856. ut_ad(lock_mutex_own());
  1857. ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
  1858. || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
  1859. ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
  1860. || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
  1861. ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
  1862. || (LOCK_MODE_MASK & mode) == LOCK_X);
  1863. ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
  1864. || mode - (LOCK_MODE_MASK & mode) == 0
  1865. || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
  1866. ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
  1867. DBUG_EXECUTE_IF("innodb_report_deadlock", return(DB_DEADLOCK););
  1868. trx = thr_get_trx(thr);
  1869. trx_mutex_enter(trx);
  1870. if (lock_rec_has_expl(mode, block, heap_no, trx->id)) {
  1871. /* The trx already has a strong enough lock on rec: do
  1872. nothing */
  1873. } else if (lock_rec_other_has_conflicting(
  1874. static_cast<enum lock_mode>(mode),
  1875. block, heap_no, trx)) {
  1876. /* If another transaction has a non-gap conflicting
  1877. request in the queue, as this transaction does not
  1878. have a lock strong enough already granted on the
  1879. record, we have to wait. */
  1880. err = lock_rec_enqueue_waiting(
  1881. mode, block, heap_no, index, thr);
  1882. } else if (!impl) {
  1883. /* Set the requested lock on the record, note that
  1884. we already own the transaction mutex. */
  1885. lock_rec_add_to_queue(
  1886. LOCK_REC | mode, block, heap_no, index, trx, TRUE);
  1887. err = DB_SUCCESS_LOCKED_REC;
  1888. }
  1889. trx_mutex_exit(trx);
  1890. return(err);
  1891. }
  1892. /*********************************************************************//**
  1893. Tries to lock the specified record in the mode requested. If not immediately
  1894. possible, enqueues a waiting lock request. This is a low-level function
  1895. which does NOT look at implicit locks! Checks lock compatibility within
  1896. explicit locks. This function sets a normal next-key lock, or in the case
  1897. of a page supremum record, a gap type lock.
  1898. @return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
  1899. or DB_QUE_THR_SUSPENDED */
  1900. static
  1901. dberr_t
  1902. lock_rec_lock(
  1903. /*==========*/
  1904. ibool impl, /*!< in: if TRUE, no lock is set
  1905. if no wait is necessary: we
  1906. assume that the caller will
  1907. set an implicit lock */
  1908. ulint mode, /*!< in: lock mode: LOCK_X or
  1909. LOCK_S possibly ORed to either
  1910. LOCK_GAP or LOCK_REC_NOT_GAP */
  1911. const buf_block_t* block, /*!< in: buffer block containing
  1912. the record */
  1913. ulint heap_no,/*!< in: heap number of record */
  1914. dict_index_t* index, /*!< in: index of record */
  1915. que_thr_t* thr) /*!< in: query thread */
  1916. {
  1917. ut_ad(lock_mutex_own());
  1918. ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
  1919. || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
  1920. ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
  1921. || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
  1922. ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
  1923. || (LOCK_MODE_MASK & mode) == LOCK_X);
  1924. ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
  1925. || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
  1926. || mode - (LOCK_MODE_MASK & mode) == 0);
  1927. ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
  1928. /* We try a simplified and faster subroutine for the most
  1929. common cases */
  1930. switch (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) {
  1931. case LOCK_REC_SUCCESS:
  1932. return(DB_SUCCESS);
  1933. case LOCK_REC_SUCCESS_CREATED:
  1934. return(DB_SUCCESS_LOCKED_REC);
  1935. case LOCK_REC_FAIL:
  1936. return(lock_rec_lock_slow(impl, mode, block,
  1937. heap_no, index, thr));
  1938. }
  1939. ut_error;
  1940. return(DB_ERROR);
  1941. }
  1942. /*********************************************************************//**
  1943. Checks if a waiting record lock request still has to wait in a queue.
  1944. @return lock that is causing the wait */
  1945. static
  1946. const lock_t*
  1947. lock_rec_has_to_wait_in_queue(
  1948. /*==========================*/
  1949. const lock_t* wait_lock) /*!< in: waiting record lock */
  1950. {
  1951. const lock_t* lock;
  1952. ulint space;
  1953. ulint page_no;
  1954. ulint heap_no;
  1955. ulint bit_mask;
  1956. ulint bit_offset;
  1957. ut_ad(lock_mutex_own());
  1958. ut_ad(lock_get_wait(wait_lock));
  1959. ut_ad(lock_get_type_low(wait_lock) == LOCK_REC);
  1960. space = wait_lock->un_member.rec_lock.space;
  1961. page_no = wait_lock->un_member.rec_lock.page_no;
  1962. heap_no = lock_rec_find_set_bit(wait_lock);
  1963. bit_offset = heap_no / 8;
  1964. bit_mask = static_cast<ulint>(1 << (heap_no % 8));
  1965. for (lock = lock_rec_get_first_on_page_addr(space, page_no);
  1966. lock != wait_lock;
  1967. lock = lock_rec_get_next_on_page_const(lock)) {
  1968. const byte* p = (const byte*) &lock[1];
  1969. if (heap_no < lock_rec_get_n_bits(lock)
  1970. && (p[bit_offset] & bit_mask)
  1971. && lock_has_to_wait(wait_lock, lock)) {
  1972. return(lock);
  1973. }
  1974. }
  1975. return(NULL);
  1976. }
  1977. /*************************************************************//**
  1978. Grants a lock to a waiting lock request and releases the waiting transaction.
  1979. The caller must hold lock_sys->mutex but not lock->trx->mutex. */
  1980. static
  1981. void
  1982. lock_grant(
  1983. /*=======*/
  1984. lock_t* lock) /*!< in/out: waiting lock request */
  1985. {
  1986. ut_ad(lock_mutex_own());
  1987. lock_reset_lock_and_trx_wait(lock);
  1988. trx_mutex_enter(lock->trx);
  1989. if (lock_get_mode(lock) == LOCK_AUTO_INC) {
  1990. dict_table_t* table = lock->un_member.tab_lock.table;
  1991. if (UNIV_UNLIKELY(table->autoinc_trx == lock->trx)) {
  1992. fprintf(stderr,
  1993. "InnoDB: Error: trx already had"
  1994. " an AUTO-INC lock!\n");
  1995. } else {
  1996. table->autoinc_trx = lock->trx;
  1997. ib_vector_push(lock->trx->autoinc_locks, &lock);
  1998. }
  1999. }
  2000. #ifdef UNIV_DEBUG
  2001. if (lock_print_waits) {
  2002. fprintf(stderr, "Lock wait for trx " TRX_ID_FMT " ends\n",
  2003. lock->trx->id);
  2004. }
  2005. #endif /* UNIV_DEBUG */
  2006. /* If we are resolving a deadlock by choosing another transaction
  2007. as a victim, then our original transaction may not be in the
  2008. TRX_QUE_LOCK_WAIT state, and there is no need to end the lock wait
  2009. for it */
  2010. if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
  2011. que_thr_t* thr;
  2012. thr = que_thr_end_lock_wait(lock->trx);
  2013. if (thr != NULL) {
  2014. lock_wait_release_thread_if_suspended(thr);
  2015. }
  2016. }
  2017. trx_mutex_exit(lock->trx);
  2018. }
  2019. /*************************************************************//**
  2020. Cancels a waiting record lock request and releases the waiting transaction
  2021. that requested it. NOTE: does NOT check if waiting lock requests behind this
  2022. one can now be granted! */
  2023. static
  2024. void
  2025. lock_rec_cancel(
  2026. /*============*/
  2027. lock_t* lock) /*!< in: waiting record lock request */
  2028. {
  2029. que_thr_t* thr;
  2030. ut_ad(lock_mutex_own());
  2031. ut_ad(lock_get_type_low(lock) == LOCK_REC);
  2032. /* Reset the bit (there can be only one set bit) in the lock bitmap */
  2033. lock_rec_reset_nth_bit(lock, lock_rec_find_set_bit(lock));
  2034. /* Reset the wait flag and the back pointer to lock in trx */
  2035. lock_reset_lock_and_trx_wait(lock);
  2036. /* The following function releases the trx from lock wait */
  2037. trx_mutex_enter(lock->trx);
  2038. thr = que_thr_end_lock_wait(lock->trx);
  2039. if (thr != NULL) {
  2040. lock_wait_release_thread_if_suspended(thr);
  2041. }
  2042. trx_mutex_exit(lock->trx);
  2043. }
  2044. /*************************************************************//**
  2045. Removes a record lock request, waiting or granted, from the queue and
  2046. grants locks to other transactions in the queue if they now are entitled
  2047. to a lock. NOTE: all record locks contained in in_lock are removed. */
  2048. static
  2049. void
  2050. lock_rec_dequeue_from_page(
  2051. /*=======================*/
  2052. lock_t* in_lock) /*!< in: record lock object: all
  2053. record locks which are contained in
  2054. this lock object are removed;
  2055. transactions waiting behind will
  2056. get their lock requests granted,
  2057. if they are now qualified to it */
  2058. {
  2059. ulint space;
  2060. ulint page_no;
  2061. lock_t* lock;
  2062. trx_lock_t* trx_lock;
  2063. ut_ad(lock_mutex_own());
  2064. ut_ad(lock_get_type_low(in_lock) == LOCK_REC);
  2065. /* We may or may not be holding in_lock->trx->mutex here. */
  2066. trx_lock = &in_lock->trx->lock;
  2067. space = in_lock->un_member.rec_lock.space;
  2068. page_no = in_lock->un_member.rec_lock.page_no;
  2069. in_lock->index->table->n_rec_locks--;
  2070. HASH_DELETE(lock_t, hash, lock_sys->rec_hash,
  2071. lock_rec_fold(space, page_no), in_lock);
  2072. lock_sys->rec_num--;
  2073. UT_LIST_REMOVE(trx_locks, trx_lock->trx_locks, in_lock);
  2074. MONITOR_INC(MONITOR_RECLOCK_REMOVED);
  2075. MONITOR_DEC(MONITOR_NUM_RECLOCK);
  2076. /* Check if waiting locks in the queue can now be granted: grant
  2077. locks if there are no conflicting locks ahead. Stop at the first
  2078. X lock that is waiting or has been granted. */
  2079. for (lock = lock_rec_get_first_on_page_addr(space, page_no);
  2080. lock != NULL;
  2081. lock = lock_rec_get_next_on_page(lock)) {
  2082. if (lock_get_wait(lock)
  2083. && !lock_rec_has_to_wait_in_queue(lock)) {
  2084. /* Grant the lock */
  2085. ut_ad(lock->trx != in_lock->trx);
  2086. lock_grant(lock);
  2087. }
  2088. }
  2089. }
  2090. /*************************************************************//**
  2091. Removes a record lock request, waiting or granted, from the queue. */
  2092. static
  2093. void
  2094. lock_rec_discard(
  2095. /*=============*/
  2096. lock_t* in_lock) /*!< in: record lock object: all
  2097. record locks which are contained
  2098. in this lock object are removed */
  2099. {
  2100. ulint space;
  2101. ulint page_no;
  2102. trx_lock_t* trx_lock;
  2103. ut_ad(lock_mutex_own());
  2104. ut_ad(lock_get_type_low(in_lock) == LOCK_REC);
  2105. trx_lock = &in_lock->trx->lock;
  2106. space = in_lock->un_member.rec_lock.space;
  2107. page_no = in_lock->un_member.rec_lock.page_no;
  2108. in_lock->index->table->n_rec_locks--;
  2109. HASH_DELETE(lock_t, hash, lock_sys->rec_hash,
  2110. lock_rec_fold(space, page_no), in_lock);
  2111. lock_sys->rec_num--;
  2112. UT_LIST_REMOVE(trx_locks, trx_lock->trx_locks, in_lock);
  2113. MONITOR_INC(MONITOR_RECLOCK_REMOVED);
  2114. MONITOR_DEC(MONITOR_NUM_RECLOCK);
  2115. }
  2116. /*************************************************************//**
  2117. Removes record lock objects set on an index page which is discarded. This
  2118. function does not move locks, or check for waiting locks, therefore the
  2119. lock bitmaps must already be reset when this function is called. */
  2120. static
  2121. void
  2122. lock_rec_free_all_from_discard_page(
  2123. /*================================*/
  2124. const buf_block_t* block) /*!< in: page to be discarded */
  2125. {
  2126. ulint space;
  2127. ulint page_no;
  2128. lock_t* lock;
  2129. lock_t* next_lock;
  2130. ut_ad(lock_mutex_own());
  2131. space = buf_block_get_space(block);
  2132. page_no = buf_block_get_page_no(block);
  2133. lock = lock_rec_get_first_on_page_addr(space, page_no);
  2134. while (lock != NULL) {
  2135. ut_ad(lock_rec_find_set_bit(lock) == ULINT_UNDEFINED);
  2136. ut_ad(!lock_get_wait(lock));
  2137. next_lock = lock_rec_get_next_on_page(lock);
  2138. lock_rec_discard(lock);
  2139. lock = next_lock;
  2140. }
  2141. }
  2142. /*============= RECORD LOCK MOVING AND INHERITING ===================*/
  2143. /*************************************************************//**
  2144. Resets the lock bits for a single record. Releases transactions waiting for
  2145. lock requests here. */
  2146. static
  2147. void
  2148. lock_rec_reset_and_release_wait(
  2149. /*============================*/
  2150. const buf_block_t* block, /*!< in: buffer block containing
  2151. the record */
  2152. ulint heap_no)/*!< in: heap number of record */
  2153. {
  2154. lock_t* lock;
  2155. ut_ad(lock_mutex_own());
  2156. for (lock = lock_rec_get_first(block, heap_no);
  2157. lock != NULL;
  2158. lock = lock_rec_get_next(heap_no, lock)) {
  2159. if (lock_get_wait(lock)) {
  2160. lock_rec_cancel(lock);
  2161. } else {
  2162. lock_rec_reset_nth_bit(lock, heap_no);
  2163. }
  2164. }
  2165. }
  2166. /*************************************************************//**
  2167. Makes a record to inherit the locks (except LOCK_INSERT_INTENTION type)
  2168. of another record as gap type locks, but does not reset the lock bits of
  2169. the other record. Also waiting lock requests on rec are inherited as
  2170. GRANTED gap locks. */
  2171. static
  2172. void
  2173. lock_rec_inherit_to_gap(
  2174. /*====================*/
  2175. const buf_block_t* heir_block, /*!< in: block containing the
  2176. record which inherits */
  2177. const buf_block_t* block, /*!< in: block containing the
  2178. record from which inherited;
  2179. does NOT reset the locks on
  2180. this record */
  2181. ulint heir_heap_no, /*!< in: heap_no of the
  2182. inheriting record */
  2183. ulint heap_no) /*!< in: heap_no of the
  2184. donating record */
  2185. {
  2186. lock_t* lock;
  2187. ut_ad(lock_mutex_own());
  2188. /* If srv_locks_unsafe_for_binlog is TRUE or session is using
  2189. READ COMMITTED isolation level, we do not want locks set
  2190. by an UPDATE or a DELETE to be inherited as gap type locks. But we
  2191. DO want S-locks set by a consistency constraint to be inherited also
  2192. then. */
  2193. for (lock = lock_rec_get_first(block, heap_no);
  2194. lock != NULL;
  2195. lock = lock_rec_get_next(heap_no, lock)) {
  2196. if (!lock_rec_get_insert_intention(lock)
  2197. && !((srv_locks_unsafe_for_binlog
  2198. || lock->trx->isolation_level
  2199. <= TRX_ISO_READ_COMMITTED)
  2200. && lock_get_mode(lock) == LOCK_X)) {
  2201. lock_rec_add_to_queue(
  2202. LOCK_REC | LOCK_GAP | lock_get_mode(lock),
  2203. heir_block, heir_heap_no, lock->index,
  2204. lock->trx, FALSE);
  2205. }
  2206. }
  2207. }
  2208. /*************************************************************//**
  2209. Makes a record to inherit the gap locks (except LOCK_INSERT_INTENTION type)
  2210. of another record as gap type locks, but does not reset the lock bits of the
  2211. other record. Also waiting lock requests are inherited as GRANTED gap locks. */
  2212. static
  2213. void
  2214. lock_rec_inherit_to_gap_if_gap_lock(
  2215. /*================================*/
  2216. const buf_block_t* block, /*!< in: buffer block */
  2217. ulint heir_heap_no, /*!< in: heap_no of
  2218. record which inherits */
  2219. ulint heap_no) /*!< in: heap_no of record
  2220. from which inherited;
  2221. does NOT reset the locks
  2222. on this record */
  2223. {
  2224. lock_t* lock;
  2225. lock_mutex_enter();
  2226. for (lock = lock_rec_get_first(block, heap_no);
  2227. lock != NULL;
  2228. lock = lock_rec_get_next(heap_no, lock)) {
  2229. if (!lock_rec_get_insert_intention(lock)
  2230. && (heap_no == PAGE_HEAP_NO_SUPREMUM
  2231. || !lock_rec_get_rec_not_gap(lock))) {
  2232. lock_rec_add_to_queue(
  2233. LOCK_REC | LOCK_GAP | lock_get_mode(lock),
  2234. block, heir_heap_no, lock->index,
  2235. lock->trx, FALSE);
  2236. }
  2237. }
  2238. lock_mutex_exit();
  2239. }
  2240. /*************************************************************//**
  2241. Moves the locks of a record to another record and resets the lock bits of
  2242. the donating record. */
  2243. static
  2244. void
  2245. lock_rec_move(
  2246. /*==========*/
  2247. const buf_block_t* receiver, /*!< in: buffer block containing
  2248. the receiving record */
  2249. const buf_block_t* donator, /*!< in: buffer block containing
  2250. the donating record */
  2251. ulint receiver_heap_no,/*!< in: heap_no of the record
  2252. which gets the locks; there
  2253. must be no lock requests
  2254. on it! */
  2255. ulint donator_heap_no)/*!< in: heap_no of the record
  2256. which gives the locks */
  2257. {
  2258. lock_t* lock;
  2259. ut_ad(lock_mutex_own());
  2260. ut_ad(lock_rec_get_first(receiver, receiver_heap_no) == NULL);
  2261. for (lock = lock_rec_get_first(donator, donator_heap_no);
  2262. lock != NULL;
  2263. lock = lock_rec_get_next(donator_heap_no, lock)) {
  2264. const ulint type_mode = lock->type_mode;
  2265. lock_rec_reset_nth_bit(lock, donator_heap_no);
  2266. if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
  2267. lock_reset_lock_and_trx_wait(lock);
  2268. }
  2269. /* Note that we FIRST reset the bit, and then set the lock:
  2270. the function works also if donator == receiver */
  2271. lock_rec_add_to_queue(
  2272. type_mode, receiver, receiver_heap_no,
  2273. lock->index, lock->trx, FALSE);
  2274. }
  2275. ut_ad(lock_rec_get_first(donator, donator_heap_no) == NULL);
  2276. }
  2277. /*************************************************************//**
  2278. Updates the lock table when we have reorganized a page. NOTE: we copy
  2279. also the locks set on the infimum of the page; the infimum may carry
  2280. locks if an update of a record is occurring on the page, and its locks
  2281. were temporarily stored on the infimum. */
  2282. UNIV_INTERN
  2283. void
  2284. lock_move_reorganize_page(
  2285. /*======================*/
  2286. const buf_block_t* block, /*!< in: old index page, now
  2287. reorganized */
  2288. const buf_block_t* oblock) /*!< in: copy of the old, not
  2289. reorganized page */
  2290. {
  2291. lock_t* lock;
  2292. UT_LIST_BASE_NODE_T(lock_t) old_locks;
  2293. mem_heap_t* heap = NULL;
  2294. ulint comp;
  2295. lock_mutex_enter();
  2296. lock = lock_rec_get_first_on_page(block);
  2297. if (lock == NULL) {
  2298. lock_mutex_exit();
  2299. return;
  2300. }
  2301. heap = mem_heap_create(256);
  2302. /* Copy first all the locks on the page to heap and reset the
  2303. bitmaps in the original locks; chain the copies of the locks
  2304. using the trx_locks field in them. */
  2305. UT_LIST_INIT(old_locks);
  2306. do {
  2307. /* Make a copy of the lock */
  2308. lock_t* old_lock = lock_rec_copy(lock, heap);
  2309. UT_LIST_ADD_LAST(trx_locks, old_locks, old_lock);
  2310. /* Reset bitmap of lock */
  2311. lock_rec_bitmap_reset(lock);
  2312. if (lock_get_wait(lock)) {
  2313. lock_reset_lock_and_trx_wait(lock);
  2314. }
  2315. lock = lock_rec_get_next_on_page(lock);
  2316. } while (lock != NULL);
  2317. comp = page_is_comp(block->frame);
  2318. ut_ad(comp == page_is_comp(oblock->frame));
  2319. for (lock = UT_LIST_GET_FIRST(old_locks); lock;
  2320. lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
  2321. /* NOTE: we copy also the locks set on the infimum and
  2322. supremum of the page; the infimum may carry locks if an
  2323. update of a record is occurring on the page, and its locks
  2324. were temporarily stored on the infimum */
  2325. page_cur_t cur1;
  2326. page_cur_t cur2;
  2327. page_cur_set_before_first(block, &cur1);
  2328. page_cur_set_before_first(oblock, &cur2);
  2329. /* Set locks according to old locks */
  2330. for (;;) {
  2331. ulint old_heap_no;
  2332. ulint new_heap_no;
  2333. ut_ad(comp || !memcmp(page_cur_get_rec(&cur1),
  2334. page_cur_get_rec(&cur2),
  2335. rec_get_data_size_old(
  2336. page_cur_get_rec(
  2337. &cur2))));
  2338. if (UNIV_LIKELY(comp)) {
  2339. old_heap_no = rec_get_heap_no_new(
  2340. page_cur_get_rec(&cur2));
  2341. new_heap_no = rec_get_heap_no_new(
  2342. page_cur_get_rec(&cur1));
  2343. } else {
  2344. old_heap_no = rec_get_heap_no_old(
  2345. page_cur_get_rec(&cur2));
  2346. new_heap_no = rec_get_heap_no_old(
  2347. page_cur_get_rec(&cur1));
  2348. }
  2349. if (lock_rec_get_nth_bit(lock, old_heap_no)) {
  2350. /* Clear the bit in old_lock. */
  2351. ut_d(lock_rec_reset_nth_bit(lock,
  2352. old_heap_no));
  2353. /* NOTE that the old lock bitmap could be too
  2354. small for the new heap number! */
  2355. lock_rec_add_to_queue(
  2356. lock->type_mode, block, new_heap_no,
  2357. lock->index, lock->trx, FALSE);
  2358. /* if (new_heap_no == PAGE_HEAP_NO_SUPREMUM
  2359. && lock_get_wait(lock)) {
  2360. fprintf(stderr,
  2361. "---\n--\n!!!Lock reorg: supr type %lu\n",
  2362. lock->type_mode);
  2363. } */
  2364. }
  2365. if (UNIV_UNLIKELY
  2366. (new_heap_no == PAGE_HEAP_NO_SUPREMUM)) {
  2367. ut_ad(old_heap_no == PAGE_HEAP_NO_SUPREMUM);
  2368. break;
  2369. }
  2370. page_cur_move_to_next(&cur1);
  2371. page_cur_move_to_next(&cur2);
  2372. }
  2373. #ifdef UNIV_DEBUG
  2374. {
  2375. ulint i = lock_rec_find_set_bit(lock);
  2376. /* Check that all locks were moved. */
  2377. if (UNIV_UNLIKELY(i != ULINT_UNDEFINED)) {
  2378. fprintf(stderr,
  2379. "lock_move_reorganize_page():"
  2380. " %lu not moved in %p\n",
  2381. (ulong) i, (void*) lock);
  2382. ut_error;
  2383. }
  2384. }
  2385. #endif /* UNIV_DEBUG */
  2386. }
  2387. lock_mutex_exit();
  2388. mem_heap_free(heap);
  2389. #ifdef UNIV_DEBUG_LOCK_VALIDATE
  2390. ut_ad(lock_rec_validate_page(block));
  2391. #endif
  2392. }
  2393. /*************************************************************//**
  2394. Moves the explicit locks on user records to another page if a record
  2395. list end is moved to another page. */
  2396. UNIV_INTERN
  2397. void
  2398. lock_move_rec_list_end(
  2399. /*===================*/
  2400. const buf_block_t* new_block, /*!< in: index page to move to */
  2401. const buf_block_t* block, /*!< in: index page */
  2402. const rec_t* rec) /*!< in: record on page: this
  2403. is the first record moved */
  2404. {
  2405. lock_t* lock;
  2406. const ulint comp = page_rec_is_comp(rec);
  2407. lock_mutex_enter();
  2408. /* Note: when we move locks from record to record, waiting locks
  2409. and possible granted gap type locks behind them are enqueued in
  2410. the original order, because new elements are inserted to a hash
  2411. table to the end of the hash chain, and lock_rec_add_to_queue
  2412. does not reuse locks if there are waiters in the queue. */
  2413. for (lock = lock_rec_get_first_on_page(block); lock;
  2414. lock = lock_rec_get_next_on_page(lock)) {
  2415. page_cur_t cur1;
  2416. page_cur_t cur2;
  2417. const ulint type_mode = lock->type_mode;
  2418. page_cur_position(rec, block, &cur1);
  2419. if (page_cur_is_before_first(&cur1)) {
  2420. page_cur_move_to_next(&cur1);
  2421. }
  2422. page_cur_set_before_first(new_block, &cur2);
  2423. page_cur_move_to_next(&cur2);
  2424. /* Copy lock requests on user records to new page and
  2425. reset the lock bits on the old */
  2426. while (!page_cur_is_after_last(&cur1)) {
  2427. ulint heap_no;
  2428. if (comp) {
  2429. heap_no = rec_get_heap_no_new(
  2430. page_cur_get_rec(&cur1));
  2431. } else {
  2432. heap_no = rec_get_heap_no_old(
  2433. page_cur_get_rec(&cur1));
  2434. ut_ad(!memcmp(page_cur_get_rec(&cur1),
  2435. page_cur_get_rec(&cur2),
  2436. rec_get_data_size_old(
  2437. page_cur_get_rec(&cur2))));
  2438. }
  2439. if (lock_rec_get_nth_bit(lock, heap_no)) {
  2440. lock_rec_reset_nth_bit(lock, heap_no);
  2441. if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
  2442. lock_reset_lock_and_trx_wait(lock);
  2443. }
  2444. if (comp) {
  2445. heap_no = rec_get_heap_no_new(
  2446. page_cur_get_rec(&cur2));
  2447. } else {
  2448. heap_no = rec_get_heap_no_old(
  2449. page_cur_get_rec(&cur2));
  2450. }
  2451. lock_rec_add_to_queue(
  2452. type_mode, new_block, heap_no,
  2453. lock->index, lock->trx, FALSE);
  2454. }
  2455. page_cur_move_to_next(&cur1);
  2456. page_cur_move_to_next(&cur2);
  2457. }
  2458. }
  2459. lock_mutex_exit();
  2460. #ifdef UNIV_DEBUG_LOCK_VALIDATE
  2461. ut_ad(lock_rec_validate_page(block));
  2462. ut_ad(lock_rec_validate_page(new_block));
  2463. #endif
  2464. }
  2465. /*************************************************************//**
  2466. Moves the explicit locks on user records to another page if a record
  2467. list start is moved to another page. */
  2468. UNIV_INTERN
  2469. void
  2470. lock_move_rec_list_start(
  2471. /*=====================*/
  2472. const buf_block_t* new_block, /*!< in: index page to
  2473. move to */
  2474. const buf_block_t* block, /*!< in: index page */
  2475. const rec_t* rec, /*!< in: record on page:
  2476. this is the first
  2477. record NOT copied */
  2478. const rec_t* old_end) /*!< in: old
  2479. previous-to-last
  2480. record on new_page
  2481. before the records
  2482. were copied */
  2483. {
  2484. lock_t* lock;
  2485. const ulint comp = page_rec_is_comp(rec);
  2486. ut_ad(block->frame == page_align(rec));
  2487. ut_ad(new_block->frame == page_align(old_end));
  2488. lock_mutex_enter();
  2489. for (lock = lock_rec_get_first_on_page(block); lock;
  2490. lock = lock_rec_get_next_on_page(lock)) {
  2491. page_cur_t cur1;
  2492. page_cur_t cur2;
  2493. const ulint type_mode = lock->type_mode;
  2494. page_cur_set_before_first(block, &cur1);
  2495. page_cur_move_to_next(&cur1);
  2496. page_cur_position(old_end, new_block, &cur2);
  2497. page_cur_move_to_next(&cur2);
  2498. /* Copy lock requests on user records to new page and
  2499. reset the lock bits on the old */
  2500. while (page_cur_get_rec(&cur1) != rec) {
  2501. ulint heap_no;
  2502. if (comp) {
  2503. heap_no = rec_get_heap_no_new(
  2504. page_cur_get_rec(&cur1));
  2505. } else {
  2506. heap_no = rec_get_heap_no_old(
  2507. page_cur_get_rec(&cur1));
  2508. ut_ad(!memcmp(page_cur_get_rec(&cur1),
  2509. page_cur_get_rec(&cur2),
  2510. rec_get_data_size_old(
  2511. page_cur_get_rec(
  2512. &cur2))));
  2513. }
  2514. if (lock_rec_get_nth_bit(lock, heap_no)) {
  2515. lock_rec_reset_nth_bit(lock, heap_no);
  2516. if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
  2517. lock_reset_lock_and_trx_wait(lock);
  2518. }
  2519. if (comp) {
  2520. heap_no = rec_get_heap_no_new(
  2521. page_cur_get_rec(&cur2));
  2522. } else {
  2523. heap_no = rec_get_heap_no_old(
  2524. page_cur_get_rec(&cur2));
  2525. }
  2526. lock_rec_add_to_queue(
  2527. type_mode, new_block, heap_no,
  2528. lock->index, lock->trx, FALSE);
  2529. }
  2530. page_cur_move_to_next(&cur1);
  2531. page_cur_move_to_next(&cur2);
  2532. }
  2533. #ifdef UNIV_DEBUG
  2534. if (page_rec_is_supremum(rec)) {
  2535. ulint i;
  2536. for (i = PAGE_HEAP_NO_USER_LOW;
  2537. i < lock_rec_get_n_bits(lock); i++) {
  2538. if (UNIV_UNLIKELY
  2539. (lock_rec_get_nth_bit(lock, i))) {
  2540. fprintf(stderr,
  2541. "lock_move_rec_list_start():"
  2542. " %lu not moved in %p\n",
  2543. (ulong) i, (void*) lock);
  2544. ut_error;
  2545. }
  2546. }
  2547. }
  2548. #endif /* UNIV_DEBUG */
  2549. }
  2550. lock_mutex_exit();
  2551. #ifdef UNIV_DEBUG_LOCK_VALIDATE
  2552. ut_ad(lock_rec_validate_page(block));
  2553. #endif
  2554. }
  2555. /*************************************************************//**
  2556. Updates the lock table when a page is split to the right. */
  2557. UNIV_INTERN
  2558. void
  2559. lock_update_split_right(
  2560. /*====================*/
  2561. const buf_block_t* right_block, /*!< in: right page */
  2562. const buf_block_t* left_block) /*!< in: left page */
  2563. {
  2564. ulint heap_no = lock_get_min_heap_no(right_block);
  2565. lock_mutex_enter();
  2566. /* Move the locks on the supremum of the left page to the supremum
  2567. of the right page */
  2568. lock_rec_move(right_block, left_block,
  2569. PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
  2570. /* Inherit the locks to the supremum of left page from the successor
  2571. of the infimum on right page */
  2572. lock_rec_inherit_to_gap(left_block, right_block,
  2573. PAGE_HEAP_NO_SUPREMUM, heap_no);
  2574. lock_mutex_exit();
  2575. }
  2576. /*************************************************************//**
  2577. Updates the lock table when a page is merged to the right. */
  2578. UNIV_INTERN
  2579. void
  2580. lock_update_merge_right(
  2581. /*====================*/
  2582. const buf_block_t* right_block, /*!< in: right page to
  2583. which merged */
  2584. const rec_t* orig_succ, /*!< in: original
  2585. successor of infimum
  2586. on the right page
  2587. before merge */
  2588. const buf_block_t* left_block) /*!< in: merged index
  2589. page which will be
  2590. discarded */
  2591. {
  2592. lock_mutex_enter();
  2593. /* Inherit the locks from the supremum of the left page to the
  2594. original successor of infimum on the right page, to which the left
  2595. page was merged */
  2596. lock_rec_inherit_to_gap(right_block, left_block,
  2597. page_rec_get_heap_no(orig_succ),
  2598. PAGE_HEAP_NO_SUPREMUM);
  2599. /* Reset the locks on the supremum of the left page, releasing
  2600. waiting transactions */
  2601. lock_rec_reset_and_release_wait(left_block,
  2602. PAGE_HEAP_NO_SUPREMUM);
  2603. lock_rec_free_all_from_discard_page(left_block);
  2604. lock_mutex_exit();
  2605. }
  2606. /*************************************************************//**
  2607. Updates the lock table when the root page is copied to another in
  2608. btr_root_raise_and_insert. Note that we leave lock structs on the
  2609. root page, even though they do not make sense on other than leaf
  2610. pages: the reason is that in a pessimistic update the infimum record
  2611. of the root page will act as a dummy carrier of the locks of the record
  2612. to be updated. */
  2613. UNIV_INTERN
  2614. void
  2615. lock_update_root_raise(
  2616. /*===================*/
  2617. const buf_block_t* block, /*!< in: index page to which copied */
  2618. const buf_block_t* root) /*!< in: root page */
  2619. {
  2620. lock_mutex_enter();
  2621. /* Move the locks on the supremum of the root to the supremum
  2622. of block */
  2623. lock_rec_move(block, root,
  2624. PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
  2625. lock_mutex_exit();
  2626. }
  2627. /*************************************************************//**
  2628. Updates the lock table when a page is copied to another and the original page
  2629. is removed from the chain of leaf pages, except if page is the root! */
  2630. UNIV_INTERN
  2631. void
  2632. lock_update_copy_and_discard(
  2633. /*=========================*/
  2634. const buf_block_t* new_block, /*!< in: index page to
  2635. which copied */
  2636. const buf_block_t* block) /*!< in: index page;
  2637. NOT the root! */
  2638. {
  2639. lock_mutex_enter();
  2640. /* Move the locks on the supremum of the old page to the supremum
  2641. of new_page */
  2642. lock_rec_move(new_block, block,
  2643. PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
  2644. lock_rec_free_all_from_discard_page(block);
  2645. lock_mutex_exit();
  2646. }
  2647. /*************************************************************//**
  2648. Updates the lock table when a page is split to the left. */
  2649. UNIV_INTERN
  2650. void
  2651. lock_update_split_left(
  2652. /*===================*/
  2653. const buf_block_t* right_block, /*!< in: right page */
  2654. const buf_block_t* left_block) /*!< in: left page */
  2655. {
  2656. ulint heap_no = lock_get_min_heap_no(right_block);
  2657. lock_mutex_enter();
  2658. /* Inherit the locks to the supremum of the left page from the
  2659. successor of the infimum on the right page */
  2660. lock_rec_inherit_to_gap(left_block, right_block,
  2661. PAGE_HEAP_NO_SUPREMUM, heap_no);
  2662. lock_mutex_exit();
  2663. }
  2664. /*************************************************************//**
  2665. Updates the lock table when a page is merged to the left. */
  2666. UNIV_INTERN
  2667. void
  2668. lock_update_merge_left(
  2669. /*===================*/
  2670. const buf_block_t* left_block, /*!< in: left page to
  2671. which merged */
  2672. const rec_t* orig_pred, /*!< in: original predecessor
  2673. of supremum on the left page
  2674. before merge */
  2675. const buf_block_t* right_block) /*!< in: merged index page
  2676. which will be discarded */
  2677. {
  2678. const rec_t* left_next_rec;
  2679. ut_ad(left_block->frame == page_align(orig_pred));
  2680. lock_mutex_enter();
  2681. left_next_rec = page_rec_get_next_const(orig_pred);
  2682. if (!page_rec_is_supremum(left_next_rec)) {
  2683. /* Inherit the locks on the supremum of the left page to the
  2684. first record which was moved from the right page */
  2685. lock_rec_inherit_to_gap(left_block, left_block,
  2686. page_rec_get_heap_no(left_next_rec),
  2687. PAGE_HEAP_NO_SUPREMUM);
  2688. /* Reset the locks on the supremum of the left page,
  2689. releasing waiting transactions */
  2690. lock_rec_reset_and_release_wait(left_block,
  2691. PAGE_HEAP_NO_SUPREMUM);
  2692. }
  2693. /* Move the locks from the supremum of right page to the supremum
  2694. of the left page */
  2695. lock_rec_move(left_block, right_block,
  2696. PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
  2697. lock_rec_free_all_from_discard_page(right_block);
  2698. lock_mutex_exit();
  2699. }
  2700. /*************************************************************//**
  2701. Resets the original locks on heir and replaces them with gap type locks
  2702. inherited from rec. */
  2703. UNIV_INTERN
  2704. void
  2705. lock_rec_reset_and_inherit_gap_locks(
  2706. /*=================================*/
  2707. const buf_block_t* heir_block, /*!< in: block containing the
  2708. record which inherits */
  2709. const buf_block_t* block, /*!< in: block containing the
  2710. record from which inherited;
  2711. does NOT reset the locks on
  2712. this record */
  2713. ulint heir_heap_no, /*!< in: heap_no of the
  2714. inheriting record */
  2715. ulint heap_no) /*!< in: heap_no of the
  2716. donating record */
  2717. {
  2718. lock_mutex_enter();
  2719. lock_rec_reset_and_release_wait(heir_block, heir_heap_no);
  2720. lock_rec_inherit_to_gap(heir_block, block, heir_heap_no, heap_no);
  2721. lock_mutex_exit();
  2722. }
  2723. /*************************************************************//**
  2724. Updates the lock table when a page is discarded. */
  2725. UNIV_INTERN
  2726. void
  2727. lock_update_discard(
  2728. /*================*/
  2729. const buf_block_t* heir_block, /*!< in: index page
  2730. which will inherit the locks */
  2731. ulint heir_heap_no, /*!< in: heap_no of the record
  2732. which will inherit the locks */
  2733. const buf_block_t* block) /*!< in: index page
  2734. which will be discarded */
  2735. {
  2736. const page_t* page = block->frame;
  2737. const rec_t* rec;
  2738. ulint heap_no;
  2739. lock_mutex_enter();
  2740. if (!lock_rec_get_first_on_page(block)) {
  2741. /* No locks exist on page, nothing to do */
  2742. lock_mutex_exit();
  2743. return;
  2744. }
  2745. /* Inherit all the locks on the page to the record and reset all
  2746. the locks on the page */
  2747. if (page_is_comp(page)) {
  2748. rec = page + PAGE_NEW_INFIMUM;
  2749. do {
  2750. heap_no = rec_get_heap_no_new(rec);
  2751. lock_rec_inherit_to_gap(heir_block, block,
  2752. heir_heap_no, heap_no);
  2753. lock_rec_reset_and_release_wait(block, heap_no);
  2754. rec = page + rec_get_next_offs(rec, TRUE);
  2755. } while (heap_no != PAGE_HEAP_NO_SUPREMUM);
  2756. } else {
  2757. rec = page + PAGE_OLD_INFIMUM;
  2758. do {
  2759. heap_no = rec_get_heap_no_old(rec);
  2760. lock_rec_inherit_to_gap(heir_block, block,
  2761. heir_heap_no, heap_no);
  2762. lock_rec_reset_and_release_wait(block, heap_no);
  2763. rec = page + rec_get_next_offs(rec, FALSE);
  2764. } while (heap_no != PAGE_HEAP_NO_SUPREMUM);
  2765. }
  2766. lock_rec_free_all_from_discard_page(block);
  2767. lock_mutex_exit();
  2768. }
  2769. /*************************************************************//**
  2770. Updates the lock table when a new user record is inserted. */
  2771. UNIV_INTERN
  2772. void
  2773. lock_update_insert(
  2774. /*===============*/
  2775. const buf_block_t* block, /*!< in: buffer block containing rec */
  2776. const rec_t* rec) /*!< in: the inserted record */
  2777. {
  2778. ulint receiver_heap_no;
  2779. ulint donator_heap_no;
  2780. ut_ad(block->frame == page_align(rec));
  2781. /* Inherit the gap-locking locks for rec, in gap mode, from the next
  2782. record */
  2783. if (page_rec_is_comp(rec)) {
  2784. receiver_heap_no = rec_get_heap_no_new(rec);
  2785. donator_heap_no = rec_get_heap_no_new(
  2786. page_rec_get_next_low(rec, TRUE));
  2787. } else {
  2788. receiver_heap_no = rec_get_heap_no_old(rec);
  2789. donator_heap_no = rec_get_heap_no_old(
  2790. page_rec_get_next_low(rec, FALSE));
  2791. }
  2792. lock_rec_inherit_to_gap_if_gap_lock(
  2793. block, receiver_heap_no, donator_heap_no);
  2794. }
  2795. /*************************************************************//**
  2796. Updates the lock table when a record is removed. */
  2797. UNIV_INTERN
  2798. void
  2799. lock_update_delete(
  2800. /*===============*/
  2801. const buf_block_t* block, /*!< in: buffer block containing rec */
  2802. const rec_t* rec) /*!< in: the record to be removed */
  2803. {
  2804. const page_t* page = block->frame;
  2805. ulint heap_no;
  2806. ulint next_heap_no;
  2807. ut_ad(page == page_align(rec));
  2808. if (page_is_comp(page)) {
  2809. heap_no = rec_get_heap_no_new(rec);
  2810. next_heap_no = rec_get_heap_no_new(page
  2811. + rec_get_next_offs(rec,
  2812. TRUE));
  2813. } else {
  2814. heap_no = rec_get_heap_no_old(rec);
  2815. next_heap_no = rec_get_heap_no_old(page
  2816. + rec_get_next_offs(rec,
  2817. FALSE));
  2818. }
  2819. lock_mutex_enter();
  2820. /* Let the next record inherit the locks from rec, in gap mode */
  2821. lock_rec_inherit_to_gap(block, block, next_heap_no, heap_no);
  2822. /* Reset the lock bits on rec and release waiting transactions */
  2823. lock_rec_reset_and_release_wait(block, heap_no);
  2824. lock_mutex_exit();
  2825. }
  2826. /*********************************************************************//**
  2827. Stores on the page infimum record the explicit locks of another record.
  2828. This function is used to store the lock state of a record when it is
  2829. updated and the size of the record changes in the update. The record
  2830. is moved in such an update, perhaps to another page. The infimum record
  2831. acts as a dummy carrier record, taking care of lock releases while the
  2832. actual record is being moved. */
  2833. UNIV_INTERN
  2834. void
  2835. lock_rec_store_on_page_infimum(
  2836. /*===========================*/
  2837. const buf_block_t* block, /*!< in: buffer block containing rec */
  2838. const rec_t* rec) /*!< in: record whose lock state
  2839. is stored on the infimum
  2840. record of the same page; lock
  2841. bits are reset on the
  2842. record */
  2843. {
  2844. ulint heap_no = page_rec_get_heap_no(rec);
  2845. ut_ad(block->frame == page_align(rec));
  2846. lock_mutex_enter();
  2847. lock_rec_move(block, block, PAGE_HEAP_NO_INFIMUM, heap_no);
  2848. lock_mutex_exit();
  2849. }
  2850. /*********************************************************************//**
  2851. Restores the state of explicit lock requests on a single record, where the
  2852. state was stored on the infimum of the page. */
  2853. UNIV_INTERN
  2854. void
  2855. lock_rec_restore_from_page_infimum(
  2856. /*===============================*/
  2857. const buf_block_t* block, /*!< in: buffer block containing rec */
  2858. const rec_t* rec, /*!< in: record whose lock state
  2859. is restored */
  2860. const buf_block_t* donator)/*!< in: page (rec is not
  2861. necessarily on this page)
  2862. whose infimum stored the lock
  2863. state; lock bits are reset on
  2864. the infimum */
  2865. {
  2866. ulint heap_no = page_rec_get_heap_no(rec);
  2867. lock_mutex_enter();
  2868. lock_rec_move(block, donator, heap_no, PAGE_HEAP_NO_INFIMUM);
  2869. lock_mutex_exit();
  2870. }
  2871. /*=========== DEADLOCK CHECKING ======================================*/
  2872. /*********************************************************************//**
  2873. rewind(3) the file used for storing the latest detected deadlock and
  2874. print a heading message to stderr if printing of all deadlocks to stderr
  2875. is enabled. */
  2876. UNIV_INLINE
  2877. void
  2878. lock_deadlock_start_print()
  2879. /*=======================*/
  2880. {
  2881. ut_ad(lock_mutex_own());
  2882. ut_ad(!srv_read_only_mode);
  2883. rewind(lock_latest_err_file);
  2884. ut_print_timestamp(lock_latest_err_file);
  2885. if (srv_print_all_deadlocks) {
  2886. ut_print_timestamp(stderr);
  2887. fprintf(stderr, "InnoDB: transactions deadlock detected, "
  2888. "dumping detailed information.\n");
  2889. ut_print_timestamp(stderr);
  2890. }
  2891. }
  2892. /*********************************************************************//**
  2893. Print a message to the deadlock file and possibly to stderr. */
  2894. UNIV_INLINE
  2895. void
  2896. lock_deadlock_fputs(
  2897. /*================*/
  2898. const char* msg) /*!< in: message to print */
  2899. {
  2900. if (!srv_read_only_mode) {
  2901. fputs(msg, lock_latest_err_file);
  2902. if (srv_print_all_deadlocks) {
  2903. fputs(msg, stderr);
  2904. }
  2905. }
  2906. }
  2907. /*********************************************************************//**
  2908. Print transaction data to the deadlock file and possibly to stderr. */
  2909. UNIV_INLINE
  2910. void
  2911. lock_deadlock_trx_print(
  2912. /*====================*/
  2913. const trx_t* trx, /*!< in: transaction */
  2914. ulint max_query_len) /*!< in: max query length to print,
  2915. or 0 to use the default max length */
  2916. {
  2917. ut_ad(lock_mutex_own());
  2918. ut_ad(!srv_read_only_mode);
  2919. ulint n_rec_locks = lock_number_of_rows_locked(&trx->lock);
  2920. ulint n_trx_locks = UT_LIST_GET_LEN(trx->lock.trx_locks);
  2921. ulint heap_size = mem_heap_get_size(trx->lock.lock_heap);
  2922. mutex_enter(&trx_sys->mutex);
  2923. trx_print_low(lock_latest_err_file, trx, max_query_len,
  2924. n_rec_locks, n_trx_locks, heap_size);
  2925. if (srv_print_all_deadlocks) {
  2926. trx_print_low(stderr, trx, max_query_len,
  2927. n_rec_locks, n_trx_locks, heap_size);
  2928. }
  2929. mutex_exit(&trx_sys->mutex);
  2930. }
  2931. /*********************************************************************//**
  2932. Print lock data to the deadlock file and possibly to stderr. */
  2933. UNIV_INLINE
  2934. void
  2935. lock_deadlock_lock_print(
  2936. /*=====================*/
  2937. const lock_t* lock) /*!< in: record or table type lock */
  2938. {
  2939. ut_ad(lock_mutex_own());
  2940. ut_ad(!srv_read_only_mode);
  2941. if (lock_get_type_low(lock) == LOCK_REC) {
  2942. lock_rec_print(lock_latest_err_file, lock);
  2943. if (srv_print_all_deadlocks) {
  2944. lock_rec_print(stderr, lock);
  2945. }
  2946. } else {
  2947. lock_table_print(lock_latest_err_file, lock);
  2948. if (srv_print_all_deadlocks) {
  2949. lock_table_print(stderr, lock);
  2950. }
  2951. }
  2952. }
  2953. /** Used in deadlock tracking. Protected by lock_sys->mutex. */
  2954. static ib_uint64_t lock_mark_counter = 0;
  2955. /** Check if the search is too deep. */
  2956. #define lock_deadlock_too_deep(c) \
  2957. (c->depth > LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK \
  2958. || c->cost > LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK)
  2959. /********************************************************************//**
  2960. Get the next lock in the queue that is owned by a transaction whose
  2961. sub-tree has not already been searched.
  2962. @return next lock or NULL if at end of queue */
  2963. static
  2964. const lock_t*
  2965. lock_get_next_lock(
  2966. /*===============*/
  2967. const lock_deadlock_ctx_t*
  2968. ctx, /*!< in: deadlock context */
  2969. const lock_t* lock, /*!< in: lock in the queue */
  2970. ulint heap_no)/*!< in: heap no if rec lock else
  2971. ULINT_UNDEFINED */
  2972. {
  2973. ut_ad(lock_mutex_own());
  2974. do {
  2975. if (lock_get_type_low(lock) == LOCK_REC) {
  2976. ut_ad(heap_no != ULINT_UNDEFINED);
  2977. lock = lock_rec_get_next_const(heap_no, lock);
  2978. } else {
  2979. ut_ad(heap_no == ULINT_UNDEFINED);
  2980. ut_ad(lock_get_type_low(lock) == LOCK_TABLE);
  2981. lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock);
  2982. }
  2983. } while (lock != NULL
  2984. && lock->trx->lock.deadlock_mark > ctx->mark_start);
  2985. ut_ad(lock == NULL
  2986. || lock_get_type_low(lock) == lock_get_type_low(ctx->wait_lock));
  2987. return(lock);
  2988. }
  2989. /********************************************************************//**
  2990. Get the first lock to search. The search starts from the current
  2991. wait_lock. What we are really interested in is an edge from the
  2992. current wait_lock's owning transaction to another transaction that has
  2993. a lock ahead in the queue. We skip locks where the owning transaction's
  2994. sub-tree has already been searched.
  2995. @return first lock or NULL */
  2996. static
  2997. const lock_t*
  2998. lock_get_first_lock(
  2999. /*================*/
  3000. const lock_deadlock_ctx_t*
  3001. ctx, /*!< in: deadlock context */
  3002. ulint* heap_no)/*!< out: heap no if rec lock,
  3003. else ULINT_UNDEFINED */
  3004. {
  3005. const lock_t* lock;
  3006. ut_ad(lock_mutex_own());
  3007. lock = ctx->wait_lock;
  3008. if (lock_get_type_low(lock) == LOCK_REC) {
  3009. *heap_no = lock_rec_find_set_bit(lock);
  3010. ut_ad(*heap_no != ULINT_UNDEFINED);
  3011. lock = lock_rec_get_first_on_page_addr(
  3012. lock->un_member.rec_lock.space,
  3013. lock->un_member.rec_lock.page_no);
  3014. /* Position on the first lock on the physical record. */
  3015. if (!lock_rec_get_nth_bit(lock, *heap_no)) {
  3016. lock = lock_rec_get_next_const(*heap_no, lock);
  3017. }
  3018. } else {
  3019. *heap_no = ULINT_UNDEFINED;
  3020. ut_ad(lock_get_type_low(lock) == LOCK_TABLE);
  3021. lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock);
  3022. }
  3023. ut_a(lock != NULL);
  3024. ut_a(lock != ctx->wait_lock);
  3025. ut_ad(lock_get_type_low(lock) == lock_get_type_low(ctx->wait_lock));
  3026. return(lock);
  3027. }
  3028. /********************************************************************//**
  3029. Notify that a deadlock has been detected and print the conflicting
  3030. transaction info. */
  3031. static
  3032. void
  3033. lock_deadlock_notify(
  3034. /*=================*/
  3035. const lock_deadlock_ctx_t* ctx, /*!< in: deadlock context */
  3036. const lock_t* lock) /*!< in: lock causing
  3037. deadlock */
  3038. {
  3039. ut_ad(lock_mutex_own());
  3040. ut_ad(!srv_read_only_mode);
  3041. lock_deadlock_start_print();
  3042. lock_deadlock_fputs("\n*** (1) TRANSACTION:\n");
  3043. lock_deadlock_trx_print(ctx->wait_lock->trx, 3000);
  3044. lock_deadlock_fputs("*** (1) WAITING FOR THIS LOCK TO BE GRANTED:\n");
  3045. lock_deadlock_lock_print(ctx->wait_lock);
  3046. lock_deadlock_fputs("*** (2) TRANSACTION:\n");
  3047. lock_deadlock_trx_print(lock->trx, 3000);
  3048. lock_deadlock_fputs("*** (2) HOLDS THE LOCK(S):\n");
  3049. lock_deadlock_lock_print(lock);
  3050. /* It is possible that the joining transaction was granted its
  3051. lock when we rolled back some other waiting transaction. */
  3052. if (ctx->start->lock.wait_lock != 0) {
  3053. lock_deadlock_fputs(
  3054. "*** (2) WAITING FOR THIS LOCK TO BE GRANTED:\n");
  3055. lock_deadlock_lock_print(ctx->start->lock.wait_lock);
  3056. }
  3057. #ifdef UNIV_DEBUG
  3058. if (lock_print_waits) {
  3059. fputs("Deadlock detected\n", stderr);
  3060. }
  3061. #endif /* UNIV_DEBUG */
  3062. }
  3063. /********************************************************************//**
  3064. Select the victim transaction that should be rolledback.
  3065. @return victim transaction */
  3066. static
  3067. const trx_t*
  3068. lock_deadlock_select_victim(
  3069. /*========================*/
  3070. const lock_deadlock_ctx_t* ctx) /*!< in: deadlock context */
  3071. {
  3072. ut_ad(lock_mutex_own());
  3073. ut_ad(ctx->start->lock.wait_lock != 0);
  3074. ut_ad(ctx->wait_lock->trx != ctx->start);
  3075. if (trx_weight_ge(ctx->wait_lock->trx, ctx->start)) {
  3076. /* The joining transaction is 'smaller',
  3077. choose it as the victim and roll it back. */
  3078. return(ctx->start);
  3079. }
  3080. return(ctx->wait_lock->trx);
  3081. }
  3082. /********************************************************************//**
  3083. Pop the deadlock search state from the stack.
  3084. @return stack slot instance that was on top of the stack. */
  3085. static
  3086. const lock_stack_t*
  3087. lock_deadlock_pop(
  3088. /*==============*/
  3089. lock_deadlock_ctx_t* ctx) /*!< in/out: context */
  3090. {
  3091. ut_ad(lock_mutex_own());
  3092. ut_ad(ctx->depth > 0);
  3093. return(&lock_stack[--ctx->depth]);
  3094. }
  3095. /********************************************************************//**
  3096. Push the deadlock search state onto the stack.
  3097. @return slot that was used in the stack */
  3098. static
  3099. lock_stack_t*
  3100. lock_deadlock_push(
  3101. /*===============*/
  3102. lock_deadlock_ctx_t* ctx, /*!< in/out: context */
  3103. const lock_t* lock, /*!< in: current lock */
  3104. ulint heap_no) /*!< in: heap number */
  3105. {
  3106. ut_ad(lock_mutex_own());
  3107. /* Save current search state. */
  3108. if (LOCK_STACK_SIZE > ctx->depth) {
  3109. lock_stack_t* stack;
  3110. stack = &lock_stack[ctx->depth++];
  3111. stack->lock = lock;
  3112. stack->heap_no = heap_no;
  3113. stack->wait_lock = ctx->wait_lock;
  3114. return(stack);
  3115. }
  3116. return(NULL);
  3117. }
  3118. /********************************************************************//**
  3119. Looks iteratively for a deadlock. Note: the joining transaction may
  3120. have been granted its lock by the deadlock checks.
  3121. @return 0 if no deadlock else the victim transaction id.*/
  3122. static
  3123. trx_id_t
  3124. lock_deadlock_search(
  3125. /*=================*/
  3126. lock_deadlock_ctx_t* ctx) /*!< in/out: deadlock context */
  3127. {
  3128. const lock_t* lock;
  3129. ulint heap_no;
  3130. ut_ad(lock_mutex_own());
  3131. ut_ad(!trx_mutex_own(ctx->start));
  3132. ut_ad(ctx->start != NULL);
  3133. ut_ad(ctx->wait_lock != NULL);
  3134. assert_trx_in_list(ctx->wait_lock->trx);
  3135. ut_ad(ctx->mark_start <= lock_mark_counter);
  3136. /* Look at the locks ahead of wait_lock in the lock queue. */
  3137. lock = lock_get_first_lock(ctx, &heap_no);
  3138. for (;;) {
  3139. /* We should never visit the same sub-tree more than once. */
  3140. ut_ad(lock == NULL
  3141. || lock->trx->lock.deadlock_mark <= ctx->mark_start);
  3142. while (ctx->depth > 0 && lock == NULL) {
  3143. const lock_stack_t* stack;
  3144. /* Restore previous search state. */
  3145. stack = lock_deadlock_pop(ctx);
  3146. lock = stack->lock;
  3147. heap_no = stack->heap_no;
  3148. ctx->wait_lock = stack->wait_lock;
  3149. lock = lock_get_next_lock(ctx, lock, heap_no);
  3150. }
  3151. if (lock == NULL) {
  3152. break;
  3153. } else if (lock == ctx->wait_lock) {
  3154. /* We can mark this subtree as searched */
  3155. ut_ad(lock->trx->lock.deadlock_mark <= ctx->mark_start);
  3156. lock->trx->lock.deadlock_mark = ++lock_mark_counter;
  3157. /* We are not prepared for an overflow. This 64-bit
  3158. counter should never wrap around. At 10^9 increments
  3159. per second, it would take 10^3 years of uptime. */
  3160. ut_ad(lock_mark_counter > 0);
  3161. lock = NULL;
  3162. } else if (!lock_has_to_wait(ctx->wait_lock, lock)) {
  3163. /* No conflict, next lock */
  3164. lock = lock_get_next_lock(ctx, lock, heap_no);
  3165. } else if (lock->trx == ctx->start) {
  3166. /* Found a cycle. */
  3167. lock_deadlock_notify(ctx, lock);
  3168. return(lock_deadlock_select_victim(ctx)->id);
  3169. } else if (lock_deadlock_too_deep(ctx)) {
  3170. /* Search too deep to continue. */
  3171. ctx->too_deep = TRUE;
  3172. /* Select the joining transaction as the victim. */
  3173. return(ctx->start->id);
  3174. } else {
  3175. /* We do not need to report autoinc locks to the upper
  3176. layer. These locks are released before commit, so they can
  3177. not cause deadlocks with binlog-fixed commit order. */
  3178. if (lock_get_type_low(lock) != LOCK_TABLE ||
  3179. lock_get_mode(lock) != LOCK_AUTO_INC)
  3180. thd_report_wait_for(ctx->start->mysql_thd,
  3181. lock->trx->mysql_thd);
  3182. if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
  3183. /* Another trx ahead has requested a lock in an
  3184. incompatible mode, and is itself waiting for a lock. */
  3185. ++ctx->cost;
  3186. /* Save current search state. */
  3187. if (!lock_deadlock_push(ctx, lock, heap_no)) {
  3188. /* Unable to save current search state, stack
  3189. size not big enough. */
  3190. ctx->too_deep = TRUE;
  3191. return(ctx->start->id);
  3192. }
  3193. ctx->wait_lock = lock->trx->lock.wait_lock;
  3194. lock = lock_get_first_lock(ctx, &heap_no);
  3195. if (lock->trx->lock.deadlock_mark > ctx->mark_start) {
  3196. lock = lock_get_next_lock(ctx, lock, heap_no);
  3197. }
  3198. } else {
  3199. lock = lock_get_next_lock(ctx, lock, heap_no);
  3200. }
  3201. }
  3202. }
  3203. ut_a(lock == NULL && ctx->depth == 0);
  3204. /* No deadlock found. */
  3205. return(0);
  3206. }
  3207. /********************************************************************//**
  3208. Print info about transaction that was rolled back. */
  3209. static
  3210. void
  3211. lock_deadlock_joining_trx_print(
  3212. /*============================*/
  3213. const trx_t* trx, /*!< in: transaction rolled back */
  3214. const lock_t* lock) /*!< in: lock trx wants */
  3215. {
  3216. ut_ad(lock_mutex_own());
  3217. ut_ad(!srv_read_only_mode);
  3218. /* If the lock search exceeds the max step
  3219. or the max depth, the current trx will be
  3220. the victim. Print its information. */
  3221. lock_deadlock_start_print();
  3222. lock_deadlock_fputs(
  3223. "TOO DEEP OR LONG SEARCH IN THE LOCK TABLE"
  3224. " WAITS-FOR GRAPH, WE WILL ROLL BACK"
  3225. " FOLLOWING TRANSACTION \n\n"
  3226. "*** TRANSACTION:\n");
  3227. lock_deadlock_trx_print(trx, 3000);
  3228. lock_deadlock_fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n");
  3229. lock_deadlock_lock_print(lock);
  3230. }
  3231. /********************************************************************//**
  3232. Rollback transaction selected as the victim. */
  3233. static
  3234. void
  3235. lock_deadlock_trx_rollback(
  3236. /*=======================*/
  3237. lock_deadlock_ctx_t* ctx) /*!< in: deadlock context */
  3238. {
  3239. trx_t* trx;
  3240. ut_ad(lock_mutex_own());
  3241. trx = ctx->wait_lock->trx;
  3242. lock_deadlock_fputs("*** WE ROLL BACK TRANSACTION (1)\n");
  3243. trx_mutex_enter(trx);
  3244. trx->lock.was_chosen_as_deadlock_victim = TRUE;
  3245. lock_cancel_waiting_and_release(trx->lock.wait_lock);
  3246. trx_mutex_exit(trx);
  3247. }
  3248. /********************************************************************//**
  3249. Checks if a joining lock request results in a deadlock. If a deadlock is
  3250. found this function will resolve the dadlock by choosing a victim transaction
  3251. and rolling it back. It will attempt to resolve all deadlocks. The returned
  3252. transaction id will be the joining transaction id or 0 if some other
  3253. transaction was chosen as a victim and rolled back or no deadlock found.
  3254. @return id of transaction chosen as victim or 0 */
  3255. static
  3256. trx_id_t
  3257. lock_deadlock_check_and_resolve(
  3258. /*============================*/
  3259. const lock_t* lock, /*!< in: lock the transaction is requesting */
  3260. const trx_t* trx) /*!< in: transaction */
  3261. {
  3262. trx_id_t victim_trx_id;
  3263. ut_ad(trx != NULL);
  3264. ut_ad(lock != NULL);
  3265. ut_ad(lock_mutex_own());
  3266. assert_trx_in_list(trx);
  3267. /* Try and resolve as many deadlocks as possible. */
  3268. do {
  3269. lock_deadlock_ctx_t ctx;
  3270. /* Reset the context. */
  3271. ctx.cost = 0;
  3272. ctx.depth = 0;
  3273. ctx.start = trx;
  3274. ctx.too_deep = FALSE;
  3275. ctx.wait_lock = lock;
  3276. ctx.mark_start = lock_mark_counter;
  3277. victim_trx_id = lock_deadlock_search(&ctx);
  3278. /* Search too deep, we rollback the joining transaction. */
  3279. if (ctx.too_deep) {
  3280. ut_a(trx == ctx.start);
  3281. ut_a(victim_trx_id == trx->id);
  3282. if (!srv_read_only_mode) {
  3283. lock_deadlock_joining_trx_print(trx, lock);
  3284. }
  3285. MONITOR_INC(MONITOR_DEADLOCK);
  3286. } else if (victim_trx_id != 0 && victim_trx_id != trx->id) {
  3287. ut_ad(victim_trx_id == ctx.wait_lock->trx->id);
  3288. lock_deadlock_trx_rollback(&ctx);
  3289. lock_deadlock_found = TRUE;
  3290. MONITOR_INC(MONITOR_DEADLOCK);
  3291. }
  3292. } while (victim_trx_id != 0 && victim_trx_id != trx->id);
  3293. /* If the joining transaction was selected as the victim. */
  3294. if (victim_trx_id != 0) {
  3295. ut_a(victim_trx_id == trx->id);
  3296. srv_stats.lock_deadlock_count.inc();
  3297. lock_deadlock_fputs("*** WE ROLL BACK TRANSACTION (2)\n");
  3298. lock_deadlock_found = TRUE;
  3299. }
  3300. return(victim_trx_id);
  3301. }
  3302. /*========================= TABLE LOCKS ==============================*/
  3303. /*********************************************************************//**
  3304. Creates a table lock object and adds it as the last in the lock queue
  3305. of the table. Does NOT check for deadlocks or lock compatibility.
  3306. @return own: new lock object */
  3307. UNIV_INLINE
  3308. lock_t*
  3309. lock_table_create(
  3310. /*==============*/
  3311. dict_table_t* table, /*!< in/out: database table
  3312. in dictionary cache */
  3313. ulint type_mode,/*!< in: lock mode possibly ORed with
  3314. LOCK_WAIT */
  3315. trx_t* trx) /*!< in: trx */
  3316. {
  3317. lock_t* lock;
  3318. ut_ad(table && trx);
  3319. ut_ad(lock_mutex_own());
  3320. ut_ad(trx_mutex_own(trx));
  3321. /* Non-locking autocommit read-only transactions should not set
  3322. any locks. */
  3323. assert_trx_in_list(trx);
  3324. if ((type_mode & LOCK_MODE_MASK) == LOCK_AUTO_INC) {
  3325. ++table->n_waiting_or_granted_auto_inc_locks;
  3326. }
  3327. /* For AUTOINC locking we reuse the lock instance only if
  3328. there is no wait involved else we allocate the waiting lock
  3329. from the transaction lock heap. */
  3330. if (type_mode == LOCK_AUTO_INC) {
  3331. lock = table->autoinc_lock;
  3332. table->autoinc_trx = trx;
  3333. ib_vector_push(trx->autoinc_locks, &lock);
  3334. } else {
  3335. lock = static_cast<lock_t*>(
  3336. mem_heap_alloc(trx->lock.lock_heap, sizeof(*lock)));
  3337. }
  3338. lock->type_mode = type_mode | LOCK_TABLE;
  3339. lock->trx = trx;
  3340. lock->un_member.tab_lock.table = table;
  3341. ut_ad(table->n_ref_count > 0 || !table->can_be_evicted);
  3342. UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock);
  3343. UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
  3344. if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
  3345. lock_set_lock_and_trx_wait(lock, trx);
  3346. }
  3347. ib_vector_push(lock->trx->lock.table_locks, &lock);
  3348. MONITOR_INC(MONITOR_TABLELOCK_CREATED);
  3349. MONITOR_INC(MONITOR_NUM_TABLELOCK);
  3350. return(lock);
  3351. }
  3352. /*************************************************************//**
  3353. Pops autoinc lock requests from the transaction's autoinc_locks. We
  3354. handle the case where there are gaps in the array and they need to
  3355. be popped off the stack. */
  3356. UNIV_INLINE
  3357. void
  3358. lock_table_pop_autoinc_locks(
  3359. /*=========================*/
  3360. trx_t* trx) /*!< in/out: transaction that owns the AUTOINC locks */
  3361. {
  3362. ut_ad(lock_mutex_own());
  3363. ut_ad(!ib_vector_is_empty(trx->autoinc_locks));
  3364. /* Skip any gaps, gaps are NULL lock entries in the
  3365. trx->autoinc_locks vector. */
  3366. do {
  3367. ib_vector_pop(trx->autoinc_locks);
  3368. if (ib_vector_is_empty(trx->autoinc_locks)) {
  3369. return;
  3370. }
  3371. } while (*(lock_t**) ib_vector_get_last(trx->autoinc_locks) == NULL);
  3372. }
  3373. /*************************************************************//**
  3374. Removes an autoinc lock request from the transaction's autoinc_locks. */
  3375. UNIV_INLINE
  3376. void
  3377. lock_table_remove_autoinc_lock(
  3378. /*===========================*/
  3379. lock_t* lock, /*!< in: table lock */
  3380. trx_t* trx) /*!< in/out: transaction that owns the lock */
  3381. {
  3382. lock_t* autoinc_lock;
  3383. lint i = ib_vector_size(trx->autoinc_locks) - 1;
  3384. ut_ad(lock_mutex_own());
  3385. ut_ad(lock_get_mode(lock) == LOCK_AUTO_INC);
  3386. ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
  3387. ut_ad(!ib_vector_is_empty(trx->autoinc_locks));
  3388. /* With stored functions and procedures the user may drop
  3389. a table within the same "statement". This special case has
  3390. to be handled by deleting only those AUTOINC locks that were
  3391. held by the table being dropped. */
  3392. autoinc_lock = *static_cast<lock_t**>(
  3393. ib_vector_get(trx->autoinc_locks, i));
  3394. /* This is the default fast case. */
  3395. if (autoinc_lock == lock) {
  3396. lock_table_pop_autoinc_locks(trx);
  3397. } else {
  3398. /* The last element should never be NULL */
  3399. ut_a(autoinc_lock != NULL);
  3400. /* Handle freeing the locks from within the stack. */
  3401. while (--i >= 0) {
  3402. autoinc_lock = *static_cast<lock_t**>(
  3403. ib_vector_get(trx->autoinc_locks, i));
  3404. if (UNIV_LIKELY(autoinc_lock == lock)) {
  3405. void* null_var = NULL;
  3406. ib_vector_set(trx->autoinc_locks, i, &null_var);
  3407. return;
  3408. }
  3409. }
  3410. /* Must find the autoinc lock. */
  3411. ut_error;
  3412. }
  3413. }
  3414. /*************************************************************//**
  3415. Removes a table lock request from the queue and the trx list of locks;
  3416. this is a low-level function which does NOT check if waiting requests
  3417. can now be granted. */
  3418. UNIV_INLINE
  3419. void
  3420. lock_table_remove_low(
  3421. /*==================*/
  3422. lock_t* lock) /*!< in/out: table lock */
  3423. {
  3424. trx_t* trx;
  3425. dict_table_t* table;
  3426. ut_ad(lock_mutex_own());
  3427. trx = lock->trx;
  3428. table = lock->un_member.tab_lock.table;
  3429. /* Remove the table from the transaction's AUTOINC vector, if
  3430. the lock that is being released is an AUTOINC lock. */
  3431. if (lock_get_mode(lock) == LOCK_AUTO_INC) {
  3432. /* The table's AUTOINC lock can get transferred to
  3433. another transaction before we get here. */
  3434. if (table->autoinc_trx == trx) {
  3435. table->autoinc_trx = NULL;
  3436. }
  3437. /* The locks must be freed in the reverse order from
  3438. the one in which they were acquired. This is to avoid
  3439. traversing the AUTOINC lock vector unnecessarily.
  3440. We only store locks that were granted in the
  3441. trx->autoinc_locks vector (see lock_table_create()
  3442. and lock_grant()). Therefore it can be empty and we
  3443. need to check for that. */
  3444. if (!lock_get_wait(lock)
  3445. && !ib_vector_is_empty(trx->autoinc_locks)) {
  3446. lock_table_remove_autoinc_lock(lock, trx);
  3447. }
  3448. ut_a(table->n_waiting_or_granted_auto_inc_locks > 0);
  3449. table->n_waiting_or_granted_auto_inc_locks--;
  3450. }
  3451. UT_LIST_REMOVE(trx_locks, trx->lock.trx_locks, lock);
  3452. UT_LIST_REMOVE(un_member.tab_lock.locks, table->locks, lock);
  3453. MONITOR_INC(MONITOR_TABLELOCK_REMOVED);
  3454. MONITOR_DEC(MONITOR_NUM_TABLELOCK);
  3455. }
  3456. /*********************************************************************//**
  3457. Enqueues a waiting request for a table lock which cannot be granted
  3458. immediately. Checks for deadlocks.
  3459. @return DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED, or
  3460. DB_SUCCESS; DB_SUCCESS means that there was a deadlock, but another
  3461. transaction was chosen as a victim, and we got the lock immediately:
  3462. no need to wait then */
  3463. static
  3464. dberr_t
  3465. lock_table_enqueue_waiting(
  3466. /*=======================*/
  3467. ulint mode, /*!< in: lock mode this transaction is
  3468. requesting */
  3469. dict_table_t* table, /*!< in/out: table */
  3470. que_thr_t* thr) /*!< in: query thread */
  3471. {
  3472. trx_t* trx;
  3473. lock_t* lock;
  3474. trx_id_t victim_trx_id;
  3475. ulint sec;
  3476. ulint ms;
  3477. ut_ad(lock_mutex_own());
  3478. ut_ad(!srv_read_only_mode);
  3479. trx = thr_get_trx(thr);
  3480. ut_ad(trx_mutex_own(trx));
  3481. /* Test if there already is some other reason to suspend thread:
  3482. we do not enqueue a lock request if the query thread should be
  3483. stopped anyway */
  3484. if (que_thr_stop(thr)) {
  3485. ut_error;
  3486. return(DB_QUE_THR_SUSPENDED);
  3487. }
  3488. switch (trx_get_dict_operation(trx)) {
  3489. case TRX_DICT_OP_NONE:
  3490. break;
  3491. case TRX_DICT_OP_TABLE:
  3492. case TRX_DICT_OP_INDEX:
  3493. ut_print_timestamp(stderr);
  3494. fputs(" InnoDB: Error: a table lock wait happens"
  3495. " in a dictionary operation!\n"
  3496. "InnoDB: Table name ", stderr);
  3497. ut_print_name(stderr, trx, TRUE, table->name);
  3498. fputs(".\n"
  3499. "InnoDB: Submit a detailed bug report"
  3500. " to http://bugs.mysql.com\n",
  3501. stderr);
  3502. ut_ad(0);
  3503. }
  3504. /* Enqueue the lock request that will wait to be granted */
  3505. lock = lock_table_create(table, mode | LOCK_WAIT, trx);
  3506. /* Release the mutex to obey the latching order.
  3507. This is safe, because lock_deadlock_check_and_resolve()
  3508. is invoked when a lock wait is enqueued for the currently
  3509. running transaction. Because trx is a running transaction
  3510. (it is not currently suspended because of a lock wait),
  3511. its state can only be changed by this thread, which is
  3512. currently associated with the transaction. */
  3513. trx_mutex_exit(trx);
  3514. victim_trx_id = lock_deadlock_check_and_resolve(lock, trx);
  3515. trx_mutex_enter(trx);
  3516. if (victim_trx_id != 0) {
  3517. ut_ad(victim_trx_id == trx->id);
  3518. /* The order here is important, we don't want to
  3519. lose the state of the lock before calling remove. */
  3520. lock_table_remove_low(lock);
  3521. lock_reset_lock_and_trx_wait(lock);
  3522. return(DB_DEADLOCK);
  3523. } else if (trx->lock.wait_lock == NULL) {
  3524. /* Deadlock resolution chose another transaction as a victim,
  3525. and we accidentally got our lock granted! */
  3526. return(DB_SUCCESS);
  3527. }
  3528. trx->lock.que_state = TRX_QUE_LOCK_WAIT;
  3529. trx->lock.wait_started = ut_time();
  3530. trx->lock.was_chosen_as_deadlock_victim = FALSE;
  3531. if (UNIV_UNLIKELY(trx->take_stats)) {
  3532. ut_usectime(&sec, &ms);
  3533. trx->lock_que_wait_ustarted = (ib_uint64_t)sec * 1000000 + ms;
  3534. }
  3535. ut_a(que_thr_stop(thr));
  3536. MONITOR_INC(MONITOR_TABLELOCK_WAIT);
  3537. return(DB_LOCK_WAIT);
  3538. }
  3539. /*********************************************************************//**
  3540. Checks if other transactions have an incompatible mode lock request in
  3541. the lock queue.
  3542. @return lock or NULL */
  3543. UNIV_INLINE
  3544. const lock_t*
  3545. lock_table_other_has_incompatible(
  3546. /*==============================*/
  3547. const trx_t* trx, /*!< in: transaction, or NULL if all
  3548. transactions should be included */
  3549. ulint wait, /*!< in: LOCK_WAIT if also
  3550. waiting locks are taken into
  3551. account, or 0 if not */
  3552. const dict_table_t* table, /*!< in: table */
  3553. enum lock_mode mode) /*!< in: lock mode */
  3554. {
  3555. const lock_t* lock;
  3556. ut_ad(lock_mutex_own());
  3557. for (lock = UT_LIST_GET_LAST(table->locks);
  3558. lock != NULL;
  3559. lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock)) {
  3560. if (lock->trx != trx
  3561. && !lock_mode_compatible(lock_get_mode(lock), mode)
  3562. && (wait || !lock_get_wait(lock))) {
  3563. return(lock);
  3564. }
  3565. }
  3566. return(NULL);
  3567. }
  3568. /*********************************************************************//**
  3569. Locks the specified database table in the mode given. If the lock cannot
  3570. be granted immediately, the query thread is put to wait.
  3571. @return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
  3572. UNIV_INTERN
  3573. dberr_t
  3574. lock_table(
  3575. /*=======*/
  3576. ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG bit is set,
  3577. does nothing */
  3578. dict_table_t* table, /*!< in/out: database table
  3579. in dictionary cache */
  3580. enum lock_mode mode, /*!< in: lock mode */
  3581. que_thr_t* thr) /*!< in: query thread */
  3582. {
  3583. trx_t* trx;
  3584. dberr_t err;
  3585. const lock_t* wait_for;
  3586. ut_ad(table && thr);
  3587. if (flags & BTR_NO_LOCKING_FLAG) {
  3588. return(DB_SUCCESS);
  3589. }
  3590. ut_a(flags == 0);
  3591. trx = thr_get_trx(thr);
  3592. if (UNIV_UNLIKELY(trx->fake_changes && mode == LOCK_IX)) {
  3593. mode = LOCK_IS;
  3594. }
  3595. /* Look for equal or stronger locks the same trx already
  3596. has on the table. No need to acquire the lock mutex here
  3597. because only this transacton can add/access table locks
  3598. to/from trx_t::table_locks. */
  3599. if (lock_table_has(trx, table, mode)) {
  3600. return(DB_SUCCESS);
  3601. }
  3602. lock_mutex_enter();
  3603. /* We have to check if the new lock is compatible with any locks
  3604. other transactions have in the table lock queue. */
  3605. wait_for = lock_table_other_has_incompatible(
  3606. trx, LOCK_WAIT, table, mode);
  3607. trx_mutex_enter(trx);
  3608. /* Another trx has a request on the table in an incompatible
  3609. mode: this trx may have to wait */
  3610. if (wait_for != NULL) {
  3611. err = lock_table_enqueue_waiting(mode | flags, table, thr);
  3612. } else {
  3613. lock_table_create(table, mode | flags, trx);
  3614. ut_a(!flags || mode == LOCK_S || mode == LOCK_X);
  3615. err = DB_SUCCESS;
  3616. }
  3617. lock_mutex_exit();
  3618. trx_mutex_exit(trx);
  3619. return(err);
  3620. }
  3621. /*********************************************************************//**
  3622. Creates a table IX lock object for a resurrected transaction. */
  3623. UNIV_INTERN
  3624. void
  3625. lock_table_ix_resurrect(
  3626. /*====================*/
  3627. dict_table_t* table, /*!< in/out: table */
  3628. trx_t* trx) /*!< in/out: transaction */
  3629. {
  3630. ut_ad(trx->is_recovered);
  3631. if (lock_table_has(trx, table, LOCK_IX)) {
  3632. return;
  3633. }
  3634. lock_mutex_enter();
  3635. /* We have to check if the new lock is compatible with any locks
  3636. other transactions have in the table lock queue. */
  3637. ut_ad(!lock_table_other_has_incompatible(
  3638. trx, LOCK_WAIT, table, LOCK_IX));
  3639. trx_mutex_enter(trx);
  3640. lock_table_create(table, LOCK_IX, trx);
  3641. lock_mutex_exit();
  3642. trx_mutex_exit(trx);
  3643. }
  3644. /*********************************************************************//**
  3645. Checks if a waiting table lock request still has to wait in a queue.
  3646. @return TRUE if still has to wait */
  3647. static
  3648. ibool
  3649. lock_table_has_to_wait_in_queue(
  3650. /*============================*/
  3651. const lock_t* wait_lock) /*!< in: waiting table lock */
  3652. {
  3653. const dict_table_t* table;
  3654. const lock_t* lock;
  3655. ut_ad(lock_mutex_own());
  3656. ut_ad(lock_get_wait(wait_lock));
  3657. table = wait_lock->un_member.tab_lock.table;
  3658. for (lock = UT_LIST_GET_FIRST(table->locks);
  3659. lock != wait_lock;
  3660. lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock)) {
  3661. if (lock_has_to_wait(wait_lock, lock)) {
  3662. return(TRUE);
  3663. }
  3664. }
  3665. return(FALSE);
  3666. }
  3667. /*************************************************************//**
  3668. Removes a table lock request, waiting or granted, from the queue and grants
  3669. locks to other transactions in the queue, if they now are entitled to a
  3670. lock. */
  3671. static
  3672. void
  3673. lock_table_dequeue(
  3674. /*===============*/
  3675. lock_t* in_lock)/*!< in/out: table lock object; transactions waiting
  3676. behind will get their lock requests granted, if
  3677. they are now qualified to it */
  3678. {
  3679. lock_t* lock;
  3680. ut_ad(lock_mutex_own());
  3681. ut_a(lock_get_type_low(in_lock) == LOCK_TABLE);
  3682. lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock);
  3683. lock_table_remove_low(in_lock);
  3684. /* Check if waiting locks in the queue can now be granted: grant
  3685. locks if there are no conflicting locks ahead. */
  3686. for (/* No op */;
  3687. lock != NULL;
  3688. lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock)) {
  3689. if (lock_get_wait(lock)
  3690. && !lock_table_has_to_wait_in_queue(lock)) {
  3691. /* Grant the lock */
  3692. ut_ad(in_lock->trx != lock->trx);
  3693. lock_grant(lock);
  3694. }
  3695. }
  3696. }
  3697. /*=========================== LOCK RELEASE ==============================*/
  3698. /*************************************************************//**
  3699. Removes a granted record lock of a transaction from the queue and grants
  3700. locks to other transactions waiting in the queue if they now are entitled
  3701. to a lock. */
  3702. UNIV_INTERN
  3703. void
  3704. lock_rec_unlock(
  3705. /*============*/
  3706. trx_t* trx, /*!< in/out: transaction that has
  3707. set a record lock */
  3708. const buf_block_t* block, /*!< in: buffer block containing rec */
  3709. const rec_t* rec, /*!< in: record */
  3710. enum lock_mode lock_mode)/*!< in: LOCK_S or LOCK_X */
  3711. {
  3712. lock_t* first_lock;
  3713. lock_t* lock;
  3714. ulint heap_no;
  3715. const char* stmt;
  3716. size_t stmt_len;
  3717. ut_ad(trx);
  3718. ut_ad(rec);
  3719. ut_ad(block->frame == page_align(rec));
  3720. ut_ad(!trx->lock.wait_lock);
  3721. ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
  3722. heap_no = page_rec_get_heap_no(rec);
  3723. lock_mutex_enter();
  3724. trx_mutex_enter(trx);
  3725. first_lock = lock_rec_get_first(block, heap_no);
  3726. /* Find the last lock with the same lock_mode and transaction
  3727. on the record. */
  3728. for (lock = first_lock; lock != NULL;
  3729. lock = lock_rec_get_next(heap_no, lock)) {
  3730. if (lock->trx == trx && lock_get_mode(lock) == lock_mode) {
  3731. goto released;
  3732. }
  3733. }
  3734. lock_mutex_exit();
  3735. trx_mutex_exit(trx);
  3736. stmt = innobase_get_stmt(trx->mysql_thd, &stmt_len);
  3737. ut_print_timestamp(stderr);
  3738. fprintf(stderr,
  3739. " InnoDB: Error: unlock row could not"
  3740. " find a %lu mode lock on the record\n",
  3741. (ulong) lock_mode);
  3742. ut_print_timestamp(stderr);
  3743. fprintf(stderr, " InnoDB: current statement: %.*s\n",
  3744. (int) stmt_len, stmt);
  3745. return;
  3746. released:
  3747. ut_a(!lock_get_wait(lock));
  3748. lock_rec_reset_nth_bit(lock, heap_no);
  3749. /* Check if we can now grant waiting lock requests */
  3750. for (lock = first_lock; lock != NULL;
  3751. lock = lock_rec_get_next(heap_no, lock)) {
  3752. if (lock_get_wait(lock)
  3753. && !lock_rec_has_to_wait_in_queue(lock)) {
  3754. /* Grant the lock */
  3755. ut_ad(trx != lock->trx);
  3756. lock_grant(lock);
  3757. }
  3758. }
  3759. lock_mutex_exit();
  3760. trx_mutex_exit(trx);
  3761. }
  3762. /*********************************************************************//**
  3763. Releases transaction locks, and releases possible other transactions waiting
  3764. because of these locks. */
  3765. static
  3766. void
  3767. lock_release(
  3768. /*=========*/
  3769. trx_t* trx) /*!< in/out: transaction */
  3770. {
  3771. lock_t* lock;
  3772. ulint count = 0;
  3773. trx_id_t max_trx_id;
  3774. ut_ad(lock_mutex_own());
  3775. ut_ad(!trx_mutex_own(trx));
  3776. max_trx_id = trx_sys_get_max_trx_id();
  3777. for (lock = UT_LIST_GET_LAST(trx->lock.trx_locks);
  3778. lock != NULL;
  3779. lock = UT_LIST_GET_LAST(trx->lock.trx_locks)) {
  3780. if (lock_get_type_low(lock) == LOCK_REC) {
  3781. #ifdef UNIV_DEBUG
  3782. /* Check if the transcation locked a record
  3783. in a system table in X mode. It should have set
  3784. the dict_op code correctly if it did. */
  3785. if (lock->index->table->id < DICT_HDR_FIRST_ID
  3786. && lock_get_mode(lock) == LOCK_X) {
  3787. ut_ad(lock_get_mode(lock) != LOCK_IX);
  3788. ut_ad(trx->dict_operation != TRX_DICT_OP_NONE);
  3789. }
  3790. #endif /* UNIV_DEBUG */
  3791. lock_rec_dequeue_from_page(lock);
  3792. } else {
  3793. dict_table_t* table;
  3794. table = lock->un_member.tab_lock.table;
  3795. #ifdef UNIV_DEBUG
  3796. ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
  3797. /* Check if the transcation locked a system table
  3798. in IX mode. It should have set the dict_op code
  3799. correctly if it did. */
  3800. if (table->id < DICT_HDR_FIRST_ID
  3801. && (lock_get_mode(lock) == LOCK_X
  3802. || lock_get_mode(lock) == LOCK_IX)) {
  3803. ut_ad(trx->dict_operation != TRX_DICT_OP_NONE);
  3804. }
  3805. #endif /* UNIV_DEBUG */
  3806. if (lock_get_mode(lock) != LOCK_IS
  3807. && trx->undo_no != 0) {
  3808. /* The trx may have modified the table. We
  3809. block the use of the MySQL query cache for
  3810. all currently active transactions. */
  3811. table->query_cache_inv_trx_id = max_trx_id;
  3812. }
  3813. lock_table_dequeue(lock);
  3814. }
  3815. if (count == LOCK_RELEASE_INTERVAL) {
  3816. /* Release the mutex for a while, so that we
  3817. do not monopolize it */
  3818. lock_mutex_exit();
  3819. lock_mutex_enter();
  3820. count = 0;
  3821. }
  3822. ++count;
  3823. }
  3824. /* We don't remove the locks one by one from the vector for
  3825. efficiency reasons. We simply reset it because we would have
  3826. released all the locks anyway. */
  3827. ib_vector_reset(trx->lock.table_locks);
  3828. ut_a(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0);
  3829. ut_a(ib_vector_is_empty(trx->autoinc_locks));
  3830. ut_a(ib_vector_is_empty(trx->lock.table_locks));
  3831. mem_heap_empty(trx->lock.lock_heap);
  3832. }
  3833. /* True if a lock mode is S or X */
  3834. #define IS_LOCK_S_OR_X(lock) \
  3835. (lock_get_mode(lock) == LOCK_S \
  3836. || lock_get_mode(lock) == LOCK_X)
  3837. /*********************************************************************//**
  3838. Removes table locks of the transaction on a table to be dropped. */
  3839. static
  3840. void
  3841. lock_trx_table_locks_remove(
  3842. /*========================*/
  3843. const lock_t* lock_to_remove) /*!< in: lock to remove */
  3844. {
  3845. lint i;
  3846. trx_t* trx = lock_to_remove->trx;
  3847. ut_ad(lock_mutex_own());
  3848. /* It is safe to read this because we are holding the lock mutex */
  3849. if (!trx->lock.cancel) {
  3850. trx_mutex_enter(trx);
  3851. } else {
  3852. ut_ad(trx_mutex_own(trx));
  3853. }
  3854. for (i = ib_vector_size(trx->lock.table_locks) - 1; i >= 0; --i) {
  3855. const lock_t* lock;
  3856. lock = *static_cast<lock_t**>(
  3857. ib_vector_get(trx->lock.table_locks, i));
  3858. if (lock == NULL) {
  3859. continue;
  3860. }
  3861. ut_a(trx == lock->trx);
  3862. ut_a(lock_get_type_low(lock) & LOCK_TABLE);
  3863. ut_a(lock->un_member.tab_lock.table != NULL);
  3864. if (lock == lock_to_remove) {
  3865. void* null_var = NULL;
  3866. ib_vector_set(trx->lock.table_locks, i, &null_var);
  3867. if (!trx->lock.cancel) {
  3868. trx_mutex_exit(trx);
  3869. }
  3870. return;
  3871. }
  3872. }
  3873. if (!trx->lock.cancel) {
  3874. trx_mutex_exit(trx);
  3875. }
  3876. /* Lock must exist in the vector. */
  3877. ut_error;
  3878. }
  3879. /*********************************************************************//**
  3880. Removes locks of a transaction on a table to be dropped.
  3881. If remove_also_table_sx_locks is TRUE then table-level S and X locks are
  3882. also removed in addition to other table-level and record-level locks.
  3883. No lock that is going to be removed is allowed to be a wait lock. */
  3884. static
  3885. void
  3886. lock_remove_all_on_table_for_trx(
  3887. /*=============================*/
  3888. dict_table_t* table, /*!< in: table to be dropped */
  3889. trx_t* trx, /*!< in: a transaction */
  3890. ibool remove_also_table_sx_locks)/*!< in: also removes
  3891. table S and X locks */
  3892. {
  3893. lock_t* lock;
  3894. lock_t* prev_lock;
  3895. ut_ad(lock_mutex_own());
  3896. for (lock = UT_LIST_GET_LAST(trx->lock.trx_locks);
  3897. lock != NULL;
  3898. lock = prev_lock) {
  3899. prev_lock = UT_LIST_GET_PREV(trx_locks, lock);
  3900. if (lock_get_type_low(lock) == LOCK_REC
  3901. && lock->index->table == table) {
  3902. ut_a(!lock_get_wait(lock));
  3903. lock_rec_discard(lock);
  3904. } else if (lock_get_type_low(lock) & LOCK_TABLE
  3905. && lock->un_member.tab_lock.table == table
  3906. && (remove_also_table_sx_locks
  3907. || !IS_LOCK_S_OR_X(lock))) {
  3908. ut_a(!lock_get_wait(lock));
  3909. lock_trx_table_locks_remove(lock);
  3910. lock_table_remove_low(lock);
  3911. }
  3912. }
  3913. }
  3914. /*******************************************************************//**
  3915. Remove any explicit record locks held by recovering transactions on
  3916. the table.
  3917. @return number of recovered transactions examined */
  3918. static
  3919. ulint
  3920. lock_remove_recovered_trx_record_locks(
  3921. /*===================================*/
  3922. dict_table_t* table) /*!< in: check if there are any locks
  3923. held on records in this table or on the
  3924. table itself */
  3925. {
  3926. trx_t* trx;
  3927. ulint n_recovered_trx = 0;
  3928. ut_a(table != NULL);
  3929. ut_ad(lock_mutex_own());
  3930. mutex_enter(&trx_sys->mutex);
  3931. for (trx = UT_LIST_GET_FIRST(trx_sys->rw_trx_list);
  3932. trx != NULL;
  3933. trx = UT_LIST_GET_NEXT(trx_list, trx)) {
  3934. lock_t* lock;
  3935. lock_t* next_lock;
  3936. assert_trx_in_rw_list(trx);
  3937. if (!trx->is_recovered) {
  3938. continue;
  3939. }
  3940. /* Because we are holding the lock_sys->mutex,
  3941. implicit locks cannot be converted to explicit ones
  3942. while we are scanning the explicit locks. */
  3943. for (lock = UT_LIST_GET_FIRST(trx->lock.trx_locks);
  3944. lock != NULL;
  3945. lock = next_lock) {
  3946. ut_a(lock->trx == trx);
  3947. /* Recovered transactions can't wait on a lock. */
  3948. ut_a(!lock_get_wait(lock));
  3949. next_lock = UT_LIST_GET_NEXT(trx_locks, lock);
  3950. switch (lock_get_type_low(lock)) {
  3951. default:
  3952. ut_error;
  3953. case LOCK_TABLE:
  3954. if (lock->un_member.tab_lock.table == table) {
  3955. lock_trx_table_locks_remove(lock);
  3956. lock_table_remove_low(lock);
  3957. }
  3958. break;
  3959. case LOCK_REC:
  3960. if (lock->index->table == table) {
  3961. lock_rec_discard(lock);
  3962. }
  3963. }
  3964. }
  3965. ++n_recovered_trx;
  3966. }
  3967. mutex_exit(&trx_sys->mutex);
  3968. return(n_recovered_trx);
  3969. }
  3970. /*********************************************************************//**
  3971. Removes locks on a table to be dropped or truncated.
  3972. If remove_also_table_sx_locks is TRUE then table-level S and X locks are
  3973. also removed in addition to other table-level and record-level locks.
  3974. No lock, that is going to be removed, is allowed to be a wait lock. */
  3975. UNIV_INTERN
  3976. void
  3977. lock_remove_all_on_table(
  3978. /*=====================*/
  3979. dict_table_t* table, /*!< in: table to be dropped
  3980. or truncated */
  3981. ibool remove_also_table_sx_locks)/*!< in: also removes
  3982. table S and X locks */
  3983. {
  3984. lock_t* lock;
  3985. lock_mutex_enter();
  3986. for (lock = UT_LIST_GET_FIRST(table->locks);
  3987. lock != NULL;
  3988. /* No op */) {
  3989. lock_t* prev_lock;
  3990. prev_lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock);
  3991. /* If we should remove all locks (remove_also_table_sx_locks
  3992. is TRUE), or if the lock is not table-level S or X lock,
  3993. then check we are not going to remove a wait lock. */
  3994. if (remove_also_table_sx_locks
  3995. || !(lock_get_type(lock) == LOCK_TABLE
  3996. && IS_LOCK_S_OR_X(lock))) {
  3997. ut_a(!lock_get_wait(lock));
  3998. }
  3999. lock_remove_all_on_table_for_trx(
  4000. table, lock->trx, remove_also_table_sx_locks);
  4001. if (prev_lock == NULL) {
  4002. if (lock == UT_LIST_GET_FIRST(table->locks)) {
  4003. /* lock was not removed, pick its successor */
  4004. lock = UT_LIST_GET_NEXT(
  4005. un_member.tab_lock.locks, lock);
  4006. } else {
  4007. /* lock was removed, pick the first one */
  4008. lock = UT_LIST_GET_FIRST(table->locks);
  4009. }
  4010. } else if (UT_LIST_GET_NEXT(un_member.tab_lock.locks,
  4011. prev_lock) != lock) {
  4012. /* If lock was removed by
  4013. lock_remove_all_on_table_for_trx() then pick the
  4014. successor of prev_lock ... */
  4015. lock = UT_LIST_GET_NEXT(
  4016. un_member.tab_lock.locks, prev_lock);
  4017. } else {
  4018. /* ... otherwise pick the successor of lock. */
  4019. lock = UT_LIST_GET_NEXT(
  4020. un_member.tab_lock.locks, lock);
  4021. }
  4022. }
  4023. /* Note: Recovered transactions don't have table level IX or IS locks
  4024. but can have implicit record locks that have been converted to explicit
  4025. record locks. Such record locks cannot be freed by traversing the
  4026. transaction lock list in dict_table_t (as above). */
  4027. if (!lock_sys->rollback_complete
  4028. && lock_remove_recovered_trx_record_locks(table) == 0) {
  4029. lock_sys->rollback_complete = TRUE;
  4030. }
  4031. lock_mutex_exit();
  4032. }
  4033. /*===================== VALIDATION AND DEBUGGING ====================*/
  4034. /*********************************************************************//**
  4035. Prints info of a table lock. */
  4036. UNIV_INTERN
  4037. void
  4038. lock_table_print(
  4039. /*=============*/
  4040. FILE* file, /*!< in: file where to print */
  4041. const lock_t* lock) /*!< in: table type lock */
  4042. {
  4043. ut_ad(lock_mutex_own());
  4044. ut_a(lock_get_type_low(lock) == LOCK_TABLE);
  4045. fputs("TABLE LOCK table ", file);
  4046. ut_print_name(file, lock->trx, TRUE,
  4047. lock->un_member.tab_lock.table->name);
  4048. fprintf(file, " trx id " TRX_ID_FMT, lock->trx->id);
  4049. if (lock_get_mode(lock) == LOCK_S) {
  4050. fputs(" lock mode S", file);
  4051. } else if (lock_get_mode(lock) == LOCK_X) {
  4052. fputs(" lock mode X", file);
  4053. } else if (lock_get_mode(lock) == LOCK_IS) {
  4054. fputs(" lock mode IS", file);
  4055. } else if (lock_get_mode(lock) == LOCK_IX) {
  4056. fputs(" lock mode IX", file);
  4057. } else if (lock_get_mode(lock) == LOCK_AUTO_INC) {
  4058. fputs(" lock mode AUTO-INC", file);
  4059. } else {
  4060. fprintf(file, " unknown lock mode %lu",
  4061. (ulong) lock_get_mode(lock));
  4062. }
  4063. if (lock_get_wait(lock)) {
  4064. fputs(" waiting", file);
  4065. }
  4066. putc('\n', file);
  4067. }
  4068. /*********************************************************************//**
  4069. Prints info of a record lock. */
  4070. UNIV_INTERN
  4071. void
  4072. lock_rec_print(
  4073. /*===========*/
  4074. FILE* file, /*!< in: file where to print */
  4075. const lock_t* lock) /*!< in: record type lock */
  4076. {
  4077. const buf_block_t* block;
  4078. ulint space;
  4079. ulint page_no;
  4080. ulint i;
  4081. mtr_t mtr;
  4082. mem_heap_t* heap = NULL;
  4083. ulint offsets_[REC_OFFS_NORMAL_SIZE];
  4084. ulint* offsets = offsets_;
  4085. rec_offs_init(offsets_);
  4086. ut_ad(lock_mutex_own());
  4087. ut_a(lock_get_type_low(lock) == LOCK_REC);
  4088. space = lock->un_member.rec_lock.space;
  4089. page_no = lock->un_member.rec_lock.page_no;
  4090. fprintf(file, "RECORD LOCKS space id %lu page no %lu n bits %lu ",
  4091. (ulong) space, (ulong) page_no,
  4092. (ulong) lock_rec_get_n_bits(lock));
  4093. dict_index_name_print(file, lock->trx, lock->index);
  4094. fprintf(file, " trx id " TRX_ID_FMT, lock->trx->id);
  4095. if (lock_get_mode(lock) == LOCK_S) {
  4096. fputs(" lock mode S", file);
  4097. } else if (lock_get_mode(lock) == LOCK_X) {
  4098. fputs(" lock_mode X", file);
  4099. } else {
  4100. ut_error;
  4101. }
  4102. if (lock_rec_get_gap(lock)) {
  4103. fputs(" locks gap before rec", file);
  4104. }
  4105. if (lock_rec_get_rec_not_gap(lock)) {
  4106. fputs(" locks rec but not gap", file);
  4107. }
  4108. if (lock_rec_get_insert_intention(lock)) {
  4109. fputs(" insert intention", file);
  4110. }
  4111. if (lock_get_wait(lock)) {
  4112. fputs(" waiting", file);
  4113. }
  4114. mtr_start(&mtr);
  4115. putc('\n', file);
  4116. if ( srv_show_verbose_locks ) {
  4117. block = buf_page_try_get(space, page_no, &mtr);
  4118. for (i = 0; i < lock_rec_get_n_bits(lock); ++i) {
  4119. if (!lock_rec_get_nth_bit(lock, i)) {
  4120. continue;
  4121. }
  4122. fprintf(file, "Record lock, heap no %lu", (ulong) i);
  4123. if (block) {
  4124. const rec_t* rec;
  4125. rec = page_find_rec_with_heap_no(
  4126. buf_block_get_frame(block), i);
  4127. offsets = rec_get_offsets(
  4128. rec, lock->index, offsets,
  4129. ULINT_UNDEFINED, &heap);
  4130. putc(' ', file);
  4131. rec_print_new(file, rec, offsets);
  4132. }
  4133. putc('\n', file);
  4134. }
  4135. }
  4136. mtr_commit(&mtr);
  4137. if (UNIV_LIKELY_NULL(heap)) {
  4138. mem_heap_free(heap);
  4139. }
  4140. }
  4141. #ifdef UNIV_DEBUG
  4142. /* Print the number of lock structs from lock_print_info_summary() only
  4143. in non-production builds for performance reasons, see
  4144. http://bugs.mysql.com/36942 */
  4145. #define PRINT_NUM_OF_LOCK_STRUCTS
  4146. #endif /* UNIV_DEBUG */
  4147. #ifdef PRINT_NUM_OF_LOCK_STRUCTS
  4148. /*********************************************************************//**
  4149. Calculates the number of record lock structs in the record lock hash table.
  4150. @return number of record locks */
  4151. static
  4152. ulint
  4153. lock_get_n_rec_locks(void)
  4154. /*======================*/
  4155. {
  4156. ulint n_locks = 0;
  4157. ulint i;
  4158. ut_ad(lock_mutex_own());
  4159. for (i = 0; i < hash_get_n_cells(lock_sys->rec_hash); i++) {
  4160. const lock_t* lock;
  4161. for (lock = static_cast<const lock_t*>(
  4162. HASH_GET_FIRST(lock_sys->rec_hash, i));
  4163. lock != 0;
  4164. lock = static_cast<const lock_t*>(
  4165. HASH_GET_NEXT(hash, lock))) {
  4166. n_locks++;
  4167. }
  4168. }
  4169. return(n_locks);
  4170. }
  4171. #endif /* PRINT_NUM_OF_LOCK_STRUCTS */
  4172. /*********************************************************************//**
  4173. Prints info of locks for all transactions.
  4174. @return FALSE if not able to obtain lock mutex
  4175. and exits without printing info */
  4176. UNIV_INTERN
  4177. ibool
  4178. lock_print_info_summary(
  4179. /*====================*/
  4180. FILE* file, /*!< in: file where to print */
  4181. ibool nowait) /*!< in: whether to wait for the lock mutex */
  4182. {
  4183. /* if nowait is FALSE, wait on the lock mutex,
  4184. otherwise return immediately if fail to obtain the
  4185. mutex. */
  4186. if (!nowait) {
  4187. lock_mutex_enter();
  4188. } else if (lock_mutex_enter_nowait()) {
  4189. fputs("FAIL TO OBTAIN LOCK MUTEX, "
  4190. "SKIP LOCK INFO PRINTING\n", file);
  4191. return(FALSE);
  4192. }
  4193. if (lock_deadlock_found) {
  4194. fputs("------------------------\n"
  4195. "LATEST DETECTED DEADLOCK\n"
  4196. "------------------------\n", file);
  4197. if (!srv_read_only_mode) {
  4198. ut_copy_file(file, lock_latest_err_file);
  4199. }
  4200. }
  4201. fputs("------------\n"
  4202. "TRANSACTIONS\n"
  4203. "------------\n", file);
  4204. fprintf(file, "Trx id counter " TRX_ID_FMT "\n",
  4205. trx_sys_get_max_trx_id());
  4206. fprintf(file,
  4207. "Purge done for trx's n:o < " TRX_ID_FMT
  4208. " undo n:o < " TRX_ID_FMT " state: ",
  4209. purge_sys->iter.trx_no,
  4210. purge_sys->iter.undo_no);
  4211. /* Note: We are reading the state without the latch. One because it
  4212. will violate the latching order and two because we are merely querying
  4213. the state of the variable for display. */
  4214. switch (purge_sys->state){
  4215. case PURGE_STATE_INIT:
  4216. /* Should never be in this state while the system is running. */
  4217. ut_error;
  4218. case PURGE_STATE_EXIT:
  4219. fprintf(file, "exited");
  4220. break;
  4221. case PURGE_STATE_DISABLED:
  4222. fprintf(file, "disabled");
  4223. break;
  4224. case PURGE_STATE_RUN:
  4225. fprintf(file, "running");
  4226. /* Check if it is waiting for more data to arrive. */
  4227. if (!purge_sys->running) {
  4228. fprintf(file, " but idle");
  4229. }
  4230. break;
  4231. case PURGE_STATE_STOP:
  4232. fprintf(file, "stopped");
  4233. break;
  4234. }
  4235. fprintf(file, "\n");
  4236. fprintf(file,
  4237. "History list length %lu\n",
  4238. (ulong) trx_sys->rseg_history_len);
  4239. #ifdef PRINT_NUM_OF_LOCK_STRUCTS
  4240. fprintf(file,
  4241. "Total number of lock structs in row lock hash table %lu\n",
  4242. (ulong) lock_get_n_rec_locks());
  4243. #endif /* PRINT_NUM_OF_LOCK_STRUCTS */
  4244. return(TRUE);
  4245. }
  4246. /*********************************************************************//**
  4247. Prints info of locks for each transaction. This function assumes that the
  4248. caller holds the lock mutex and more importantly it will release the lock
  4249. mutex on behalf of the caller. (This should be fixed in the future). */
  4250. UNIV_INTERN
  4251. void
  4252. lock_print_info_all_transactions(
  4253. /*=============================*/
  4254. FILE* file) /*!< in: file where to print */
  4255. {
  4256. const lock_t* lock;
  4257. ibool load_page_first = TRUE;
  4258. ulint nth_trx = 0;
  4259. ulint nth_lock = 0;
  4260. ulint i;
  4261. mtr_t mtr;
  4262. const trx_t* trx;
  4263. trx_list_t* trx_list = &trx_sys->rw_trx_list;
  4264. fprintf(file, "LIST OF TRANSACTIONS FOR EACH SESSION:\n");
  4265. ut_ad(lock_mutex_own());
  4266. mutex_enter(&trx_sys->mutex);
  4267. /* First print info on non-active transactions */
  4268. /* NOTE: information of auto-commit non-locking read-only
  4269. transactions will be omitted here. The information will be
  4270. available from INFORMATION_SCHEMA.INNODB_TRX. */
  4271. for (trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
  4272. trx != NULL;
  4273. trx = UT_LIST_GET_NEXT(mysql_trx_list, trx)) {
  4274. ut_ad(trx->in_mysql_trx_list);
  4275. /* See state transitions and locking rules in trx0trx.h */
  4276. if (trx_state_eq(trx, TRX_STATE_NOT_STARTED)) {
  4277. fputs("---", file);
  4278. trx_print_latched(file, trx, 600);
  4279. }
  4280. }
  4281. loop:
  4282. /* Since we temporarily release lock_sys->mutex and
  4283. trx_sys->mutex when reading a database page in below,
  4284. variable trx may be obsolete now and we must loop
  4285. through the trx list to get probably the same trx,
  4286. or some other trx. */
  4287. for (trx = UT_LIST_GET_FIRST(*trx_list), i = 0;
  4288. trx && (i < nth_trx);
  4289. trx = UT_LIST_GET_NEXT(trx_list, trx), i++) {
  4290. assert_trx_in_list(trx);
  4291. ut_ad(trx->read_only == (trx_list == &trx_sys->ro_trx_list));
  4292. }
  4293. ut_ad(trx == NULL
  4294. || trx->read_only == (trx_list == &trx_sys->ro_trx_list));
  4295. if (trx == NULL) {
  4296. /* Check the read-only transaction list next. */
  4297. if (trx_list == &trx_sys->rw_trx_list) {
  4298. trx_list = &trx_sys->ro_trx_list;
  4299. nth_trx = 0;
  4300. nth_lock = 0;
  4301. goto loop;
  4302. }
  4303. lock_mutex_exit();
  4304. mutex_exit(&trx_sys->mutex);
  4305. ut_ad(lock_validate());
  4306. return;
  4307. }
  4308. assert_trx_in_list(trx);
  4309. if (nth_lock == 0) {
  4310. fputs("---", file);
  4311. trx_print_latched(file, trx, 600);
  4312. if (trx->read_view) {
  4313. fprintf(file,
  4314. "Trx read view will not see trx with"
  4315. " id >= " TRX_ID_FMT
  4316. ", sees < " TRX_ID_FMT "\n",
  4317. trx->read_view->low_limit_id,
  4318. trx->read_view->up_limit_id);
  4319. }
  4320. if (trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
  4321. fprintf(file,
  4322. "------- TRX HAS BEEN WAITING %lu SEC"
  4323. " FOR THIS LOCK TO BE GRANTED:\n",
  4324. (ulong) difftime(ut_time(),
  4325. trx->lock.wait_started));
  4326. if (lock_get_type_low(trx->lock.wait_lock) == LOCK_REC) {
  4327. lock_rec_print(file, trx->lock.wait_lock);
  4328. } else {
  4329. lock_table_print(file, trx->lock.wait_lock);
  4330. }
  4331. fputs("------------------\n", file);
  4332. }
  4333. }
  4334. if (!srv_print_innodb_lock_monitor && !srv_show_locks_held) {
  4335. nth_trx++;
  4336. goto loop;
  4337. }
  4338. i = 0;
  4339. /* Look at the note about the trx loop above why we loop here:
  4340. lock may be an obsolete pointer now. */
  4341. lock = UT_LIST_GET_FIRST(trx->lock.trx_locks);
  4342. while (lock && (i < nth_lock)) {
  4343. lock = UT_LIST_GET_NEXT(trx_locks, lock);
  4344. i++;
  4345. }
  4346. if (lock == NULL) {
  4347. nth_trx++;
  4348. nth_lock = 0;
  4349. goto loop;
  4350. }
  4351. if (lock_get_type_low(lock) == LOCK_REC) {
  4352. if (load_page_first) {
  4353. ulint space = lock->un_member.rec_lock.space;
  4354. ulint zip_size= fil_space_get_zip_size(space);
  4355. ulint page_no = lock->un_member.rec_lock.page_no;
  4356. if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
  4357. /* It is a single table tablespace and
  4358. the .ibd file is missing (TRUNCATE
  4359. TABLE probably stole the locks): just
  4360. print the lock without attempting to
  4361. load the page in the buffer pool. */
  4362. fprintf(file, "RECORD LOCKS on"
  4363. " non-existing space %lu\n",
  4364. (ulong) space);
  4365. goto print_rec;
  4366. }
  4367. lock_mutex_exit();
  4368. mutex_exit(&trx_sys->mutex);
  4369. if (srv_show_verbose_locks) {
  4370. mtr_start(&mtr);
  4371. buf_page_get_gen(space, zip_size, page_no,
  4372. RW_NO_LATCH, NULL,
  4373. BUF_GET_POSSIBLY_FREED,
  4374. __FILE__, __LINE__, &mtr);
  4375. mtr_commit(&mtr);
  4376. }
  4377. load_page_first = FALSE;
  4378. lock_mutex_enter();
  4379. mutex_enter(&trx_sys->mutex);
  4380. goto loop;
  4381. }
  4382. print_rec:
  4383. lock_rec_print(file, lock);
  4384. } else {
  4385. ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
  4386. lock_table_print(file, lock);
  4387. }
  4388. load_page_first = TRUE;
  4389. nth_lock++;
  4390. if (nth_lock >= srv_show_locks_held) {
  4391. fputs("TOO MANY LOCKS PRINTED FOR THIS TRX:"
  4392. " SUPPRESSING FURTHER PRINTS\n",
  4393. file);
  4394. nth_trx++;
  4395. nth_lock = 0;
  4396. }
  4397. goto loop;
  4398. }
  4399. #ifdef UNIV_DEBUG
  4400. /*********************************************************************//**
  4401. Find the the lock in the trx_t::trx_lock_t::table_locks vector.
  4402. @return TRUE if found */
  4403. static
  4404. ibool
  4405. lock_trx_table_locks_find(
  4406. /*======================*/
  4407. trx_t* trx, /*!< in: trx to validate */
  4408. const lock_t* find_lock) /*!< in: lock to find */
  4409. {
  4410. lint i;
  4411. ibool found = FALSE;
  4412. trx_mutex_enter(trx);
  4413. for (i = ib_vector_size(trx->lock.table_locks) - 1; i >= 0; --i) {
  4414. const lock_t* lock;
  4415. lock = *static_cast<const lock_t**>(
  4416. ib_vector_get(trx->lock.table_locks, i));
  4417. if (lock == NULL) {
  4418. continue;
  4419. } else if (lock == find_lock) {
  4420. /* Can't be duplicates. */
  4421. ut_a(!found);
  4422. found = TRUE;
  4423. }
  4424. ut_a(trx == lock->trx);
  4425. ut_a(lock_get_type_low(lock) & LOCK_TABLE);
  4426. ut_a(lock->un_member.tab_lock.table != NULL);
  4427. }
  4428. trx_mutex_exit(trx);
  4429. return(found);
  4430. }
  4431. /*********************************************************************//**
  4432. Validates the lock queue on a table.
  4433. @return TRUE if ok */
  4434. static
  4435. ibool
  4436. lock_table_queue_validate(
  4437. /*======================*/
  4438. const dict_table_t* table) /*!< in: table */
  4439. {
  4440. const lock_t* lock;
  4441. ut_ad(lock_mutex_own());
  4442. ut_ad(mutex_own(&trx_sys->mutex));
  4443. for (lock = UT_LIST_GET_FIRST(table->locks);
  4444. lock != NULL;
  4445. lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock)) {
  4446. /* lock->trx->state cannot change from or to NOT_STARTED
  4447. while we are holding the trx_sys->mutex. It may change
  4448. from ACTIVE to PREPARED, but it may not change to
  4449. COMMITTED, because we are holding the lock_sys->mutex. */
  4450. ut_ad(trx_assert_started(lock->trx));
  4451. if (!lock_get_wait(lock)) {
  4452. ut_a(!lock_table_other_has_incompatible(
  4453. lock->trx, 0, table,
  4454. lock_get_mode(lock)));
  4455. } else {
  4456. ut_a(lock_table_has_to_wait_in_queue(lock));
  4457. }
  4458. ut_a(lock_trx_table_locks_find(lock->trx, lock));
  4459. }
  4460. return(TRUE);
  4461. }
  4462. /*********************************************************************//**
  4463. Validates the lock queue on a single record.
  4464. @return TRUE if ok */
  4465. static
  4466. ibool
  4467. lock_rec_queue_validate(
  4468. /*====================*/
  4469. ibool locked_lock_trx_sys,
  4470. /*!< in: if the caller holds
  4471. both the lock mutex and
  4472. trx_sys_t->lock. */
  4473. const buf_block_t* block, /*!< in: buffer block containing rec */
  4474. const rec_t* rec, /*!< in: record to look at */
  4475. const dict_index_t* index, /*!< in: index, or NULL if not known */
  4476. const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
  4477. {
  4478. const lock_t* lock;
  4479. ulint heap_no;
  4480. ut_a(rec);
  4481. ut_a(block->frame == page_align(rec));
  4482. ut_ad(rec_offs_validate(rec, index, offsets));
  4483. ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
  4484. ut_ad(lock_mutex_own() == locked_lock_trx_sys);
  4485. ut_ad(!index || dict_index_is_clust(index)
  4486. || !dict_index_is_online_ddl(index));
  4487. heap_no = page_rec_get_heap_no(rec);
  4488. if (!locked_lock_trx_sys) {
  4489. lock_mutex_enter();
  4490. mutex_enter(&trx_sys->mutex);
  4491. }
  4492. if (!page_rec_is_user_rec(rec)) {
  4493. for (lock = lock_rec_get_first(block, heap_no);
  4494. lock != NULL;
  4495. lock = lock_rec_get_next_const(heap_no, lock)) {
  4496. ut_a(trx_in_trx_list(lock->trx));
  4497. if (lock_get_wait(lock)) {
  4498. ut_a(lock_rec_has_to_wait_in_queue(lock));
  4499. }
  4500. if (index) {
  4501. ut_a(lock->index == index);
  4502. }
  4503. }
  4504. goto func_exit;
  4505. }
  4506. if (!index);
  4507. else if (dict_index_is_clust(index)) {
  4508. trx_id_t trx_id;
  4509. trx_id_t* trx_desc;
  4510. /* Unlike the non-debug code, this invariant can only succeed
  4511. if the check and assertion are covered by the lock mutex. */
  4512. trx_id = lock_clust_rec_some_has_impl(rec, index, offsets);
  4513. trx_desc = trx_find_descriptor(trx_sys->descriptors,
  4514. trx_sys->descr_n_used,
  4515. trx_id);
  4516. ut_ad(lock_mutex_own());
  4517. /* trx_id cannot be committed until lock_mutex_exit()
  4518. because lock_trx_release_locks() acquires lock_sys->mutex */
  4519. if (trx_desc != NULL
  4520. && lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,
  4521. block, heap_no, trx_id)) {
  4522. ut_ad(trx_id == *trx_desc);
  4523. ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
  4524. block, heap_no, trx_id));
  4525. }
  4526. }
  4527. for (lock = lock_rec_get_first(block, heap_no);
  4528. lock != NULL;
  4529. lock = lock_rec_get_next_const(heap_no, lock)) {
  4530. ut_a(trx_in_trx_list(lock->trx));
  4531. if (index) {
  4532. ut_a(lock->index == index);
  4533. }
  4534. if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) {
  4535. enum lock_mode mode;
  4536. if (lock_get_mode(lock) == LOCK_S) {
  4537. mode = LOCK_X;
  4538. } else {
  4539. mode = LOCK_S;
  4540. }
  4541. ut_a(!lock_rec_other_has_expl_req(
  4542. mode, 0, 0, block, heap_no,
  4543. lock->trx->id));
  4544. } else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) {
  4545. ut_a(lock_rec_has_to_wait_in_queue(lock));
  4546. }
  4547. }
  4548. func_exit:
  4549. if (!locked_lock_trx_sys) {
  4550. lock_mutex_exit();
  4551. mutex_exit(&trx_sys->mutex);
  4552. }
  4553. return(TRUE);
  4554. }
  4555. /*********************************************************************//**
  4556. Validates the record lock queues on a page.
  4557. @return TRUE if ok */
  4558. static
  4559. ibool
  4560. lock_rec_validate_page(
  4561. /*===================*/
  4562. const buf_block_t* block) /*!< in: buffer block */
  4563. {
  4564. const lock_t* lock;
  4565. const rec_t* rec;
  4566. ulint nth_lock = 0;
  4567. ulint nth_bit = 0;
  4568. ulint i;
  4569. mem_heap_t* heap = NULL;
  4570. ulint offsets_[REC_OFFS_NORMAL_SIZE];
  4571. ulint* offsets = offsets_;
  4572. rec_offs_init(offsets_);
  4573. ut_ad(!lock_mutex_own());
  4574. lock_mutex_enter();
  4575. mutex_enter(&trx_sys->mutex);
  4576. loop:
  4577. lock = lock_rec_get_first_on_page_addr(buf_block_get_space(block),
  4578. buf_block_get_page_no(block));
  4579. if (!lock) {
  4580. goto function_exit;
  4581. }
  4582. #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
  4583. ut_a(!block->page.file_page_was_freed);
  4584. #endif
  4585. for (i = 0; i < nth_lock; i++) {
  4586. lock = lock_rec_get_next_on_page_const(lock);
  4587. if (!lock) {
  4588. goto function_exit;
  4589. }
  4590. }
  4591. ut_a(trx_in_trx_list(lock->trx));
  4592. # ifdef UNIV_SYNC_DEBUG
  4593. /* Only validate the record queues when this thread is not
  4594. holding a space->latch. Deadlocks are possible due to
  4595. latching order violation when UNIV_DEBUG is defined while
  4596. UNIV_SYNC_DEBUG is not. */
  4597. if (!sync_thread_levels_contains(SYNC_FSP))
  4598. # endif /* UNIV_SYNC_DEBUG */
  4599. for (i = nth_bit; i < lock_rec_get_n_bits(lock); i++) {
  4600. if (i == 1 || lock_rec_get_nth_bit(lock, i)) {
  4601. rec = page_find_rec_with_heap_no(block->frame, i);
  4602. ut_a(rec);
  4603. offsets = rec_get_offsets(rec, lock->index, offsets,
  4604. ULINT_UNDEFINED, &heap);
  4605. #if 0
  4606. fprintf(stderr,
  4607. "Validating %u %u\n",
  4608. block->page.space, block->page.offset);
  4609. #endif
  4610. /* If this thread is holding the file space
  4611. latch (fil_space_t::latch), the following
  4612. check WILL break the latching order and may
  4613. cause a deadlock of threads. */
  4614. lock_rec_queue_validate(
  4615. TRUE, block, rec, lock->index, offsets);
  4616. nth_bit = i + 1;
  4617. goto loop;
  4618. }
  4619. }
  4620. nth_bit = 0;
  4621. nth_lock++;
  4622. goto loop;
  4623. function_exit:
  4624. lock_mutex_exit();
  4625. mutex_exit(&trx_sys->mutex);
  4626. if (UNIV_LIKELY_NULL(heap)) {
  4627. mem_heap_free(heap);
  4628. }
  4629. return(TRUE);
  4630. }
  4631. /*********************************************************************//**
  4632. Validates the table locks.
  4633. @return TRUE if ok */
  4634. static
  4635. ibool
  4636. lock_validate_table_locks(
  4637. /*======================*/
  4638. const trx_list_t* trx_list) /*!< in: trx list */
  4639. {
  4640. const trx_t* trx;
  4641. ut_ad(lock_mutex_own());
  4642. ut_ad(mutex_own(&trx_sys->mutex));
  4643. ut_ad(trx_list == &trx_sys->rw_trx_list
  4644. || trx_list == &trx_sys->ro_trx_list);
  4645. for (trx = UT_LIST_GET_FIRST(*trx_list);
  4646. trx != NULL;
  4647. trx = UT_LIST_GET_NEXT(trx_list, trx)) {
  4648. const lock_t* lock;
  4649. assert_trx_in_list(trx);
  4650. ut_ad(trx->read_only == (trx_list == &trx_sys->ro_trx_list));
  4651. for (lock = UT_LIST_GET_FIRST(trx->lock.trx_locks);
  4652. lock != NULL;
  4653. lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
  4654. if (lock_get_type_low(lock) & LOCK_TABLE) {
  4655. lock_table_queue_validate(
  4656. lock->un_member.tab_lock.table);
  4657. }
  4658. }
  4659. }
  4660. return(TRUE);
  4661. }
  4662. /*********************************************************************//**
  4663. Validate record locks up to a limit.
  4664. @return lock at limit or NULL if no more locks in the hash bucket */
  4665. static __attribute__((nonnull, warn_unused_result))
  4666. const lock_t*
  4667. lock_rec_validate(
  4668. /*==============*/
  4669. ulint start, /*!< in: lock_sys->rec_hash
  4670. bucket */
  4671. ib_uint64_t* limit) /*!< in/out: upper limit of
  4672. (space, page_no) */
  4673. {
  4674. ut_ad(lock_mutex_own());
  4675. ut_ad(mutex_own(&trx_sys->mutex));
  4676. for (const lock_t* lock = static_cast<const lock_t*>(
  4677. HASH_GET_FIRST(lock_sys->rec_hash, start));
  4678. lock != NULL;
  4679. lock = static_cast<const lock_t*>(HASH_GET_NEXT(hash, lock))) {
  4680. ib_uint64_t current;
  4681. ut_a(trx_in_trx_list(lock->trx));
  4682. ut_a(lock_get_type(lock) == LOCK_REC);
  4683. current = ut_ull_create(
  4684. lock->un_member.rec_lock.space,
  4685. lock->un_member.rec_lock.page_no);
  4686. if (current > *limit) {
  4687. *limit = current + 1;
  4688. return(lock);
  4689. }
  4690. }
  4691. return(0);
  4692. }
  4693. /*********************************************************************//**
  4694. Validate a record lock's block */
  4695. static
  4696. void
  4697. lock_rec_block_validate(
  4698. /*====================*/
  4699. ulint space,
  4700. ulint page_no)
  4701. {
  4702. /* The lock and the block that it is referring to may be freed at
  4703. this point. We pass BUF_GET_POSSIBLY_FREED to skip a debug check.
  4704. If the lock exists in lock_rec_validate_page() we assert
  4705. !block->page.file_page_was_freed. */
  4706. buf_block_t* block;
  4707. mtr_t mtr;
  4708. /* Make sure that the tablespace is not deleted while we are
  4709. trying to access the page. */
  4710. if (!fil_inc_pending_ops(space)) {
  4711. mtr_start(&mtr);
  4712. block = buf_page_get_gen(
  4713. space, fil_space_get_zip_size(space),
  4714. page_no, RW_X_LATCH, NULL,
  4715. BUF_GET_POSSIBLY_FREED,
  4716. __FILE__, __LINE__, &mtr);
  4717. buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
  4718. ut_ad(lock_rec_validate_page(block));
  4719. mtr_commit(&mtr);
  4720. fil_decr_pending_ops(space);
  4721. }
  4722. }
  4723. /*********************************************************************//**
  4724. Validates the lock system.
  4725. @return TRUE if ok */
  4726. static
  4727. bool
  4728. lock_validate()
  4729. /*===========*/
  4730. {
  4731. typedef std::pair<ulint, ulint> page_addr_t;
  4732. typedef std::set<page_addr_t> page_addr_set;
  4733. page_addr_set pages;
  4734. lock_mutex_enter();
  4735. mutex_enter(&trx_sys->mutex);
  4736. ut_a(lock_validate_table_locks(&trx_sys->rw_trx_list));
  4737. ut_a(lock_validate_table_locks(&trx_sys->ro_trx_list));
  4738. /* Iterate over all the record locks and validate the locks. We
  4739. don't want to hog the lock_sys_t::mutex and the trx_sys_t::mutex.
  4740. Release both mutexes during the validation check. */
  4741. for (ulint i = 0; i < hash_get_n_cells(lock_sys->rec_hash); i++) {
  4742. const lock_t* lock;
  4743. ib_uint64_t limit = 0;
  4744. while ((lock = lock_rec_validate(i, &limit)) != 0) {
  4745. ulint space = lock->un_member.rec_lock.space;
  4746. ulint page_no = lock->un_member.rec_lock.page_no;
  4747. pages.insert(std::make_pair(space, page_no));
  4748. }
  4749. }
  4750. mutex_exit(&trx_sys->mutex);
  4751. lock_mutex_exit();
  4752. for (page_addr_set::const_iterator it = pages.begin();
  4753. it != pages.end();
  4754. ++it) {
  4755. lock_rec_block_validate((*it).first, (*it).second);
  4756. }
  4757. return(true);
  4758. }
  4759. #endif /* UNIV_DEBUG */
  4760. /*============ RECORD LOCK CHECKS FOR ROW OPERATIONS ====================*/
  4761. /*********************************************************************//**
  4762. Checks if locks of other transactions prevent an immediate insert of
  4763. a record. If they do, first tests if the query thread should anyway
  4764. be suspended for some reason; if not, then puts the transaction and
  4765. the query thread to the lock wait state and inserts a waiting request
  4766. for a gap x-lock to the lock queue.
  4767. @return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
  4768. UNIV_INTERN
  4769. dberr_t
  4770. lock_rec_insert_check_and_lock(
  4771. /*===========================*/
  4772. ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG bit is
  4773. set, does nothing */
  4774. const rec_t* rec, /*!< in: record after which to insert */
  4775. buf_block_t* block, /*!< in/out: buffer block of rec */
  4776. dict_index_t* index, /*!< in: index */
  4777. que_thr_t* thr, /*!< in: query thread */
  4778. mtr_t* mtr, /*!< in/out: mini-transaction */
  4779. ibool* inherit)/*!< out: set to TRUE if the new
  4780. inserted record maybe should inherit
  4781. LOCK_GAP type locks from the successor
  4782. record */
  4783. {
  4784. const rec_t* next_rec;
  4785. trx_t* trx;
  4786. lock_t* lock;
  4787. dberr_t err;
  4788. ulint next_rec_heap_no;
  4789. ut_ad(block->frame == page_align(rec));
  4790. ut_ad(!dict_index_is_online_ddl(index)
  4791. || dict_index_is_clust(index)
  4792. || (flags & BTR_CREATE_FLAG));
  4793. if (flags & BTR_NO_LOCKING_FLAG) {
  4794. return(DB_SUCCESS);
  4795. }
  4796. trx = thr_get_trx(thr);
  4797. if (UNIV_UNLIKELY(trx->fake_changes)) {
  4798. return(DB_SUCCESS);
  4799. }
  4800. next_rec = page_rec_get_next_const(rec);
  4801. next_rec_heap_no = page_rec_get_heap_no(next_rec);
  4802. lock_mutex_enter();
  4803. /* Because this code is invoked for a running transaction by
  4804. the thread that is serving the transaction, it is not necessary
  4805. to hold trx->mutex here. */
  4806. /* When inserting a record into an index, the table must be at
  4807. least IX-locked. When we are building an index, we would pass
  4808. BTR_NO_LOCKING_FLAG and skip the locking altogether. */
  4809. ut_ad(lock_table_has(trx, index->table, LOCK_IX));
  4810. lock = lock_rec_get_first(block, next_rec_heap_no);
  4811. if (UNIV_LIKELY(lock == NULL)) {
  4812. /* We optimize CPU time usage in the simplest case */
  4813. lock_mutex_exit();
  4814. if (!dict_index_is_clust(index)) {
  4815. /* Update the page max trx id field */
  4816. page_update_max_trx_id(block,
  4817. buf_block_get_page_zip(block),
  4818. trx->id, mtr);
  4819. }
  4820. *inherit = FALSE;
  4821. return(DB_SUCCESS);
  4822. }
  4823. *inherit = TRUE;
  4824. /* If another transaction has an explicit lock request which locks
  4825. the gap, waiting or granted, on the successor, the insert has to wait.
  4826. An exception is the case where the lock by the another transaction
  4827. is a gap type lock which it placed to wait for its turn to insert. We
  4828. do not consider that kind of a lock conflicting with our insert. This
  4829. eliminates an unnecessary deadlock which resulted when 2 transactions
  4830. had to wait for their insert. Both had waiting gap type lock requests
  4831. on the successor, which produced an unnecessary deadlock. */
  4832. if (lock_rec_other_has_conflicting(
  4833. static_cast<enum lock_mode>(
  4834. LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION),
  4835. block, next_rec_heap_no, trx)) {
  4836. /* Note that we may get DB_SUCCESS also here! */
  4837. trx_mutex_enter(trx);
  4838. err = lock_rec_enqueue_waiting(
  4839. LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,
  4840. block, next_rec_heap_no, index, thr);
  4841. trx_mutex_exit(trx);
  4842. } else {
  4843. err = DB_SUCCESS;
  4844. }
  4845. lock_mutex_exit();
  4846. switch (err) {
  4847. case DB_SUCCESS_LOCKED_REC:
  4848. err = DB_SUCCESS;
  4849. /* fall through */
  4850. case DB_SUCCESS:
  4851. if (dict_index_is_clust(index)) {
  4852. break;
  4853. }
  4854. /* Update the page max trx id field */
  4855. page_update_max_trx_id(block,
  4856. buf_block_get_page_zip(block),
  4857. trx->id, mtr);
  4858. default:
  4859. /* We only care about the two return values. */
  4860. break;
  4861. }
  4862. #ifdef UNIV_DEBUG
  4863. {
  4864. mem_heap_t* heap = NULL;
  4865. ulint offsets_[REC_OFFS_NORMAL_SIZE];
  4866. const ulint* offsets;
  4867. rec_offs_init(offsets_);
  4868. offsets = rec_get_offsets(next_rec, index, offsets_,
  4869. ULINT_UNDEFINED, &heap);
  4870. ut_ad(lock_rec_queue_validate(
  4871. FALSE, block, next_rec, index, offsets));
  4872. if (UNIV_LIKELY_NULL(heap)) {
  4873. mem_heap_free(heap);
  4874. }
  4875. }
  4876. #endif /* UNIV_DEBUG */
  4877. return(err);
  4878. }
  4879. /*********************************************************************//**
  4880. If a transaction has an implicit x-lock on a record, but no explicit x-lock
  4881. set on the record, sets one for it. */
  4882. static
  4883. void
  4884. lock_rec_convert_impl_to_expl(
  4885. /*==========================*/
  4886. const buf_block_t* block, /*!< in: buffer block of rec */
  4887. const rec_t* rec, /*!< in: user record on page */
  4888. dict_index_t* index, /*!< in: index of record */
  4889. const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
  4890. {
  4891. trx_id_t trx_id;
  4892. ut_ad(!lock_mutex_own());
  4893. ut_ad(page_rec_is_user_rec(rec));
  4894. ut_ad(rec_offs_validate(rec, index, offsets));
  4895. ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
  4896. if (dict_index_is_clust(index)) {
  4897. trx_id = lock_clust_rec_some_has_impl(rec, index, offsets);
  4898. /* The clustered index record was last modified by
  4899. this transaction. The transaction may have been
  4900. committed a long time ago. */
  4901. } else {
  4902. ut_ad(!dict_index_is_online_ddl(index));
  4903. trx_id = lock_sec_rec_some_has_impl(rec, index, offsets);
  4904. /* The transaction can be committed before the
  4905. trx_is_active(trx_id, NULL) check below, because we are not
  4906. holding lock_mutex. */
  4907. ut_ad(!lock_rec_other_trx_holds_expl(LOCK_S | LOCK_REC_NOT_GAP,
  4908. trx_id, rec, block));
  4909. }
  4910. if (trx_id != 0) {
  4911. trx_id_t* impl_trx_desc;
  4912. ulint heap_no = page_rec_get_heap_no(rec);
  4913. lock_mutex_enter();
  4914. /* If the transaction is still active and has no
  4915. explicit x-lock set on the record, set one for it */
  4916. mutex_enter(&trx_sys->mutex);
  4917. impl_trx_desc = trx_find_descriptor(trx_sys->descriptors,
  4918. trx_sys->descr_n_used,
  4919. trx_id);
  4920. mutex_exit(&trx_sys->mutex);
  4921. /* trx_id cannot be committed until lock_mutex_exit()
  4922. because lock_trx_release_locks() acquires lock_sys->mutex */
  4923. if (impl_trx_desc != NULL
  4924. && !lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, block,
  4925. heap_no, trx_id)) {
  4926. ulint type_mode = (LOCK_REC | LOCK_X
  4927. | LOCK_REC_NOT_GAP);
  4928. mutex_enter(&trx_sys->mutex);
  4929. trx_t* impl_trx = trx_rw_get_active_trx_by_id(trx_id,
  4930. NULL);
  4931. mutex_exit(&trx_sys->mutex);
  4932. ut_ad(impl_trx != NULL);
  4933. lock_rec_add_to_queue(
  4934. type_mode, block, heap_no, index,
  4935. impl_trx, FALSE);
  4936. }
  4937. lock_mutex_exit();
  4938. }
  4939. }
  4940. /*********************************************************************//**
  4941. Checks if locks of other transactions prevent an immediate modify (update,
  4942. delete mark, or delete unmark) of a clustered index record. If they do,
  4943. first tests if the query thread should anyway be suspended for some
  4944. reason; if not, then puts the transaction and the query thread to the
  4945. lock wait state and inserts a waiting request for a record x-lock to the
  4946. lock queue.
  4947. @return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
  4948. UNIV_INTERN
  4949. dberr_t
  4950. lock_clust_rec_modify_check_and_lock(
  4951. /*=================================*/
  4952. ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
  4953. bit is set, does nothing */
  4954. const buf_block_t* block, /*!< in: buffer block of rec */
  4955. const rec_t* rec, /*!< in: record which should be
  4956. modified */
  4957. dict_index_t* index, /*!< in: clustered index */
  4958. const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
  4959. que_thr_t* thr) /*!< in: query thread */
  4960. {
  4961. dberr_t err;
  4962. ulint heap_no;
  4963. ut_ad(rec_offs_validate(rec, index, offsets));
  4964. ut_ad(dict_index_is_clust(index));
  4965. ut_ad(block->frame == page_align(rec));
  4966. if (flags & BTR_NO_LOCKING_FLAG) {
  4967. return(DB_SUCCESS);
  4968. }
  4969. if (UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes)) {
  4970. return(DB_SUCCESS);
  4971. }
  4972. heap_no = rec_offs_comp(offsets)
  4973. ? rec_get_heap_no_new(rec)
  4974. : rec_get_heap_no_old(rec);
  4975. /* If a transaction has no explicit x-lock set on the record, set one
  4976. for it */
  4977. lock_rec_convert_impl_to_expl(block, rec, index, offsets);
  4978. lock_mutex_enter();
  4979. ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
  4980. err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP,
  4981. block, heap_no, index, thr);
  4982. MONITOR_INC(MONITOR_NUM_RECLOCK_REQ);
  4983. lock_mutex_exit();
  4984. ut_ad(lock_rec_queue_validate(FALSE, block, rec, index, offsets));
  4985. if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) {
  4986. err = DB_SUCCESS;
  4987. }
  4988. return(err);
  4989. }
  4990. /*********************************************************************//**
  4991. Checks if locks of other transactions prevent an immediate modify (delete
  4992. mark or delete unmark) of a secondary index record.
  4993. @return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
  4994. UNIV_INTERN
  4995. dberr_t
  4996. lock_sec_rec_modify_check_and_lock(
  4997. /*===============================*/
  4998. ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
  4999. bit is set, does nothing */
  5000. buf_block_t* block, /*!< in/out: buffer block of rec */
  5001. const rec_t* rec, /*!< in: record which should be
  5002. modified; NOTE: as this is a secondary
  5003. index, we always have to modify the
  5004. clustered index record first: see the
  5005. comment below */
  5006. dict_index_t* index, /*!< in: secondary index */
  5007. que_thr_t* thr, /*!< in: query thread
  5008. (can be NULL if BTR_NO_LOCKING_FLAG) */
  5009. mtr_t* mtr) /*!< in/out: mini-transaction */
  5010. {
  5011. dberr_t err;
  5012. ulint heap_no;
  5013. ut_ad(!dict_index_is_clust(index));
  5014. ut_ad(!dict_index_is_online_ddl(index) || (flags & BTR_CREATE_FLAG));
  5015. ut_ad(block->frame == page_align(rec));
  5016. if (flags & BTR_NO_LOCKING_FLAG) {
  5017. return(DB_SUCCESS);
  5018. }
  5019. if (UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes)) {
  5020. return(DB_SUCCESS);
  5021. }
  5022. heap_no = page_rec_get_heap_no(rec);
  5023. /* Another transaction cannot have an implicit lock on the record,
  5024. because when we come here, we already have modified the clustered
  5025. index record, and this would not have been possible if another active
  5026. transaction had modified this secondary index record. */
  5027. lock_mutex_enter();
  5028. ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
  5029. err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP,
  5030. block, heap_no, index, thr);
  5031. MONITOR_INC(MONITOR_NUM_RECLOCK_REQ);
  5032. lock_mutex_exit();
  5033. #ifdef UNIV_DEBUG
  5034. {
  5035. mem_heap_t* heap = NULL;
  5036. ulint offsets_[REC_OFFS_NORMAL_SIZE];
  5037. const ulint* offsets;
  5038. rec_offs_init(offsets_);
  5039. offsets = rec_get_offsets(rec, index, offsets_,
  5040. ULINT_UNDEFINED, &heap);
  5041. ut_ad(lock_rec_queue_validate(
  5042. FALSE, block, rec, index, offsets));
  5043. if (UNIV_LIKELY_NULL(heap)) {
  5044. mem_heap_free(heap);
  5045. }
  5046. }
  5047. #endif /* UNIV_DEBUG */
  5048. if (err == DB_SUCCESS || err == DB_SUCCESS_LOCKED_REC) {
  5049. /* Update the page max trx id field */
  5050. /* It might not be necessary to do this if
  5051. err == DB_SUCCESS (no new lock created),
  5052. but it should not cost too much performance. */
  5053. page_update_max_trx_id(block,
  5054. buf_block_get_page_zip(block),
  5055. thr_get_trx(thr)->id, mtr);
  5056. err = DB_SUCCESS;
  5057. }
  5058. return(err);
  5059. }
  5060. /*********************************************************************//**
  5061. Like lock_clust_rec_read_check_and_lock(), but reads a
  5062. secondary index record.
  5063. @return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
  5064. or DB_QUE_THR_SUSPENDED */
  5065. UNIV_INTERN
  5066. dberr_t
  5067. lock_sec_rec_read_check_and_lock(
  5068. /*=============================*/
  5069. ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
  5070. bit is set, does nothing */
  5071. const buf_block_t* block, /*!< in: buffer block of rec */
  5072. const rec_t* rec, /*!< in: user record or page
  5073. supremum record which should
  5074. be read or passed over by a
  5075. read cursor */
  5076. dict_index_t* index, /*!< in: secondary index */
  5077. const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
  5078. enum lock_mode mode, /*!< in: mode of the lock which
  5079. the read cursor should set on
  5080. records: LOCK_S or LOCK_X; the
  5081. latter is possible in
  5082. SELECT FOR UPDATE */
  5083. ulint gap_mode,/*!< in: LOCK_ORDINARY, LOCK_GAP, or
  5084. LOCK_REC_NOT_GAP */
  5085. que_thr_t* thr) /*!< in: query thread */
  5086. {
  5087. dberr_t err;
  5088. ulint heap_no;
  5089. ut_ad(!dict_index_is_clust(index));
  5090. ut_ad(!dict_index_is_online_ddl(index));
  5091. ut_ad(block->frame == page_align(rec));
  5092. ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
  5093. ut_ad(rec_offs_validate(rec, index, offsets));
  5094. ut_ad(mode == LOCK_X || mode == LOCK_S);
  5095. if (flags & BTR_NO_LOCKING_FLAG) {
  5096. return(DB_SUCCESS);
  5097. }
  5098. if (UNIV_UNLIKELY((thr && thr_get_trx(thr)->fake_changes))) {
  5099. if (!srv_fake_changes_locks) {
  5100. return(DB_SUCCESS);
  5101. }
  5102. if (mode == LOCK_X) {
  5103. mode = LOCK_S;
  5104. }
  5105. }
  5106. heap_no = page_rec_get_heap_no(rec);
  5107. /* Some transaction may have an implicit x-lock on the record only
  5108. if the max trx id for the page >= min trx id for the trx list or a
  5109. database recovery is running. */
  5110. if ((page_get_max_trx_id(block->frame) >= trx_rw_min_trx_id()
  5111. || recv_recovery_is_on())
  5112. && !page_rec_is_supremum(rec)) {
  5113. lock_rec_convert_impl_to_expl(block, rec, index, offsets);
  5114. }
  5115. lock_mutex_enter();
  5116. ut_ad(mode != LOCK_X
  5117. || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
  5118. ut_ad(mode != LOCK_S
  5119. || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
  5120. err = lock_rec_lock(FALSE, mode | gap_mode,
  5121. block, heap_no, index, thr);
  5122. MONITOR_INC(MONITOR_NUM_RECLOCK_REQ);
  5123. lock_mutex_exit();
  5124. ut_ad(lock_rec_queue_validate(FALSE, block, rec, index, offsets));
  5125. return(err);
  5126. }
  5127. /*********************************************************************//**
  5128. Checks if locks of other transactions prevent an immediate read, or passing
  5129. over by a read cursor, of a clustered index record. If they do, first tests
  5130. if the query thread should anyway be suspended for some reason; if not, then
  5131. puts the transaction and the query thread to the lock wait state and inserts a
  5132. waiting request for a record lock to the lock queue. Sets the requested mode
  5133. lock on the record.
  5134. @return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
  5135. or DB_QUE_THR_SUSPENDED */
  5136. UNIV_INTERN
  5137. dberr_t
  5138. lock_clust_rec_read_check_and_lock(
  5139. /*===============================*/
  5140. ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
  5141. bit is set, does nothing */
  5142. const buf_block_t* block, /*!< in: buffer block of rec */
  5143. const rec_t* rec, /*!< in: user record or page
  5144. supremum record which should
  5145. be read or passed over by a
  5146. read cursor */
  5147. dict_index_t* index, /*!< in: clustered index */
  5148. const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
  5149. enum lock_mode mode, /*!< in: mode of the lock which
  5150. the read cursor should set on
  5151. records: LOCK_S or LOCK_X; the
  5152. latter is possible in
  5153. SELECT FOR UPDATE */
  5154. ulint gap_mode,/*!< in: LOCK_ORDINARY, LOCK_GAP, or
  5155. LOCK_REC_NOT_GAP */
  5156. que_thr_t* thr) /*!< in: query thread */
  5157. {
  5158. dberr_t err;
  5159. ulint heap_no;
  5160. ut_ad(dict_index_is_clust(index));
  5161. ut_ad(block->frame == page_align(rec));
  5162. ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
  5163. ut_ad(gap_mode == LOCK_ORDINARY || gap_mode == LOCK_GAP
  5164. || gap_mode == LOCK_REC_NOT_GAP);
  5165. ut_ad(rec_offs_validate(rec, index, offsets));
  5166. if (flags & BTR_NO_LOCKING_FLAG) {
  5167. return(DB_SUCCESS);
  5168. }
  5169. if (UNIV_UNLIKELY((thr && thr_get_trx(thr)->fake_changes))) {
  5170. if (!srv_fake_changes_locks) {
  5171. return(DB_SUCCESS);
  5172. }
  5173. if (mode == LOCK_X) {
  5174. mode = LOCK_S;
  5175. }
  5176. }
  5177. heap_no = page_rec_get_heap_no(rec);
  5178. if (UNIV_LIKELY(heap_no != PAGE_HEAP_NO_SUPREMUM)) {
  5179. lock_rec_convert_impl_to_expl(block, rec, index, offsets);
  5180. }
  5181. lock_mutex_enter();
  5182. ut_ad(mode != LOCK_X
  5183. || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
  5184. ut_ad(mode != LOCK_S
  5185. || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
  5186. err = lock_rec_lock(FALSE, mode | gap_mode,
  5187. block, heap_no, index, thr);
  5188. MONITOR_INC(MONITOR_NUM_RECLOCK_REQ);
  5189. lock_mutex_exit();
  5190. ut_ad(lock_rec_queue_validate(FALSE, block, rec, index, offsets));
  5191. return(err);
  5192. }
  5193. /*********************************************************************//**
  5194. Checks if locks of other transactions prevent an immediate read, or passing
  5195. over by a read cursor, of a clustered index record. If they do, first tests
  5196. if the query thread should anyway be suspended for some reason; if not, then
  5197. puts the transaction and the query thread to the lock wait state and inserts a
  5198. waiting request for a record lock to the lock queue. Sets the requested mode
  5199. lock on the record. This is an alternative version of
  5200. lock_clust_rec_read_check_and_lock() that does not require the parameter
  5201. "offsets".
  5202. @return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
  5203. UNIV_INTERN
  5204. dberr_t
  5205. lock_clust_rec_read_check_and_lock_alt(
  5206. /*===================================*/
  5207. ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
  5208. bit is set, does nothing */
  5209. const buf_block_t* block, /*!< in: buffer block of rec */
  5210. const rec_t* rec, /*!< in: user record or page
  5211. supremum record which should
  5212. be read or passed over by a
  5213. read cursor */
  5214. dict_index_t* index, /*!< in: clustered index */
  5215. enum lock_mode mode, /*!< in: mode of the lock which
  5216. the read cursor should set on
  5217. records: LOCK_S or LOCK_X; the
  5218. latter is possible in
  5219. SELECT FOR UPDATE */
  5220. ulint gap_mode,/*!< in: LOCK_ORDINARY, LOCK_GAP, or
  5221. LOCK_REC_NOT_GAP */
  5222. que_thr_t* thr) /*!< in: query thread */
  5223. {
  5224. mem_heap_t* tmp_heap = NULL;
  5225. ulint offsets_[REC_OFFS_NORMAL_SIZE];
  5226. ulint* offsets = offsets_;
  5227. dberr_t err;
  5228. rec_offs_init(offsets_);
  5229. offsets = rec_get_offsets(rec, index, offsets,
  5230. ULINT_UNDEFINED, &tmp_heap);
  5231. err = lock_clust_rec_read_check_and_lock(flags, block, rec, index,
  5232. offsets, mode, gap_mode, thr);
  5233. if (tmp_heap) {
  5234. mem_heap_free(tmp_heap);
  5235. }
  5236. if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) {
  5237. err = DB_SUCCESS;
  5238. }
  5239. return(err);
  5240. }
  5241. /*******************************************************************//**
  5242. Release the last lock from the transaction's autoinc locks. */
  5243. UNIV_INLINE
  5244. void
  5245. lock_release_autoinc_last_lock(
  5246. /*===========================*/
  5247. ib_vector_t* autoinc_locks) /*!< in/out: vector of AUTOINC locks */
  5248. {
  5249. ulint last;
  5250. lock_t* lock;
  5251. ut_ad(lock_mutex_own());
  5252. ut_a(!ib_vector_is_empty(autoinc_locks));
  5253. /* The lock to be release must be the last lock acquired. */
  5254. last = ib_vector_size(autoinc_locks) - 1;
  5255. lock = *static_cast<lock_t**>(ib_vector_get(autoinc_locks, last));
  5256. /* Should have only AUTOINC locks in the vector. */
  5257. ut_a(lock_get_mode(lock) == LOCK_AUTO_INC);
  5258. ut_a(lock_get_type(lock) == LOCK_TABLE);
  5259. ut_a(lock->un_member.tab_lock.table != NULL);
  5260. /* This will remove the lock from the trx autoinc_locks too. */
  5261. lock_table_dequeue(lock);
  5262. /* Remove from the table vector too. */
  5263. lock_trx_table_locks_remove(lock);
  5264. }
  5265. /*******************************************************************//**
  5266. Check if a transaction holds any autoinc locks.
  5267. @return TRUE if the transaction holds any AUTOINC locks. */
  5268. static
  5269. ibool
  5270. lock_trx_holds_autoinc_locks(
  5271. /*=========================*/
  5272. const trx_t* trx) /*!< in: transaction */
  5273. {
  5274. ut_a(trx->autoinc_locks != NULL);
  5275. return(!ib_vector_is_empty(trx->autoinc_locks));
  5276. }
  5277. /*******************************************************************//**
  5278. Release all the transaction's autoinc locks. */
  5279. static
  5280. void
  5281. lock_release_autoinc_locks(
  5282. /*=======================*/
  5283. trx_t* trx) /*!< in/out: transaction */
  5284. {
  5285. ut_ad(lock_mutex_own());
  5286. /* If this is invoked for a running transaction by the thread
  5287. that is serving the transaction, then it is not necessary to
  5288. hold trx->mutex here. */
  5289. ut_a(trx->autoinc_locks != NULL);
  5290. /* We release the locks in the reverse order. This is to
  5291. avoid searching the vector for the element to delete at
  5292. the lower level. See (lock_table_remove_low()) for details. */
  5293. while (!ib_vector_is_empty(trx->autoinc_locks)) {
  5294. /* lock_table_remove_low() will also remove the lock from
  5295. the transaction's autoinc_locks vector. */
  5296. lock_release_autoinc_last_lock(trx->autoinc_locks);
  5297. }
  5298. /* Should release all locks. */
  5299. ut_a(ib_vector_is_empty(trx->autoinc_locks));
  5300. }
  5301. /*******************************************************************//**
  5302. Gets the type of a lock. Non-inline version for using outside of the
  5303. lock module.
  5304. @return LOCK_TABLE or LOCK_REC */
  5305. UNIV_INTERN
  5306. ulint
  5307. lock_get_type(
  5308. /*==========*/
  5309. const lock_t* lock) /*!< in: lock */
  5310. {
  5311. return(lock_get_type_low(lock));
  5312. }
  5313. /*******************************************************************//**
  5314. Gets the id of the transaction owning a lock.
  5315. @return transaction id */
  5316. UNIV_INTERN
  5317. trx_id_t
  5318. lock_get_trx_id(
  5319. /*============*/
  5320. const lock_t* lock) /*!< in: lock */
  5321. {
  5322. return(lock->trx->id);
  5323. }
  5324. /*******************************************************************//**
  5325. Gets the mode of a lock in a human readable string.
  5326. The string should not be free()'d or modified.
  5327. @return lock mode */
  5328. UNIV_INTERN
  5329. const char*
  5330. lock_get_mode_str(
  5331. /*==============*/
  5332. const lock_t* lock) /*!< in: lock */
  5333. {
  5334. ibool is_gap_lock;
  5335. is_gap_lock = lock_get_type_low(lock) == LOCK_REC
  5336. && lock_rec_get_gap(lock);
  5337. switch (lock_get_mode(lock)) {
  5338. case LOCK_S:
  5339. if (is_gap_lock) {
  5340. return("S,GAP");
  5341. } else {
  5342. return("S");
  5343. }
  5344. case LOCK_X:
  5345. if (is_gap_lock) {
  5346. return("X,GAP");
  5347. } else {
  5348. return("X");
  5349. }
  5350. case LOCK_IS:
  5351. if (is_gap_lock) {
  5352. return("IS,GAP");
  5353. } else {
  5354. return("IS");
  5355. }
  5356. case LOCK_IX:
  5357. if (is_gap_lock) {
  5358. return("IX,GAP");
  5359. } else {
  5360. return("IX");
  5361. }
  5362. case LOCK_AUTO_INC:
  5363. return("AUTO_INC");
  5364. default:
  5365. return("UNKNOWN");
  5366. }
  5367. }
  5368. /*******************************************************************//**
  5369. Gets the type of a lock in a human readable string.
  5370. The string should not be free()'d or modified.
  5371. @return lock type */
  5372. UNIV_INTERN
  5373. const char*
  5374. lock_get_type_str(
  5375. /*==============*/
  5376. const lock_t* lock) /*!< in: lock */
  5377. {
  5378. switch (lock_get_type_low(lock)) {
  5379. case LOCK_REC:
  5380. return("RECORD");
  5381. case LOCK_TABLE:
  5382. return("TABLE");
  5383. default:
  5384. return("UNKNOWN");
  5385. }
  5386. }
  5387. /*******************************************************************//**
  5388. Gets the table on which the lock is.
  5389. @return table */
  5390. UNIV_INLINE
  5391. dict_table_t*
  5392. lock_get_table(
  5393. /*===========*/
  5394. const lock_t* lock) /*!< in: lock */
  5395. {
  5396. switch (lock_get_type_low(lock)) {
  5397. case LOCK_REC:
  5398. ut_ad(dict_index_is_clust(lock->index)
  5399. || !dict_index_is_online_ddl(lock->index));
  5400. return(lock->index->table);
  5401. case LOCK_TABLE:
  5402. return(lock->un_member.tab_lock.table);
  5403. default:
  5404. ut_error;
  5405. return(NULL);
  5406. }
  5407. }
  5408. /*******************************************************************//**
  5409. Gets the id of the table on which the lock is.
  5410. @return id of the table */
  5411. UNIV_INTERN
  5412. table_id_t
  5413. lock_get_table_id(
  5414. /*==============*/
  5415. const lock_t* lock) /*!< in: lock */
  5416. {
  5417. dict_table_t* table;
  5418. table = lock_get_table(lock);
  5419. return(table->id);
  5420. }
  5421. /*******************************************************************//**
  5422. Gets the name of the table on which the lock is.
  5423. The string should not be free()'d or modified.
  5424. @return name of the table */
  5425. UNIV_INTERN
  5426. const char*
  5427. lock_get_table_name(
  5428. /*================*/
  5429. const lock_t* lock) /*!< in: lock */
  5430. {
  5431. dict_table_t* table;
  5432. table = lock_get_table(lock);
  5433. return(table->name);
  5434. }
  5435. /*******************************************************************//**
  5436. For a record lock, gets the index on which the lock is.
  5437. @return index */
  5438. UNIV_INTERN
  5439. const dict_index_t*
  5440. lock_rec_get_index(
  5441. /*===============*/
  5442. const lock_t* lock) /*!< in: lock */
  5443. {
  5444. ut_a(lock_get_type_low(lock) == LOCK_REC);
  5445. ut_ad(dict_index_is_clust(lock->index)
  5446. || !dict_index_is_online_ddl(lock->index));
  5447. return(lock->index);
  5448. }
  5449. /*******************************************************************//**
  5450. For a record lock, gets the name of the index on which the lock is.
  5451. The string should not be free()'d or modified.
  5452. @return name of the index */
  5453. UNIV_INTERN
  5454. const char*
  5455. lock_rec_get_index_name(
  5456. /*====================*/
  5457. const lock_t* lock) /*!< in: lock */
  5458. {
  5459. ut_a(lock_get_type_low(lock) == LOCK_REC);
  5460. ut_ad(dict_index_is_clust(lock->index)
  5461. || !dict_index_is_online_ddl(lock->index));
  5462. return(lock->index->name);
  5463. }
  5464. /*******************************************************************//**
  5465. For a record lock, gets the tablespace number on which the lock is.
  5466. @return tablespace number */
  5467. UNIV_INTERN
  5468. ulint
  5469. lock_rec_get_space_id(
  5470. /*==================*/
  5471. const lock_t* lock) /*!< in: lock */
  5472. {
  5473. ut_a(lock_get_type_low(lock) == LOCK_REC);
  5474. return(lock->un_member.rec_lock.space);
  5475. }
  5476. /*******************************************************************//**
  5477. For a record lock, gets the page number on which the lock is.
  5478. @return page number */
  5479. UNIV_INTERN
  5480. ulint
  5481. lock_rec_get_page_no(
  5482. /*=================*/
  5483. const lock_t* lock) /*!< in: lock */
  5484. {
  5485. ut_a(lock_get_type_low(lock) == LOCK_REC);
  5486. return(lock->un_member.rec_lock.page_no);
  5487. }
  5488. /*********************************************************************//**
  5489. Cancels a waiting lock request and releases possible other transactions
  5490. waiting behind it. */
  5491. UNIV_INTERN
  5492. void
  5493. lock_cancel_waiting_and_release(
  5494. /*============================*/
  5495. lock_t* lock) /*!< in/out: waiting lock request */
  5496. {
  5497. que_thr_t* thr;
  5498. ut_ad(lock_mutex_own());
  5499. ut_ad(trx_mutex_own(lock->trx));
  5500. lock->trx->lock.cancel = TRUE;
  5501. if (lock_get_type_low(lock) == LOCK_REC) {
  5502. lock_rec_dequeue_from_page(lock);
  5503. } else {
  5504. ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
  5505. if (lock->trx->autoinc_locks != NULL) {
  5506. /* Release the transaction's AUTOINC locks. */
  5507. lock_release_autoinc_locks(lock->trx);
  5508. }
  5509. lock_table_dequeue(lock);
  5510. }
  5511. /* Reset the wait flag and the back pointer to lock in trx. */
  5512. lock_reset_lock_and_trx_wait(lock);
  5513. /* The following function releases the trx from lock wait. */
  5514. thr = que_thr_end_lock_wait(lock->trx);
  5515. if (thr != NULL) {
  5516. lock_wait_release_thread_if_suspended(thr);
  5517. }
  5518. lock->trx->lock.cancel = FALSE;
  5519. }
  5520. /*********************************************************************//**
  5521. Unlocks AUTO_INC type locks that were possibly reserved by a trx. This
  5522. function should be called at the the end of an SQL statement, by the
  5523. connection thread that owns the transaction (trx->mysql_thd). */
  5524. UNIV_INTERN
  5525. void
  5526. lock_unlock_table_autoinc(
  5527. /*======================*/
  5528. trx_t* trx) /*!< in/out: transaction */
  5529. {
  5530. ut_ad(!lock_mutex_own());
  5531. ut_ad(!trx_mutex_own(trx));
  5532. ut_ad(!trx->lock.wait_lock);
  5533. /* This can be invoked on NOT_STARTED, ACTIVE, PREPARED,
  5534. but not COMMITTED transactions. */
  5535. ut_ad(trx_state_eq(trx, TRX_STATE_NOT_STARTED)
  5536. || !trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY));
  5537. /* This function is invoked for a running transaction by the
  5538. thread that is serving the transaction. Therefore it is not
  5539. necessary to hold trx->mutex here. */
  5540. if (lock_trx_holds_autoinc_locks(trx)) {
  5541. lock_mutex_enter();
  5542. lock_release_autoinc_locks(trx);
  5543. lock_mutex_exit();
  5544. }
  5545. }
  5546. /*********************************************************************//**
  5547. Releases a transaction's locks, and releases possible other transactions
  5548. waiting because of these locks. Change the state of the transaction to
  5549. TRX_STATE_COMMITTED_IN_MEMORY. */
  5550. UNIV_INTERN
  5551. void
  5552. lock_trx_release_locks(
  5553. /*===================*/
  5554. trx_t* trx) /*!< in/out: transaction */
  5555. {
  5556. assert_trx_in_list(trx);
  5557. if (trx_state_eq(trx, TRX_STATE_PREPARED)) {
  5558. mutex_enter(&trx_sys->mutex);
  5559. ut_a(trx_sys->n_prepared_trx > 0);
  5560. trx_sys->n_prepared_trx--;
  5561. if (trx->is_recovered) {
  5562. ut_a(trx_sys->n_prepared_recovered_trx > 0);
  5563. trx_sys->n_prepared_recovered_trx--;
  5564. }
  5565. mutex_exit(&trx_sys->mutex);
  5566. } else {
  5567. ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
  5568. }
  5569. /* The transition of trx->state to TRX_STATE_COMMITTED_IN_MEMORY
  5570. is protected by both the lock_sys->mutex and the trx->mutex.
  5571. We also lock trx_sys->mutex, because state transition to
  5572. TRX_STATE_COMMITTED_IN_MEMORY must be atomic with removing trx
  5573. from the descriptors array. */
  5574. lock_mutex_enter();
  5575. mutex_enter(&trx_sys->mutex);
  5576. trx_mutex_enter(trx);
  5577. /* The following assignment makes the transaction committed in memory
  5578. and makes its changes to data visible to other transactions.
  5579. NOTE that there is a small discrepancy from the strict formal
  5580. visibility rules here: a human user of the database can see
  5581. modifications made by another transaction T even before the necessary
  5582. log segment has been flushed to the disk. If the database happens to
  5583. crash before the flush, the user has seen modifications from T which
  5584. will never be a committed transaction. However, any transaction T2
  5585. which sees the modifications of the committing transaction T, and
  5586. which also itself makes modifications to the database, will get an lsn
  5587. larger than the committing transaction T. In the case where the log
  5588. flush fails, and T never gets committed, also T2 will never get
  5589. committed. */
  5590. /*--------------------------------------*/
  5591. trx->state = TRX_STATE_COMMITTED_IN_MEMORY;
  5592. /* The following also removes trx from trx_serial_list */
  5593. trx_release_descriptor(trx);
  5594. /*--------------------------------------*/
  5595. /* If the background thread trx_rollback_or_clean_recovered()
  5596. is still active then there is a chance that the rollback
  5597. thread may see this trx as COMMITTED_IN_MEMORY and goes ahead
  5598. to clean it up calling trx_cleanup_at_db_startup(). This can
  5599. happen in the case we are committing a trx here that is left
  5600. in PREPARED state during the crash. Note that commit of the
  5601. rollback of a PREPARED trx happens in the recovery thread
  5602. while the rollback of other transactions happen in the
  5603. background thread. To avoid this race we unconditionally unset
  5604. the is_recovered flag. */
  5605. trx->is_recovered = FALSE;
  5606. trx_mutex_exit(trx);
  5607. mutex_exit(&trx_sys->mutex);
  5608. lock_release(trx);
  5609. lock_mutex_exit();
  5610. }
  5611. /*********************************************************************//**
  5612. Check whether the transaction has already been rolled back because it
  5613. was selected as a deadlock victim, or if it has to wait then cancel
  5614. the wait lock.
  5615. @return DB_DEADLOCK, DB_LOCK_WAIT or DB_SUCCESS */
  5616. UNIV_INTERN
  5617. dberr_t
  5618. lock_trx_handle_wait(
  5619. /*=================*/
  5620. trx_t* trx) /*!< in/out: trx lock state */
  5621. {
  5622. dberr_t err;
  5623. lock_mutex_enter();
  5624. trx_mutex_enter(trx);
  5625. if (trx->lock.was_chosen_as_deadlock_victim) {
  5626. err = DB_DEADLOCK;
  5627. } else if (trx->lock.wait_lock != NULL) {
  5628. lock_cancel_waiting_and_release(trx->lock.wait_lock);
  5629. err = DB_LOCK_WAIT;
  5630. } else {
  5631. /* The lock was probably granted before we got here. */
  5632. err = DB_SUCCESS;
  5633. }
  5634. lock_mutex_exit();
  5635. trx_mutex_exit(trx);
  5636. return(err);
  5637. }
  5638. /*********************************************************************//**
  5639. Get the number of locks on a table.
  5640. @return number of locks */
  5641. UNIV_INTERN
  5642. ulint
  5643. lock_table_get_n_locks(
  5644. /*===================*/
  5645. const dict_table_t* table) /*!< in: table */
  5646. {
  5647. ulint n_table_locks;
  5648. lock_mutex_enter();
  5649. n_table_locks = UT_LIST_GET_LEN(table->locks);
  5650. lock_mutex_exit();
  5651. return(n_table_locks);
  5652. }
  5653. #ifdef UNIV_DEBUG
  5654. /*******************************************************************//**
  5655. Do an exhaustive check for any locks (table or rec) against the table.
  5656. @return lock if found */
  5657. static
  5658. const lock_t*
  5659. lock_table_locks_lookup(
  5660. /*====================*/
  5661. const dict_table_t* table, /*!< in: check if there are
  5662. any locks held on records in
  5663. this table or on the table
  5664. itself */
  5665. const trx_list_t* trx_list) /*!< in: trx list to check */
  5666. {
  5667. trx_t* trx;
  5668. ut_a(table != NULL);
  5669. ut_ad(lock_mutex_own());
  5670. ut_ad(mutex_own(&trx_sys->mutex));
  5671. ut_ad(trx_list == &trx_sys->rw_trx_list
  5672. || trx_list == &trx_sys->ro_trx_list);
  5673. for (trx = UT_LIST_GET_FIRST(*trx_list);
  5674. trx != NULL;
  5675. trx = UT_LIST_GET_NEXT(trx_list, trx)) {
  5676. const lock_t* lock;
  5677. assert_trx_in_list(trx);
  5678. ut_ad(trx->read_only == (trx_list == &trx_sys->ro_trx_list));
  5679. for (lock = UT_LIST_GET_FIRST(trx->lock.trx_locks);
  5680. lock != NULL;
  5681. lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
  5682. ut_a(lock->trx == trx);
  5683. if (lock_get_type_low(lock) == LOCK_REC) {
  5684. ut_ad(!dict_index_is_online_ddl(lock->index)
  5685. || dict_index_is_clust(lock->index));
  5686. if (lock->index->table == table) {
  5687. return(lock);
  5688. }
  5689. } else if (lock->un_member.tab_lock.table == table) {
  5690. return(lock);
  5691. }
  5692. }
  5693. }
  5694. return(NULL);
  5695. }
  5696. #endif /* UNIV_DEBUG */
  5697. /*******************************************************************//**
  5698. Check if there are any locks (table or rec) against table.
  5699. @return TRUE if table has either table or record locks. */
  5700. UNIV_INTERN
  5701. ibool
  5702. lock_table_has_locks(
  5703. /*=================*/
  5704. const dict_table_t* table) /*!< in: check if there are any locks
  5705. held on records in this table or on the
  5706. table itself */
  5707. {
  5708. ibool has_locks;
  5709. lock_mutex_enter();
  5710. has_locks = UT_LIST_GET_LEN(table->locks) > 0 || table->n_rec_locks > 0;
  5711. #ifdef UNIV_DEBUG
  5712. if (!has_locks) {
  5713. mutex_enter(&trx_sys->mutex);
  5714. ut_ad(!lock_table_locks_lookup(table, &trx_sys->rw_trx_list));
  5715. ut_ad(!lock_table_locks_lookup(table, &trx_sys->ro_trx_list));
  5716. mutex_exit(&trx_sys->mutex);
  5717. }
  5718. #endif /* UNIV_DEBUG */
  5719. lock_mutex_exit();
  5720. return(has_locks);
  5721. }
  5722. #ifdef UNIV_DEBUG
  5723. /*******************************************************************//**
  5724. Check if the transaction holds any locks on the sys tables
  5725. or its records.
  5726. @return the strongest lock found on any sys table or 0 for none */
  5727. UNIV_INTERN
  5728. const lock_t*
  5729. lock_trx_has_sys_table_locks(
  5730. /*=========================*/
  5731. const trx_t* trx) /*!< in: transaction to check */
  5732. {
  5733. lint i;
  5734. const lock_t* strongest_lock = 0;
  5735. lock_mode strongest = LOCK_NONE;
  5736. lock_mutex_enter();
  5737. /* Find a valid mode. Note: ib_vector_size() can be 0. */
  5738. for (i = ib_vector_size(trx->lock.table_locks) - 1; i >= 0; --i) {
  5739. const lock_t* lock;
  5740. lock = *static_cast<const lock_t**>(
  5741. ib_vector_get(trx->lock.table_locks, i));
  5742. if (lock != NULL
  5743. && dict_is_sys_table(lock->un_member.tab_lock.table->id)) {
  5744. strongest = lock_get_mode(lock);
  5745. ut_ad(strongest != LOCK_NONE);
  5746. strongest_lock = lock;
  5747. break;
  5748. }
  5749. }
  5750. if (strongest == LOCK_NONE) {
  5751. lock_mutex_exit();
  5752. return(NULL);
  5753. }
  5754. for (/* No op */; i >= 0; --i) {
  5755. const lock_t* lock;
  5756. lock = *static_cast<const lock_t**>(
  5757. ib_vector_get(trx->lock.table_locks, i));
  5758. if (lock == NULL) {
  5759. continue;
  5760. }
  5761. ut_ad(trx == lock->trx);
  5762. ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
  5763. ut_ad(lock->un_member.tab_lock.table != NULL);
  5764. lock_mode mode = lock_get_mode(lock);
  5765. if (dict_is_sys_table(lock->un_member.tab_lock.table->id)
  5766. && lock_mode_stronger_or_eq(mode, strongest)) {
  5767. strongest = mode;
  5768. strongest_lock = lock;
  5769. }
  5770. }
  5771. lock_mutex_exit();
  5772. return(strongest_lock);
  5773. }
  5774. /*******************************************************************//**
  5775. Check if the transaction holds an exclusive lock on a record.
  5776. @return whether the locks are held */
  5777. UNIV_INTERN
  5778. bool
  5779. lock_trx_has_rec_x_lock(
  5780. /*====================*/
  5781. const trx_t* trx, /*!< in: transaction to check */
  5782. const dict_table_t* table, /*!< in: table to check */
  5783. const buf_block_t* block, /*!< in: buffer block of the record */
  5784. ulint heap_no)/*!< in: record heap number */
  5785. {
  5786. enum lock_mode intention_lock;
  5787. enum lock_mode rec_lock;
  5788. ut_ad(heap_no > PAGE_HEAP_NO_SUPREMUM);
  5789. if (UNIV_UNLIKELY(trx->fake_changes)) {
  5790. intention_lock = LOCK_IS;
  5791. rec_lock = LOCK_S;
  5792. } else {
  5793. intention_lock = LOCK_IX;
  5794. rec_lock = LOCK_X;
  5795. }
  5796. lock_mutex_enter();
  5797. ut_a(lock_table_has(trx, table, intention_lock));
  5798. if (UNIV_LIKELY(srv_fake_changes_locks)) {
  5799. ut_a(lock_rec_has_expl(rec_lock | LOCK_REC_NOT_GAP,
  5800. block, heap_no, trx->id));
  5801. }
  5802. lock_mutex_exit();
  5803. return(true);
  5804. }
  5805. #endif /* UNIV_DEBUG */