MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
lock0lock.cc
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free Software
7 Foundation; version 2 of the License.
8 
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
16 
17 *****************************************************************************/
18 
19 /**************************************************/
26 #define LOCK_MODULE_IMPLEMENTATION
27 
28 #include "lock0lock.h"
29 #include "lock0priv.h"
30 
31 #ifdef UNIV_NONINL
32 #include "lock0lock.ic"
33 #include "lock0priv.ic"
34 #endif
35 
36 #include "ha_prototypes.h"
37 #include "usr0sess.h"
38 #include "trx0purge.h"
39 #include "dict0mem.h"
40 #include "dict0boot.h"
41 #include "trx0sys.h"
42 #include "pars0pars.h" /* pars_complete_graph_for_exec() */
43 #include "que0que.h" /* que_node_get_parent() */
44 #include "row0mysql.h" /* row_mysql_handle_errors() */
45 #include "row0sel.h" /* sel_node_create(), sel_node_t */
46 #include "row0types.h" /* sel_node_t */
47 #include "srv0mon.h"
48 #include "ut0vec.h"
49 #include "btr0btr.h"
50 #include "dict0boot.h"
51 #include <set>
52 
53 /* Restricts the length of search we will do in the waits-for
54 graph of transactions */
55 #define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000
56 
57 /* Restricts the search depth we will do in the waits-for graph of
58 transactions */
59 #define LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK 200
60 
61 /* When releasing transaction locks, this specifies how often we release
62 the lock mutex for a moment to give also others access to it */
63 
64 #define LOCK_RELEASE_INTERVAL 1000
65 
66 /* Safety margin when creating a new record lock: this many extra records
67 can be inserted to the page without need to create a lock with a bigger
68 bitmap */
69 
70 #define LOCK_PAGE_BITMAP_MARGIN 64
71 
72 /* An explicit record lock affects both the record and the gap before it.
73 An implicit x-lock does not affect the gap, it only locks the index
74 record from read or update.
75 
76 If a transaction has modified or inserted an index record, then
77 it owns an implicit x-lock on the record. On a secondary index record,
78 a transaction has an implicit x-lock also if it has modified the
79 clustered index record, the max trx id of the page where the secondary
80 index record resides is >= trx id of the transaction (or database recovery
81 is running), and there are no explicit non-gap lock requests on the
82 secondary index record.
83 
84 This complicated definition for a secondary index comes from the
85 implementation: we want to be able to determine if a secondary index
86 record has an implicit x-lock, just by looking at the present clustered
87 index record, not at the historical versions of the record. The
88 complicated definition can be explained to the user so that there is
89 nondeterminism in the access path when a query is answered: we may,
90 or may not, access the clustered index record and thus may, or may not,
91 bump into an x-lock set there.
92 
93 Different transaction can have conflicting locks set on the gap at the
94 same time. The locks on the gap are purely inhibitive: an insert cannot
95 be made, or a select cursor may have to wait if a different transaction
96 has a conflicting lock on the gap. An x-lock on the gap does not give
97 the right to insert into the gap.
98 
99 An explicit lock can be placed on a user record or the supremum record of
100 a page. The locks on the supremum record are always thought to be of the gap
101 type, though the gap bit is not set. When we perform an update of a record
102 where the size of the record changes, we may temporarily store its explicit
103 locks on the infimum record of the page, though the infimum otherwise never
104 carries locks.
105 
106 A waiting record lock can also be of the gap type. A waiting lock request
107 can be granted when there is no conflicting mode lock request by another
108 transaction ahead of it in the explicit lock queue.
109 
110 In version 4.0.5 we added yet another explicit lock type: LOCK_REC_NOT_GAP.
111 It only locks the record it is placed on, not the gap before the record.
112 This lock type is necessary to emulate an Oracle-like READ COMMITTED isolation
113 level.
114 
115 -------------------------------------------------------------------------
116 RULE 1: If there is an implicit x-lock on a record, and there are non-gap
117 -------
118 lock requests waiting in the queue, then the transaction holding the implicit
119 x-lock also has an explicit non-gap record x-lock. Therefore, as locks are
120 released, we can grant locks to waiting lock requests purely by looking at
121 the explicit lock requests in the queue.
122 
123 RULE 3: Different transactions cannot have conflicting granted non-gap locks
124 -------
125 on a record at the same time. However, they can have conflicting granted gap
126 locks.
127 RULE 4: If a there is a waiting lock request in a queue, no lock request,
128 -------
129 gap or not, can be inserted ahead of it in the queue. In record deletes
130 and page splits new gap type locks can be created by the database manager
131 for a transaction, and without rule 4, the waits-for graph of transactions
132 might become cyclic without the database noticing it, as the deadlock check
133 is only performed when a transaction itself requests a lock!
134 -------------------------------------------------------------------------
135 
136 An insert is allowed to a gap if there are no explicit lock requests by
137 other transactions on the next record. It does not matter if these lock
138 requests are granted or waiting, gap bit set or not, with the exception
139 that a gap type request set by another transaction to wait for
140 its turn to do an insert is ignored. On the other hand, an
141 implicit x-lock by another transaction does not prevent an insert, which
142 allows for more concurrency when using an Oracle-style sequence number
143 generator for the primary key with many transactions doing inserts
144 concurrently.
145 
146 A modify of a record is allowed if the transaction has an x-lock on the
147 record, or if other transactions do not have any non-gap lock requests on the
148 record.
149 
150 A read of a single user record with a cursor is allowed if the transaction
151 has a non-gap explicit, or an implicit lock on the record, or if the other
152 transactions have no x-lock requests on the record. At a page supremum a
153 read is always allowed.
154 
155 In summary, an implicit lock is seen as a granted x-lock only on the
156 record, not on the gap. An explicit lock with no gap bit set is a lock
157 both on the record and the gap. If the gap bit is set, the lock is only
158 on the gap. Different transaction cannot own conflicting locks on the
159 record at the same time, but they may own conflicting locks on the gap.
160 Granted locks on a record give an access right to the record, but gap type
161 locks just inhibit operations.
162 
163 NOTE: Finding out if some transaction has an implicit x-lock on a secondary
164 index record can be cumbersome. We may have to look at previous versions of
165 the corresponding clustered index record to find out if a delete marked
166 secondary index record was delete marked by an active transaction, not by
167 a committed one.
168 
169 FACT A: If a transaction has inserted a row, it can delete it any time
170 without need to wait for locks.
171 
172 PROOF: The transaction has an implicit x-lock on every index record inserted
173 for the row, and can thus modify each record without the need to wait. Q.E.D.
174 
175 FACT B: If a transaction has read some result set with a cursor, it can read
176 it again, and retrieves the same result set, if it has not modified the
177 result set in the meantime. Hence, there is no phantom problem. If the
178 biggest record, in the alphabetical order, touched by the cursor is removed,
179 a lock wait may occur, otherwise not.
180 
181 PROOF: When a read cursor proceeds, it sets an s-lock on each user record
182 it passes, and a gap type s-lock on each page supremum. The cursor must
183 wait until it has these locks granted. Then no other transaction can
184 have a granted x-lock on any of the user records, and therefore cannot
185 modify the user records. Neither can any other transaction insert into
186 the gaps which were passed over by the cursor. Page splits and merges,
187 and removal of obsolete versions of records do not affect this, because
188 when a user record or a page supremum is removed, the next record inherits
189 its locks as gap type locks, and therefore blocks inserts to the same gap.
190 Also, if a page supremum is inserted, it inherits its locks from the successor
191 record. When the cursor is positioned again at the start of the result set,
192 the records it will touch on its course are either records it touched
193 during the last pass or new inserted page supremums. It can immediately
194 access all these records, and when it arrives at the biggest record, it
195 notices that the result set is complete. If the biggest record was removed,
196 lock wait can occur because the next record only inherits a gap type lock,
197 and a wait may be needed. Q.E.D. */
198 
199 /* If an index record should be changed or a new inserted, we must check
200 the lock on the record or the next. When a read cursor starts reading,
201 we will set a record level s-lock on each record it passes, except on the
202 initial record on which the cursor is positioned before we start to fetch
203 records. Our index tree search has the convention that the B-tree
204 cursor is positioned BEFORE the first possibly matching record in
205 the search. Optimizations are possible here: if the record is searched
206 on an equality condition to a unique key, we could actually set a special
207 lock on the record, a lock which would not prevent any insert before
208 this record. In the next key locking an x-lock set on a record also
209 prevents inserts just before that record.
210  There are special infimum and supremum records on each page.
211 A supremum record can be locked by a read cursor. This records cannot be
212 updated but the lock prevents insert of a user record to the end of
213 the page.
214  Next key locks will prevent the phantom problem where new rows
215 could appear to SELECT result sets after the select operation has been
216 performed. Prevention of phantoms ensures the serilizability of
217 transactions.
218  What should we check if an insert of a new record is wanted?
219 Only the lock on the next record on the same page, because also the
220 supremum record can carry a lock. An s-lock prevents insertion, but
221 what about an x-lock? If it was set by a searched update, then there
222 is implicitly an s-lock, too, and the insert should be prevented.
223 What if our transaction owns an x-lock to the next record, but there is
224 a waiting s-lock request on the next record? If this s-lock was placed
225 by a read cursor moving in the ascending order in the index, we cannot
226 do the insert immediately, because when we finally commit our transaction,
227 the read cursor should see also the new inserted record. So we should
228 move the read cursor backward from the next record for it to pass over
229 the new inserted record. This move backward may be too cumbersome to
230 implement. If we in this situation just enqueue a second x-lock request
231 for our transaction on the next record, then the deadlock mechanism
232 notices a deadlock between our transaction and the s-lock request
233 transaction. This seems to be an ok solution.
234  We could have the convention that granted explicit record locks,
235 lock the corresponding records from changing, and also lock the gaps
236 before them from inserting. A waiting explicit lock request locks the gap
237 before from inserting. Implicit record x-locks, which we derive from the
238 transaction id in the clustered index record, only lock the record itself
239 from modification, not the gap before it from inserting.
240  How should we store update locks? If the search is done by a unique
241 key, we could just modify the record trx id. Otherwise, we could put a record
242 x-lock on the record. If the update changes ordering fields of the
243 clustered index record, the inserted new record needs no record lock in
244 lock table, the trx id is enough. The same holds for a secondary index
245 record. Searched delete is similar to update.
246 
247 PROBLEM:
248 What about waiting lock requests? If a transaction is waiting to make an
249 update to a record which another modified, how does the other transaction
250 know to send the end-lock-wait signal to the waiting transaction? If we have
251 the convention that a transaction may wait for just one lock at a time, how
252 do we preserve it if lock wait ends?
253 
254 PROBLEM:
255 Checking the trx id label of a secondary index record. In the case of a
256 modification, not an insert, is this necessary? A secondary index record
257 is modified only by setting or resetting its deleted flag. A secondary index
258 record contains fields to uniquely determine the corresponding clustered
259 index record. A secondary index record is therefore only modified if we
260 also modify the clustered index record, and the trx id checking is done
261 on the clustered index record, before we come to modify the secondary index
262 record. So, in the case of delete marking or unmarking a secondary index
263 record, we do not have to care about trx ids, only the locks in the lock
264 table must be checked. In the case of a select from a secondary index, the
265 trx id is relevant, and in this case we may have to search the clustered
266 index record.
267 
268 PROBLEM: How to update record locks when page is split or merged, or
269 --------------------------------------------------------------------
270 a record is deleted or updated?
271 If the size of fields in a record changes, we perform the update by
272 a delete followed by an insert. How can we retain the locks set or
273 waiting on the record? Because a record lock is indexed in the bitmap
274 by the heap number of the record, when we remove the record from the
275 record list, it is possible still to keep the lock bits. If the page
276 is reorganized, we could make a table of old and new heap numbers,
277 and permute the bitmaps in the locks accordingly. We can add to the
278 table a row telling where the updated record ended. If the update does
279 not require a reorganization of the page, we can simply move the lock
280 bits for the updated record to the position determined by its new heap
281 number (we may have to allocate a new lock, if we run out of the bitmap
282 in the old one).
283  A more complicated case is the one where the reinsertion of the
284 updated record is done pessimistically, because the structure of the
285 tree may change.
286 
287 PROBLEM: If a supremum record is removed in a page merge, or a record
288 ---------------------------------------------------------------------
289 removed in a purge, what to do to the waiting lock requests? In a split to
290 the right, we just move the lock requests to the new supremum. If a record
291 is removed, we could move the waiting lock request to its inheritor, the
292 next record in the index. But, the next record may already have lock
293 requests on its own queue. A new deadlock check should be made then. Maybe
294 it is easier just to release the waiting transactions. They can then enqueue
295 new lock requests on appropriate records.
296 
297 PROBLEM: When a record is inserted, what locks should it inherit from the
298 -------------------------------------------------------------------------
299 upper neighbor? An insert of a new supremum record in a page split is
300 always possible, but an insert of a new user record requires that the upper
301 neighbor does not have any lock requests by other transactions, granted or
302 waiting, in its lock queue. Solution: We can copy the locks as gap type
303 locks, so that also the waiting locks are transformed to granted gap type
304 locks on the inserted record. */
305 
306 #define LOCK_STACK_SIZE OS_THREAD_MAX_N
307 
308 /* LOCK COMPATIBILITY MATRIX
309  * IS IX S X AI
310  * IS + + + - +
311  * IX + + - - +
312  * S + - + - -
313  * X - - - - -
314  * AI + + - - -
315  *
316  * Note that for rows, InnoDB only acquires S or X locks.
317  * For tables, InnoDB normally acquires IS or IX locks.
318  * S or X table locks are only acquired for LOCK TABLES.
319  * Auto-increment (AI) locks are needed because of
320  * statement-level MySQL binlog.
321  * See also lock_mode_compatible().
322  */
323 static const byte lock_compatibility_matrix[5][5] = {
325  /* IS */ { TRUE, TRUE, TRUE, FALSE, TRUE},
326  /* IX */ { TRUE, TRUE, FALSE, FALSE, TRUE},
327  /* S */ { TRUE, FALSE, TRUE, FALSE, FALSE},
328  /* X */ { FALSE, FALSE, FALSE, FALSE, FALSE},
329  /* AI */ { TRUE, TRUE, FALSE, FALSE, FALSE}
330 };
331 
332 /* STRONGER-OR-EQUAL RELATION (mode1=row, mode2=column)
333  * IS IX S X AI
334  * IS + - - - -
335  * IX + + - - -
336  * S + - + - -
337  * X + + + + +
338  * AI - - - - +
339  * See lock_mode_stronger_or_eq().
340  */
341 static const byte lock_strength_matrix[5][5] = {
343  /* IS */ { TRUE, FALSE, FALSE, FALSE, FALSE},
344  /* IX */ { TRUE, TRUE, FALSE, FALSE, FALSE},
345  /* S */ { TRUE, FALSE, TRUE, FALSE, FALSE},
346  /* X */ { TRUE, TRUE, TRUE, TRUE, TRUE},
347  /* AI */ { FALSE, FALSE, FALSE, FALSE, TRUE}
348 };
349 
352  const trx_t* start;
356  const lock_t* wait_lock;
358  ib_uint64_t mark_start;
361  ulint depth;
363  ulint cost;
365  ibool too_deep;
367 };
368 
370 struct lock_stack_t {
371  const lock_t* lock;
372  const lock_t* wait_lock;
373  ulint heap_no;
374 };
375 
379 static lock_stack_t* lock_stack;
380 
382 static const ulint lock_types = UT_ARR_SIZE(lock_compatibility_matrix);
383 
384 #ifdef UNIV_PFS_MUTEX
385 /* Key to register mutex with performance schema */
386 UNIV_INTERN mysql_pfs_key_t lock_sys_mutex_key;
387 /* Key to register mutex with performance schema */
388 UNIV_INTERN mysql_pfs_key_t lock_sys_wait_mutex_key;
389 #endif /* UNIV_PFS_MUTEX */
390 
391 #ifdef UNIV_DEBUG
392 UNIV_INTERN ibool lock_print_waits = FALSE;
393 
394 /*********************************************************************/
397 static
398 bool
399 lock_validate();
400 /*============*/
401 
402 /*********************************************************************/
405 static
406 ibool
407 lock_rec_validate_page(
408 /*===================*/
409  const buf_block_t* block)
410  __attribute__((nonnull, warn_unused_result));
411 #endif /* UNIV_DEBUG */
412 
413 /* The lock system */
414 UNIV_INTERN lock_sys_t* lock_sys = NULL;
415 
418 UNIV_INTERN ibool lock_deadlock_found = FALSE;
420 static FILE* lock_latest_err_file;
421 
422 /********************************************************************/
430 static
431 trx_id_t
432 lock_deadlock_check_and_resolve(
433 /*===========================*/
434  const lock_t* lock,
435  const trx_t* trx);
437 /*********************************************************************/
440 UNIV_INLINE
441 ibool
443 /*=================*/
444  const lock_t* lock,
445  ulint i)
446 {
447  const byte* b;
448 
449  ut_ad(lock);
450  ut_ad(lock_get_type_low(lock) == LOCK_REC);
451 
452  if (i >= lock->un_member.rec_lock.n_bits) {
453 
454  return(FALSE);
455  }
456 
457  b = ((const byte*) &lock[1]) + (i / 8);
458 
459  return(1 & *b >> (i % 8));
460 }
461 
462 /*********************************************************************/
464 UNIV_INTERN
465 void
467 /*========================*/
468  trx_id_t trx_id,
469  const rec_t* rec,
471  const ulint* offsets,
472  trx_id_t max_trx_id)
473 {
474  ut_print_timestamp(stderr);
475  fputs(" InnoDB: Error: transaction id associated with record\n",
476  stderr);
477  rec_print_new(stderr, rec, offsets);
478  fputs("InnoDB: in ", stderr);
479  dict_index_name_print(stderr, NULL, index);
480  fprintf(stderr, "\n"
481  "InnoDB: is " TRX_ID_FMT " which is higher than the"
482  " global trx id counter " TRX_ID_FMT "!\n"
483  "InnoDB: The table is corrupt. You have to do"
484  " dump + drop + reimport.\n",
485  trx_id, max_trx_id);
486 }
487 
488 /*********************************************************************/
491 #ifdef UNIV_DEBUG
492 UNIV_INTERN
493 #else
494 static __attribute__((nonnull, warn_unused_result))
495 #endif
496 bool
497 lock_check_trx_id_sanity(
498 /*=====================*/
499  trx_id_t trx_id,
500  const rec_t* rec,
502  const ulint* offsets)
503 {
504  bool is_ok;
505  trx_id_t max_trx_id;
506 
507  ut_ad(rec_offs_validate(rec, index, offsets));
508 
509  max_trx_id = trx_sys_get_max_trx_id();
510  is_ok = trx_id < max_trx_id;
511 
512  if (UNIV_UNLIKELY(!is_ok)) {
514  rec, index, offsets, max_trx_id);
515  }
516 
517  return(is_ok);
518 }
519 
520 /*********************************************************************/
524 UNIV_INTERN
525 bool
527 /*==========================*/
528  const rec_t* rec,
531  const ulint* offsets,
532  read_view_t* view)
533 {
534  trx_id_t trx_id;
535 
536  ut_ad(dict_index_is_clust(index));
538  ut_ad(rec_offs_validate(rec, index, offsets));
539 
540  /* NOTE that we call this function while holding the search
541  system latch. */
542 
543  trx_id = row_get_rec_trx_id(rec, index, offsets);
544 
545  return(read_view_sees_trx_id(view, trx_id));
546 }
547 
548 /*********************************************************************/
558 UNIV_INTERN
559 bool
561 /*========================*/
562  const rec_t* rec,
565  const read_view_t* view)
566 {
567  trx_id_t max_trx_id;
568 
570 
571  /* NOTE that we might call this function while holding the search
572  system latch. */
573 
574  if (recv_recovery_is_on()) {
575 
576  return(false);
577  }
578 
579  max_trx_id = page_get_max_trx_id(page_align(rec));
580  ut_ad(max_trx_id);
581 
582  return(max_trx_id < view->up_limit_id);
583 }
584 
585 /*********************************************************************/
587 UNIV_INTERN
588 void
590 /*============*/
591  ulint n_cells)
592 {
593  ulint lock_sys_sz;
594 
595  lock_sys_sz = sizeof(*lock_sys)
596  + OS_THREAD_MAX_N * sizeof(srv_slot_t);
597 
598  lock_sys = static_cast<lock_sys_t*>(mem_zalloc(lock_sys_sz));
599 
600  lock_stack = static_cast<lock_stack_t*>(
601  mem_zalloc(sizeof(*lock_stack) * LOCK_STACK_SIZE));
602 
603  void* ptr = &lock_sys[1];
604 
605  lock_sys->waiting_threads = static_cast<srv_slot_t*>(ptr);
606 
607  lock_sys->last_slot = lock_sys->waiting_threads;
608 
609  mutex_create(lock_sys_mutex_key, &lock_sys->mutex, SYNC_LOCK_SYS);
610 
611  mutex_create(lock_sys_wait_mutex_key,
612  &lock_sys->wait_mutex, SYNC_LOCK_WAIT_SYS);
613 
614  lock_sys->timeout_event = os_event_create();
615 
616  lock_sys->rec_hash = hash_create(n_cells);
617 
618  if (!srv_read_only_mode) {
619  lock_latest_err_file = os_file_create_tmpfile();
620  ut_a(lock_latest_err_file);
621  }
622 }
623 
624 /*********************************************************************/
626 UNIV_INTERN
627 void
629 /*================*/
630 {
631  if (lock_latest_err_file != NULL) {
632  fclose(lock_latest_err_file);
633  lock_latest_err_file = NULL;
634  }
635 
636  hash_table_free(lock_sys->rec_hash);
637 
638  mutex_free(&lock_sys->mutex);
639  mutex_free(&lock_sys->wait_mutex);
640 
641  mem_free(lock_stack);
642  mem_free(lock_sys);
643 
644  lock_sys = NULL;
645  lock_stack = NULL;
646 }
647 
648 /*********************************************************************/
651 UNIV_INTERN
652 ulint
654 /*===============*/
655 {
656  return((ulint) sizeof(lock_t));
657 }
658 
659 /*********************************************************************/
662 UNIV_INLINE
663 enum lock_mode
665 /*==========*/
666  const lock_t* lock)
667 {
668  ut_ad(lock);
669 
670  return(static_cast<enum lock_mode>(lock->type_mode & LOCK_MODE_MASK));
671 }
672 
673 /*********************************************************************/
676 UNIV_INLINE
677 ulint
679 /*==========*/
680  const lock_t* lock)
681 {
682  ut_ad(lock);
683 
684  return(lock->type_mode & LOCK_WAIT);
685 }
686 
687 /*********************************************************************/
694 UNIV_INTERN
697 /*===============*/
698  trx_t* trx,
699  dict_table_t* dest,
700  enum lock_mode* mode)
701 {
702  dict_table_t* src;
703  lock_t* lock;
704 
705  ut_ad(!lock_mutex_own());
706 
707  src = NULL;
708  *mode = LOCK_NONE;
709 
710  /* The trx mutex protects the trx_locks for our purposes.
711  Other transactions could want to convert one of our implicit
712  record locks to an explicit one. For that, they would need our
713  trx mutex. Waiting locks can be removed while only holding
714  lock_sys->mutex, but this is a running transaction and cannot
715  thus be holding any waiting locks. */
716  trx_mutex_enter(trx);
717 
718  for (lock = UT_LIST_GET_FIRST(trx->lock.trx_locks);
719  lock != NULL;
720  lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
721  lock_table_t* tab_lock;
722  enum lock_mode lock_mode;
723  if (!(lock_get_type_low(lock) & LOCK_TABLE)) {
724  /* We are only interested in table locks. */
725  continue;
726  }
727  tab_lock = &lock->un_member.tab_lock;
728  if (dest == tab_lock->table) {
729  /* We are not interested in the destination table. */
730  continue;
731  } else if (!src) {
732  /* This presumably is the source table. */
733  src = tab_lock->table;
734  if (UT_LIST_GET_LEN(src->locks) != 1
735  || UT_LIST_GET_FIRST(src->locks) != lock) {
736  /* We only support the case when
737  there is only one lock on this table. */
738  src = NULL;
739  goto func_exit;
740  }
741  } else if (src != tab_lock->table) {
742  /* The transaction is locking more than
743  two tables (src and dest): abort */
744  src = NULL;
745  goto func_exit;
746  }
747 
748  /* Check that the source table is locked by
749  LOCK_IX or LOCK_IS. */
750  lock_mode = lock_get_mode(lock);
751  if (lock_mode == LOCK_IX || lock_mode == LOCK_IS) {
752  if (*mode != LOCK_NONE && *mode != lock_mode) {
753  /* There are multiple locks on src. */
754  src = NULL;
755  goto func_exit;
756  }
757  *mode = lock_mode;
758  }
759  }
760 
761  if (!src) {
762  /* No source table lock found: flag the situation to caller */
763  src = dest;
764  }
765 
766 func_exit:
767  trx_mutex_exit(trx);
768  return(src);
769 }
770 
771 /*********************************************************************/
777 UNIV_INTERN
778 ibool
780 /*====================*/
781  const dict_table_t* table,
782  const trx_t* trx)
783 {
784  const lock_t* lock;
785  ibool ok = FALSE;
786 
787  ut_ad(table);
788  ut_ad(trx);
789 
791 
792  for (lock = UT_LIST_GET_FIRST(table->locks);
793  lock != NULL;
794  lock = UT_LIST_GET_NEXT(locks, &lock->un_member.tab_lock)) {
795  if (lock->trx != trx) {
796  /* A lock on the table is held
797  by some other transaction. */
798  goto not_ok;
799  }
800 
801  if (!(lock_get_type_low(lock) & LOCK_TABLE)) {
802  /* We are interested in table locks only. */
803  continue;
804  }
805 
806  switch (lock_get_mode(lock)) {
807  case LOCK_IX:
808  ok = TRUE;
809  break;
810  case LOCK_AUTO_INC:
811  /* It is allowed for trx to hold an
812  auto_increment lock. */
813  break;
814  default:
815 not_ok:
816  /* Other table locks than LOCK_IX are not allowed. */
817  ok = FALSE;
818  goto func_exit;
819  }
820  }
821 
822 func_exit:
823  lock_mutex_exit();
824 
825  return(ok);
826 }
827 
828 /*********************************************************************/
830 UNIV_INLINE
831 void
833 /*=======================*/
834  lock_t* lock,
835  trx_t* trx)
836 {
837  ut_ad(lock);
838  ut_ad(lock->trx == trx);
839  ut_ad(trx->lock.wait_lock == NULL);
841  ut_ad(trx_mutex_own(trx));
842 
843  trx->lock.wait_lock = lock;
844  lock->type_mode |= LOCK_WAIT;
845 }
846 
847 /**********************************************************************/
850 UNIV_INLINE
851 void
853 /*=========================*/
854  lock_t* lock)
855 {
856  ut_ad(lock_get_wait(lock));
858 
859  /* Reset the back pointer in trx to this waiting lock request */
860  if (!(lock->type_mode & LOCK_CONV_BY_OTHER)) {
861  ut_ad(lock->trx->lock.wait_lock == lock);
862  lock->trx->lock.wait_lock = NULL;
863  } else {
864  ut_ad(lock_get_type_low(lock) == LOCK_REC);
865  }
866  lock->type_mode &= ~LOCK_WAIT;
867 }
868 
869 /*********************************************************************/
872 UNIV_INLINE
873 ulint
875 /*=============*/
876  const lock_t* lock)
877 {
878  ut_ad(lock);
879  ut_ad(lock_get_type_low(lock) == LOCK_REC);
880 
881  return(lock->type_mode & LOCK_GAP);
882 }
883 
884 /*********************************************************************/
887 UNIV_INLINE
888 ulint
890 /*=====================*/
891  const lock_t* lock)
892 {
893  ut_ad(lock);
894  ut_ad(lock_get_type_low(lock) == LOCK_REC);
895 
896  return(lock->type_mode & LOCK_REC_NOT_GAP);
897 }
898 
899 /*********************************************************************/
902 UNIV_INLINE
903 ulint
905 /*==========================*/
906  const lock_t* lock)
907 {
908  ut_ad(lock);
909  ut_ad(lock_get_type_low(lock) == LOCK_REC);
910 
911  return(lock->type_mode & LOCK_INSERT_INTENTION);
912 }
913 
914 /*********************************************************************/
917 UNIV_INLINE
918 ulint
920 /*=====================*/
921  enum lock_mode mode1,
922  enum lock_mode mode2)
923 {
924  ut_ad((ulint) mode1 < lock_types);
925  ut_ad((ulint) mode2 < lock_types);
926 
927  return(lock_strength_matrix[mode1][mode2]);
928 }
929 
930 /*********************************************************************/
933 UNIV_INLINE
934 ulint
936 /*=================*/
937  enum lock_mode mode1,
938  enum lock_mode mode2)
939 {
940  ut_ad((ulint) mode1 < lock_types);
941  ut_ad((ulint) mode2 < lock_types);
942 
943  return(lock_compatibility_matrix[mode1][mode2]);
944 }
945 
946 /*********************************************************************/
949 UNIV_INLINE
950 ibool
952 /*=================*/
953  const trx_t* trx,
954  ulint type_mode,
958  const lock_t* lock2,
962  ibool lock_is_on_supremum)
966 {
967  ut_ad(trx && lock2);
968  ut_ad(lock_get_type_low(lock2) == LOCK_REC);
969 
970  if (trx != lock2->trx
971  && !lock_mode_compatible(static_cast<enum lock_mode>(
972  LOCK_MODE_MASK & type_mode),
973  lock_get_mode(lock2))) {
974 
975  /* We have somewhat complex rules when gap type record locks
976  cause waits */
977 
978  if ((lock_is_on_supremum || (type_mode & LOCK_GAP))
979  && !(type_mode & LOCK_INSERT_INTENTION)) {
980 
981  /* Gap type locks without LOCK_INSERT_INTENTION flag
982  do not need to wait for anything. This is because
983  different users can have conflicting lock types
984  on gaps. */
985 
986  return(FALSE);
987  }
988 
989  if (!(type_mode & LOCK_INSERT_INTENTION)
990  && lock_rec_get_gap(lock2)) {
991 
992  /* Record lock (LOCK_ORDINARY or LOCK_REC_NOT_GAP
993  does not need to wait for a gap type lock */
994 
995  return(FALSE);
996  }
997 
998  if ((type_mode & LOCK_GAP)
999  && lock_rec_get_rec_not_gap(lock2)) {
1000 
1001  /* Lock on gap does not need to wait for
1002  a LOCK_REC_NOT_GAP type lock */
1003 
1004  return(FALSE);
1005  }
1006 
1007  if (lock_rec_get_insert_intention(lock2)) {
1008 
1009  /* No lock request needs to wait for an insert
1010  intention lock to be removed. This is ok since our
1011  rules allow conflicting locks on gaps. This eliminates
1012  a spurious deadlock caused by a next-key lock waiting
1013  for an insert intention lock; when the insert
1014  intention lock was granted, the insert deadlocked on
1015  the waiting next-key lock.
1016 
1017  Also, insert intention locks do not disturb each
1018  other. */
1019 
1020  return(FALSE);
1021  }
1022 
1023  return(TRUE);
1024  }
1025 
1026  return(FALSE);
1027 }
1028 
1029 /*********************************************************************/
1032 UNIV_INTERN
1033 ibool
1035 /*=============*/
1036  const lock_t* lock1,
1037  const lock_t* lock2)
1041 {
1042  ut_ad(lock1 && lock2);
1043 
1044  if (lock1->trx != lock2->trx
1046  lock_get_mode(lock2))) {
1047  if (lock_get_type_low(lock1) == LOCK_REC) {
1048  ut_ad(lock_get_type_low(lock2) == LOCK_REC);
1049 
1050  /* If this lock request is for a supremum record
1051  then the second bit on the lock bitmap is set */
1052 
1053  return(lock_rec_has_to_wait(lock1->trx,
1054  lock1->type_mode, lock2,
1056  lock1, 1)));
1057  }
1058 
1059  return(TRUE);
1060  }
1061 
1062  return(FALSE);
1063 }
1064 
1065 /*============== RECORD LOCK BASIC FUNCTIONS ============================*/
1066 
1067 /*********************************************************************/
1070 UNIV_INLINE
1071 ulint
1073 /*================*/
1074  const lock_t* lock)
1075 {
1076  return(lock->un_member.rec_lock.n_bits);
1077 }
1078 
1079 /**********************************************************************/
1081 UNIV_INLINE
1082 void
1084 /*=================*/
1085  lock_t* lock,
1086  ulint i)
1087 {
1088  ulint byte_index;
1089  ulint bit_index;
1090 
1091  ut_ad(lock);
1092  ut_ad(lock_get_type_low(lock) == LOCK_REC);
1093  ut_ad(i < lock->un_member.rec_lock.n_bits);
1094 
1095  byte_index = i / 8;
1096  bit_index = i % 8;
1097 
1098  ((byte*) &lock[1])[byte_index] |= 1 << bit_index;
1099 }
1100 
1101 /**********************************************************************/
1106 UNIV_INTERN
1107 ulint
1109 /*==================*/
1110  const lock_t* lock)
1111 {
1112  ulint i;
1113 
1114  for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
1115 
1116  if (lock_rec_get_nth_bit(lock, i)) {
1117 
1118  return(i);
1119  }
1120  }
1121 
1122  return(ULINT_UNDEFINED);
1123 }
1124 
1125 /**********************************************************************/
1127 UNIV_INLINE
1128 void
1130 /*===================*/
1131  lock_t* lock,
1132  ulint i)
1134 {
1135  ulint byte_index;
1136  ulint bit_index;
1137 
1138  ut_ad(lock);
1139  ut_ad(lock_get_type_low(lock) == LOCK_REC);
1140  ut_ad(i < lock->un_member.rec_lock.n_bits);
1141 
1142  byte_index = i / 8;
1143  bit_index = i % 8;
1144 
1145  ((byte*) &lock[1])[byte_index] &= ~(1 << bit_index);
1146 }
1147 
1148 /*********************************************************************/
1151 UNIV_INLINE
1152 const lock_t*
1154 /*============================*/
1155  const lock_t* lock)
1156 {
1157  ulint space;
1158  ulint page_no;
1159 
1160  ut_ad(lock_mutex_own());
1161  ut_ad(lock_get_type_low(lock) == LOCK_REC);
1162 
1163  space = lock->un_member.rec_lock.space;
1164  page_no = lock->un_member.rec_lock.page_no;
1165 
1166  for (;;) {
1167  lock = static_cast<const lock_t*>(HASH_GET_NEXT(hash, lock));
1168 
1169  if (!lock) {
1170 
1171  break;
1172  }
1173 
1174  if ((lock->un_member.rec_lock.space == space)
1175  && (lock->un_member.rec_lock.page_no == page_no)) {
1176 
1177  break;
1178  }
1179  }
1180 
1181  return(lock);
1182 }
1183 
1184 /*********************************************************************/
1187 UNIV_INLINE
1188 lock_t*
1190 /*======================*/
1191  lock_t* lock)
1192 {
1193  return((lock_t*) lock_rec_get_next_on_page_const(lock));
1194 }
1195 
1196 /*********************************************************************/
1200 UNIV_INLINE
1201 lock_t*
1203 /*============================*/
1204  ulint space,
1205  ulint page_no)
1206 {
1207  lock_t* lock;
1208 
1209  ut_ad(lock_mutex_own());
1210 
1211  for (lock = static_cast<lock_t*>(
1212  HASH_GET_FIRST(lock_sys->rec_hash,
1213  lock_rec_hash(space, page_no)));
1214  lock != NULL;
1215  lock = static_cast<lock_t*>(HASH_GET_NEXT(hash, lock))) {
1216 
1217  if (lock->un_member.rec_lock.space == space
1218  && lock->un_member.rec_lock.page_no == page_no) {
1219 
1220  break;
1221  }
1222  }
1223 
1224  return(lock);
1225 }
1226 
1227 /*********************************************************************/
1230 UNIV_INTERN
1231 lock_t*
1233 /*========================*/
1234  ulint space,
1235  ulint page_no)
1236 {
1237  lock_t* lock;
1238 
1239  lock_mutex_enter();
1240  lock = lock_rec_get_first_on_page_addr(space, page_no);
1241  lock_mutex_exit();
1242 
1243  return(lock);
1244 }
1245 
1246 /*********************************************************************/
1250 UNIV_INLINE
1251 lock_t*
1253 /*=======================*/
1254  const buf_block_t* block)
1255 {
1256  ulint hash;
1257  lock_t* lock;
1258  ulint space = buf_block_get_space(block);
1259  ulint page_no = buf_block_get_page_no(block);
1260 
1261  ut_ad(lock_mutex_own());
1262 
1263  hash = buf_block_get_lock_hash_val(block);
1264 
1265  for (lock = static_cast<lock_t*>(
1266  HASH_GET_FIRST( lock_sys->rec_hash, hash));
1267  lock != NULL;
1268  lock = static_cast<lock_t*>(HASH_GET_NEXT(hash, lock))) {
1269 
1270  if ((lock->un_member.rec_lock.space == space)
1271  && (lock->un_member.rec_lock.page_no == page_no)) {
1272 
1273  break;
1274  }
1275  }
1276 
1277  return(lock);
1278 }
1279 
1280 /*********************************************************************/
1283 UNIV_INLINE
1284 lock_t*
1286 /*==============*/
1287  ulint heap_no,
1288  lock_t* lock)
1289 {
1290  ut_ad(lock_mutex_own());
1291 
1292  do {
1293  ut_ad(lock_get_type_low(lock) == LOCK_REC);
1294  lock = lock_rec_get_next_on_page(lock);
1295  } while (lock && !lock_rec_get_nth_bit(lock, heap_no));
1296 
1297  return(lock);
1298 }
1299 
1300 /*********************************************************************/
1303 UNIV_INLINE
1304 const lock_t*
1306 /*====================*/
1307  ulint heap_no,
1308  const lock_t* lock)
1309 {
1310  return(lock_rec_get_next(heap_no, (lock_t*) lock));
1311 }
1312 
1313 /*********************************************************************/
1316 UNIV_INLINE
1317 lock_t*
1319 /*===============*/
1320  const buf_block_t* block,
1321  ulint heap_no)
1322 {
1323  lock_t* lock;
1324 
1325  ut_ad(lock_mutex_own());
1326 
1327  for (lock = lock_rec_get_first_on_page(block); lock;
1328  lock = lock_rec_get_next_on_page(lock)) {
1329  if (lock_rec_get_nth_bit(lock, heap_no)) {
1330  break;
1331  }
1332  }
1333 
1334  return(lock);
1335 }
1336 
1337 /*********************************************************************/
1341 static
1342 void
1343 lock_rec_bitmap_reset(
1344 /*==================*/
1345  lock_t* lock)
1346 {
1347  ulint n_bytes;
1348 
1349  ut_ad(lock_get_type_low(lock) == LOCK_REC);
1350 
1351  /* Reset to zero the bitmap which resides immediately after the lock
1352  struct */
1353 
1354  n_bytes = lock_rec_get_n_bits(lock) / 8;
1355 
1356  ut_ad((lock_rec_get_n_bits(lock) % 8) == 0);
1357 
1358  memset(&lock[1], 0, n_bytes);
1359 }
1360 
1361 /*********************************************************************/
1364 static
1365 lock_t*
1366 lock_rec_copy(
1367 /*==========*/
1368  const lock_t* lock,
1369  mem_heap_t* heap)
1370 {
1371  ulint size;
1372 
1373  ut_ad(lock_get_type_low(lock) == LOCK_REC);
1374 
1375  size = sizeof(lock_t) + lock_rec_get_n_bits(lock) / 8;
1376 
1377  return(static_cast<lock_t*>(mem_heap_dup(heap, lock, size)));
1378 }
1379 
1380 /*********************************************************************/
1383 UNIV_INTERN
1384 const lock_t*
1386 /*==============*/
1387  const lock_t* in_lock,
1388  ulint heap_no)
1389 {
1390  lock_t* lock;
1391  ulint space;
1392  ulint page_no;
1393  lock_t* found_lock = NULL;
1394 
1395  ut_ad(lock_mutex_own());
1396  ut_ad(lock_get_type_low(in_lock) == LOCK_REC);
1397 
1398  space = in_lock->un_member.rec_lock.space;
1399  page_no = in_lock->un_member.rec_lock.page_no;
1400 
1401  for (lock = lock_rec_get_first_on_page_addr(space, page_no);
1402  /* No op */;
1403  lock = lock_rec_get_next_on_page(lock)) {
1404 
1405  ut_ad(lock);
1406 
1407  if (lock == in_lock) {
1408 
1409  return(found_lock);
1410  }
1411 
1412  if (lock_rec_get_nth_bit(lock, heap_no)) {
1413 
1414  found_lock = lock;
1415  }
1416  }
1417 }
1418 
1419 /*============= FUNCTIONS FOR ANALYZING TABLE LOCK QUEUE ================*/
1420 
1421 /*********************************************************************/
1425 UNIV_INLINE
1426 const lock_t*
1428 /*===========*/
1429  const trx_t* trx,
1430  const dict_table_t* table,
1431  enum lock_mode mode)
1432 {
1433  lint i;
1434 
1435  if (ib_vector_is_empty(trx->lock.table_locks)) {
1436  return(NULL);
1437  }
1438 
1439  /* Look for stronger locks the same trx already has on the table */
1440 
1441  for (i = ib_vector_size(trx->lock.table_locks) - 1; i >= 0; --i) {
1442  const lock_t* lock;
1443  enum lock_mode lock_mode;
1444 
1445  lock = *static_cast<const lock_t**>(
1446  ib_vector_get(trx->lock.table_locks, i));
1447 
1448  if (lock == NULL) {
1449  continue;
1450  }
1451 
1452  lock_mode = lock_get_mode(lock);
1453 
1454  ut_ad(trx == lock->trx);
1456  ut_ad(lock->un_member.tab_lock.table != NULL);
1457 
1458  if (table == lock->un_member.tab_lock.table
1459  && lock_mode_stronger_or_eq(lock_mode, mode)) {
1460 
1461  ut_ad(!lock_get_wait(lock));
1462 
1463  return(lock);
1464  }
1465  }
1466 
1467  return(NULL);
1468 }
1469 
1470 /*============= FUNCTIONS FOR ANALYZING RECORD LOCK QUEUE ================*/
1471 
1472 /*********************************************************************/
1476 UNIV_INLINE
1477 lock_t*
1479 /*==============*/
1480  ulint precise_mode,
1485  const buf_block_t* block,
1487  ulint heap_no,
1488  const trx_t* trx)
1489 {
1490  lock_t* lock;
1491 
1492  ut_ad(lock_mutex_own());
1493  ut_ad((precise_mode & LOCK_MODE_MASK) == LOCK_S
1494  || (precise_mode & LOCK_MODE_MASK) == LOCK_X);
1495  ut_ad(!(precise_mode & LOCK_INSERT_INTENTION));
1496 
1497  for (lock = lock_rec_get_first(block, heap_no);
1498  lock != NULL;
1499  lock = lock_rec_get_next(heap_no, lock)) {
1500 
1501  if (lock->trx == trx
1505  lock_get_mode(lock),
1506  static_cast<enum lock_mode>(
1507  precise_mode & LOCK_MODE_MASK))
1508  && (!lock_rec_get_rec_not_gap(lock)
1509  || (precise_mode & LOCK_REC_NOT_GAP)
1510  || heap_no == PAGE_HEAP_NO_SUPREMUM)
1511  && (!lock_rec_get_gap(lock)
1512  || (precise_mode & LOCK_GAP)
1513  || heap_no == PAGE_HEAP_NO_SUPREMUM)) {
1514 
1515  return(lock);
1516  }
1517  }
1518 
1519  return(NULL);
1520 }
1521 
1522 #ifdef UNIV_DEBUG
1523 /*********************************************************************/
1526 static
1527 const lock_t*
1528 lock_rec_other_has_expl_req(
1529 /*========================*/
1530  enum lock_mode mode,
1531  ulint gap,
1534  ulint wait,
1537  const buf_block_t* block,
1539  ulint heap_no,
1540  const trx_t* trx)
1543 {
1544  const lock_t* lock;
1545 
1546  ut_ad(lock_mutex_own());
1547  ut_ad(mode == LOCK_X || mode == LOCK_S);
1548  ut_ad(gap == 0 || gap == LOCK_GAP);
1549  ut_ad(wait == 0 || wait == LOCK_WAIT);
1550 
1551  for (lock = lock_rec_get_first(block, heap_no);
1552  lock != NULL;
1553  lock = lock_rec_get_next_const(heap_no, lock)) {
1554 
1555  if (lock->trx != trx
1556  && (gap
1557  || !(lock_rec_get_gap(lock)
1558  || heap_no == PAGE_HEAP_NO_SUPREMUM))
1559  && (wait || !lock_get_wait(lock))
1561 
1562  return(lock);
1563  }
1564  }
1565 
1566  return(NULL);
1567 }
1568 #endif /* UNIV_DEBUG */
1569 
1570 /*********************************************************************/
1574 static
1575 const lock_t*
1576 lock_rec_other_has_conflicting(
1577 /*===========================*/
1578  enum lock_mode mode,
1582  const buf_block_t* block,
1584  ulint heap_no,
1585  const trx_t* trx)
1586 {
1587  const lock_t* lock;
1588  ibool is_supremum;
1589 
1590  ut_ad(lock_mutex_own());
1591 
1592  is_supremum = (heap_no == PAGE_HEAP_NO_SUPREMUM);
1593 
1594  for (lock = lock_rec_get_first(block, heap_no);
1595  lock != NULL;
1596  lock = lock_rec_get_next_const(heap_no, lock)) {
1597 
1598  if (lock_rec_has_to_wait(trx, mode, lock, is_supremum)) {
1599  return(lock);
1600  }
1601  }
1602 
1603  return(NULL);
1604 }
1605 
1606 /*********************************************************************/
1611 UNIV_INLINE
1612 lock_t*
1614 /*==========================*/
1615  ulint type_mode,
1616  ulint heap_no,
1617  lock_t* lock,
1618  const trx_t* trx)
1619 {
1620  ut_ad(lock_mutex_own());
1621 
1622  for (/* No op */;
1623  lock != NULL;
1624  lock = lock_rec_get_next_on_page(lock)) {
1625 
1626  if (lock->trx == trx
1627  && lock->type_mode == type_mode
1628  && lock_rec_get_n_bits(lock) > heap_no) {
1629 
1630  return(lock);
1631  }
1632  }
1633 
1634  return(NULL);
1635 }
1636 
1637 /*********************************************************************/
1644 static
1645 trx_id_t
1646 lock_sec_rec_some_has_impl(
1647 /*=======================*/
1648  const rec_t* rec,
1649  dict_index_t* index,
1650  const ulint* offsets)
1651 {
1652  trx_id_t trx_id;
1653  trx_id_t max_trx_id;
1654  const page_t* page = page_align(rec);
1655 
1656  ut_ad(!lock_mutex_own());
1657  ut_ad(!mutex_own(&trx_sys->mutex));
1658  ut_ad(!dict_index_is_clust(index));
1660  ut_ad(rec_offs_validate(rec, index, offsets));
1661 
1662  max_trx_id = page_get_max_trx_id(page);
1663 
1664  /* Some transaction may have an implicit x-lock on the record only
1665  if the max trx id for the page >= min trx id for the trx list, or
1666  database recovery is running. We do not write the changes of a page
1667  max trx id to the log, and therefore during recovery, this value
1668  for a page may be incorrect. */
1669 
1670  if (max_trx_id < trx_rw_min_trx_id() && !recv_recovery_is_on()) {
1671 
1672  trx_id = 0;
1673 
1674  } else if (!lock_check_trx_id_sanity(max_trx_id, rec, index, offsets)) {
1675 
1676  buf_page_print(page, 0, 0);
1677 
1678  /* The page is corrupt: try to avoid a crash by returning 0 */
1679  trx_id = 0;
1680 
1681  /* In this case it is possible that some transaction has an implicit
1682  x-lock. We have to look in the clustered index. */
1683 
1684  } else {
1685  trx_id = row_vers_impl_x_locked(rec, index, offsets);
1686  }
1687 
1688  return(trx_id);
1689 }
1690 
1691 /*********************************************************************/
1696 UNIV_INTERN
1697 ulint
1699 /*=======================*/
1700  const trx_lock_t* trx_lock)
1701 {
1702  const lock_t* lock;
1703  ulint n_records = 0;
1704 
1705  ut_ad(lock_mutex_own());
1706 
1707  for (lock = UT_LIST_GET_FIRST(trx_lock->trx_locks);
1708  lock != NULL;
1709  lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
1710 
1711  if (lock_get_type_low(lock) == LOCK_REC) {
1712  ulint n_bit;
1713  ulint n_bits = lock_rec_get_n_bits(lock);
1714 
1715  for (n_bit = 0; n_bit < n_bits; n_bit++) {
1716  if (lock_rec_get_nth_bit(lock, n_bit)) {
1717  n_records++;
1718  }
1719  }
1720  }
1721  }
1722 
1723  return(n_records);
1724 }
1725 
1726 /*============== RECORD LOCK CREATION AND QUEUE MANAGEMENT =============*/
1727 
1728 /*********************************************************************/
1732 static
1733 lock_t*
1734 lock_rec_create(
1735 /*============*/
1736  ulint type_mode,
1739  const buf_block_t* block,
1741  ulint heap_no,
1742  dict_index_t* index,
1743  trx_t* trx,
1744  ibool caller_owns_trx_mutex)
1747 {
1748  lock_t* lock;
1749  ulint page_no;
1750  ulint space;
1751  ulint n_bits;
1752  ulint n_bytes;
1753  const page_t* page;
1754 
1755  ut_ad(lock_mutex_own());
1756  ut_ad(caller_owns_trx_mutex == trx_mutex_own(trx));
1758 
1759  /* Non-locking autocommit read-only transactions should not set
1760  any locks. */
1761  assert_trx_in_list(trx);
1762 
1763  space = buf_block_get_space(block);
1764  page_no = buf_block_get_page_no(block);
1765  page = block->frame;
1766 
1767  btr_assert_not_corrupted(block, index);
1768 
1769  /* If rec is the supremum record, then we reset the gap and
1770  LOCK_REC_NOT_GAP bits, as all locks on the supremum are
1771  automatically of the gap type */
1772 
1773  if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) {
1774  ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
1775 
1776  type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP);
1777  }
1778 
1779  /* Make lock bitmap bigger by a safety margin */
1780  n_bits = page_dir_get_n_heap(page) + LOCK_PAGE_BITMAP_MARGIN;
1781  n_bytes = 1 + n_bits / 8;
1782 
1783  lock = static_cast<lock_t*>(
1784  mem_heap_alloc(trx->lock.lock_heap, sizeof(lock_t) + n_bytes));
1785 
1786  lock->trx = trx;
1787 
1788  lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC;
1789  lock->index = index;
1790 
1791  lock->un_member.rec_lock.space = space;
1792  lock->un_member.rec_lock.page_no = page_no;
1793  lock->un_member.rec_lock.n_bits = n_bytes * 8;
1794 
1795  /* Reset to zero the bitmap which resides immediately after the
1796  lock struct */
1797 
1798  lock_rec_bitmap_reset(lock);
1799 
1800  /* Set the bit corresponding to rec */
1801  lock_rec_set_nth_bit(lock, heap_no);
1802 
1803  index->table->n_rec_locks++;
1804 
1805  ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted);
1806 
1807  HASH_INSERT(lock_t, hash, lock_sys->rec_hash,
1808  lock_rec_fold(space, page_no), lock);
1809 
1810  if (!caller_owns_trx_mutex) {
1811  trx_mutex_enter(trx);
1812  }
1813  ut_ad(trx_mutex_own(trx));
1814 
1815  if (lock_is_wait_not_by_other(type_mode)) {
1816 
1817  lock_set_lock_and_trx_wait(lock, trx);
1818  }
1819 
1820  UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock);
1821 
1822  if (!caller_owns_trx_mutex) {
1823  trx_mutex_exit(trx);
1824  }
1825 
1826  MONITOR_INC(MONITOR_RECLOCK_CREATED);
1827  MONITOR_INC(MONITOR_NUM_RECLOCK);
1828 
1829  return(lock);
1830 }
1831 
1832 /*********************************************************************/
1839 static
1840 dberr_t
1841 lock_rec_enqueue_waiting(
1842 /*=====================*/
1843  ulint type_mode,
1852  const buf_block_t* block,
1854  ulint heap_no,
1855  lock_t* lock,
1857  dict_index_t* index,
1858  que_thr_t* thr)
1859 {
1860  trx_t* trx;
1861  trx_id_t victim_trx_id;
1862 
1863  ut_ad(lock_mutex_own());
1866 
1867  trx = thr_get_trx(thr);
1868 
1869  ut_ad(trx_mutex_own(trx));
1870 
1871  /* Test if there already is some other reason to suspend thread:
1872  we do not enqueue a lock request if the query thread should be
1873  stopped anyway */
1874 
1875  if (que_thr_stop(thr)) {
1876  ut_error;
1877 
1878  return(DB_QUE_THR_SUSPENDED);
1879  }
1880 
1881  switch (trx_get_dict_operation(trx)) {
1882  case TRX_DICT_OP_NONE:
1883  break;
1884  case TRX_DICT_OP_TABLE:
1885  case TRX_DICT_OP_INDEX:
1886  ut_print_timestamp(stderr);
1887  fputs(" InnoDB: Error: a record lock wait happens"
1888  " in a dictionary operation!\n"
1889  "InnoDB: ", stderr);
1890  dict_index_name_print(stderr, trx, index);
1891  fputs(".\n"
1892  "InnoDB: Submit a detailed bug report"
1893  " to http://bugs.mysql.com\n",
1894  stderr);
1895  ut_ad(0);
1896  }
1897 
1898  if (lock == NULL) {
1899  /* Enqueue the lock request that will wait
1900  to be granted, note that we already own
1901  the trx mutex. */
1902  lock = lock_rec_create(
1903  type_mode | LOCK_WAIT, block, heap_no,
1904  index, trx, TRUE);
1905  } else {
1906  ut_ad(lock->type_mode & LOCK_WAIT);
1908 
1909  lock->type_mode &= ~LOCK_CONV_BY_OTHER;
1910  lock_set_lock_and_trx_wait(lock, trx);
1911  }
1912 
1913  /* Release the mutex to obey the latching order.
1914  This is safe, because lock_deadlock_check_and_resolve()
1915  is invoked when a lock wait is enqueued for the currently
1916  running transaction. Because trx is a running transaction
1917  (it is not currently suspended because of a lock wait),
1918  its state can only be changed by this thread, which is
1919  currently associated with the transaction. */
1920 
1921  trx_mutex_exit(trx);
1922 
1923  victim_trx_id = lock_deadlock_check_and_resolve(lock, trx);
1924 
1925  trx_mutex_enter(trx);
1926 
1927  if (victim_trx_id != 0) {
1928 
1929  ut_ad(victim_trx_id == trx->id);
1930 
1932  lock_rec_reset_nth_bit(lock, heap_no);
1933 
1934  return(DB_DEADLOCK);
1935 
1936  } else if (trx->lock.wait_lock == NULL) {
1937 
1938  /* If there was a deadlock but we chose another
1939  transaction as a victim, it is possible that we
1940  already have the lock now granted! */
1941 
1942  return(DB_SUCCESS_LOCKED_REC);
1943  }
1944 
1946 
1947  trx->lock.was_chosen_as_deadlock_victim = FALSE;
1948  trx->lock.wait_started = ut_time();
1949 
1950  ut_a(que_thr_stop(thr));
1951 
1952 #ifdef UNIV_DEBUG
1953  if (lock_print_waits) {
1954  fprintf(stderr, "Lock wait for trx " TRX_ID_FMT " in index ",
1955  trx->id);
1956  ut_print_name(stderr, trx, FALSE, index->name);
1957  }
1958 #endif /* UNIV_DEBUG */
1959 
1960  MONITOR_INC(MONITOR_LOCKREC_WAIT);
1961 
1962  return(DB_LOCK_WAIT);
1963 }
1964 
1965 /*********************************************************************/
1973 static
1974 lock_t*
1975 lock_rec_add_to_queue(
1976 /*==================*/
1977  ulint type_mode,
1980  const buf_block_t* block,
1982  ulint heap_no,
1983  dict_index_t* index,
1984  trx_t* trx,
1985  ibool caller_owns_trx_mutex)
1988 {
1989  lock_t* lock;
1990  lock_t* first_lock;
1991 
1992  ut_ad(lock_mutex_own());
1993  ut_ad(caller_owns_trx_mutex == trx_mutex_own(trx));
1995 #ifdef UNIV_DEBUG
1996  switch (type_mode & LOCK_MODE_MASK) {
1997  case LOCK_X:
1998  case LOCK_S:
1999  break;
2000  default:
2001  ut_error;
2002  }
2003 
2004  if (!(type_mode & (LOCK_WAIT | LOCK_GAP))) {
2005  enum lock_mode mode = (type_mode & LOCK_MODE_MASK) == LOCK_S
2006  ? LOCK_X
2007  : LOCK_S;
2008  const lock_t* other_lock
2009  = lock_rec_other_has_expl_req(mode, 0, LOCK_WAIT,
2010  block, heap_no, trx);
2011  ut_a(!other_lock);
2012  }
2013 #endif /* UNIV_DEBUG */
2014 
2015  type_mode |= LOCK_REC;
2016 
2017  /* If rec is the supremum record, then we can reset the gap bit, as
2018  all locks on the supremum are automatically of the gap type, and we
2019  try to avoid unnecessary memory consumption of a new record lock
2020  struct for a gap type lock */
2021 
2022  if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) {
2023  ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
2024 
2025  /* There should never be LOCK_REC_NOT_GAP on a supremum
2026  record, but let us play safe */
2027 
2028  type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP);
2029  }
2030 
2031  /* Look for a waiting lock request on the same record or on a gap */
2032 
2033  for (first_lock = lock = lock_rec_get_first_on_page(block);
2034  lock != NULL;
2035  lock = lock_rec_get_next_on_page(lock)) {
2036 
2037  if (lock_get_wait(lock)
2038  && lock_rec_get_nth_bit(lock, heap_no)) {
2039 
2040  goto somebody_waits;
2041  }
2042  }
2043 
2044  if (UNIV_LIKELY(!(type_mode & LOCK_WAIT))) {
2045 
2046  /* Look for a similar record lock on the same page:
2047  if one is found and there are no waiting lock requests,
2048  we can just set the bit */
2049 
2051  type_mode, heap_no, first_lock, trx);
2052 
2053  if (lock) {
2054 
2055  lock_rec_set_nth_bit(lock, heap_no);
2056 
2057  return(lock);
2058  }
2059  }
2060 
2061 somebody_waits:
2062  return(lock_rec_create(
2063  type_mode, block, heap_no, index, trx,
2064  caller_owns_trx_mutex));
2065 }
2066 
2075 };
2076 
2077 /*********************************************************************/
2085 UNIV_INLINE
2088 /*===============*/
2089  ibool impl,
2093  ulint mode,
2096  const buf_block_t* block,
2098  ulint heap_no,
2099  dict_index_t* index,
2100  que_thr_t* thr)
2101 {
2102  lock_t* lock;
2103  trx_t* trx;
2104  enum lock_rec_req_status status = LOCK_REC_SUCCESS;
2105 
2106  ut_ad(lock_mutex_own());
2107  ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
2108  || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
2109  ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
2110  || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
2111  ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
2112  || (LOCK_MODE_MASK & mode) == LOCK_X);
2113  ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
2114  || mode - (LOCK_MODE_MASK & mode) == 0
2115  || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
2117 
2118  DBUG_EXECUTE_IF("innodb_report_deadlock", return(LOCK_REC_FAIL););
2119 
2120  lock = lock_rec_get_first_on_page(block);
2121 
2122  trx = thr_get_trx(thr);
2123 
2124  if (lock == NULL) {
2125  if (!impl) {
2126  /* Note that we don't own the trx mutex. */
2127  lock = lock_rec_create(
2128  mode, block, heap_no, index, trx, FALSE);
2129 
2130  }
2131  status = LOCK_REC_SUCCESS_CREATED;
2132  } else {
2133  trx_mutex_enter(trx);
2134 
2135  if (lock_rec_get_next_on_page(lock)
2136  || lock->trx != trx
2137  || lock->type_mode != (mode | LOCK_REC)
2138  || lock_rec_get_n_bits(lock) <= heap_no) {
2139 
2140  status = LOCK_REC_FAIL;
2141  } else if (!impl) {
2142  /* If the nth bit of the record lock is already set
2143  then we do not set a new lock bit, otherwise we do
2144  set */
2145  if (!lock_rec_get_nth_bit(lock, heap_no)) {
2146  lock_rec_set_nth_bit(lock, heap_no);
2147  status = LOCK_REC_SUCCESS_CREATED;
2148  }
2149  }
2150 
2151  trx_mutex_exit(trx);
2152  }
2153 
2154  return(status);
2155 }
2156 
2157 /*********************************************************************/
2164 static
2165 dberr_t
2166 lock_rec_lock_slow(
2167 /*===============*/
2168  ibool impl,
2172  ulint mode,
2175  const buf_block_t* block,
2177  ulint heap_no,
2178  dict_index_t* index,
2179  que_thr_t* thr)
2180 {
2181  trx_t* trx;
2182  lock_t* lock;
2183  dberr_t err = DB_SUCCESS;
2184 
2185  ut_ad(lock_mutex_own());
2186  ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
2187  || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
2188  ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
2189  || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
2190  ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
2191  || (LOCK_MODE_MASK & mode) == LOCK_X);
2192  ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
2193  || mode - (LOCK_MODE_MASK & mode) == 0
2194  || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
2196 
2197  DBUG_EXECUTE_IF("innodb_report_deadlock", return(DB_DEADLOCK););
2198 
2199  trx = thr_get_trx(thr);
2200  trx_mutex_enter(trx);
2201 
2202  lock = lock_rec_has_expl(mode, block, heap_no, trx);
2203  if (lock) {
2204  if (lock->type_mode & LOCK_CONV_BY_OTHER) {
2205  /* This lock or lock waiting was created by the other
2206  transaction, not by the transaction (trx) itself.
2207  So, the transaction (trx) should treat it collectly
2208  according as whether granted or not. */
2209 
2210  if (lock->type_mode & LOCK_WAIT) {
2211  /* This lock request was not granted yet.
2212  Should wait for granted. */
2213 
2214  goto enqueue_waiting;
2215  } else {
2216  /* This lock request was already granted.
2217  Just clearing the flag. */
2218 
2219  lock->type_mode &= ~LOCK_CONV_BY_OTHER;
2220  }
2221  }
2222 
2223  /* The trx already has a strong enough lock on rec: do
2224  nothing */
2225 
2226  } else if (lock_rec_other_has_conflicting(
2227  static_cast<enum lock_mode>(mode),
2228  block, heap_no, trx)) {
2229 
2230  /* If another transaction has a non-gap conflicting
2231  request in the queue, as this transaction does not
2232  have a lock strong enough already granted on the
2233  record, we have to wait. */
2234 
2235  ut_ad(lock == NULL);
2236 enqueue_waiting:
2237  err = lock_rec_enqueue_waiting(
2238  mode, block, heap_no, lock, index, thr);
2239 
2240  } else if (!impl) {
2241  /* Set the requested lock on the record, note that
2242  we already own the transaction mutex. */
2243 
2244  lock_rec_add_to_queue(
2245  LOCK_REC | mode, block, heap_no, index, trx, TRUE);
2246 
2247  err = DB_SUCCESS_LOCKED_REC;
2248  }
2249 
2250  trx_mutex_exit(trx);
2251 
2252  return(err);
2253 }
2254 
2255 /*********************************************************************/
2263 static
2264 dberr_t
2265 lock_rec_lock(
2266 /*==========*/
2267  ibool impl,
2271  ulint mode,
2274  const buf_block_t* block,
2276  ulint heap_no,
2277  dict_index_t* index,
2278  que_thr_t* thr)
2279 {
2280  ut_ad(lock_mutex_own());
2281  ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
2282  || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
2283  ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
2284  || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
2285  ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
2286  || (LOCK_MODE_MASK & mode) == LOCK_X);
2287  ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
2288  || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
2289  || mode - (LOCK_MODE_MASK & mode) == 0);
2291 
2292  /* We try a simplified and faster subroutine for the most
2293  common cases */
2294  switch (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) {
2295  case LOCK_REC_SUCCESS:
2296  return(DB_SUCCESS);
2298  return(DB_SUCCESS_LOCKED_REC);
2299  case LOCK_REC_FAIL:
2300  return(lock_rec_lock_slow(impl, mode, block,
2301  heap_no, index, thr));
2302  }
2303 
2304  ut_error;
2305  return(DB_ERROR);
2306 }
2307 
2308 /*********************************************************************/
2311 static
2312 const lock_t*
2313 lock_rec_has_to_wait_in_queue(
2314 /*==========================*/
2315  const lock_t* wait_lock)
2316 {
2317  const lock_t* lock;
2318  ulint space;
2319  ulint page_no;
2320  ulint heap_no;
2321  ulint bit_mask;
2322  ulint bit_offset;
2323 
2324  ut_ad(lock_mutex_own());
2325  ut_ad(lock_get_wait(wait_lock));
2326  ut_ad(lock_get_type_low(wait_lock) == LOCK_REC);
2327 
2328  space = wait_lock->un_member.rec_lock.space;
2329  page_no = wait_lock->un_member.rec_lock.page_no;
2330  heap_no = lock_rec_find_set_bit(wait_lock);
2331 
2332  bit_offset = heap_no / 8;
2333  bit_mask = 1 << (heap_no % 8);
2334 
2335  for (lock = lock_rec_get_first_on_page_addr(space, page_no);
2336  lock != wait_lock;
2337  lock = lock_rec_get_next_on_page_const(lock)) {
2338 
2339  const byte* p = (const byte*) &lock[1];
2340 
2341  if (heap_no < lock_rec_get_n_bits(lock)
2342  && (p[bit_offset] & bit_mask)
2343  && lock_has_to_wait(wait_lock, lock)) {
2344 
2345  return(lock);
2346  }
2347  }
2348 
2349  return(NULL);
2350 }
2351 
2352 /*************************************************************/
2355 static
2356 void
2357 lock_grant(
2358 /*=======*/
2359  lock_t* lock)
2360 {
2361  ut_ad(lock_mutex_own());
2362 
2364 
2365  trx_mutex_enter(lock->trx);
2366 
2367  if (lock_get_mode(lock) == LOCK_AUTO_INC) {
2369 
2370  if (UNIV_UNLIKELY(table->autoinc_trx == lock->trx)) {
2371  fprintf(stderr,
2372  "InnoDB: Error: trx already had"
2373  " an AUTO-INC lock!\n");
2374  } else {
2375  table->autoinc_trx = lock->trx;
2376 
2377  ib_vector_push(lock->trx->autoinc_locks, &lock);
2378  }
2379  }
2380 
2381 #ifdef UNIV_DEBUG
2382  if (lock_print_waits) {
2383  fprintf(stderr, "Lock wait for trx " TRX_ID_FMT " ends\n",
2384  lock->trx->id);
2385  }
2386 #endif /* UNIV_DEBUG */
2387 
2388  /* If we are resolving a deadlock by choosing another transaction
2389  as a victim, then our original transaction may not be in the
2390  TRX_QUE_LOCK_WAIT state, and there is no need to end the lock wait
2391  for it */
2392 
2393  if (!(lock->type_mode & LOCK_CONV_BY_OTHER)
2394  && lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
2395  que_thr_t* thr;
2396 
2397  thr = que_thr_end_lock_wait(lock->trx);
2398 
2399  if (thr != NULL) {
2401  }
2402  }
2403 
2404  trx_mutex_exit(lock->trx);
2405 }
2406 
2407 /*************************************************************/
2411 static
2412 void
2413 lock_rec_cancel(
2414 /*============*/
2415  lock_t* lock)
2416 {
2417  que_thr_t* thr;
2418 
2419  ut_ad(lock_mutex_own());
2420  ut_ad(lock_get_type_low(lock) == LOCK_REC);
2421  ut_ad(!(lock->type_mode & LOCK_CONV_BY_OTHER));
2422 
2423  /* Reset the bit (there can be only one set bit) in the lock bitmap */
2425 
2426  /* Reset the wait flag and the back pointer to lock in trx */
2427 
2429 
2430  /* The following function releases the trx from lock wait */
2431 
2432  trx_mutex_enter(lock->trx);
2433 
2434  thr = que_thr_end_lock_wait(lock->trx);
2435 
2436  if (thr != NULL) {
2438  }
2439 
2440  trx_mutex_exit(lock->trx);
2441 }
2442 
2443 /*************************************************************/
2447 static
2448 void
2449 lock_rec_dequeue_from_page(
2450 /*=======================*/
2451  lock_t* in_lock)
2457 {
2458  ulint space;
2459  ulint page_no;
2460  lock_t* lock;
2461  trx_lock_t* trx_lock;
2462 
2463  ut_ad(lock_mutex_own());
2464  ut_ad(lock_get_type_low(in_lock) == LOCK_REC);
2465  /* We may or may not be holding in_lock->trx->mutex here. */
2466 
2467  trx_lock = &in_lock->trx->lock;
2468 
2469  space = in_lock->un_member.rec_lock.space;
2470  page_no = in_lock->un_member.rec_lock.page_no;
2471 
2472  in_lock->index->table->n_rec_locks--;
2473 
2474  HASH_DELETE(lock_t, hash, lock_sys->rec_hash,
2475  lock_rec_fold(space, page_no), in_lock);
2476 
2477  UT_LIST_REMOVE(trx_locks, trx_lock->trx_locks, in_lock);
2478 
2479  MONITOR_INC(MONITOR_RECLOCK_REMOVED);
2480  MONITOR_DEC(MONITOR_NUM_RECLOCK);
2481 
2482  /* Check if waiting locks in the queue can now be granted: grant
2483  locks if there are no conflicting locks ahead. Stop at the first
2484  X lock that is waiting or has been granted. */
2485 
2486  for (lock = lock_rec_get_first_on_page_addr(space, page_no);
2487  lock != NULL;
2488  lock = lock_rec_get_next_on_page(lock)) {
2489 
2490  if (lock_get_wait(lock)
2491  && !lock_rec_has_to_wait_in_queue(lock)) {
2492 
2493  /* Grant the lock */
2494  ut_ad(lock->trx != in_lock->trx);
2495  lock_grant(lock);
2496  }
2497  }
2498 }
2499 
2500 /*************************************************************/
2502 static
2503 void
2504 lock_rec_discard(
2505 /*=============*/
2506  lock_t* in_lock)
2509 {
2510  ulint space;
2511  ulint page_no;
2512  trx_lock_t* trx_lock;
2513 
2514  ut_ad(lock_mutex_own());
2515  ut_ad(lock_get_type_low(in_lock) == LOCK_REC);
2516 
2517  trx_lock = &in_lock->trx->lock;
2518 
2519  space = in_lock->un_member.rec_lock.space;
2520  page_no = in_lock->un_member.rec_lock.page_no;
2521 
2522  in_lock->index->table->n_rec_locks--;
2523 
2524  HASH_DELETE(lock_t, hash, lock_sys->rec_hash,
2525  lock_rec_fold(space, page_no), in_lock);
2526 
2527  UT_LIST_REMOVE(trx_locks, trx_lock->trx_locks, in_lock);
2528 
2529  MONITOR_INC(MONITOR_RECLOCK_REMOVED);
2530  MONITOR_DEC(MONITOR_NUM_RECLOCK);
2531 }
2532 
2533 /*************************************************************/
2537 static
2538 void
2539 lock_rec_free_all_from_discard_page(
2540 /*================================*/
2541  const buf_block_t* block)
2542 {
2543  ulint space;
2544  ulint page_no;
2545  lock_t* lock;
2546  lock_t* next_lock;
2547 
2548  ut_ad(lock_mutex_own());
2549 
2550  space = buf_block_get_space(block);
2551  page_no = buf_block_get_page_no(block);
2552 
2553  lock = lock_rec_get_first_on_page_addr(space, page_no);
2554 
2555  while (lock != NULL) {
2556  ut_ad(lock_rec_find_set_bit(lock) == ULINT_UNDEFINED);
2557  ut_ad(!lock_get_wait(lock));
2558 
2559  next_lock = lock_rec_get_next_on_page(lock);
2560 
2561  lock_rec_discard(lock);
2562 
2563  lock = next_lock;
2564  }
2565 }
2566 
2567 /*============= RECORD LOCK MOVING AND INHERITING ===================*/
2568 
2569 /*************************************************************/
2572 static
2573 void
2574 lock_rec_reset_and_release_wait(
2575 /*============================*/
2576  const buf_block_t* block,
2578  ulint heap_no)
2579 {
2580  lock_t* lock;
2581 
2582  ut_ad(lock_mutex_own());
2583 
2584  for (lock = lock_rec_get_first(block, heap_no);
2585  lock != NULL;
2586  lock = lock_rec_get_next(heap_no, lock)) {
2587 
2588  if (lock_is_wait_not_by_other(lock->type_mode)) {
2589  lock_rec_cancel(lock);
2590  } else if (lock_get_wait(lock)) {
2591  /* just reset LOCK_WAIT */
2592  lock_rec_reset_nth_bit(lock, heap_no);
2594  } else {
2595  lock_rec_reset_nth_bit(lock, heap_no);
2596  }
2597  }
2598 }
2599 
2600 /*************************************************************/
2605 static
2606 void
2607 lock_rec_inherit_to_gap(
2608 /*====================*/
2609  const buf_block_t* heir_block,
2611  const buf_block_t* block,
2615  ulint heir_heap_no,
2617  ulint heap_no)
2619 {
2620  lock_t* lock;
2621 
2622  ut_ad(lock_mutex_own());
2623 
2624  /* If srv_locks_unsafe_for_binlog is TRUE or session is using
2625  READ COMMITTED isolation level, we do not want locks set
2626  by an UPDATE or a DELETE to be inherited as gap type locks. But we
2627  DO want S-locks set by a consistency constraint to be inherited also
2628  then. */
2629 
2630  for (lock = lock_rec_get_first(block, heap_no);
2631  lock != NULL;
2632  lock = lock_rec_get_next(heap_no, lock)) {
2633 
2636  || lock->trx->isolation_level
2637  <= TRX_ISO_READ_COMMITTED)
2638  && lock_get_mode(lock) == LOCK_X)) {
2639 
2640  lock_rec_add_to_queue(
2641  LOCK_REC | LOCK_GAP | lock_get_mode(lock),
2642  heir_block, heir_heap_no, lock->index,
2643  lock->trx, FALSE);
2644  }
2645  }
2646 }
2647 
2648 /*************************************************************/
2652 static
2653 void
2654 lock_rec_inherit_to_gap_if_gap_lock(
2655 /*================================*/
2656  const buf_block_t* block,
2657  ulint heir_heap_no,
2659  ulint heap_no)
2663 {
2664  lock_t* lock;
2665 
2666  lock_mutex_enter();
2667 
2668  for (lock = lock_rec_get_first(block, heap_no);
2669  lock != NULL;
2670  lock = lock_rec_get_next(heap_no, lock)) {
2671 
2673  && (heap_no == PAGE_HEAP_NO_SUPREMUM
2674  || !lock_rec_get_rec_not_gap(lock))) {
2675 
2676  lock_rec_add_to_queue(
2677  LOCK_REC | LOCK_GAP | lock_get_mode(lock),
2678  block, heir_heap_no, lock->index,
2679  lock->trx, FALSE);
2680  }
2681  }
2682 
2683  lock_mutex_exit();
2684 }
2685 
2686 /*************************************************************/
2689 static
2690 void
2691 lock_rec_move(
2692 /*==========*/
2693  const buf_block_t* receiver,
2695  const buf_block_t* donator,
2697  ulint receiver_heap_no,
2701  ulint donator_heap_no)
2703 {
2704  lock_t* lock;
2705 
2706  ut_ad(lock_mutex_own());
2707 
2708  ut_ad(lock_rec_get_first(receiver, receiver_heap_no) == NULL);
2709 
2710  for (lock = lock_rec_get_first(donator, donator_heap_no);
2711  lock != NULL;
2712  lock = lock_rec_get_next(donator_heap_no, lock)) {
2713 
2714  const ulint type_mode = lock->type_mode;
2715 
2716  lock_rec_reset_nth_bit(lock, donator_heap_no);
2717 
2718  if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
2720  }
2721 
2722  /* Note that we FIRST reset the bit, and then set the lock:
2723  the function works also if donator == receiver */
2724 
2725  lock_rec_add_to_queue(
2726  type_mode, receiver, receiver_heap_no,
2727  lock->index, lock->trx, FALSE);
2728  }
2729 
2730  ut_ad(lock_rec_get_first(donator, donator_heap_no) == NULL);
2731 }
2732 
2733 /*************************************************************/
2738 UNIV_INTERN
2739 void
2741 /*======================*/
2742  const buf_block_t* block,
2744  const buf_block_t* oblock)
2746 {
2747  lock_t* lock;
2748  UT_LIST_BASE_NODE_T(lock_t) old_locks;
2749  mem_heap_t* heap = NULL;
2750  ulint comp;
2751 
2752  lock_mutex_enter();
2753 
2754  lock = lock_rec_get_first_on_page(block);
2755 
2756  if (lock == NULL) {
2757  lock_mutex_exit();
2758 
2759  return;
2760  }
2761 
2762  heap = mem_heap_create(256);
2763 
2764  /* Copy first all the locks on the page to heap and reset the
2765  bitmaps in the original locks; chain the copies of the locks
2766  using the trx_locks field in them. */
2767 
2768  UT_LIST_INIT(old_locks);
2769 
2770  do {
2771  /* Make a copy of the lock */
2772  lock_t* old_lock = lock_rec_copy(lock, heap);
2773 
2774  UT_LIST_ADD_LAST(trx_locks, old_locks, old_lock);
2775 
2776  /* Reset bitmap of lock */
2777  lock_rec_bitmap_reset(lock);
2778 
2779  if (lock_get_wait(lock)) {
2780 
2782  }
2783 
2784  lock = lock_rec_get_next_on_page(lock);
2785  } while (lock != NULL);
2786 
2787  comp = page_is_comp(block->frame);
2788  ut_ad(comp == page_is_comp(oblock->frame));
2789 
2790  for (lock = UT_LIST_GET_FIRST(old_locks); lock;
2791  lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
2792  /* NOTE: we copy also the locks set on the infimum and
2793  supremum of the page; the infimum may carry locks if an
2794  update of a record is occurring on the page, and its locks
2795  were temporarily stored on the infimum */
2796  page_cur_t cur1;
2797  page_cur_t cur2;
2798 
2799  page_cur_set_before_first(block, &cur1);
2800  page_cur_set_before_first(oblock, &cur2);
2801 
2802  /* Set locks according to old locks */
2803  for (;;) {
2804  ulint old_heap_no;
2805  ulint new_heap_no;
2806 
2807  ut_ad(comp || !memcmp(page_cur_get_rec(&cur1),
2808  page_cur_get_rec(&cur2),
2810  page_cur_get_rec(
2811  &cur2))));
2812  if (UNIV_LIKELY(comp)) {
2813  old_heap_no = rec_get_heap_no_new(
2814  page_cur_get_rec(&cur2));
2815  new_heap_no = rec_get_heap_no_new(
2816  page_cur_get_rec(&cur1));
2817  } else {
2818  old_heap_no = rec_get_heap_no_old(
2819  page_cur_get_rec(&cur2));
2820  new_heap_no = rec_get_heap_no_old(
2821  page_cur_get_rec(&cur1));
2822  }
2823 
2824  if (lock_rec_get_nth_bit(lock, old_heap_no)) {
2825 
2826  /* Clear the bit in old_lock. */
2828  old_heap_no));
2829 
2830  /* NOTE that the old lock bitmap could be too
2831  small for the new heap number! */
2832 
2833  lock_rec_add_to_queue(
2834  lock->type_mode, block, new_heap_no,
2835  lock->index, lock->trx, FALSE);
2836 
2837  /* if (new_heap_no == PAGE_HEAP_NO_SUPREMUM
2838  && lock_get_wait(lock)) {
2839  fprintf(stderr,
2840  "---\n--\n!!!Lock reorg: supr type %lu\n",
2841  lock->type_mode);
2842  } */
2843  }
2844 
2845  if (UNIV_UNLIKELY
2846  (new_heap_no == PAGE_HEAP_NO_SUPREMUM)) {
2847 
2848  ut_ad(old_heap_no == PAGE_HEAP_NO_SUPREMUM);
2849  break;
2850  }
2851 
2852  page_cur_move_to_next(&cur1);
2853  page_cur_move_to_next(&cur2);
2854  }
2855 
2856 #ifdef UNIV_DEBUG
2857  {
2858  ulint i = lock_rec_find_set_bit(lock);
2859 
2860  /* Check that all locks were moved. */
2861  if (UNIV_UNLIKELY(i != ULINT_UNDEFINED)) {
2862  fprintf(stderr,
2863  "lock_move_reorganize_page():"
2864  " %lu not moved in %p\n",
2865  (ulong) i, (void*) lock);
2866  ut_error;
2867  }
2868  }
2869 #endif /* UNIV_DEBUG */
2870  }
2871 
2872  lock_mutex_exit();
2873 
2874  mem_heap_free(heap);
2875 
2876 #ifdef UNIV_DEBUG_LOCK_VALIDATE
2877  ut_ad(lock_rec_validate_page(block));
2878 #endif
2879 }
2880 
2881 /*************************************************************/
2884 UNIV_INTERN
2885 void
2887 /*===================*/
2888  const buf_block_t* new_block,
2889  const buf_block_t* block,
2890  const rec_t* rec)
2892 {
2893  lock_t* lock;
2894  const ulint comp = page_rec_is_comp(rec);
2895 
2896  lock_mutex_enter();
2897 
2898  /* Note: when we move locks from record to record, waiting locks
2899  and possible granted gap type locks behind them are enqueued in
2900  the original order, because new elements are inserted to a hash
2901  table to the end of the hash chain, and lock_rec_add_to_queue
2902  does not reuse locks if there are waiters in the queue. */
2903 
2904  for (lock = lock_rec_get_first_on_page(block); lock;
2905  lock = lock_rec_get_next_on_page(lock)) {
2906  page_cur_t cur1;
2907  page_cur_t cur2;
2908  const ulint type_mode = lock->type_mode;
2909 
2910  page_cur_position(rec, block, &cur1);
2911 
2912  if (page_cur_is_before_first(&cur1)) {
2913  page_cur_move_to_next(&cur1);
2914  }
2915 
2916  page_cur_set_before_first(new_block, &cur2);
2917  page_cur_move_to_next(&cur2);
2918 
2919  /* Copy lock requests on user records to new page and
2920  reset the lock bits on the old */
2921 
2922  while (!page_cur_is_after_last(&cur1)) {
2923  ulint heap_no;
2924 
2925  if (comp) {
2926  heap_no = rec_get_heap_no_new(
2927  page_cur_get_rec(&cur1));
2928  } else {
2929  heap_no = rec_get_heap_no_old(
2930  page_cur_get_rec(&cur1));
2931  ut_ad(!memcmp(page_cur_get_rec(&cur1),
2932  page_cur_get_rec(&cur2),
2934  page_cur_get_rec(&cur2))));
2935  }
2936 
2937  if (lock_rec_get_nth_bit(lock, heap_no)) {
2938  lock_rec_reset_nth_bit(lock, heap_no);
2939 
2940  if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
2942  }
2943 
2944  if (comp) {
2945  heap_no = rec_get_heap_no_new(
2946  page_cur_get_rec(&cur2));
2947  } else {
2948  heap_no = rec_get_heap_no_old(
2949  page_cur_get_rec(&cur2));
2950  }
2951 
2952  lock_rec_add_to_queue(
2953  type_mode, new_block, heap_no,
2954  lock->index, lock->trx, FALSE);
2955  }
2956 
2957  page_cur_move_to_next(&cur1);
2958  page_cur_move_to_next(&cur2);
2959  }
2960  }
2961 
2962  lock_mutex_exit();
2963 
2964 #ifdef UNIV_DEBUG_LOCK_VALIDATE
2965  ut_ad(lock_rec_validate_page(block));
2966  ut_ad(lock_rec_validate_page(new_block));
2967 #endif
2968 }
2969 
2970 /*************************************************************/
2973 UNIV_INTERN
2974 void
2976 /*=====================*/
2977  const buf_block_t* new_block,
2979  const buf_block_t* block,
2980  const rec_t* rec,
2983  const rec_t* old_end)
2988 {
2989  lock_t* lock;
2990  const ulint comp = page_rec_is_comp(rec);
2991 
2992  ut_ad(block->frame == page_align(rec));
2993  ut_ad(new_block->frame == page_align(old_end));
2994 
2995  lock_mutex_enter();
2996 
2997  for (lock = lock_rec_get_first_on_page(block); lock;
2998  lock = lock_rec_get_next_on_page(lock)) {
2999  page_cur_t cur1;
3000  page_cur_t cur2;
3001  const ulint type_mode = lock->type_mode;
3002 
3003  page_cur_set_before_first(block, &cur1);
3004  page_cur_move_to_next(&cur1);
3005 
3006  page_cur_position(old_end, new_block, &cur2);
3007  page_cur_move_to_next(&cur2);
3008 
3009  /* Copy lock requests on user records to new page and
3010  reset the lock bits on the old */
3011 
3012  while (page_cur_get_rec(&cur1) != rec) {
3013  ulint heap_no;
3014 
3015  if (comp) {
3016  heap_no = rec_get_heap_no_new(
3017  page_cur_get_rec(&cur1));
3018  } else {
3019  heap_no = rec_get_heap_no_old(
3020  page_cur_get_rec(&cur1));
3021  ut_ad(!memcmp(page_cur_get_rec(&cur1),
3022  page_cur_get_rec(&cur2),
3024  page_cur_get_rec(
3025  &cur2))));
3026  }
3027 
3028  if (lock_rec_get_nth_bit(lock, heap_no)) {
3029  lock_rec_reset_nth_bit(lock, heap_no);
3030 
3031  if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
3033  }
3034 
3035  if (comp) {
3036  heap_no = rec_get_heap_no_new(
3037  page_cur_get_rec(&cur2));
3038  } else {
3039  heap_no = rec_get_heap_no_old(
3040  page_cur_get_rec(&cur2));
3041  }
3042 
3043  lock_rec_add_to_queue(
3044  type_mode, new_block, heap_no,
3045  lock->index, lock->trx, FALSE);
3046  }
3047 
3048  page_cur_move_to_next(&cur1);
3049  page_cur_move_to_next(&cur2);
3050  }
3051 
3052 #ifdef UNIV_DEBUG
3053  if (page_rec_is_supremum(rec)) {
3054  ulint i;
3055 
3056  for (i = PAGE_HEAP_NO_USER_LOW;
3057  i < lock_rec_get_n_bits(lock); i++) {
3058  if (UNIV_UNLIKELY
3059  (lock_rec_get_nth_bit(lock, i))) {
3060 
3061  fprintf(stderr,
3062  "lock_move_rec_list_start():"
3063  " %lu not moved in %p\n",
3064  (ulong) i, (void*) lock);
3065  ut_error;
3066  }
3067  }
3068  }
3069 #endif /* UNIV_DEBUG */
3070  }
3071 
3072  lock_mutex_exit();
3073 
3074 #ifdef UNIV_DEBUG_LOCK_VALIDATE
3075  ut_ad(lock_rec_validate_page(block));
3076 #endif
3077 }
3078 
3079 /*************************************************************/
3081 UNIV_INTERN
3082 void
3084 /*====================*/
3085  const buf_block_t* right_block,
3086  const buf_block_t* left_block)
3087 {
3088  ulint heap_no = lock_get_min_heap_no(right_block);
3089 
3090  lock_mutex_enter();
3091 
3092  /* Move the locks on the supremum of the left page to the supremum
3093  of the right page */
3094 
3095  lock_rec_move(right_block, left_block,
3096  PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
3097 
3098  /* Inherit the locks to the supremum of left page from the successor
3099  of the infimum on right page */
3100 
3101  lock_rec_inherit_to_gap(left_block, right_block,
3102  PAGE_HEAP_NO_SUPREMUM, heap_no);
3103 
3104  lock_mutex_exit();
3105 }
3106 
3107 /*************************************************************/
3109 UNIV_INTERN
3110 void
3112 /*====================*/
3113  const buf_block_t* right_block,
3115  const rec_t* orig_succ,
3119  const buf_block_t* left_block)
3122 {
3123  lock_mutex_enter();
3124 
3125  /* Inherit the locks from the supremum of the left page to the
3126  original successor of infimum on the right page, to which the left
3127  page was merged */
3128 
3129  lock_rec_inherit_to_gap(right_block, left_block,
3130  page_rec_get_heap_no(orig_succ),
3131  PAGE_HEAP_NO_SUPREMUM);
3132 
3133  /* Reset the locks on the supremum of the left page, releasing
3134  waiting transactions */
3135 
3136  lock_rec_reset_and_release_wait(left_block,
3137  PAGE_HEAP_NO_SUPREMUM);
3138 
3139  lock_rec_free_all_from_discard_page(left_block);
3140 
3141  lock_mutex_exit();
3142 }
3143 
3144 /*************************************************************/
3151 UNIV_INTERN
3152 void
3154 /*===================*/
3155  const buf_block_t* block,
3156  const buf_block_t* root)
3157 {
3158  lock_mutex_enter();
3159 
3160  /* Move the locks on the supremum of the root to the supremum
3161  of block */
3162 
3163  lock_rec_move(block, root,
3164  PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
3165  lock_mutex_exit();
3166 }
3167 
3168 /*************************************************************/
3171 UNIV_INTERN
3172 void
3174 /*=========================*/
3175  const buf_block_t* new_block,
3177  const buf_block_t* block)
3179 {
3180  lock_mutex_enter();
3181 
3182  /* Move the locks on the supremum of the old page to the supremum
3183  of new_page */
3184 
3185  lock_rec_move(new_block, block,
3186  PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
3187  lock_rec_free_all_from_discard_page(block);
3188 
3189  lock_mutex_exit();
3190 }
3191 
3192 /*************************************************************/
3194 UNIV_INTERN
3195 void
3197 /*===================*/
3198  const buf_block_t* right_block,
3199  const buf_block_t* left_block)
3200 {
3201  ulint heap_no = lock_get_min_heap_no(right_block);
3202 
3203  lock_mutex_enter();
3204 
3205  /* Inherit the locks to the supremum of the left page from the
3206  successor of the infimum on the right page */
3207 
3208  lock_rec_inherit_to_gap(left_block, right_block,
3209  PAGE_HEAP_NO_SUPREMUM, heap_no);
3210 
3211  lock_mutex_exit();
3212 }
3213 
3214 /*************************************************************/
3216 UNIV_INTERN
3217 void
3219 /*===================*/
3220  const buf_block_t* left_block,
3222  const rec_t* orig_pred,
3225  const buf_block_t* right_block)
3227 {
3228  const rec_t* left_next_rec;
3229 
3230  ut_ad(left_block->frame == page_align(orig_pred));
3231 
3232  lock_mutex_enter();
3233 
3234  left_next_rec = page_rec_get_next_const(orig_pred);
3235 
3236  if (!page_rec_is_supremum(left_next_rec)) {
3237 
3238  /* Inherit the locks on the supremum of the left page to the
3239  first record which was moved from the right page */
3240 
3241  lock_rec_inherit_to_gap(left_block, left_block,
3242  page_rec_get_heap_no(left_next_rec),
3243  PAGE_HEAP_NO_SUPREMUM);
3244 
3245  /* Reset the locks on the supremum of the left page,
3246  releasing waiting transactions */
3247 
3248  lock_rec_reset_and_release_wait(left_block,
3249  PAGE_HEAP_NO_SUPREMUM);
3250  }
3251 
3252  /* Move the locks from the supremum of right page to the supremum
3253  of the left page */
3254 
3255  lock_rec_move(left_block, right_block,
3256  PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
3257 
3258  lock_rec_free_all_from_discard_page(right_block);
3259 
3260  lock_mutex_exit();
3261 }
3262 
3263 /*************************************************************/
3266 UNIV_INTERN
3267 void
3269 /*=================================*/
3270  const buf_block_t* heir_block,
3272  const buf_block_t* block,
3276  ulint heir_heap_no,
3278  ulint heap_no)
3280 {
3281  lock_mutex_enter();
3282 
3283  lock_rec_reset_and_release_wait(heir_block, heir_heap_no);
3284 
3285  lock_rec_inherit_to_gap(heir_block, block, heir_heap_no, heap_no);
3286 
3287  lock_mutex_exit();
3288 }
3289 
3290 /*************************************************************/
3292 UNIV_INTERN
3293 void
3295 /*================*/
3296  const buf_block_t* heir_block,
3298  ulint heir_heap_no,
3300  const buf_block_t* block)
3302 {
3303  const page_t* page = block->frame;
3304  const rec_t* rec;
3305  ulint heap_no;
3306 
3307  lock_mutex_enter();
3308 
3309  if (!lock_rec_get_first_on_page(block)) {
3310  /* No locks exist on page, nothing to do */
3311 
3312  lock_mutex_exit();
3313 
3314  return;
3315  }
3316 
3317  /* Inherit all the locks on the page to the record and reset all
3318  the locks on the page */
3319 
3320  if (page_is_comp(page)) {
3321  rec = page + PAGE_NEW_INFIMUM;
3322 
3323  do {
3324  heap_no = rec_get_heap_no_new(rec);
3325 
3326  lock_rec_inherit_to_gap(heir_block, block,
3327  heir_heap_no, heap_no);
3328 
3329  lock_rec_reset_and_release_wait(block, heap_no);
3330 
3331  rec = page + rec_get_next_offs(rec, TRUE);
3332  } while (heap_no != PAGE_HEAP_NO_SUPREMUM);
3333  } else {
3334  rec = page + PAGE_OLD_INFIMUM;
3335 
3336  do {
3337  heap_no = rec_get_heap_no_old(rec);
3338 
3339  lock_rec_inherit_to_gap(heir_block, block,
3340  heir_heap_no, heap_no);
3341 
3342  lock_rec_reset_and_release_wait(block, heap_no);
3343 
3344  rec = page + rec_get_next_offs(rec, FALSE);
3345  } while (heap_no != PAGE_HEAP_NO_SUPREMUM);
3346  }
3347 
3348  lock_rec_free_all_from_discard_page(block);
3349 
3350  lock_mutex_exit();
3351 }
3352 
3353 /*************************************************************/
3355 UNIV_INTERN
3356 void
3358 /*===============*/
3359  const buf_block_t* block,
3360  const rec_t* rec)
3361 {
3362  ulint receiver_heap_no;
3363  ulint donator_heap_no;
3364 
3365  ut_ad(block->frame == page_align(rec));
3366 
3367  /* Inherit the gap-locking locks for rec, in gap mode, from the next
3368  record */
3369 
3370  if (page_rec_is_comp(rec)) {
3371  receiver_heap_no = rec_get_heap_no_new(rec);
3372  donator_heap_no = rec_get_heap_no_new(
3373  page_rec_get_next_low(rec, TRUE));
3374  } else {
3375  receiver_heap_no = rec_get_heap_no_old(rec);
3376  donator_heap_no = rec_get_heap_no_old(
3377  page_rec_get_next_low(rec, FALSE));
3378  }
3379 
3380  lock_rec_inherit_to_gap_if_gap_lock(
3381  block, receiver_heap_no, donator_heap_no);
3382 }
3383 
3384 /*************************************************************/
3386 UNIV_INTERN
3387 void
3389 /*===============*/
3390  const buf_block_t* block,
3391  const rec_t* rec)
3392 {
3393  const page_t* page = block->frame;
3394  ulint heap_no;
3395  ulint next_heap_no;
3396 
3397  ut_ad(page == page_align(rec));
3398 
3399  if (page_is_comp(page)) {
3400  heap_no = rec_get_heap_no_new(rec);
3401  next_heap_no = rec_get_heap_no_new(page
3402  + rec_get_next_offs(rec,
3403  TRUE));
3404  } else {
3405  heap_no = rec_get_heap_no_old(rec);
3406  next_heap_no = rec_get_heap_no_old(page
3407  + rec_get_next_offs(rec,
3408  FALSE));
3409  }
3410 
3411  lock_mutex_enter();
3412 
3413  /* Let the next record inherit the locks from rec, in gap mode */
3414 
3415  lock_rec_inherit_to_gap(block, block, next_heap_no, heap_no);
3416 
3417  /* Reset the lock bits on rec and release waiting transactions */
3418 
3419  lock_rec_reset_and_release_wait(block, heap_no);
3420 
3421  lock_mutex_exit();
3422 }
3423 
3424 /*********************************************************************/
3431 UNIV_INTERN
3432 void
3434 /*===========================*/
3435  const buf_block_t* block,
3436  const rec_t* rec)
3441 {
3442  ulint heap_no = page_rec_get_heap_no(rec);
3443 
3444  ut_ad(block->frame == page_align(rec));
3445 
3446  lock_mutex_enter();
3447 
3448  lock_rec_move(block, block, PAGE_HEAP_NO_INFIMUM, heap_no);
3449 
3450  lock_mutex_exit();
3451 }
3452 
3453 /*********************************************************************/
3456 UNIV_INTERN
3457 void
3459 /*===============================*/
3460  const buf_block_t* block,
3461  const rec_t* rec,
3463  const buf_block_t* donator)
3468 {
3469  ulint heap_no = page_rec_get_heap_no(rec);
3470 
3471  lock_mutex_enter();
3472 
3473  lock_rec_move(block, donator, heap_no, PAGE_HEAP_NO_INFIMUM);
3474 
3475  lock_mutex_exit();
3476 }
3477 
3478 /*=========== DEADLOCK CHECKING ======================================*/
3479 
3480 /*********************************************************************/
3484 UNIV_INLINE
3485 void
3487 /*=======================*/
3488 {
3489  ut_ad(lock_mutex_own());
3491 
3492  rewind(lock_latest_err_file);
3493  ut_print_timestamp(lock_latest_err_file);
3494 
3496  ut_print_timestamp(stderr);
3497  fprintf(stderr, "InnoDB: transactions deadlock detected, "
3498  "dumping detailed information.\n");
3499  ut_print_timestamp(stderr);
3500  }
3501 }
3502 
3503 /*********************************************************************/
3505 UNIV_INLINE
3506 void
3508 /*================*/
3509  const char* msg)
3510 {
3511  if (!srv_read_only_mode) {
3512  fputs(msg, lock_latest_err_file);
3513 
3515  fputs(msg, stderr);
3516  }
3517  }
3518 }
3519 
3520 /*********************************************************************/
3522 UNIV_INLINE
3523 void
3525 /*====================*/
3526  const trx_t* trx,
3527  ulint max_query_len)
3529 {
3530  ut_ad(lock_mutex_own());
3532 
3533  ulint n_rec_locks = lock_number_of_rows_locked(&trx->lock);
3534  ulint n_trx_locks = UT_LIST_GET_LEN(trx->lock.trx_locks);
3535  ulint heap_size = mem_heap_get_size(trx->lock.lock_heap);
3536 
3537  mutex_enter(&trx_sys->mutex);
3538 
3539  trx_print_low(lock_latest_err_file, trx, max_query_len,
3540  n_rec_locks, n_trx_locks, heap_size);
3541 
3543  trx_print_low(stderr, trx, max_query_len,
3544  n_rec_locks, n_trx_locks, heap_size);
3545  }
3546 
3547  mutex_exit(&trx_sys->mutex);
3548 }
3549 
3550 /*********************************************************************/
3552 UNIV_INLINE
3553 void
3555 /*=====================*/
3556  const lock_t* lock)
3557 {
3558  ut_ad(lock_mutex_own());
3560 
3561  if (lock_get_type_low(lock) == LOCK_REC) {
3562  lock_rec_print(lock_latest_err_file, lock);
3563 
3565  lock_rec_print(stderr, lock);
3566  }
3567  } else {
3568  lock_table_print(lock_latest_err_file, lock);
3569 
3571  lock_table_print(stderr, lock);
3572  }
3573  }
3574 }
3575 
3577 static ib_uint64_t lock_mark_counter = 0;
3578 
3580 #define lock_deadlock_too_deep(c) \
3581  (c->depth > LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK \
3582  || c->cost > LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK)
3583 
3584 /********************************************************************/
3588 static
3589 const lock_t*
3590 lock_get_next_lock(
3591 /*===============*/
3592  const lock_deadlock_ctx_t*
3593  ctx,
3594  const lock_t* lock,
3595  ulint heap_no)
3597 {
3598  ut_ad(lock_mutex_own());
3599 
3600  do {
3601  if (lock_get_type_low(lock) == LOCK_REC) {
3602  ut_ad(heap_no != ULINT_UNDEFINED);
3603  lock = lock_rec_get_next_const(heap_no, lock);
3604  } else {
3605  ut_ad(heap_no == ULINT_UNDEFINED);
3607 
3608  lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock);
3609  }
3610  } while (lock != NULL
3611  && lock->trx->lock.deadlock_mark > ctx->mark_start);
3612 
3613  ut_ad(lock == NULL
3614  || lock_get_type_low(lock) == lock_get_type_low(ctx->wait_lock));
3615 
3616  return(lock);
3617 }
3618 
3619 /********************************************************************/
3626 static
3627 const lock_t*
3628 lock_get_first_lock(
3629 /*================*/
3630  const lock_deadlock_ctx_t*
3631  ctx,
3632  ulint* heap_no)
3634 {
3635  const lock_t* lock;
3636 
3637  ut_ad(lock_mutex_own());
3638 
3639  lock = ctx->wait_lock;
3640 
3641  if (lock_get_type_low(lock) == LOCK_REC) {
3642 
3643  *heap_no = lock_rec_find_set_bit(lock);
3644  ut_ad(*heap_no != ULINT_UNDEFINED);
3645 
3647  lock->un_member.rec_lock.space,
3648  lock->un_member.rec_lock.page_no);
3649 
3650  /* Position on the first lock on the physical record. */
3651  if (!lock_rec_get_nth_bit(lock, *heap_no)) {
3652  lock = lock_rec_get_next_const(*heap_no, lock);
3653  }
3654 
3655  } else {
3656  *heap_no = ULINT_UNDEFINED;
3658  lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock);
3659  }
3660 
3661  ut_a(lock != NULL);
3662  ut_a(lock != ctx->wait_lock);
3664 
3665  return(lock);
3666 }
3667 
3668 /********************************************************************/
3671 static
3672 void
3673 lock_deadlock_notify(
3674 /*=================*/
3675  const lock_deadlock_ctx_t* ctx,
3676  const lock_t* lock)
3678 {
3679  ut_ad(lock_mutex_own());
3681 
3683 
3684  lock_deadlock_fputs("\n*** (1) TRANSACTION:\n");
3685 
3686  lock_deadlock_trx_print(ctx->wait_lock->trx, 3000);
3687 
3688  lock_deadlock_fputs("*** (1) WAITING FOR THIS LOCK TO BE GRANTED:\n");
3689 
3691 
3692  lock_deadlock_fputs("*** (2) TRANSACTION:\n");
3693 
3694  lock_deadlock_trx_print(lock->trx, 3000);
3695 
3696  lock_deadlock_fputs("*** (2) HOLDS THE LOCK(S):\n");
3697 
3699 
3700  /* It is possible that the joining transaction was granted its
3701  lock when we rolled back some other waiting transaction. */
3702 
3703  if (ctx->start->lock.wait_lock != 0) {
3705  "*** (2) WAITING FOR THIS LOCK TO BE GRANTED:\n");
3706 
3708  }
3709 
3710 #ifdef UNIV_DEBUG
3711  if (lock_print_waits) {
3712  fputs("Deadlock detected\n", stderr);
3713  }
3714 #endif /* UNIV_DEBUG */
3715 }
3716 
3717 /********************************************************************/
3720 static
3721 const trx_t*
3722 lock_deadlock_select_victim(
3723 /*========================*/
3724  const lock_deadlock_ctx_t* ctx)
3725 {
3726  ut_ad(lock_mutex_own());
3727  ut_ad(ctx->start->lock.wait_lock != 0);
3728  ut_ad(ctx->wait_lock->trx != ctx->start);
3729 
3730  if (trx_weight_ge(ctx->wait_lock->trx, ctx->start)) {
3731  /* The joining transaction is 'smaller',
3732  choose it as the victim and roll it back. */
3733 
3734  return(ctx->start);
3735  }
3736 
3737  return(ctx->wait_lock->trx);
3738 }
3739 
3740 /********************************************************************/
3743 static
3744 const lock_stack_t*
3745 lock_deadlock_pop(
3746 /*==============*/
3747  lock_deadlock_ctx_t* ctx)
3748 {
3749  ut_ad(lock_mutex_own());
3750 
3751  ut_ad(ctx->depth > 0);
3752 
3753  return(&lock_stack[--ctx->depth]);
3754 }
3755 
3756 /********************************************************************/
3759 static
3760 lock_stack_t*
3761 lock_deadlock_push(
3762 /*===============*/
3763  lock_deadlock_ctx_t* ctx,
3764  const lock_t* lock,
3765  ulint heap_no)
3766 {
3767  ut_ad(lock_mutex_own());
3768 
3769  /* Save current search state. */
3770 
3771  if (LOCK_STACK_SIZE > ctx->depth) {
3772  lock_stack_t* stack;
3773 
3774  stack = &lock_stack[ctx->depth++];
3775 
3776  stack->lock = lock;
3777  stack->heap_no = heap_no;
3778  stack->wait_lock = ctx->wait_lock;
3779 
3780  return(stack);
3781  }
3782 
3783  return(NULL);
3784 }
3785 
3786 /********************************************************************/
3790 static
3791 trx_id_t
3792 lock_deadlock_search(
3793 /*=================*/
3794  lock_deadlock_ctx_t* ctx)
3795 {
3796  const lock_t* lock;
3797  ulint heap_no;
3798 
3799  ut_ad(lock_mutex_own());
3800  ut_ad(!trx_mutex_own(ctx->start));
3801 
3802  ut_ad(ctx->start != NULL);
3803  ut_ad(ctx->wait_lock != NULL);
3805  ut_ad(ctx->mark_start <= lock_mark_counter);
3806 
3807  /* Look at the locks ahead of wait_lock in the lock queue. */
3808  lock = lock_get_first_lock(ctx, &heap_no);
3809 
3810  for (;;) {
3811 
3812  /* We should never visit the same sub-tree more than once. */
3813  ut_ad(lock == NULL
3814  || lock->trx->lock.deadlock_mark <= ctx->mark_start);
3815 
3816  while (ctx->depth > 0 && lock == NULL) {
3817  const lock_stack_t* stack;
3818 
3819  /* Restore previous search state. */
3820 
3821  stack = lock_deadlock_pop(ctx);
3822 
3823  lock = stack->lock;
3824  heap_no = stack->heap_no;
3825  ctx->wait_lock = stack->wait_lock;
3826 
3827  lock = lock_get_next_lock(ctx, lock, heap_no);
3828  }
3829 
3830  if (lock == NULL) {
3831  break;
3832  } else if (lock == ctx->wait_lock) {
3833 
3834  /* We can mark this subtree as searched */
3835  ut_ad(lock->trx->lock.deadlock_mark <= ctx->mark_start);
3836 
3837  lock->trx->lock.deadlock_mark = ++lock_mark_counter;
3838 
3839  /* We are not prepared for an overflow. This 64-bit
3840  counter should never wrap around. At 10^9 increments
3841  per second, it would take 10^3 years of uptime. */
3842 
3843  ut_ad(lock_mark_counter > 0);
3844 
3845  lock = NULL;
3846 
3847  } else if (!lock_has_to_wait(ctx->wait_lock, lock)) {
3848 
3849  /* No conflict, next lock */
3850  lock = lock_get_next_lock(ctx, lock, heap_no);
3851 
3852  } else if (lock->trx == ctx->start) {
3853 
3854  /* Found a cycle. */
3855 
3856  lock_deadlock_notify(ctx, lock);
3857 
3858  return(lock_deadlock_select_victim(ctx)->id);
3859 
3860  } else if (lock_deadlock_too_deep(ctx)) {
3861 
3862  /* Search too deep to continue. */
3863 
3864  ctx->too_deep = TRUE;
3865 
3866  /* Select the joining transaction as the victim. */
3867  return(ctx->start->id);
3868 
3869  } else if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
3870 
3871  /* Another trx ahead has requested a lock in an
3872  incompatible mode, and is itself waiting for a lock. */
3873 
3874  ++ctx->cost;
3875 
3876  /* Save current search state. */
3877  if (!lock_deadlock_push(ctx, lock, heap_no)) {
3878 
3879  /* Unable to save current search state, stack
3880  size not big enough. */
3881 
3882  ctx->too_deep = TRUE;
3883 
3884  return(ctx->start->id);
3885  }
3886 
3887  ctx->wait_lock = lock->trx->lock.wait_lock;
3888  lock = lock_get_first_lock(ctx, &heap_no);
3889 
3890  if (lock->trx->lock.deadlock_mark > ctx->mark_start) {
3891  lock = lock_get_next_lock(ctx, lock, heap_no);
3892  }
3893 
3894  } else {
3895  lock = lock_get_next_lock(ctx, lock, heap_no);
3896  }
3897  }
3898 
3899  ut_a(lock == NULL && ctx->depth == 0);
3900 
3901  /* No deadlock found. */
3902  return(0);
3903 }
3904 
3905 /********************************************************************/
3907 static
3908 void
3909 lock_deadlock_joining_trx_print(
3910 /*============================*/
3911  const trx_t* trx,
3912  const lock_t* lock)
3913 {
3914  ut_ad(lock_mutex_own());
3916 
3917  /* If the lock search exceeds the max step
3918  or the max depth, the current trx will be
3919  the victim. Print its information. */
3921 
3923  "TOO DEEP OR LONG SEARCH IN THE LOCK TABLE"
3924  " WAITS-FOR GRAPH, WE WILL ROLL BACK"
3925  " FOLLOWING TRANSACTION \n\n"
3926  "*** TRANSACTION:\n");
3927 
3928  lock_deadlock_trx_print(trx, 3000);
3929 
3930  lock_deadlock_fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n");
3931 
3933 }
3934 
3935 /********************************************************************/
3937 static
3938 void
3939 lock_deadlock_trx_rollback(
3940 /*=======================*/
3941  lock_deadlock_ctx_t* ctx)
3942 {
3943  trx_t* trx;
3944 
3945  ut_ad(lock_mutex_own());
3946 
3947  trx = ctx->wait_lock->trx;
3948 
3949  lock_deadlock_fputs("*** WE ROLL BACK TRANSACTION (1)\n");
3950 
3951  trx_mutex_enter(trx);
3952 
3953  trx->lock.was_chosen_as_deadlock_victim = TRUE;
3954 
3956 
3957  trx_mutex_exit(trx);
3958 }
3959 
3960 /********************************************************************/
3968 static
3969 trx_id_t
3970 lock_deadlock_check_and_resolve(
3971 /*============================*/
3972  const lock_t* lock,
3973  const trx_t* trx)
3974 {
3975  trx_id_t victim_trx_id;
3976 
3977  ut_ad(trx != NULL);
3978  ut_ad(lock != NULL);
3979  ut_ad(lock_mutex_own());
3980  assert_trx_in_list(trx);
3981 
3982  /* Try and resolve as many deadlocks as possible. */
3983  do {
3984  lock_deadlock_ctx_t ctx;
3985 
3986  /* Reset the context. */
3987  ctx.cost = 0;
3988  ctx.depth = 0;
3989  ctx.start = trx;
3990  ctx.too_deep = FALSE;
3991  ctx.wait_lock = lock;
3992  ctx.mark_start = lock_mark_counter;
3993 
3994  victim_trx_id = lock_deadlock_search(&ctx);
3995 
3996  /* Search too deep, we rollback the joining transaction. */
3997  if (ctx.too_deep) {
3998 
3999  ut_a(trx == ctx.start);
4000  ut_a(victim_trx_id == trx->id);
4001 
4002  if (!srv_read_only_mode) {
4003  lock_deadlock_joining_trx_print(trx, lock);
4004  }
4005 
4006  MONITOR_INC(MONITOR_DEADLOCK);
4007 
4008  } else if (victim_trx_id != 0 && victim_trx_id != trx->id) {
4009 
4010  ut_ad(victim_trx_id == ctx.wait_lock->trx->id);
4011  lock_deadlock_trx_rollback(&ctx);
4012 
4013  lock_deadlock_found = TRUE;
4014 
4015  MONITOR_INC(MONITOR_DEADLOCK);
4016  }
4017 
4018  } while (victim_trx_id != 0 && victim_trx_id != trx->id);
4019 
4020  /* If the joining transaction was selected as the victim. */
4021  if (victim_trx_id != 0) {
4022  ut_a(victim_trx_id == trx->id);
4023 
4024  lock_deadlock_fputs("*** WE ROLL BACK TRANSACTION (2)\n");
4025 
4026  lock_deadlock_found = TRUE;
4027  }
4028 
4029  return(victim_trx_id);
4030 }
4031 
4032 /*========================= TABLE LOCKS ==============================*/
4033 
4034 /*********************************************************************/
4038 UNIV_INLINE
4039 lock_t*
4041 /*==============*/
4042  dict_table_t* table,
4044  ulint type_mode,
4046  trx_t* trx)
4047 {
4048  lock_t* lock;
4049 
4050  ut_ad(table && trx);
4051  ut_ad(lock_mutex_own());
4052  ut_ad(trx_mutex_own(trx));
4053  ut_ad(!(type_mode & LOCK_CONV_BY_OTHER));
4054 
4055  /* Non-locking autocommit read-only transactions should not set
4056  any locks. */
4057  assert_trx_in_list(trx);
4058 
4059  if ((type_mode & LOCK_MODE_MASK) == LOCK_AUTO_INC) {
4061  }
4062 
4063  /* For AUTOINC locking we reuse the lock instance only if
4064  there is no wait involved else we allocate the waiting lock
4065  from the transaction lock heap. */
4066  if (type_mode == LOCK_AUTO_INC) {
4067 
4068  lock = table->autoinc_lock;
4069 
4070  table->autoinc_trx = trx;
4071 
4072  ib_vector_push(trx->autoinc_locks, &lock);
4073  } else {
4074  lock = static_cast<lock_t*>(
4075  mem_heap_alloc(trx->lock.lock_heap, sizeof(*lock)));
4076  }
4077 
4078  lock->type_mode = type_mode | LOCK_TABLE;
4079  lock->trx = trx;
4080 
4081  lock->un_member.tab_lock.table = table;
4082 
4083  ut_ad(table->n_ref_count > 0 || !table->can_be_evicted);
4084 
4085  UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock);
4086  UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
4087 
4088  if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
4089 
4090  lock_set_lock_and_trx_wait(lock, trx);
4091  }
4092 
4093  ib_vector_push(lock->trx->lock.table_locks, &lock);
4094 
4095  MONITOR_INC(MONITOR_TABLELOCK_CREATED);
4096  MONITOR_INC(MONITOR_NUM_TABLELOCK);
4097 
4098  return(lock);
4099 }
4100 
4101 /*************************************************************/
4105 UNIV_INLINE
4106 void
4108 /*=========================*/
4109  trx_t* trx)
4110 {
4111  ut_ad(lock_mutex_own());
4112  ut_ad(!ib_vector_is_empty(trx->autoinc_locks));
4113 
4114  /* Skip any gaps, gaps are NULL lock entries in the
4115  trx->autoinc_locks vector. */
4116 
4117  do {
4118  ib_vector_pop(trx->autoinc_locks);
4119 
4120  if (ib_vector_is_empty(trx->autoinc_locks)) {
4121  return;
4122  }
4123 
4124  } while (*(lock_t**) ib_vector_get_last(trx->autoinc_locks) == NULL);
4125 }
4126 
4127 /*************************************************************/
4129 UNIV_INLINE
4130 void
4132 /*===========================*/
4133  lock_t* lock,
4134  trx_t* trx)
4135 {
4136  lock_t* autoinc_lock;
4137  lint i = ib_vector_size(trx->autoinc_locks) - 1;
4138 
4139  ut_ad(lock_mutex_own());
4140  ut_ad(lock_get_mode(lock) == LOCK_AUTO_INC);
4142  ut_ad(!ib_vector_is_empty(trx->autoinc_locks));
4143 
4144  /* With stored functions and procedures the user may drop
4145  a table within the same "statement". This special case has
4146  to be handled by deleting only those AUTOINC locks that were
4147  held by the table being dropped. */
4148 
4149  autoinc_lock = *static_cast<lock_t**>(
4150  ib_vector_get(trx->autoinc_locks, i));
4151 
4152  /* This is the default fast case. */
4153 
4154  if (autoinc_lock == lock) {
4156  } else {
4157  /* The last element should never be NULL */
4158  ut_a(autoinc_lock != NULL);
4159 
4160  /* Handle freeing the locks from within the stack. */
4161 
4162  while (--i >= 0) {
4163  autoinc_lock = *static_cast<lock_t**>(
4164  ib_vector_get(trx->autoinc_locks, i));
4165 
4166  if (UNIV_LIKELY(autoinc_lock == lock)) {
4167  void* null_var = NULL;
4168  ib_vector_set(trx->autoinc_locks, i, &null_var);
4169  return;
4170  }
4171  }
4172 
4173  /* Must find the autoinc lock. */
4174  ut_error;
4175  }
4176 }
4177 
4178 /*************************************************************/
4182 UNIV_INLINE
4183 void
4185 /*==================*/
4186  lock_t* lock)
4187 {
4188  trx_t* trx;
4190 
4191  ut_ad(lock_mutex_own());
4192 
4193  trx = lock->trx;
4194  table = lock->un_member.tab_lock.table;
4195 
4196  /* Remove the table from the transaction's AUTOINC vector, if
4197  the lock that is being released is an AUTOINC lock. */
4198  if (lock_get_mode(lock) == LOCK_AUTO_INC) {
4199 
4200  /* The table's AUTOINC lock can get transferred to
4201  another transaction before we get here. */
4202  if (table->autoinc_trx == trx) {
4203  table->autoinc_trx = NULL;
4204  }
4205 
4206  /* The locks must be freed in the reverse order from
4207  the one in which they were acquired. This is to avoid
4208  traversing the AUTOINC lock vector unnecessarily.
4209 
4210  We only store locks that were granted in the
4211  trx->autoinc_locks vector (see lock_table_create()
4212  and lock_grant()). Therefore it can be empty and we
4213  need to check for that. */
4214 
4215  if (!lock_get_wait(lock)
4216  && !ib_vector_is_empty(trx->autoinc_locks)) {
4217 
4218  lock_table_remove_autoinc_lock(lock, trx);
4219  }
4220 
4223  }
4224 
4225  UT_LIST_REMOVE(trx_locks, trx->lock.trx_locks, lock);
4226  UT_LIST_REMOVE(un_member.tab_lock.locks, table->locks, lock);
4227 
4228  MONITOR_INC(MONITOR_TABLELOCK_REMOVED);
4229  MONITOR_DEC(MONITOR_NUM_TABLELOCK);
4230 }
4231 
4232 /*********************************************************************/
4239 static
4240 dberr_t
4241 lock_table_enqueue_waiting(
4242 /*=======================*/
4243  ulint mode,
4245  dict_table_t* table,
4246  que_thr_t* thr)
4247 {
4248  trx_t* trx;
4249  lock_t* lock;
4250  trx_id_t victim_trx_id;
4251 
4252  ut_ad(lock_mutex_own());
4254 
4255  trx = thr_get_trx(thr);
4256  ut_ad(trx_mutex_own(trx));
4257 
4258  /* Test if there already is some other reason to suspend thread:
4259  we do not enqueue a lock request if the query thread should be
4260  stopped anyway */
4261 
4262  if (que_thr_stop(thr)) {
4263  ut_error;
4264 
4265  return(DB_QUE_THR_SUSPENDED);
4266  }
4267 
4268  switch (trx_get_dict_operation(trx)) {
4269  case TRX_DICT_OP_NONE:
4270  break;
4271  case TRX_DICT_OP_TABLE:
4272  case TRX_DICT_OP_INDEX:
4273  ut_print_timestamp(stderr);
4274  fputs(" InnoDB: Error: a table lock wait happens"
4275  " in a dictionary operation!\n"
4276  "InnoDB: Table name ", stderr);
4277  ut_print_name(stderr, trx, TRUE, table->name);
4278  fputs(".\n"
4279  "InnoDB: Submit a detailed bug report"
4280  " to http://bugs.mysql.com\n",
4281  stderr);
4282  ut_ad(0);
4283  }
4284 
4285  /* Enqueue the lock request that will wait to be granted */
4286 
4287  lock = lock_table_create(table, mode | LOCK_WAIT, trx);
4288 
4289  /* Release the mutex to obey the latching order.
4290  This is safe, because lock_deadlock_check_and_resolve()
4291  is invoked when a lock wait is enqueued for the currently
4292  running transaction. Because trx is a running transaction
4293  (it is not currently suspended because of a lock wait),
4294  its state can only be changed by this thread, which is
4295  currently associated with the transaction. */
4296 
4297  trx_mutex_exit(trx);
4298 
4299  victim_trx_id = lock_deadlock_check_and_resolve(lock, trx);
4300 
4301  trx_mutex_enter(trx);
4302 
4303  if (victim_trx_id != 0) {
4304  ut_ad(victim_trx_id == trx->id);
4305 
4306  /* The order here is important, we don't want to
4307  lose the state of the lock before calling remove. */
4308  lock_table_remove_low(lock);
4310 
4311  return(DB_DEADLOCK);
4312  } else if (trx->lock.wait_lock == NULL) {
4313  /* Deadlock resolution chose another transaction as a victim,
4314  and we accidentally got our lock granted! */
4315 
4316  return(DB_SUCCESS);
4317  }
4318 
4320 
4321  trx->lock.wait_started = ut_time();
4322  trx->lock.was_chosen_as_deadlock_victim = FALSE;
4323 
4324  ut_a(que_thr_stop(thr));
4325 
4326  MONITOR_INC(MONITOR_TABLELOCK_WAIT);
4327 
4328  return(DB_LOCK_WAIT);
4329 }
4330 
4331 /*********************************************************************/
4335 UNIV_INLINE
4336 const lock_t*
4338 /*==============================*/
4339  const trx_t* trx,
4341  ulint wait,
4344  const dict_table_t* table,
4345  enum lock_mode mode)
4346 {
4347  const lock_t* lock;
4348 
4349  ut_ad(lock_mutex_own());
4350 
4351  for (lock = UT_LIST_GET_LAST(table->locks);
4352  lock != NULL;
4353  lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock)) {
4354 
4355  if (lock->trx != trx
4356  && !lock_mode_compatible(lock_get_mode(lock), mode)
4357  && (wait || !lock_get_wait(lock))) {
4358 
4359  return(lock);
4360  }
4361  }
4362 
4363  return(NULL);
4364 }
4365 
4366 /*********************************************************************/
4370 UNIV_INTERN
4371 dberr_t
4373 /*=======*/
4374  ulint flags,
4376  dict_table_t* table,
4378  enum lock_mode mode,
4379  que_thr_t* thr)
4380 {
4381  trx_t* trx;
4382  dberr_t err;
4383  const lock_t* wait_for;
4384 
4385  ut_ad(table && thr);
4386 
4387  if (flags & BTR_NO_LOCKING_FLAG) {
4388 
4389  return(DB_SUCCESS);
4390  }
4391 
4392  ut_a(flags == 0);
4393 
4394  trx = thr_get_trx(thr);
4395 
4396  /* Look for equal or stronger locks the same trx already
4397  has on the table. No need to acquire the lock mutex here
4398  because only this transacton can add/access table locks
4399  to/from trx_t::table_locks. */
4400 
4401  if (lock_table_has(trx, table, mode)) {
4402 
4403  return(DB_SUCCESS);
4404  }
4405 
4406  lock_mutex_enter();
4407 
4408  /* We have to check if the new lock is compatible with any locks
4409  other transactions have in the table lock queue. */
4410 
4412  trx, LOCK_WAIT, table, mode);
4413 
4414  trx_mutex_enter(trx);
4415 
4416  /* Another trx has a request on the table in an incompatible
4417  mode: this trx may have to wait */
4418 
4419  if (wait_for != NULL) {
4420  err = lock_table_enqueue_waiting(mode | flags, table, thr);
4421  } else {
4422  lock_table_create(table, mode | flags, trx);
4423 
4424  ut_a(!flags || mode == LOCK_S || mode == LOCK_X);
4425 
4426  err = DB_SUCCESS;
4427  }
4428 
4429  lock_mutex_exit();
4430 
4431  trx_mutex_exit(trx);
4432 
4433  return(err);
4434 }
4435 
4436 /*********************************************************************/
4438 UNIV_INTERN
4439 void
4441 /*====================*/
4442  dict_table_t* table,
4443  trx_t* trx)
4444 {
4445  ut_ad(trx->is_recovered);
4446 
4447  if (lock_table_has(trx, table, LOCK_IX)) {
4448  return;
4449  }
4450 
4451  lock_mutex_enter();
4452 
4453  /* We have to check if the new lock is compatible with any locks
4454  other transactions have in the table lock queue. */
4455 
4457  trx, LOCK_WAIT, table, LOCK_IX));
4458 
4459  trx_mutex_enter(trx);
4460  lock_table_create(table, LOCK_IX, trx);
4461  lock_mutex_exit();
4462  trx_mutex_exit(trx);
4463 }
4464 
4465 /*********************************************************************/
4468 static
4469 ibool
4470 lock_table_has_to_wait_in_queue(
4471 /*============================*/
4472  const lock_t* wait_lock)
4473 {
4474  const dict_table_t* table;
4475  const lock_t* lock;
4476 
4477  ut_ad(lock_mutex_own());
4478  ut_ad(lock_get_wait(wait_lock));
4479 
4480  table = wait_lock->un_member.tab_lock.table;
4481 
4482  for (lock = UT_LIST_GET_FIRST(table->locks);
4483  lock != wait_lock;
4484  lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock)) {
4485 
4486  if (lock_has_to_wait(wait_lock, lock)) {
4487 
4488  return(TRUE);
4489  }
4490  }
4491 
4492  return(FALSE);
4493 }
4494 
4495 /*************************************************************/
4499 static
4500 void
4501 lock_table_dequeue(
4502 /*===============*/
4503  lock_t* in_lock)
4506 {
4507  lock_t* lock;
4508 
4509  ut_ad(lock_mutex_own());
4510  ut_a(lock_get_type_low(in_lock) == LOCK_TABLE);
4511 
4512  lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock);
4513 
4514  lock_table_remove_low(in_lock);
4515 
4516  /* Check if waiting locks in the queue can now be granted: grant
4517  locks if there are no conflicting locks ahead. */
4518 
4519  for (/* No op */;
4520  lock != NULL;
4521  lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock)) {
4522 
4523  if (lock_get_wait(lock)
4524  && !lock_table_has_to_wait_in_queue(lock)) {
4525 
4526  /* Grant the lock */
4527  ut_ad(in_lock->trx != lock->trx);
4528  lock_grant(lock);
4529  }
4530  }
4531 }
4532 
4533 /*=========================== LOCK RELEASE ==============================*/
4534 
4535 /*************************************************************/
4539 UNIV_INTERN
4540 void
4542 /*============*/
4543  trx_t* trx,
4545  const buf_block_t* block,
4546  const rec_t* rec,
4547  enum lock_mode lock_mode)
4548 {
4549  lock_t* first_lock;
4550  lock_t* lock;
4551  ulint heap_no;
4552  const char* stmt;
4553  size_t stmt_len;
4554 
4555  ut_ad(trx);
4556  ut_ad(rec);
4557  ut_ad(block->frame == page_align(rec));
4558  ut_ad(!trx->lock.wait_lock);
4559  ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
4560 
4561  heap_no = page_rec_get_heap_no(rec);
4562 
4563  lock_mutex_enter();
4564  trx_mutex_enter(trx);
4565 
4566  first_lock = lock_rec_get_first(block, heap_no);
4567 
4568  /* Find the last lock with the same lock_mode and transaction
4569  on the record. */
4570 
4571  for (lock = first_lock; lock != NULL;
4572  lock = lock_rec_get_next(heap_no, lock)) {
4573  if (lock->trx == trx && lock_get_mode(lock) == lock_mode) {
4574  goto released;
4575  }
4576  }
4577 
4578  lock_mutex_exit();
4579  trx_mutex_exit(trx);
4580 
4581  stmt = innobase_get_stmt(trx->mysql_thd, &stmt_len);
4582  ut_print_timestamp(stderr);
4583  fprintf(stderr,
4584  " InnoDB: Error: unlock row could not"
4585  " find a %lu mode lock on the record\n",
4586  (ulong) lock_mode);
4587  ut_print_timestamp(stderr);
4588  fprintf(stderr, " InnoDB: current statement: %.*s\n",
4589  (int) stmt_len, stmt);
4590 
4591  return;
4592 
4593 released:
4594  ut_a(!lock_get_wait(lock));
4595  lock_rec_reset_nth_bit(lock, heap_no);
4596 
4597  /* Check if we can now grant waiting lock requests */
4598 
4599  for (lock = first_lock; lock != NULL;
4600  lock = lock_rec_get_next(heap_no, lock)) {
4601  if (lock_get_wait(lock)
4602  && !lock_rec_has_to_wait_in_queue(lock)) {
4603 
4604  /* Grant the lock */
4605  ut_ad(trx != lock->trx);
4606  lock_grant(lock);
4607  }
4608  }
4609 
4610  lock_mutex_exit();
4611  trx_mutex_exit(trx);
4612 }
4613 
4614 /*********************************************************************/
4617 static
4618 void
4619 lock_release(
4620 /*=========*/
4621  trx_t* trx)
4622 {
4623  lock_t* lock;
4624  ulint count = 0;
4625  trx_id_t max_trx_id;
4626 
4627  ut_ad(lock_mutex_own());
4628  ut_ad(!trx_mutex_own(trx));
4629 
4630  max_trx_id = trx_sys_get_max_trx_id();
4631 
4632  for (lock = UT_LIST_GET_LAST(trx->lock.trx_locks);
4633  lock != NULL;
4634  lock = UT_LIST_GET_LAST(trx->lock.trx_locks)) {
4635 
4636  if (lock_get_type_low(lock) == LOCK_REC) {
4637 
4638 #ifdef UNIV_DEBUG
4639  /* Check if the transcation locked a record
4640  in a system table in X mode. It should have set
4641  the dict_op code correctly if it did. */
4642  if (lock->index->table->id < DICT_HDR_FIRST_ID
4643  && lock_get_mode(lock) == LOCK_X) {
4644 
4645  ut_ad(lock_get_mode(lock) != LOCK_IX);
4647  }
4648 #endif /* UNIV_DEBUG */
4649 
4650  lock_rec_dequeue_from_page(lock);
4651  } else {
4653 
4654  table = lock->un_member.tab_lock.table;
4655 #ifdef UNIV_DEBUG
4657 
4658  /* Check if the transcation locked a system table
4659  in IX mode. It should have set the dict_op code
4660  correctly if it did. */
4661  if (table->id < DICT_HDR_FIRST_ID
4662  && (lock_get_mode(lock) == LOCK_X
4663  || lock_get_mode(lock) == LOCK_IX)) {
4664 
4666  }
4667 #endif /* UNIV_DEBUG */
4668 
4669  if (lock_get_mode(lock) != LOCK_IS
4670  && trx->undo_no != 0) {
4671 
4672  /* The trx may have modified the table. We
4673  block the use of the MySQL query cache for
4674  all currently active transactions. */
4675 
4676  table->query_cache_inv_trx_id = max_trx_id;
4677  }
4678 
4679  lock_table_dequeue(lock);
4680  }
4681 
4682  if (count == LOCK_RELEASE_INTERVAL) {
4683  /* Release the mutex for a while, so that we
4684  do not monopolize it */
4685 
4686  lock_mutex_exit();
4687 
4688  lock_mutex_enter();
4689 
4690  count = 0;
4691  }
4692 
4693  ++count;
4694  }
4695 
4696  /* We don't remove the locks one by one from the vector for
4697  efficiency reasons. We simply reset it because we would have
4698  released all the locks anyway. */
4699 
4700  ib_vector_reset(trx->lock.table_locks);
4701 
4702  ut_a(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0);
4703  ut_a(ib_vector_is_empty(trx->autoinc_locks));
4705 
4707 }
4708 
4709 /* True if a lock mode is S or X */
4710 #define IS_LOCK_S_OR_X(lock) \
4711  (lock_get_mode(lock) == LOCK_S \
4712  || lock_get_mode(lock) == LOCK_X)
4713 
4714 /*********************************************************************/
4716 static
4717 void
4718 lock_trx_table_locks_remove(
4719 /*========================*/
4720  const lock_t* lock_to_remove)
4721 {
4722  lint i;
4723  trx_t* trx = lock_to_remove->trx;
4724 
4725  ut_ad(lock_mutex_own());
4726 
4727  /* It is safe to read this because we are holding the lock mutex */
4728  if (!trx->lock.cancel) {
4729  trx_mutex_enter(trx);
4730  } else {
4731  ut_ad(trx_mutex_own(trx));
4732  }
4733 
4734  for (i = ib_vector_size(trx->lock.table_locks) - 1; i >= 0; --i) {
4735  const lock_t* lock;
4736 
4737  lock = *static_cast<lock_t**>(
4738  ib_vector_get(trx->lock.table_locks, i));
4739 
4740  if (lock == NULL) {
4741  continue;
4742  }
4743 
4744  ut_a(trx == lock->trx);
4746  ut_a(lock->un_member.tab_lock.table != NULL);
4747 
4748  if (lock == lock_to_remove) {
4749  void* null_var = NULL;
4750  ib_vector_set(trx->lock.table_locks, i, &null_var);
4751 
4752  if (!trx->lock.cancel) {
4753  trx_mutex_exit(trx);
4754  }
4755 
4756  return;
4757  }
4758  }
4759 
4760  if (!trx->lock.cancel) {
4761  trx_mutex_exit(trx);
4762  }
4763 
4764  /* Lock must exist in the vector. */
4765  ut_error;
4766 }
4767 
4768 /*********************************************************************/
4773 static
4774 void
4775 lock_remove_all_on_table_for_trx(
4776 /*=============================*/
4777  dict_table_t* table,
4778  trx_t* trx,
4779  ibool remove_also_table_sx_locks)
4781 {
4782  lock_t* lock;
4783  lock_t* prev_lock;
4784 
4785  ut_ad(lock_mutex_own());
4786 
4787  for (lock = UT_LIST_GET_LAST(trx->lock.trx_locks);
4788  lock != NULL;
4789  lock = prev_lock) {
4790 
4791  prev_lock = UT_LIST_GET_PREV(trx_locks, lock);
4792 
4793  if (lock_get_type_low(lock) == LOCK_REC
4794  && lock->index->table == table) {
4795  ut_a(!lock_get_wait(lock));
4796 
4797  lock_rec_discard(lock);
4798  } else if (lock_get_type_low(lock) & LOCK_TABLE
4799  && lock->un_member.tab_lock.table == table
4800  && (remove_also_table_sx_locks
4801  || !IS_LOCK_S_OR_X(lock))) {
4802 
4803  ut_a(!lock_get_wait(lock));
4804 
4805  lock_trx_table_locks_remove(lock);
4806  lock_table_remove_low(lock);
4807  }
4808  }
4809 }
4810 
4811 /*******************************************************************/
4815 static
4816 ulint
4817 lock_remove_recovered_trx_record_locks(
4818 /*===================================*/
4819  dict_table_t* table)
4822 {
4823  trx_t* trx;
4824  ulint n_recovered_trx = 0;
4825 
4826  ut_a(table != NULL);
4827  ut_ad(lock_mutex_own());
4828 
4829  mutex_enter(&trx_sys->mutex);
4830 
4831  for (trx = UT_LIST_GET_FIRST(trx_sys->rw_trx_list);
4832  trx != NULL;
4833  trx = UT_LIST_GET_NEXT(trx_list, trx)) {
4834 
4835  lock_t* lock;
4836  lock_t* next_lock;
4837 
4838  assert_trx_in_rw_list(trx);
4839 
4840  if (!trx->is_recovered) {
4841  continue;
4842  }
4843 
4844  /* Because we are holding the lock_sys->mutex,
4845  implicit locks cannot be converted to explicit ones
4846  while we are scanning the explicit locks. */
4847 
4848  for (lock = UT_LIST_GET_FIRST(trx->lock.trx_locks);
4849  lock != NULL;
4850  lock = next_lock) {
4851 
4852  ut_a(lock->trx == trx);
4853 
4854  /* Recovered transactions can't wait on a lock. */
4855 
4856  ut_a(!lock_get_wait(lock));
4857 
4858  next_lock = UT_LIST_GET_NEXT(trx_locks, lock);
4859 
4860  switch (lock_get_type_low(lock)) {
4861  default:
4862  ut_error;
4863  case LOCK_TABLE:
4864  if (lock->un_member.tab_lock.table == table) {
4865  lock_trx_table_locks_remove(lock);
4866  lock_table_remove_low(lock);
4867  }
4868  break;
4869  case LOCK_REC:
4870  if (lock->index->table == table) {
4871  lock_rec_discard(lock);
4872  }
4873  }
4874  }
4875 
4876  ++n_recovered_trx;
4877  }
4878 
4879  mutex_exit(&trx_sys->mutex);
4880 
4881  return(n_recovered_trx);
4882 }
4883 
4884 /*********************************************************************/
4889 UNIV_INTERN
4890 void
4892 /*=====================*/
4893  dict_table_t* table,
4895  ibool remove_also_table_sx_locks)
4897 {
4898  lock_t* lock;
4899 
4900  lock_mutex_enter();
4901 
4902  for (lock = UT_LIST_GET_FIRST(table->locks);
4903  lock != NULL;
4904  /* No op */) {
4905 
4906  lock_t* prev_lock;
4907 
4908  prev_lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock);
4909 
4910  /* If we should remove all locks (remove_also_table_sx_locks
4911  is TRUE), or if the lock is not table-level S or X lock,
4912  then check we are not going to remove a wait lock. */
4913  if (remove_also_table_sx_locks
4914  || !(lock_get_type(lock) == LOCK_TABLE
4915  && IS_LOCK_S_OR_X(lock))) {
4916 
4917  ut_a(!lock_get_wait(lock));
4918  }
4919 
4920  lock_remove_all_on_table_for_trx(
4921  table, lock->trx, remove_also_table_sx_locks);
4922 
4923  if (prev_lock == NULL) {
4924  if (lock == UT_LIST_GET_FIRST(table->locks)) {
4925  /* lock was not removed, pick its successor */
4926  lock = UT_LIST_GET_NEXT(
4927  un_member.tab_lock.locks, lock);
4928  } else {
4929  /* lock was removed, pick the first one */
4930  lock = UT_LIST_GET_FIRST(table->locks);
4931  }
4932  } else if (UT_LIST_GET_NEXT(un_member.tab_lock.locks,
4933  prev_lock) != lock) {
4934  /* If lock was removed by
4935  lock_remove_all_on_table_for_trx() then pick the
4936  successor of prev_lock ... */
4937  lock = UT_LIST_GET_NEXT(
4938  un_member.tab_lock.locks, prev_lock);
4939  } else {
4940  /* ... otherwise pick the successor of lock. */
4941  lock = UT_LIST_GET_NEXT(
4942  un_member.tab_lock.locks, lock);
4943  }
4944  }
4945 
4946  /* Note: Recovered transactions don't have table level IX or IS locks
4947  but can have implicit record locks that have been converted to explicit
4948  record locks. Such record locks cannot be freed by traversing the
4949  transaction lock list in dict_table_t (as above). */
4950 
4951  if (!lock_sys->rollback_complete
4952  && lock_remove_recovered_trx_record_locks(table) == 0) {
4953 
4954  lock_sys->rollback_complete = TRUE;
4955  }
4956 
4957  lock_mutex_exit();
4958 }
4959 
4960 /*===================== VALIDATION AND DEBUGGING ====================*/
4961 
4962 /*********************************************************************/
4964 UNIV_INTERN
4965 void
4967 /*=============*/
4968  FILE* file,
4969  const lock_t* lock)
4970 {
4971  ut_ad(lock_mutex_own());
4972  ut_a(lock_get_type_low(lock) == LOCK_TABLE);
4973 
4974  fputs("TABLE LOCK table ", file);
4975  ut_print_name(file, lock->trx, TRUE,
4976  lock->un_member.tab_lock.table->name);
4977  fprintf(file, " trx id " TRX_ID_FMT, lock->trx->id);
4978 
4979  if (lock_get_mode(lock) == LOCK_S) {
4980  fputs(" lock mode S", file);
4981  } else if (lock_get_mode(lock) == LOCK_X) {
4982  fputs(" lock mode X", file);
4983  } else if (lock_get_mode(lock) == LOCK_IS) {
4984  fputs(" lock mode IS", file);
4985  } else if (lock_get_mode(lock) == LOCK_IX) {
4986  fputs(" lock mode IX", file);
4987  } else if (lock_get_mode(lock) == LOCK_AUTO_INC) {
4988  fputs(" lock mode AUTO-INC", file);
4989  } else {
4990  fprintf(file, " unknown lock mode %lu",
4991  (ulong) lock_get_mode(lock));
4992  }
4993 
4994  if (lock_get_wait(lock)) {
4995  fputs(" waiting", file);
4996  }
4997 
4998  putc('\n', file);
4999 }
5000 
5001 /*********************************************************************/
5003 UNIV_INTERN
5004 void
5006 /*===========*/
5007  FILE* file,
5008  const lock_t* lock)
5009 {
5010  const buf_block_t* block;
5011  ulint space;
5012  ulint page_no;
5013  ulint i;
5014  mtr_t mtr;
5015  mem_heap_t* heap = NULL;
5016  ulint offsets_[REC_OFFS_NORMAL_SIZE];
5017  ulint* offsets = offsets_;
5018  rec_offs_init(offsets_);
5019 
5020  ut_ad(lock_mutex_own());
5021  ut_a(lock_get_type_low(lock) == LOCK_REC);
5022 
5023  space = lock->un_member.rec_lock.space;
5024  page_no = lock->un_member.rec_lock.page_no;
5025 
5026  fprintf(file, "RECORD LOCKS space id %lu page no %lu n bits %lu ",
5027  (ulong) space, (ulong) page_no,
5028  (ulong) lock_rec_get_n_bits(lock));
5029  dict_index_name_print(file, lock->trx, lock->index);
5030  fprintf(file, " trx id " TRX_ID_FMT, lock->trx->id);
5031 
5032  if (lock_get_mode(lock) == LOCK_S) {
5033  fputs(" lock mode S", file);
5034  } else if (lock_get_mode(lock) == LOCK_X) {
5035  fputs(" lock_mode X", file);
5036  } else {
5037  ut_error;
5038  }
5039 
5040  if (lock_rec_get_gap(lock)) {
5041  fputs(" locks gap before rec", file);
5042  }
5043 
5044  if (lock_rec_get_rec_not_gap(lock)) {
5045  fputs(" locks rec but not gap", file);
5046  }
5047 
5048  if (lock_rec_get_insert_intention(lock)) {
5049  fputs(" insert intention", file);
5050  }
5051 
5052  if (lock_get_wait(lock)) {
5053  fputs(" waiting", file);
5054  }
5055 
5056  mtr_start(&mtr);
5057 
5058  putc('\n', file);
5059 
5060  block = buf_page_try_get(space, page_no, &mtr);
5061 
5062  for (i = 0; i < lock_rec_get_n_bits(lock); ++i) {
5063 
5064  if (!lock_rec_get_nth_bit(lock, i)) {
5065  continue;
5066  }
5067 
5068  fprintf(file, "Record lock, heap no %lu", (ulong) i);
5069 
5070  if (block) {
5071  const rec_t* rec;
5072 
5074  buf_block_get_frame(block), i);
5075 
5076  offsets = rec_get_offsets(
5077  rec, lock->index, offsets,
5078  ULINT_UNDEFINED, &heap);
5079 
5080  putc(' ', file);
5081  rec_print_new(file, rec, offsets);
5082  }
5083 
5084  putc('\n', file);
5085  }
5086 
5087  mtr_commit(&mtr);
5088  if (UNIV_LIKELY_NULL(heap)) {
5089  mem_heap_free(heap);
5090  }
5091 }
5092 
5093 #ifdef UNIV_DEBUG
5094 /* Print the number of lock structs from lock_print_info_summary() only
5095 in non-production builds for performance reasons, see
5096 http://bugs.mysql.com/36942 */
5097 #define PRINT_NUM_OF_LOCK_STRUCTS
5098 #endif /* UNIV_DEBUG */
5099 
5100 #ifdef PRINT_NUM_OF_LOCK_STRUCTS
5101 /*********************************************************************/
5104 static
5105 ulint
5106 lock_get_n_rec_locks(void)
5107 /*======================*/
5108 {
5109  ulint n_locks = 0;
5110  ulint i;
5111 
5112  ut_ad(lock_mutex_own());
5113 
5114  for (i = 0; i < hash_get_n_cells(lock_sys->rec_hash); i++) {
5115  const lock_t* lock;
5116 
5117  for (lock = static_cast<const lock_t*>(
5118  HASH_GET_FIRST(lock_sys->rec_hash, i));
5119  lock != 0;
5120  lock = static_cast<const lock_t*>(
5121  HASH_GET_NEXT(hash, lock))) {
5122 
5123  n_locks++;
5124  }
5125  }
5126 
5127  return(n_locks);
5128 }
5129 #endif /* PRINT_NUM_OF_LOCK_STRUCTS */
5130 
5131 /*********************************************************************/
5135 UNIV_INTERN
5136 ibool
5138 /*====================*/
5139  FILE* file,
5140  ibool nowait)
5141 {
5142  /* if nowait is FALSE, wait on the lock mutex,
5143  otherwise return immediately if fail to obtain the
5144  mutex. */
5145  if (!nowait) {
5146  lock_mutex_enter();
5147  } else if (lock_mutex_enter_nowait()) {
5148  fputs("FAIL TO OBTAIN LOCK MUTEX, "
5149  "SKIP LOCK INFO PRINTING\n", file);
5150  return(FALSE);
5151  }
5152 
5153  if (lock_deadlock_found) {
5154  fputs("------------------------\n"
5155  "LATEST DETECTED DEADLOCK\n"
5156  "------------------------\n", file);
5157 
5158  if (!srv_read_only_mode) {
5159  ut_copy_file(file, lock_latest_err_file);
5160  }
5161  }
5162 
5163  fputs("------------\n"
5164  "TRANSACTIONS\n"
5165  "------------\n", file);
5166 
5167  fprintf(file, "Trx id counter " TRX_ID_FMT "\n",
5169 
5170  fprintf(file,
5171  "Purge done for trx's n:o < " TRX_ID_FMT
5172  " undo n:o < " TRX_ID_FMT " state: ",
5173  purge_sys->iter.trx_no,
5174  purge_sys->iter.undo_no);
5175 
5176  /* Note: We are reading the state without the latch. One because it
5177  will violate the latching order and two because we are merely querying
5178  the state of the variable for display. */
5179 
5180  switch (purge_sys->state){
5181  case PURGE_STATE_EXIT:
5182  case PURGE_STATE_INIT:
5183  /* Should never be in this state while the system is running. */
5184  ut_error;
5185 
5186  case PURGE_STATE_DISABLED:
5187  fprintf(file, "disabled");
5188  break;
5189 
5190  case PURGE_STATE_RUN:
5191  fprintf(file, "running");
5192  /* Check if it is waiting for more data to arrive. */
5193  if (!purge_sys->running) {
5194  fprintf(file, " but idle");
5195  }
5196  break;
5197 
5198  case PURGE_STATE_STOP:
5199  fprintf(file, "stopped");
5200  break;
5201  }
5202 
5203  fprintf(file, "\n");
5204 
5205  fprintf(file,
5206  "History list length %lu\n",
5207  (ulong) trx_sys->rseg_history_len);
5208 
5209 #ifdef PRINT_NUM_OF_LOCK_STRUCTS
5210  fprintf(file,
5211  "Total number of lock structs in row lock hash table %lu\n",
5212  (ulong) lock_get_n_rec_locks());
5213 #endif /* PRINT_NUM_OF_LOCK_STRUCTS */
5214  return(TRUE);
5215 }
5216 
5217 /*********************************************************************/
5221 UNIV_INTERN
5222 void
5224 /*=============================*/
5225  FILE* file)
5226 {
5227  const lock_t* lock;
5228  ibool load_page_first = TRUE;
5229  ulint nth_trx = 0;
5230  ulint nth_lock = 0;
5231  ulint i;
5232  mtr_t mtr;
5233  const trx_t* trx;
5234  trx_list_t* trx_list = &trx_sys->rw_trx_list;
5235 
5236  fprintf(file, "LIST OF TRANSACTIONS FOR EACH SESSION:\n");
5237 
5238  ut_ad(lock_mutex_own());
5239 
5240  mutex_enter(&trx_sys->mutex);
5241 
5242  /* First print info on non-active transactions */
5243 
5244  /* NOTE: information of auto-commit non-locking read-only
5245  transactions will be omitted here. The information will be
5246  available from INFORMATION_SCHEMA.INNODB_TRX. */
5247 
5249  trx != NULL;
5250  trx = UT_LIST_GET_NEXT(mysql_trx_list, trx)) {
5251 
5252  ut_ad(trx->in_mysql_trx_list);
5253 
5254  /* See state transitions and locking rules in trx0trx.h */
5255 
5256  if (trx_state_eq(trx, TRX_STATE_NOT_STARTED)) {
5257  fputs("---", file);
5258  trx_print_latched(file, trx, 600);
5259  }
5260  }
5261 
5262 loop:
5263  /* Since we temporarily release lock_sys->mutex and
5264  trx_sys->mutex when reading a database page in below,
5265  variable trx may be obsolete now and we must loop
5266  through the trx list to get probably the same trx,
5267  or some other trx. */
5268 
5269  for (trx = UT_LIST_GET_FIRST(*trx_list), i = 0;
5270  trx && (i < nth_trx);
5271  trx = UT_LIST_GET_NEXT(trx_list, trx), i++) {
5272 
5273  assert_trx_in_list(trx);
5274  ut_ad(trx->read_only == (trx_list == &trx_sys->ro_trx_list));
5275  }
5276 
5277  ut_ad(trx == NULL
5278  || trx->read_only == (trx_list == &trx_sys->ro_trx_list));
5279 
5280  if (trx == NULL) {
5281  /* Check the read-only transaction list next. */
5282  if (trx_list == &trx_sys->rw_trx_list) {
5283  trx_list = &trx_sys->ro_trx_list;
5284  nth_trx = 0;
5285  nth_lock = 0;
5286  goto loop;
5287  }
5288 
5289  lock_mutex_exit();
5290  mutex_exit(&trx_sys->mutex);
5291 
5292  ut_ad(lock_validate());
5293 
5294  return;
5295  }
5296 
5297  assert_trx_in_list(trx);
5298 
5299  if (nth_lock == 0) {
5300  fputs("---", file);
5301 
5302  trx_print_latched(file, trx, 600);
5303 
5304  if (trx->read_view) {
5305  fprintf(file,
5306  "Trx read view will not see trx with"
5307  " id >= " TRX_ID_FMT
5308  ", sees < " TRX_ID_FMT "\n",
5309  trx->read_view->low_limit_id,
5310  trx->read_view->up_limit_id);
5311  }
5312 
5313  if (trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
5314 
5315  fprintf(file,
5316  "------- TRX HAS BEEN WAITING %lu SEC"
5317  " FOR THIS LOCK TO BE GRANTED:\n",
5318  (ulong) difftime(ut_time(),
5319  trx->lock.wait_started));
5320 
5321  if (lock_get_type_low(trx->lock.wait_lock) == LOCK_REC) {
5322  lock_rec_print(file, trx->lock.wait_lock);
5323  } else {
5324  lock_table_print(file, trx->lock.wait_lock);
5325  }
5326 
5327  fputs("------------------\n", file);
5328  }
5329  }
5330 
5331  if (!srv_print_innodb_lock_monitor) {
5332  nth_trx++;
5333  goto loop;
5334  }
5335 
5336  i = 0;
5337 
5338  /* Look at the note about the trx loop above why we loop here:
5339  lock may be an obsolete pointer now. */
5340 
5341  lock = UT_LIST_GET_FIRST(trx->lock.trx_locks);
5342 
5343  while (lock && (i < nth_lock)) {
5344  lock = UT_LIST_GET_NEXT(trx_locks, lock);
5345  i++;
5346  }
5347 
5348  if (lock == NULL) {
5349  nth_trx++;
5350  nth_lock = 0;
5351 
5352  goto loop;
5353  }
5354 
5355  if (lock_get_type_low(lock) == LOCK_REC) {
5356  if (load_page_first) {
5357  ulint space = lock->un_member.rec_lock.space;
5358  ulint zip_size= fil_space_get_zip_size(space);
5359  ulint page_no = lock->un_member.rec_lock.page_no;
5360 
5361  if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
5362 
5363  /* It is a single table tablespace and
5364  the .ibd file is missing (TRUNCATE
5365  TABLE probably stole the locks): just
5366  print the lock without attempting to
5367  load the page in the buffer pool. */
5368 
5369  fprintf(file, "RECORD LOCKS on"
5370  " non-existing space %lu\n",
5371  (ulong) space);
5372  goto print_rec;
5373  }
5374 
5375  lock_mutex_exit();
5376  mutex_exit(&trx_sys->mutex);
5377 
5378  mtr_start(&mtr);
5379 
5381  space, zip_size, page_no, &mtr);
5382 
5383  mtr_commit(&mtr);
5384 
5385  load_page_first = FALSE;
5386 
5387  lock_mutex_enter();
5388 
5389  mutex_enter(&trx_sys->mutex);
5390 
5391  goto loop;
5392  }
5393 
5394 print_rec:
5395  lock_rec_print(file, lock);
5396  } else {
5398 
5399  lock_table_print(file, lock);
5400  }
5401 
5402  load_page_first = TRUE;
5403 
5404  nth_lock++;
5405 
5406  if (nth_lock >= 10) {
5407  fputs("10 LOCKS PRINTED FOR THIS TRX:"
5408  " SUPPRESSING FURTHER PRINTS\n",
5409  file);
5410 
5411  nth_trx++;
5412  nth_lock = 0;
5413  }
5414 
5415  goto loop;
5416 }
5417 
5418 #ifdef UNIV_DEBUG
5419 /*********************************************************************/
5422 static
5423 ibool
5424 lock_trx_table_locks_find(
5425 /*======================*/
5426  trx_t* trx,
5427  const lock_t* find_lock)
5428 {
5429  lint i;
5430  ibool found = FALSE;
5431 
5432  trx_mutex_enter(trx);
5433 
5434  for (i = ib_vector_size(trx->lock.table_locks) - 1; i >= 0; --i) {
5435  const lock_t* lock;
5436 
5437  lock = *static_cast<const lock_t**>(
5438  ib_vector_get(trx->lock.table_locks, i));
5439 
5440  if (lock == NULL) {
5441  continue;
5442  } else if (lock == find_lock) {
5443  /* Can't be duplicates. */
5444  ut_a(!found);
5445  found = TRUE;
5446  }
5447 
5448  ut_a(trx == lock->trx);
5450  ut_a(lock->un_member.tab_lock.table != NULL);
5451  }
5452 
5453  trx_mutex_exit(trx);
5454 
5455  return(found);
5456 }
5457 
5458 /*********************************************************************/
5461 static
5462 ibool
5463 lock_table_queue_validate(
5464 /*======================*/
5465  const dict_table_t* table)
5466 {
5467  const lock_t* lock;
5468 
5469  ut_ad(lock_mutex_own());
5470  ut_ad(mutex_own(&trx_sys->mutex));
5471 
5472  for (lock = UT_LIST_GET_FIRST(table->locks);
5473  lock != NULL;
5474  lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock)) {
5475 
5476  /* lock->trx->state cannot change from or to NOT_STARTED
5477  while we are holding the trx_sys->mutex. It may change
5478  from ACTIVE to PREPARED, but it may not change to
5479  COMMITTED, because we are holding the lock_sys->mutex. */
5480  ut_ad(trx_assert_started(lock->trx));
5481 
5482  if (!lock_get_wait(lock)) {
5483 
5485  lock->trx, 0, table,
5486  lock_get_mode(lock)));
5487  } else {
5488 
5489  ut_a(lock_table_has_to_wait_in_queue(lock));
5490  }
5491 
5492  ut_a(lock_trx_table_locks_find(lock->trx, lock));
5493  }
5494 
5495  return(TRUE);
5496 }
5497 
5498 /*********************************************************************/
5501 static
5502 ibool
5503 lock_rec_queue_validate(
5504 /*====================*/
5505  ibool locked_lock_trx_sys,
5509  const buf_block_t* block,
5510  const rec_t* rec,
5511  const dict_index_t* index,
5512  const ulint* offsets)
5513 {
5514  const trx_t* impl_trx;
5515  const lock_t* lock;
5516  ulint heap_no;
5517 
5518  ut_a(rec);
5519  ut_a(block->frame == page_align(rec));
5520  ut_ad(rec_offs_validate(rec, index, offsets));
5521  ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
5522  ut_ad(lock_mutex_own() == locked_lock_trx_sys);
5523  ut_ad(!index || dict_index_is_clust(index)
5524  || !dict_index_is_online_ddl(index));
5525 
5526  heap_no = page_rec_get_heap_no(rec);
5527 
5528  if (!locked_lock_trx_sys) {
5529  lock_mutex_enter();
5530  mutex_enter(&trx_sys->mutex);
5531  }
5532 
5533  if (!page_rec_is_user_rec(rec)) {
5534 
5535  for (lock = lock_rec_get_first(block, heap_no);
5536  lock != NULL;
5537  lock = lock_rec_get_next_const(heap_no, lock)) {
5538 
5539  ut_a(trx_in_trx_list(lock->trx));
5540 
5541  if (lock_get_wait(lock)) {
5542  ut_a(lock_rec_has_to_wait_in_queue(lock));
5543  }
5544 
5545  if (index) {
5546  ut_a(lock->index == index);
5547  }
5548  }
5549 
5550  goto func_exit;
5551  }
5552 
5553  if (!index);
5554  else if (dict_index_is_clust(index)) {
5555  trx_id_t trx_id;
5556 
5557  /* Unlike the non-debug code, this invariant can only succeed
5558  if the check and assertion are covered by the lock mutex. */
5559 
5560  trx_id = lock_clust_rec_some_has_impl(rec, index, offsets);
5561  impl_trx = trx_rw_is_active_low(trx_id, NULL);
5562 
5563  ut_ad(lock_mutex_own());
5564  /* impl_trx cannot be committed until lock_mutex_exit()
5565  because lock_trx_release_locks() acquires lock_sys->mutex */
5566 
5567  if (impl_trx != NULL
5568  && lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,
5569  block, heap_no, impl_trx)) {
5570 
5572  block, heap_no, impl_trx));
5573  }
5574  }
5575 
5576  for (lock = lock_rec_get_first(block, heap_no);
5577  lock != NULL;
5578  lock = lock_rec_get_next_const(heap_no, lock)) {
5579 
5580  ut_a(trx_in_trx_list(lock->trx));
5581 
5582  if (index) {
5583  ut_a(lock->index == index);
5584  }
5585 
5586  if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) {
5587 
5588  enum lock_mode mode;
5589 
5590  if (lock_get_mode(lock) == LOCK_S) {
5591  mode = LOCK_X;
5592  } else {
5593  mode = LOCK_S;
5594  }
5595  ut_a(!lock_rec_other_has_expl_req(
5596  mode, 0, 0, block, heap_no, lock->trx));
5597 
5598  } else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) {
5599 
5600  ut_a(lock_rec_has_to_wait_in_queue(lock));
5601  }
5602  }
5603 
5604 func_exit:
5605  if (!locked_lock_trx_sys) {
5606  lock_mutex_exit();
5607  mutex_exit(&trx_sys->mutex);
5608  }
5609 
5610  return(TRUE);
5611 }
5612 
5613 /*********************************************************************/
5616 static
5617 ibool
5618 lock_rec_validate_page(
5619 /*===================*/
5620  const buf_block_t* block)
5621 {
5622  const lock_t* lock;
5623  const rec_t* rec;
5624  ulint nth_lock = 0;
5625  ulint nth_bit = 0;
5626  ulint i;
5627  mem_heap_t* heap = NULL;
5628  ulint offsets_[REC_OFFS_NORMAL_SIZE];
5629  ulint* offsets = offsets_;
5630  rec_offs_init(offsets_);
5631 
5632  ut_ad(!lock_mutex_own());
5633 
5634  lock_mutex_enter();
5635  mutex_enter(&trx_sys->mutex);
5636 loop:
5638  buf_block_get_page_no(block));
5639 
5640  if (!lock) {
5641  goto function_exit;
5642  }
5643 
5644 #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
5645  ut_a(!block->page.file_page_was_freed);
5646 #endif
5647 
5648  for (i = 0; i < nth_lock; i++) {
5649 
5650  lock = lock_rec_get_next_on_page_const(lock);
5651 
5652  if (!lock) {
5653  goto function_exit;
5654  }
5655  }
5656 
5657  ut_a(trx_in_trx_list(lock->trx));
5658 
5659 # ifdef UNIV_SYNC_DEBUG
5660  /* Only validate the record queues when this thread is not
5661  holding a space->latch. Deadlocks are possible due to
5662  latching order violation when UNIV_DEBUG is defined while
5663  UNIV_SYNC_DEBUG is not. */
5664  if (!sync_thread_levels_contains(SYNC_FSP))
5665 # endif /* UNIV_SYNC_DEBUG */
5666  for (i = nth_bit; i < lock_rec_get_n_bits(lock); i++) {
5667 
5668  if (i == 1 || lock_rec_get_nth_bit(lock, i)) {
5669 
5670  rec = page_find_rec_with_heap_no(block->frame, i);
5671  ut_a(rec);
5672  offsets = rec_get_offsets(rec, lock->index, offsets,
5673  ULINT_UNDEFINED, &heap);
5674 #if 0
5675  fprintf(stderr,
5676  "Validating %u %u\n",
5677  block->page.space, block->page.offset);
5678 #endif
5679  /* If this thread is holding the file space
5680  latch (fil_space_t::latch), the following
5681  check WILL break the latching order and may
5682  cause a deadlock of threads. */
5683 
5684  lock_rec_queue_validate(
5685  TRUE, block, rec, lock->index, offsets);
5686 
5687  nth_bit = i + 1;
5688 
5689  goto loop;
5690  }
5691  }
5692 
5693  nth_bit = 0;
5694  nth_lock++;
5695 
5696  goto loop;
5697 
5698 function_exit:
5699  lock_mutex_exit();
5700  mutex_exit(&trx_sys->mutex);
5701 
5702  if (UNIV_LIKELY_NULL(heap)) {
5703  mem_heap_free(heap);
5704  }
5705  return(TRUE);
5706 }
5707 
5708 /*********************************************************************/
5711 static
5712 ibool
5713 lock_validate_table_locks(
5714 /*======================*/
5715  const trx_list_t* trx_list)
5716 {
5717  const trx_t* trx;
5718 
5719  ut_ad(lock_mutex_own());
5720  ut_ad(mutex_own(&trx_sys->mutex));
5721 
5722  ut_ad(trx_list == &trx_sys->rw_trx_list
5723  || trx_list == &trx_sys->ro_trx_list);
5724 
5725  for (trx = UT_LIST_GET_FIRST(*trx_list);
5726  trx != NULL;
5727  trx = UT_LIST_GET_NEXT(trx_list, trx)) {
5728 
5729  const lock_t* lock;
5730 
5731  assert_trx_in_list(trx);
5732  ut_ad(trx->read_only == (trx_list == &trx_sys->ro_trx_list));
5733 
5734  for (lock = UT_LIST_GET_FIRST(trx->lock.trx_locks);
5735  lock != NULL;
5736  lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
5737 
5738  if (lock_get_type_low(lock) & LOCK_TABLE) {
5739 
5740  lock_table_queue_validate(
5741  lock->un_member.tab_lock.table);
5742  }
5743  }
5744  }
5745 
5746  return(TRUE);
5747 }
5748 
5749 /*********************************************************************/
5752 static __attribute__((nonnull, warn_unused_result))
5753 const lock_t*
5754 lock_rec_validate(
5755 /*==============*/
5756  ulint start,
5758  ib_uint64_t* limit)
5760 {
5761  ut_ad(lock_mutex_own());
5762  ut_ad(mutex_own(&trx_sys->mutex));
5763 
5764  for (const lock_t* lock = static_cast<const lock_t*>(
5765  HASH_GET_FIRST(lock_sys->rec_hash, start));
5766  lock != NULL;
5767  lock = static_cast<const lock_t*>(HASH_GET_NEXT(hash, lock))) {
5768 
5769  ib_uint64_t current;
5770 
5771  ut_a(trx_in_trx_list(lock->trx));
5772  ut_a(lock_get_type(lock) == LOCK_REC);
5773 
5774  current = ut_ull_create(
5775  lock->un_member.rec_lock.space,
5776  lock->un_member.rec_lock.page_no);
5777 
5778  if (current > *limit) {
5779  *limit = current + 1;
5780  return(lock);
5781  }
5782  }
5783 
5784  return(0);
5785 }
5786 
5787 /*********************************************************************/
5789 static
5790 void
5791 lock_rec_block_validate(
5792 /*====================*/
5793  ulint space,
5794  ulint page_no)
5795 {
5796  /* The lock and the block that it is referring to may be freed at
5797  this point. We pass BUF_GET_POSSIBLY_FREED to skip a debug check.
5798  If the lock exists in lock_rec_validate_page() we assert
5799  !block->page.file_page_was_freed. */
5800 
5801  buf_block_t* block;
5802  mtr_t mtr;
5803 
5804  /* Make sure that the tablespace is not deleted while we are
5805  trying to access the page. */
5806  if (!fil_inc_pending_ops(space)) {
5807  mtr_start(&mtr);
5808  block = buf_page_get_gen(
5809  space, fil_space_get_zip_size(space),
5810  page_no, RW_X_LATCH, NULL,
5812  __FILE__, __LINE__, &mtr);
5813 
5814  buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
5815 
5816  ut_ad(lock_rec_validate_page(block));
5817  mtr_commit(&mtr);
5818 
5819  fil_decr_pending_ops(space);
5820  }
5821 }
5822 
5823 /*********************************************************************/
5826 static
5827 bool
5828 lock_validate()
5829 /*===========*/
5830 {
5831  typedef std::pair<ulint, ulint> page_addr_t;
5832  typedef std::set<page_addr_t> page_addr_set;
5833  page_addr_set pages;
5834 
5835  lock_mutex_enter();
5836  mutex_enter(&trx_sys->mutex);
5837 
5838  ut_a(lock_validate_table_locks(&trx_sys->rw_trx_list));
5839  ut_a(lock_validate_table_locks(&trx_sys->ro_trx_list));
5840 
5841  /* Iterate over all the record locks and validate the locks. We
5842  don't want to hog the lock_sys_t::mutex and the trx_sys_t::mutex.
5843  Release both mutexes during the validation check. */
5844 
5845  for (ulint i = 0; i < hash_get_n_cells(lock_sys->rec_hash); i++) {
5846  const lock_t* lock;
5847  ib_uint64_t limit = 0;
5848 
5849  while ((lock = lock_rec_validate(i, &limit)) != 0) {
5850 
5851  ulint space = lock->un_member.rec_lock.space;
5852  ulint page_no = lock->un_member.rec_lock.page_no;
5853 
5854  pages.insert(std::make_pair(space, page_no));
5855  }
5856  }
5857 
5858  mutex_exit(&trx_sys->mutex);
5859  lock_mutex_exit();
5860 
5861  for (page_addr_set::const_iterator it = pages.begin();
5862  it != pages.end();
5863  ++it) {
5864  lock_rec_block_validate((*it).first, (*it).second);
5865  }
5866 
5867  return(true);
5868 }
5869 #endif /* UNIV_DEBUG */
5870 /*============ RECORD LOCK CHECKS FOR ROW OPERATIONS ====================*/
5871 
5872 /*********************************************************************/
5879 UNIV_INTERN
5880 dberr_t
5882 /*===========================*/
5883  ulint flags,
5885  const rec_t* rec,
5886  buf_block_t* block,
5887  dict_index_t* index,
5888  que_thr_t* thr,
5889  mtr_t* mtr,
5890  ibool* inherit)
5894 {
5895  const rec_t* next_rec;
5896  trx_t* trx;
5897  lock_t* lock;
5898  dberr_t err;
5899  ulint next_rec_heap_no;
5900 
5901  ut_ad(block->frame == page_align(rec));
5903  || dict_index_is_clust(index)
5904  || (flags & BTR_CREATE_FLAG));
5905 
5906  if (flags & BTR_NO_LOCKING_FLAG) {
5907 
5908  return(DB_SUCCESS);
5909  }
5910 
5911  trx = thr_get_trx(thr);
5912  next_rec = page_rec_get_next_const(rec);
5913  next_rec_heap_no = page_rec_get_heap_no(next_rec);
5914 
5915  lock_mutex_enter();
5916  /* Because this code is invoked for a running transaction by
5917  the thread that is serving the transaction, it is not necessary
5918  to hold trx->mutex here. */
5919 
5920  /* When inserting a record into an index, the table must be at
5921  least IX-locked. When we are building an index, we would pass
5922  BTR_NO_LOCKING_FLAG and skip the locking altogether. */
5923  ut_ad(lock_table_has(trx, index->table, LOCK_IX));
5924 
5925  lock = lock_rec_get_first(block, next_rec_heap_no);
5926 
5927  if (UNIV_LIKELY(lock == NULL)) {
5928  /* We optimize CPU time usage in the simplest case */
5929 
5930  lock_mutex_exit();
5931 
5932  if (!dict_index_is_clust(index)) {
5933  /* Update the page max trx id field */
5934  page_update_max_trx_id(block,
5935  buf_block_get_page_zip(block),
5936  trx->id, mtr);
5937  }
5938 
5939  *inherit = FALSE;
5940 
5941  return(DB_SUCCESS);
5942  }
5943 
5944  *inherit = TRUE;
5945 
5946  /* If another transaction has an explicit lock request which locks
5947  the gap, waiting or granted, on the successor, the insert has to wait.
5948 
5949  An exception is the case where the lock by the another transaction
5950  is a gap type lock which it placed to wait for its turn to insert. We
5951  do not consider that kind of a lock conflicting with our insert. This
5952  eliminates an unnecessary deadlock which resulted when 2 transactions
5953  had to wait for their insert. Both had waiting gap type lock requests
5954  on the successor, which produced an unnecessary deadlock. */
5955 
5956  if (lock_rec_other_has_conflicting(
5957  static_cast<enum lock_mode>(
5958  LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION),
5959  block, next_rec_heap_no, trx)) {
5960 
5961  /* Note that we may get DB_SUCCESS also here! */
5962  trx_mutex_enter(trx);
5963 
5964  err = lock_rec_enqueue_waiting(
5965  LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,
5966  block, next_rec_heap_no, NULL, index, thr);
5967 
5968  trx_mutex_exit(trx);
5969  } else {
5970  err = DB_SUCCESS;
5971  }
5972 
5973  lock_mutex_exit();
5974 
5975  switch (err) {
5976  case DB_SUCCESS_LOCKED_REC:
5977  err = DB_SUCCESS;
5978  /* fall through */
5979  case DB_SUCCESS:
5980  if (dict_index_is_clust(index)) {
5981  break;
5982  }
5983  /* Update the page max trx id field */
5984  page_update_max_trx_id(block,
5985  buf_block_get_page_zip(block),
5986  trx->id, mtr);
5987  default:
5988  /* We only care about the two return values. */
5989  break;
5990  }
5991 
5992 #ifdef UNIV_DEBUG
5993  {
5994  mem_heap_t* heap = NULL;
5995  ulint offsets_[REC_OFFS_NORMAL_SIZE];
5996  const ulint* offsets;
5997  rec_offs_init(offsets_);
5998 
5999  offsets = rec_get_offsets(next_rec, index, offsets_,
6000  ULINT_UNDEFINED, &heap);
6001 
6002  ut_ad(lock_rec_queue_validate(
6003  FALSE, block, next_rec, index, offsets));
6004 
6005  if (UNIV_LIKELY_NULL(heap)) {
6006  mem_heap_free(heap);
6007  }
6008  }
6009 #endif /* UNIV_DEBUG */
6010 
6011  return(err);
6012 }
6013 
6014 /*********************************************************************/
6017 static
6018 void
6019 lock_rec_convert_impl_to_expl(
6020 /*==========================*/
6021  const buf_block_t* block,
6022  const rec_t* rec,
6023  dict_index_t* index,
6024  const ulint* offsets)
6025 {
6026  trx_id_t trx_id;
6027 
6028  ut_ad(!lock_mutex_own());
6030  ut_ad(rec_offs_validate(rec, index, offsets));
6031  ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
6032 
6033  if (dict_index_is_clust(index)) {
6034  trx_id = lock_clust_rec_some_has_impl(rec, index, offsets);
6035  /* The clustered index record was last modified by
6036  this transaction. The transaction may have been
6037  committed a long time ago. */
6038  } else {
6040  trx_id = lock_sec_rec_some_has_impl(rec, index, offsets);
6041  /* The transaction can be committed before the
6042  trx_is_active(trx_id, NULL) check below, because we are not
6043  holding lock_mutex. */
6044  }
6045 
6046  if (trx_id != 0) {
6047  trx_t* impl_trx;
6048  ulint heap_no = page_rec_get_heap_no(rec);
6049 
6050  lock_mutex_enter();
6051 
6052  /* If the transaction is still active and has no
6053  explicit x-lock set on the record, set one for it */
6054 
6055  impl_trx = trx_rw_is_active(trx_id, NULL);
6056 
6057  /* impl_trx cannot be committed until lock_mutex_exit()
6058  because lock_trx_release_locks() acquires lock_sys->mutex */
6059 
6060  if (impl_trx != NULL
6061  && !lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, block,
6062  heap_no, impl_trx)) {
6063  ulint type_mode = (LOCK_REC | LOCK_X
6064  | LOCK_REC_NOT_GAP);
6065 
6066  /* If the delete-marked record was locked already,
6067  we should reserve lock waiting for impl_trx as
6068  implicit lock. Because cannot lock at this moment.*/
6069 
6070  if (rec_get_deleted_flag(rec, rec_offs_comp(offsets))
6071  && lock_rec_other_has_conflicting(
6072  static_cast<enum lock_mode>
6073  (LOCK_X | LOCK_REC_NOT_GAP), block,
6074  heap_no, impl_trx)) {
6075 
6076  type_mode |= (LOCK_WAIT
6077  | LOCK_CONV_BY_OTHER);
6078  }
6079 
6080  lock_rec_add_to_queue(
6081  type_mode, block, heap_no, index,
6082  impl_trx, FALSE);
6083  }
6084 
6085  lock_mutex_exit();
6086  }
6087 }
6088 
6089 /*********************************************************************/
6097 UNIV_INTERN
6098 dberr_t
6100 /*=================================*/
6101  ulint flags,
6103  const buf_block_t* block,
6104  const rec_t* rec,
6106  dict_index_t* index,
6107  const ulint* offsets,
6108  que_thr_t* thr)
6109 {
6110  dberr_t err;
6111  ulint heap_no;
6112 
6113  ut_ad(rec_offs_validate(rec, index, offsets));
6114  ut_ad(dict_index_is_clust(index));
6115  ut_ad(block->frame == page_align(rec));
6116 
6117  if (flags & BTR_NO_LOCKING_FLAG) {
6118 
6119  return(DB_SUCCESS);
6120  }
6121 
6122  heap_no = rec_offs_comp(offsets)
6123  ? rec_get_heap_no_new(rec)
6124  : rec_get_heap_no_old(rec);
6125 
6126  /* If a transaction has no explicit x-lock set on the record, set one
6127  for it */
6128 
6129  lock_rec_convert_impl_to_expl(block, rec, index, offsets);
6130 
6131  lock_mutex_enter();
6132 
6133  ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
6134 
6135  err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP,
6136  block, heap_no, index, thr);
6137 
6138  MONITOR_INC(MONITOR_NUM_RECLOCK_REQ);
6139 
6140  lock_mutex_exit();
6141 
6142  ut_ad(lock_rec_queue_validate(FALSE, block, rec, index, offsets));
6143 
6144  if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) {
6145  err = DB_SUCCESS;
6146  }
6147 
6148  return(err);
6149 }
6150 
6151 /*********************************************************************/
6155 UNIV_INTERN
6156 dberr_t
6158 /*===============================*/
6159  ulint flags,
6161  buf_block_t* block,
6162  const rec_t* rec,
6167  dict_index_t* index,
6168  que_thr_t* thr,
6170  mtr_t* mtr)
6171 {
6172  dberr_t err;
6173  ulint heap_no;
6174 
6175  ut_ad(!dict_index_is_clust(index));
6176  ut_ad(!dict_index_is_online_ddl(index) || (flags & BTR_CREATE_FLAG));
6177  ut_ad(block->frame == page_align(rec));
6178 
6179  if (flags & BTR_NO_LOCKING_FLAG) {
6180 
6181  return(DB_SUCCESS);
6182  }
6183 
6184  heap_no = page_rec_get_heap_no(rec);
6185 
6186  /* Another transaction cannot have an implicit lock on the record,
6187  because when we come here, we already have modified the clustered
6188  index record, and this would not have been possible if another active
6189  transaction had modified this secondary index record. */
6190 
6191  lock_mutex_enter();
6192 
6193  ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
6194 
6195  err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP,
6196  block, heap_no, index, thr);
6197 
6198  MONITOR_INC(MONITOR_NUM_RECLOCK_REQ);
6199 
6200  lock_mutex_exit();
6201 
6202 #ifdef UNIV_DEBUG
6203  {
6204  mem_heap_t* heap = NULL;
6205  ulint offsets_[REC_OFFS_NORMAL_SIZE];
6206  const ulint* offsets;
6207  rec_offs_init(offsets_);
6208 
6209  offsets = rec_get_offsets(rec, index, offsets_,
6210  ULINT_UNDEFINED, &heap);
6211 
6212  ut_ad(lock_rec_queue_validate(
6213  FALSE, block, rec, index, offsets));
6214 
6215  if (UNIV_LIKELY_NULL(heap)) {
6216  mem_heap_free(heap);
6217  }
6218  }
6219 #endif /* UNIV_DEBUG */
6220 
6221  if (err == DB_SUCCESS || err == DB_SUCCESS_LOCKED_REC) {
6222  /* Update the page max trx id field */
6223  /* It might not be necessary to do this if
6224  err == DB_SUCCESS (no new lock created),
6225  but it should not cost too much performance. */
6226  page_update_max_trx_id(block,
6227  buf_block_get_page_zip(block),
6228  thr_get_trx(thr)->id, mtr);
6229  err = DB_SUCCESS;
6230  }
6231 
6232  return(err);
6233 }
6234 
6235 /*********************************************************************/
6240 UNIV_INTERN
6241 dberr_t
6243 /*=============================*/
6244  ulint flags,
6246  const buf_block_t* block,
6247  const rec_t* rec,
6251  dict_index_t* index,
6252  const ulint* offsets,
6253  enum lock_mode mode,
6258  ulint gap_mode,
6260  que_thr_t* thr)
6261 {
6262  dberr_t err;
6263  ulint heap_no;
6264 
6265  ut_ad(!dict_index_is_clust(index));
6267  ut_ad(block->frame == page_align(rec));
6269  ut_ad(rec_offs_validate(rec, index, offsets));
6270  ut_ad(mode == LOCK_X || mode == LOCK_S);
6271 
6272  if (flags & BTR_NO_LOCKING_FLAG) {
6273 
6274  return(DB_SUCCESS);
6275  }
6276 
6277  heap_no = page_rec_get_heap_no(rec);
6278 
6279  /* Some transaction may have an implicit x-lock on the record only
6280  if the max trx id for the page >= min trx id for the trx list or a
6281  database recovery is running. */
6282 
6283  if ((page_get_max_trx_id(block->frame) >= trx_rw_min_trx_id()
6284  || recv_recovery_is_on())
6285  && !page_rec_is_supremum(rec)) {
6286 
6287  lock_rec_convert_impl_to_expl(block, rec, index, offsets);
6288  }
6289 
6290  lock_mutex_enter();
6291 
6292  ut_ad(mode != LOCK_X
6293  || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
6294  ut_ad(mode != LOCK_S
6295  || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
6296 
6297  err = lock_rec_lock(FALSE, mode | gap_mode,
6298  block, heap_no, index, thr);
6299 
6300  MONITOR_INC(MONITOR_NUM_RECLOCK_REQ);
6301 
6302  lock_mutex_exit();
6303 
6304  ut_ad(lock_rec_queue_validate(FALSE, block, rec, index, offsets));
6305 
6306  return(err);
6307 }
6308 
6309 /*********************************************************************/
6318 UNIV_INTERN
6319 dberr_t
6321 /*===============================*/
6322  ulint flags,
6324  const buf_block_t* block,
6325  const rec_t* rec,
6329  dict_index_t* index,
6330  const ulint* offsets,
6331  enum lock_mode mode,
6336  ulint gap_mode,
6338  que_thr_t* thr)
6339 {
6340  dberr_t err;
6341  ulint heap_no;
6342 
6343  ut_ad(dict_index_is_clust(index));
6344  ut_ad(block->frame == page_align(rec));
6346  ut_ad(gap_mode == LOCK_ORDINARY || gap_mode == LOCK_GAP
6347  || gap_mode == LOCK_REC_NOT_GAP);
6348  ut_ad(rec_offs_validate(rec, index, offsets));
6349 
6350  if (flags & BTR_NO_LOCKING_FLAG) {
6351 
6352  return(DB_SUCCESS);
6353  }
6354 
6355  heap_no = page_rec_get_heap_no(rec);
6356 
6357  if (UNIV_LIKELY(heap_no != PAGE_HEAP_NO_SUPREMUM)) {
6358 
6359  lock_rec_convert_impl_to_expl(block, rec, index, offsets);
6360  }
6361 
6362  lock_mutex_enter();
6363 
6364  ut_ad(mode != LOCK_X
6365  || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
6366  ut_ad(mode != LOCK_S
6367  || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
6368 
6369  err = lock_rec_lock(FALSE, mode | gap_mode,
6370  block, heap_no, index, thr);
6371 
6372  MONITOR_INC(MONITOR_NUM_RECLOCK_REQ);
6373 
6374  lock_mutex_exit();
6375 
6376  ut_ad(lock_rec_queue_validate(FALSE, block, rec, index, offsets));
6377 
6378  return(err);
6379 }
6380 /*********************************************************************/
6390 UNIV_INTERN
6391 dberr_t
6393 /*===================================*/
6394  ulint flags,
6396  const buf_block_t* block,
6397  const rec_t* rec,
6401  dict_index_t* index,
6402  enum lock_mode mode,
6407  ulint gap_mode,
6409  que_thr_t* thr)
6410 {
6411  mem_heap_t* tmp_heap = NULL;
6412  ulint offsets_[REC_OFFS_NORMAL_SIZE];
6413  ulint* offsets = offsets_;
6414  dberr_t err;
6415  rec_offs_init(offsets_);
6416 
6417  offsets = rec_get_offsets(rec, index, offsets,
6418  ULINT_UNDEFINED, &tmp_heap);
6419  err = lock_clust_rec_read_check_and_lock(flags, block, rec, index,
6420  offsets, mode, gap_mode, thr);
6421  if (tmp_heap) {
6422  mem_heap_free(tmp_heap);
6423  }
6424 
6425  if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) {
6426  err = DB_SUCCESS;
6427  }
6428 
6429  return(err);
6430 }
6431 
6432 /*******************************************************************/
6434 UNIV_INLINE
6435 void
6437 /*===========================*/
6438  ib_vector_t* autoinc_locks)
6439 {
6440  ulint last;
6441  lock_t* lock;
6442 
6443  ut_ad(lock_mutex_own());
6444  ut_a(!ib_vector_is_empty(autoinc_locks));
6445 
6446  /* The lock to be release must be the last lock acquired. */
6447  last = ib_vector_size(autoinc_locks) - 1;
6448  lock = *static_cast<lock_t**>(ib_vector_get(autoinc_locks, last));
6449 
6450  /* Should have only AUTOINC locks in the vector. */
6451  ut_a(lock_get_mode(lock) == LOCK_AUTO_INC);
6452  ut_a(lock_get_type(lock) == LOCK_TABLE);
6453 
6454  ut_a(lock->un_member.tab_lock.table != NULL);
6455 
6456  /* This will remove the lock from the trx autoinc_locks too. */
6457  lock_table_dequeue(lock);
6458 
6459  /* Remove from the table vector too. */
6460  lock_trx_table_locks_remove(lock);
6461 }
6462 
6463 /*******************************************************************/
6466 static
6467 ibool
6468 lock_trx_holds_autoinc_locks(
6469 /*=========================*/
6470  const trx_t* trx)
6471 {
6472  ut_a(trx->autoinc_locks != NULL);
6473 
6474  return(!ib_vector_is_empty(trx->autoinc_locks));
6475 }
6476 
6477 /*******************************************************************/
6479 static
6480 void
6481 lock_release_autoinc_locks(
6482 /*=======================*/
6483  trx_t* trx)
6484 {
6485  ut_ad(lock_mutex_own());
6486  /* If this is invoked for a running transaction by the thread
6487  that is serving the transaction, then it is not necessary to
6488  hold trx->mutex here. */
6489 
6490  ut_a(trx->autoinc_locks != NULL);
6491 
6492  /* We release the locks in the reverse order. This is to
6493  avoid searching the vector for the element to delete at
6494  the lower level. See (lock_table_remove_low()) for details. */
6495  while (!ib_vector_is_empty(trx->autoinc_locks)) {
6496 
6497  /* lock_table_remove_low() will also remove the lock from
6498  the transaction's autoinc_locks vector. */
6499  lock_release_autoinc_last_lock(trx->autoinc_locks);
6500  }
6501 
6502  /* Should release all locks. */
6503  ut_a(ib_vector_is_empty(trx->autoinc_locks));
6504 }
6505 
6506 /*******************************************************************/
6510 UNIV_INTERN
6511 ulint
6513 /*==========*/
6514  const lock_t* lock)
6515 {
6516  return(lock_get_type_low(lock));
6517 }
6518 
6519 /*******************************************************************/
6522 UNIV_INTERN
6523 trx_id_t
6525 /*============*/
6526  const lock_t* lock)
6527 {
6528  return(lock->trx->id);
6529 }
6530 
6531 /*******************************************************************/
6535 UNIV_INTERN
6536 const char*
6538 /*==============*/
6539  const lock_t* lock)
6540 {
6541  ibool is_gap_lock;
6542 
6543  is_gap_lock = lock_get_type_low(lock) == LOCK_REC
6544  && lock_rec_get_gap(lock);
6545 
6546  switch (lock_get_mode(lock)) {
6547  case LOCK_S:
6548  if (is_gap_lock) {
6549  return("S,GAP");
6550  } else {
6551  return("S");
6552  }
6553  case LOCK_X:
6554  if (is_gap_lock) {
6555  return("X,GAP");
6556  } else {
6557  return("X");
6558  }
6559  case LOCK_IS:
6560  if (is_gap_lock) {
6561  return("IS,GAP");
6562  } else {
6563  return("IS");
6564  }
6565  case LOCK_IX:
6566  if (is_gap_lock) {
6567  return("IX,GAP");
6568  } else {
6569  return("IX");
6570  }
6571  case LOCK_AUTO_INC:
6572  return("AUTO_INC");
6573  default:
6574  return("UNKNOWN");
6575  }
6576 }
6577 
6578 /*******************************************************************/
6582 UNIV_INTERN
6583 const char*
6585 /*==============*/
6586  const lock_t* lock)
6587 {
6588  switch (lock_get_type_low(lock)) {
6589  case LOCK_REC:
6590  return("RECORD");
6591  case LOCK_TABLE:
6592  return("TABLE");
6593  default:
6594  return("UNKNOWN");
6595  }
6596 }
6597 
6598 /*******************************************************************/
6601 UNIV_INLINE
6602 dict_table_t*
6604 /*===========*/
6605  const lock_t* lock)
6606 {
6607  switch (lock_get_type_low(lock)) {
6608  case LOCK_REC:
6610  || !dict_index_is_online_ddl(lock->index));
6611  return(lock->index->table);
6612  case LOCK_TABLE:
6613  return(lock->un_member.tab_lock.table);
6614  default:
6615  ut_error;
6616  return(NULL);
6617  }
6618 }
6619 
6620 /*******************************************************************/
6623 UNIV_INTERN
6624 table_id_t
6626 /*==============*/
6627  const lock_t* lock)
6628 {
6630 
6631  table = lock_get_table(lock);
6632 
6633  return(table->id);
6634 }
6635 
6636 /*******************************************************************/
6640 UNIV_INTERN
6641 const char*
6643 /*================*/
6644  const lock_t* lock)
6645 {
6647 
6648  table = lock_get_table(lock);
6649 
6650  return(table->name);
6651 }
6652 
6653 /*******************************************************************/
6656 UNIV_INTERN
6657 const dict_index_t*
6659 /*===============*/
6660  const lock_t* lock)
6661 {
6662  ut_a(lock_get_type_low(lock) == LOCK_REC);
6664  || !dict_index_is_online_ddl(lock->index));
6665 
6666  return(lock->index);
6667 }
6668 
6669 /*******************************************************************/
6673 UNIV_INTERN
6674 const char*
6676 /*====================*/
6677  const lock_t* lock)
6678 {
6679  ut_a(lock_get_type_low(lock) == LOCK_REC);
6681  || !dict_index_is_online_ddl(lock->index));
6682 
6683  return(lock->index->name);
6684 }
6685 
6686 /*******************************************************************/
6689 UNIV_INTERN
6690 ulint
6692 /*==================*/
6693  const lock_t* lock)
6694 {
6695  ut_a(lock_get_type_low(lock) == LOCK_REC);
6696 
6697  return(lock->un_member.rec_lock.space);
6698 }
6699 
6700 /*******************************************************************/
6703 UNIV_INTERN
6704 ulint
6706 /*=================*/
6707  const lock_t* lock)
6708 {
6709  ut_a(lock_get_type_low(lock) == LOCK_REC);
6710 
6711  return(lock->un_member.rec_lock.page_no);
6712 }
6713 
6714 /*********************************************************************/
6717 UNIV_INTERN
6718 void
6720 /*============================*/
6721  lock_t* lock)
6722 {
6723  que_thr_t* thr;
6724 
6725  ut_ad(lock_mutex_own());
6726  ut_ad(trx_mutex_own(lock->trx));
6727  ut_ad(!(lock->type_mode & LOCK_CONV_BY_OTHER));
6728 
6729  lock->trx->lock.cancel = TRUE;
6730 
6731  if (lock_get_type_low(lock) == LOCK_REC) {
6732 
6733  lock_rec_dequeue_from_page(lock);
6734  } else {
6736 
6737  if (lock->trx->autoinc_locks != NULL) {
6738  /* Release the transaction's AUTOINC locks. */
6739  lock_release_autoinc_locks(lock->trx);
6740  }
6741 
6742  lock_table_dequeue(lock);
6743  }
6744 
6745  /* Reset the wait flag and the back pointer to lock in trx. */
6746 
6748 
6749  /* The following function releases the trx from lock wait. */
6750 
6751  thr = que_thr_end_lock_wait(lock->trx);
6752 
6753  if (thr != NULL) {
6755  }
6756 
6757  lock->trx->lock.cancel = FALSE;
6758 }
6759 
6760 /*********************************************************************/
6764 UNIV_INTERN
6765 void
6767 /*======================*/
6768  trx_t* trx)
6769 {
6770  ut_ad(!lock_mutex_own());
6771  ut_ad(!trx_mutex_own(trx));
6772  ut_ad(!trx->lock.wait_lock);
6773  /* This can be invoked on NOT_STARTED, ACTIVE, PREPARED,
6774  but not COMMITTED transactions. */
6775  ut_ad(trx_state_eq(trx, TRX_STATE_NOT_STARTED)
6776  || !trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY));
6777 
6778  /* This function is invoked for a running transaction by the
6779  thread that is serving the transaction. Therefore it is not
6780  necessary to hold trx->mutex here. */
6781 
6782  if (lock_trx_holds_autoinc_locks(trx)) {
6783  lock_mutex_enter();
6784 
6785  lock_release_autoinc_locks(trx);
6786 
6787  lock_mutex_exit();
6788  }
6789 }
6790 
6791 /*********************************************************************/
6795 UNIV_INTERN
6796 void
6798 /*===================*/
6799  trx_t* trx)
6800 {
6801  assert_trx_in_list(trx);
6802 
6803  if (trx_state_eq(trx, TRX_STATE_PREPARED)) {
6804  mutex_enter(&trx_sys->mutex);
6805  ut_a(trx_sys->n_prepared_trx > 0);
6807  if (trx->is_recovered) {
6810  }
6811  mutex_exit(&trx_sys->mutex);
6812  } else {
6813  ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
6814  }
6815 
6816  /* The transition of trx->state to TRX_STATE_COMMITTED_IN_MEMORY
6817  is protected by both the lock_sys->mutex and the trx->mutex. */
6818  lock_mutex_enter();
6819  trx_mutex_enter(trx);
6820 
6821  /* The following assignment makes the transaction committed in memory
6822  and makes its changes to data visible to other transactions.
6823  NOTE that there is a small discrepancy from the strict formal
6824  visibility rules here: a human user of the database can see
6825  modifications made by another transaction T even before the necessary
6826  log segment has been flushed to the disk. If the database happens to
6827  crash before the flush, the user has seen modifications from T which
6828  will never be a committed transaction. However, any transaction T2
6829  which sees the modifications of the committing transaction T, and
6830  which also itself makes modifications to the database, will get an lsn
6831  larger than the committing transaction T. In the case where the log
6832  flush fails, and T never gets committed, also T2 will never get
6833  committed. */
6834 
6835  /*--------------------------------------*/
6836  trx->state = TRX_STATE_COMMITTED_IN_MEMORY;
6837  /*--------------------------------------*/
6838 
6839  /* If the background thread trx_rollback_or_clean_recovered()
6840  is still active then there is a chance that the rollback
6841  thread may see this trx as COMMITTED_IN_MEMORY and goes ahead
6842  to clean it up calling trx_cleanup_at_db_startup(). This can
6843  happen in the case we are committing a trx here that is left
6844  in PREPARED state during the crash. Note that commit of the
6845  rollback of a PREPARED trx happens in the recovery thread
6846  while the rollback of other transactions happen in the
6847  background thread. To avoid this race we unconditionally unset
6848  the is_recovered flag. */
6849 
6850  trx->is_recovered = FALSE;
6851 
6852  trx_mutex_exit(trx);
6853 
6854  lock_release(trx);
6855 
6856  lock_mutex_exit();
6857 }
6858 
6859 /*********************************************************************/
6864 UNIV_INTERN
6865 dberr_t
6867 /*=================*/
6868  trx_t* trx)
6869 {
6870  dberr_t err;
6871 
6872  lock_mutex_enter();
6873 
6874  trx_mutex_enter(trx);
6875 
6877  err = DB_DEADLOCK;
6878  } else if (trx->lock.wait_lock != NULL) {
6880  err = DB_LOCK_WAIT;
6881  } else {
6882  /* The lock was probably granted before we got here. */
6883  err = DB_SUCCESS;
6884  }
6885 
6886  lock_mutex_exit();
6887  trx_mutex_exit(trx);
6888 
6889  return(err);
6890 }
6891 
6892 /*********************************************************************/
6895 UNIV_INTERN
6896 ulint
6898 /*===================*/
6899  const dict_table_t* table)
6900 {
6901  ulint n_table_locks;
6902 
6903  lock_mutex_enter();
6904 
6905  n_table_locks = UT_LIST_GET_LEN(table->locks);
6906 
6907  lock_mutex_exit();
6908 
6909  return(n_table_locks);
6910 }
6911 
6912 #ifdef UNIV_DEBUG
6913 /*******************************************************************/
6916 static
6917 const lock_t*
6918 lock_table_locks_lookup(
6919 /*====================*/
6920  const dict_table_t* table,
6924  const trx_list_t* trx_list)
6925 {
6926  trx_t* trx;
6927 
6928  ut_a(table != NULL);
6929  ut_ad(lock_mutex_own());
6930  ut_ad(mutex_own(&trx_sys->mutex));
6931 
6932  ut_ad(trx_list == &trx_sys->rw_trx_list
6933  || trx_list == &trx_sys->ro_trx_list);
6934 
6935  for (trx = UT_LIST_GET_FIRST(*trx_list);
6936  trx != NULL;
6937  trx = UT_LIST_GET_NEXT(trx_list, trx)) {
6938 
6939  const lock_t* lock;
6940 
6941  assert_trx_in_list(trx);
6942  ut_ad(trx->read_only == (trx_list == &trx_sys->ro_trx_list));
6943 
6944  for (lock = UT_LIST_GET_FIRST(trx->lock.trx_locks);
6945  lock != NULL;
6946  lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
6947 
6948  ut_a(lock->trx == trx);
6949 
6950  if (lock_get_type_low(lock) == LOCK_REC) {
6952  || dict_index_is_clust(lock->index));
6953  if (lock->index->table == table) {
6954  return(lock);
6955  }
6956  } else if (lock->un_member.tab_lock.table == table) {
6957  return(lock);
6958  }
6959  }
6960  }
6961 
6962  return(NULL);
6963 }
6964 #endif /* UNIV_DEBUG */
6965 
6966 /*******************************************************************/
6969 UNIV_INTERN
6970 ibool
6972 /*=================*/
6973  const dict_table_t* table)
6976 {
6977  ibool has_locks;
6978 
6979  lock_mutex_enter();
6980 
6981  has_locks = UT_LIST_GET_LEN(table->locks) > 0 || table->n_rec_locks > 0;
6982 
6983 #ifdef UNIV_DEBUG
6984  if (!has_locks) {
6985  mutex_enter(&trx_sys->mutex);
6986 
6987  ut_ad(!lock_table_locks_lookup(table, &trx_sys->rw_trx_list));
6988  ut_ad(!lock_table_locks_lookup(table, &trx_sys->ro_trx_list));
6989 
6990  mutex_exit(&trx_sys->mutex);
6991  }
6992 #endif /* UNIV_DEBUG */
6993 
6994  lock_mutex_exit();
6995 
6996  return(has_locks);
6997 }
6998 
6999 #ifdef UNIV_DEBUG
7000 /*******************************************************************/
7004 UNIV_INTERN
7005 const lock_t*
7006 lock_trx_has_sys_table_locks(
7007 /*=========================*/
7008  const trx_t* trx)
7009 {
7010  lint i;
7011  const lock_t* strongest_lock = 0;
7012  lock_mode strongest = LOCK_NONE;
7013 
7014  lock_mutex_enter();
7015 
7016  /* Find a valid mode. Note: ib_vector_size() can be 0. */
7017  for (i = ib_vector_size(trx->lock.table_locks) - 1; i >= 0; --i) {
7018  const lock_t* lock;
7019 
7020  lock = *static_cast<const lock_t**>(
7021  ib_vector_get(trx->lock.table_locks, i));
7022 
7023  if (lock != NULL
7025 
7026  strongest = lock_get_mode(lock);
7027  ut_ad(strongest != LOCK_NONE);
7028  strongest_lock = lock;
7029  break;
7030  }
7031  }
7032 
7033  if (strongest == LOCK_NONE) {
7034  lock_mutex_exit();
7035  return(NULL);
7036  }
7037 
7038  for (/* No op */; i >= 0; --i) {
7039  const lock_t* lock;
7040 
7041  lock = *static_cast<const lock_t**>(
7042  ib_vector_get(trx->lock.table_locks, i));
7043 
7044  if (lock == NULL) {
7045  continue;
7046  }
7047 
7048  ut_ad(trx == lock->trx);
7050  ut_ad(lock->un_member.tab_lock.table != NULL);
7051 
7052  lock_mode mode = lock_get_mode(lock);
7053 
7055  && lock_mode_stronger_or_eq(mode, strongest)) {
7056 
7057  strongest = mode;
7058  strongest_lock = lock;
7059  }
7060  }
7061 
7062  lock_mutex_exit();
7063 
7064  return(strongest_lock);
7065 }
7066 
7067 /*******************************************************************/
7070 UNIV_INTERN
7071 bool
7072 lock_trx_has_rec_x_lock(
7073 /*====================*/
7074  const trx_t* trx,
7075  const dict_table_t* table,
7076  const buf_block_t* block,
7077  ulint heap_no)
7078 {
7079  ut_ad(heap_no > PAGE_HEAP_NO_SUPREMUM);
7080 
7081  lock_mutex_enter();
7082  ut_a(lock_table_has(trx, table, LOCK_IX));
7084  block, heap_no, trx));
7085  lock_mutex_exit();
7086  return(true);
7087 }
7088 #endif /* UNIV_DEBUG */