1 /*****************************************************************************
2 
3 Copyright (c) 1996, 2021, Oracle and/or its affiliates.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8 
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation.  The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License, version 2.0, for more details.
20 
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
24 
25 *****************************************************************************/
26 
27 /**************************************************//**
28 @file include/lock0lock.h
29 The transaction lock system
30 
31 Created 5/7/1996 Heikki Tuuri
32 *******************************************************/
33 
34 #ifndef lock0lock_h
35 #define lock0lock_h
36 
37 #include "univ.i"
38 #include "buf0types.h"
39 #include "trx0types.h"
40 #include "mtr0types.h"
41 #include "rem0types.h"
42 #include "dict0types.h"
43 #include "que0types.h"
44 #include "lock0types.h"
45 #include "hash0hash.h"
46 #include "srv0srv.h"
47 #include "ut0vec.h"
48 #include "gis0rtree.h"
49 #include "lock0prdt.h"
50 
51 // Forward declaration
52 class ReadView;
53 
54 extern my_bool	innobase_deadlock_detect;
55 
56 /*********************************************************************//**
57 Gets the size of a lock struct.
58 @return size in bytes */
59 ulint
60 lock_get_size(void);
61 /*===============*/
62 /*********************************************************************//**
63 Creates the lock system at database start. */
64 void
65 lock_sys_create(
66 /*============*/
67 	ulint	n_cells);	/*!< in: number of slots in lock hash table */
68 /** Resize the lock hash table.
69 @param[in]	n_cells	number of slots in lock hash table */
70 void
71 lock_sys_resize(
72 	ulint	n_cells);
73 
74 /*********************************************************************//**
75 Closes the lock system at database shutdown. */
76 void
77 lock_sys_close(void);
78 /*================*/
79 /*********************************************************************//**
80 Gets the heap_no of the smallest user record on a page.
81 @return heap_no of smallest user record, or PAGE_HEAP_NO_SUPREMUM */
82 UNIV_INLINE
83 ulint
84 lock_get_min_heap_no(
85 /*=================*/
86 	const buf_block_t*	block);	/*!< in: buffer block */
87 /*************************************************************//**
88 Updates the lock table when we have reorganized a page. NOTE: we copy
89 also the locks set on the infimum of the page; the infimum may carry
90 locks if an update of a record is occurring on the page, and its locks
91 were temporarily stored on the infimum. */
92 void
93 lock_move_reorganize_page(
94 /*======================*/
95 	const buf_block_t*	block,	/*!< in: old index page, now
96 					reorganized */
97 	const buf_block_t*	oblock);/*!< in: copy of the old, not
98 					reorganized page */
99 /*************************************************************//**
100 Moves the explicit locks on user records to another page if a record
101 list end is moved to another page. */
102 void
103 lock_move_rec_list_end(
104 /*===================*/
105 	const buf_block_t*	new_block,	/*!< in: index page to move to */
106 	const buf_block_t*	block,		/*!< in: index page */
107 	const rec_t*		rec);		/*!< in: record on page: this
108 						is the first record moved */
109 /*************************************************************//**
110 Moves the explicit locks on user records to another page if a record
111 list start is moved to another page. */
112 void
113 lock_move_rec_list_start(
114 /*=====================*/
115 	const buf_block_t*	new_block,	/*!< in: index page to move to */
116 	const buf_block_t*	block,		/*!< in: index page */
117 	const rec_t*		rec,		/*!< in: record on page:
118 						this is the first
119 						record NOT copied */
120 	const rec_t*		old_end);	/*!< in: old
121 						previous-to-last
122 						record on new_page
123 						before the records
124 						were copied */
125 /*************************************************************//**
126 Updates the lock table when a page is split to the right. */
127 void
128 lock_update_split_right(
129 /*====================*/
130 	const buf_block_t*	right_block,	/*!< in: right page */
131 	const buf_block_t*	left_block);	/*!< in: left page */
132 /*************************************************************//**
133 Updates the lock table when a page is merged to the right. */
134 void
135 lock_update_merge_right(
136 /*====================*/
137 	const buf_block_t*	right_block,	/*!< in: right page to
138 						which merged */
139 	const rec_t*		orig_succ,	/*!< in: original
140 						successor of infimum
141 						on the right page
142 						before merge */
143 	const buf_block_t*	left_block);	/*!< in: merged index
144 						page which will be
145 						discarded */
146 /*************************************************************//**
147 Updates the lock table when the root page is copied to another in
148 btr_root_raise_and_insert. Note that we leave lock structs on the
149 root page, even though they do not make sense on other than leaf
150 pages: the reason is that in a pessimistic update the infimum record
151 of the root page will act as a dummy carrier of the locks of the record
152 to be updated. */
153 void
154 lock_update_root_raise(
155 /*===================*/
156 	const buf_block_t*	block,	/*!< in: index page to which copied */
157 	const buf_block_t*	root);	/*!< in: root page */
158 /*************************************************************//**
159 Updates the lock table when a page is copied to another and the original page
160 is removed from the chain of leaf pages, except if page is the root! */
161 void
162 lock_update_copy_and_discard(
163 /*=========================*/
164 	const buf_block_t*	new_block,	/*!< in: index page to
165 						which copied */
166 	const buf_block_t*	block);		/*!< in: index page;
167 						NOT the root! */
168 /*************************************************************//**
169 Updates the lock table when a page is split to the left. */
170 void
171 lock_update_split_left(
172 /*===================*/
173 	const buf_block_t*	right_block,	/*!< in: right page */
174 	const buf_block_t*	left_block);	/*!< in: left page */
175 /*************************************************************//**
176 Updates the lock table when a page is merged to the left. */
177 void
178 lock_update_merge_left(
179 /*===================*/
180 	const buf_block_t*	left_block,	/*!< in: left page to
181 						which merged */
182 	const rec_t*		orig_pred,	/*!< in: original predecessor
183 						of supremum on the left page
184 						before merge */
185 	const buf_block_t*	right_block);	/*!< in: merged index page
186 						which will be discarded */
187 /*************************************************************//**
188 Resets the original locks on heir and replaces them with gap type locks
189 inherited from rec. */
190 void
191 lock_rec_reset_and_inherit_gap_locks(
192 /*=================================*/
193 	const buf_block_t*	heir_block,	/*!< in: block containing the
194 						record which inherits */
195 	const buf_block_t*	block,		/*!< in: block containing the
196 						record from which inherited;
197 						does NOT reset the locks on
198 						this record */
199 	ulint			heir_heap_no,	/*!< in: heap_no of the
200 						inheriting record */
201 	ulint			heap_no);	/*!< in: heap_no of the
202 						donating record */
203 /*************************************************************//**
204 Updates the lock table when a page is discarded. */
205 void
206 lock_update_discard(
207 /*================*/
208 	const buf_block_t*	heir_block,	/*!< in: index page
209 						which will inherit the locks */
210 	ulint			heir_heap_no,	/*!< in: heap_no of the record
211 						which will inherit the locks */
212 	const buf_block_t*	block);		/*!< in: index page
213 						which will be discarded */
214 /*************************************************************//**
215 Updates the lock table when a new user record is inserted. */
216 void
217 lock_update_insert(
218 /*===============*/
219 	const buf_block_t*	block,	/*!< in: buffer block containing rec */
220 	const rec_t*		rec);	/*!< in: the inserted record */
221 /*************************************************************//**
222 Updates the lock table when a record is removed. */
223 void
224 lock_update_delete(
225 /*===============*/
226 	const buf_block_t*	block,	/*!< in: buffer block containing rec */
227 	const rec_t*		rec);	/*!< in: the record to be removed */
228 /*********************************************************************//**
229 Stores on the page infimum record the explicit locks of another record.
230 This function is used to store the lock state of a record when it is
231 updated and the size of the record changes in the update. The record
232 is in such an update moved, perhaps to another page. The infimum record
233 acts as a dummy carrier record, taking care of lock releases while the
234 actual record is being moved. */
235 void
236 lock_rec_store_on_page_infimum(
237 /*===========================*/
238 	const buf_block_t*	block,	/*!< in: buffer block containing rec */
239 	const rec_t*		rec);	/*!< in: record whose lock state
240 					is stored on the infimum
241 					record of the same page; lock
242 					bits are reset on the
243 					record */
244 /*********************************************************************//**
245 Restores the state of explicit lock requests on a single record, where the
246 state was stored on the infimum of the page. */
247 void
248 lock_rec_restore_from_page_infimum(
249 /*===============================*/
250 	const buf_block_t*	block,	/*!< in: buffer block containing rec */
251 	const rec_t*		rec,	/*!< in: record whose lock state
252 					is restored */
253 	const buf_block_t*	donator);/*!< in: page (rec is not
254 					necessarily on this page)
255 					whose infimum stored the lock
256 					state; lock bits are reset on
257 					the infimum */
258 /*********************************************************************//**
259 Determines if there are explicit record locks on a page.
260 @return an explicit record lock on the page, or NULL if there are none */
261 lock_t*
262 lock_rec_expl_exist_on_page(
263 /*========================*/
264 	ulint	space,	/*!< in: space id */
265 	ulint	page_no)/*!< in: page number */
266 	MY_ATTRIBUTE((warn_unused_result));
267 /*********************************************************************//**
268 Checks if locks of other transactions prevent an immediate insert of
269 a record. If they do, first tests if the query thread should anyway
270 be suspended for some reason; if not, then puts the transaction and
271 the query thread to the lock wait state and inserts a waiting request
272 for a gap x-lock to the lock queue.
273 @return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
274 dberr_t
275 lock_rec_insert_check_and_lock(
276 /*===========================*/
277 	ulint		flags,	/*!< in: if BTR_NO_LOCKING_FLAG bit is
278 				set, does nothing */
279 	const rec_t*	rec,	/*!< in: record after which to insert */
280 	buf_block_t*	block,	/*!< in/out: buffer block of rec */
281 	dict_index_t*	index,	/*!< in: index */
282 	que_thr_t*	thr,	/*!< in: query thread */
283 	mtr_t*		mtr,	/*!< in/out: mini-transaction */
284 	ibool*		inherit)/*!< out: set to TRUE if the new
285 				inserted record maybe should inherit
286 				LOCK_GAP type locks from the successor
287 				record */
288 	MY_ATTRIBUTE((warn_unused_result));
289 
290 /*********************************************************************//**
291 Enqueues a waiting request for a lock which cannot be granted immediately.
292 Checks for deadlocks.
293 @return DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED, or
294 DB_SUCCESS_LOCKED_REC; DB_SUCCESS_LOCKED_REC means that
295 there was a deadlock, but another transaction was chosen as a victim,
296 and we got the lock immediately: no need to wait then */
297 dberr_t
298 lock_rec_enqueue_waiting(
299 /*=====================*/
300 	ulint			type_mode,/*!< in: lock mode this
301 					transaction is requesting:
302 					LOCK_S or LOCK_X, possibly
303 					ORed with LOCK_GAP or
304 					LOCK_REC_NOT_GAP, ORed with
305 					LOCK_INSERT_INTENTION if this
306 					waiting lock request is set
307 					when performing an insert of
308 					an index record */
309 	const buf_block_t*	block,	/*!< in: buffer block containing
310 					the record */
311 	ulint			heap_no,/*!< in: heap number of the record */
312 	dict_index_t*		index,	/*!< in: index of record */
313 	que_thr_t*		thr,	/*!< in: query thread */
314 	lock_prdt_t*		prdt);	/*!< in: Minimum Bounding Box */
315 
316 /*************************************************************//**
317 Removes a record lock request, waiting or granted, from the queue and
318 grants locks to other transactions in the queue if they now are entitled
319 to a lock. NOTE: all record locks contained in in_lock are removed. */
320 void
321 lock_rec_dequeue_from_page(
322 /*=======================*/
323         lock_t*         in_lock);        /*!< in: record lock object: all
324                                         record locks which are contained in
325                                         this lock object are removed;
326                                         transactions waiting behind will
327                                         get their lock requests granted,
328                                         if they are now qualified to it */
329 
330 /*************************************************************//**
331 Moves the locks of a record to another record and resets the lock bits of
332 the donating record. */
333 UNIV_INLINE
334 void
335 lock_rec_move(
336 /*==========*/
337         const buf_block_t*      receiver,       /*!< in: buffer block containing
338                                                 the receiving record */
339         const buf_block_t*      donator,        /*!< in: buffer block containing
340                                                 the donating record */
341         ulint                   receiver_heap_no,/*!< in: heap_no of the record
342                                                 which gets the locks; there
343                                                 must be no lock requests
344                                                 on it! */
345         ulint                   donator_heap_no);/*!< in: heap_no of the record
346                                                 which gives the locks */
347 
348 /*************************************************************//**
349 Moves the locks of a record to another record and resets the lock bits of
350 the donating record. */
351 void
352 lock_rec_move_low(
353 /*==============*/
354 	hash_table_t*		lock_hash,	/*!< in: hash  table to use */
355         const buf_block_t*      receiver,       /*!< in: buffer block containing
356                                                 the receiving record */
357         const buf_block_t*      donator,        /*!< in: buffer block containing
358                                                 the donating record */
359         ulint                   receiver_heap_no,/*!< in: heap_no of the record
360                                                 which gets the locks; there
361                                                 must be no lock requests
362                                                 on it! */
363         ulint                   donator_heap_no);/*!< in: heap_no of the record
364                                                 which gives the locks */
365 /*********************************************************************//**
366 Checks if locks of other transactions prevent an immediate modify (update,
367 delete mark, or delete unmark) of a clustered index record. If they do,
368 first tests if the query thread should anyway be suspended for some
369 reason; if not, then puts the transaction and the query thread to the
370 lock wait state and inserts a waiting request for a record x-lock to the
371 lock queue.
372 @return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
373 dberr_t
374 lock_clust_rec_modify_check_and_lock(
375 /*=================================*/
376 	ulint			flags,	/*!< in: if BTR_NO_LOCKING_FLAG
377 					bit is set, does nothing */
378 	const buf_block_t*	block,	/*!< in: buffer block of rec */
379 	const rec_t*		rec,	/*!< in: record which should be
380 					modified */
381 	dict_index_t*		index,	/*!< in: clustered index */
382 	const ulint*		offsets,/*!< in: rec_get_offsets(rec, index) */
383 	que_thr_t*		thr)	/*!< in: query thread */
384 	MY_ATTRIBUTE((warn_unused_result));
385 /*********************************************************************//**
386 Checks if locks of other transactions prevent an immediate modify
387 (delete mark or delete unmark) of a secondary index record.
388 @return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
389 dberr_t
390 lock_sec_rec_modify_check_and_lock(
391 /*===============================*/
392 	ulint		flags,	/*!< in: if BTR_NO_LOCKING_FLAG
393 				bit is set, does nothing */
394 	buf_block_t*	block,	/*!< in/out: buffer block of rec */
395 	const rec_t*	rec,	/*!< in: record which should be
396 				modified; NOTE: as this is a secondary
397 				index, we always have to modify the
398 				clustered index record first: see the
399 				comment below */
400 	dict_index_t*	index,	/*!< in: secondary index */
401 	que_thr_t*	thr,	/*!< in: query thread
402 				(can be NULL if BTR_NO_LOCKING_FLAG) */
403 	mtr_t*		mtr)	/*!< in/out: mini-transaction */
404 	MY_ATTRIBUTE((warn_unused_result));
405 /*********************************************************************//**
406 Like lock_clust_rec_read_check_and_lock(), but reads a
407 secondary index record.
408 @return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
409 or DB_QUE_THR_SUSPENDED */
410 dberr_t
411 lock_sec_rec_read_check_and_lock(
412 /*=============================*/
413 	ulint			flags,	/*!< in: if BTR_NO_LOCKING_FLAG
414 					bit is set, does nothing */
415 	const buf_block_t*	block,	/*!< in: buffer block of rec */
416 	const rec_t*		rec,	/*!< in: user record or page
417 					supremum record which should
418 					be read or passed over by a
419 					read cursor */
420 	dict_index_t*		index,	/*!< in: secondary index */
421 	const ulint*		offsets,/*!< in: rec_get_offsets(rec, index) */
422 	lock_mode		mode,	/*!< in: mode of the lock which
423 					the read cursor should set on
424 					records: LOCK_S or LOCK_X; the
425 					latter is possible in
426 					SELECT FOR UPDATE */
427 	ulint			gap_mode,/*!< in: LOCK_ORDINARY, LOCK_GAP, or
428 					LOCK_REC_NOT_GAP */
429 	que_thr_t*		thr);	/*!< in: query thread */
430 /*********************************************************************//**
431 Checks if locks of other transactions prevent an immediate read, or passing
432 over by a read cursor, of a clustered index record. If they do, first tests
433 if the query thread should anyway be suspended for some reason; if not, then
434 puts the transaction and the query thread to the lock wait state and inserts a
435 waiting request for a record lock to the lock queue. Sets the requested mode
436 lock on the record.
437 @return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
438 or DB_QUE_THR_SUSPENDED */
439 dberr_t
440 lock_clust_rec_read_check_and_lock(
441 /*===============================*/
442 	ulint			flags,	/*!< in: if BTR_NO_LOCKING_FLAG
443 					bit is set, does nothing */
444 	const buf_block_t*	block,	/*!< in: buffer block of rec */
445 	const rec_t*		rec,	/*!< in: user record or page
446 					supremum record which should
447 					be read or passed over by a
448 					read cursor */
449 	dict_index_t*		index,	/*!< in: clustered index */
450 	const ulint*		offsets,/*!< in: rec_get_offsets(rec, index) */
451 	lock_mode		mode,	/*!< in: mode of the lock which
452 					the read cursor should set on
453 					records: LOCK_S or LOCK_X; the
454 					latter is possible in
455 					SELECT FOR UPDATE */
456 	ulint			gap_mode,/*!< in: LOCK_ORDINARY, LOCK_GAP, or
457 					LOCK_REC_NOT_GAP */
458 	que_thr_t*		thr);	/*!< in: query thread */
459 /*********************************************************************//**
460 Checks if locks of other transactions prevent an immediate read, or passing
461 over by a read cursor, of a clustered index record. If they do, first tests
462 if the query thread should anyway be suspended for some reason; if not, then
463 puts the transaction and the query thread to the lock wait state and inserts a
464 waiting request for a record lock to the lock queue. Sets the requested mode
465 lock on the record. This is an alternative version of
466 lock_clust_rec_read_check_and_lock() that does not require the parameter
467 "offsets".
468 @return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
469 dberr_t
470 lock_clust_rec_read_check_and_lock_alt(
471 /*===================================*/
472 	ulint			flags,	/*!< in: if BTR_NO_LOCKING_FLAG
473 					bit is set, does nothing */
474 	const buf_block_t*	block,	/*!< in: buffer block of rec */
475 	const rec_t*		rec,	/*!< in: user record or page
476 					supremum record which should
477 					be read or passed over by a
478 					read cursor */
479 	dict_index_t*		index,	/*!< in: clustered index */
480 	lock_mode		mode,	/*!< in: mode of the lock which
481 					the read cursor should set on
482 					records: LOCK_S or LOCK_X; the
483 					latter is possible in
484 					SELECT FOR UPDATE */
485 	ulint			gap_mode,/*!< in: LOCK_ORDINARY, LOCK_GAP, or
486 					LOCK_REC_NOT_GAP */
487 	que_thr_t*		thr)	/*!< in: query thread */
488 	MY_ATTRIBUTE((warn_unused_result));
489 /*********************************************************************//**
490 Checks that a record is seen in a consistent read.
491 @return true if sees, or false if an earlier version of the record
492 should be retrieved */
493 bool
494 lock_clust_rec_cons_read_sees(
495 /*==========================*/
496 	const rec_t*	rec,	/*!< in: user record which should be read or
497 				passed over by a read cursor */
498 	dict_index_t*	index,	/*!< in: clustered index */
499 	const ulint*	offsets,/*!< in: rec_get_offsets(rec, index) */
500 	ReadView*	view);	/*!< in: consistent read view */
501 /*********************************************************************//**
502 Checks that a non-clustered index record is seen in a consistent read.
503 
504 NOTE that a non-clustered index page contains so little information on
505 its modifications that also in the case false, the present version of
506 rec may be the right, but we must check this from the clustered index
507 record.
508 
509 @return true if certainly sees, or false if an earlier version of the
510 clustered index record might be needed */
511 bool
512 lock_sec_rec_cons_read_sees(
513 /*========================*/
514 	const rec_t*		rec,	/*!< in: user record which
515 					should be read or passed over
516 					by a read cursor */
517 	const dict_index_t*     index,  /*!< in: index */
518 	const ReadView*	view)	/*!< in: consistent read view */
519 	MY_ATTRIBUTE((warn_unused_result));
520 /*********************************************************************//**
521 Locks the specified database table in the mode given. If the lock cannot
522 be granted immediately, the query thread is put to wait.
523 @return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
524 dberr_t
525 lock_table(
526 /*=======*/
527 	ulint		flags,	/*!< in: if BTR_NO_LOCKING_FLAG bit is set,
528 				does nothing */
529 	dict_table_t*	table,	/*!< in/out: database table
530 				in dictionary cache */
531 	lock_mode	mode,	/*!< in: lock mode */
532 	que_thr_t*	thr)	/*!< in: query thread */
533 	MY_ATTRIBUTE((warn_unused_result));
534 /*********************************************************************//**
535 Creates a table IX lock object for a resurrected transaction. */
536 void
537 lock_table_ix_resurrect(
538 /*====================*/
539 	dict_table_t*	table,	/*!< in/out: table */
540 	trx_t*		trx);	/*!< in/out: transaction */
541 
542 /** Sets a lock on a table based on the given mode.
543 @param[in]	table	table to lock
544 @param[in,out]	trx	transaction
545 @param[in]	mode	LOCK_X or LOCK_S
546 @return error code or DB_SUCCESS. */
547 dberr_t
548 lock_table_for_trx(
549 	dict_table_t*	table,
550 	trx_t*		trx,
551 	enum lock_mode	mode)
552 	MY_ATTRIBUTE((nonnull, warn_unused_result));
553 
554 /*************************************************************//**
555 Removes a granted record lock of a transaction from the queue and grants
556 locks to other transactions waiting in the queue if they now are entitled
557 to a lock. */
558 void
559 lock_rec_unlock(
560 /*============*/
561 	trx_t*			trx,	/*!< in/out: transaction that has
562 					set a record lock */
563 	const buf_block_t*	block,	/*!< in: buffer block containing rec */
564 	const rec_t*		rec,	/*!< in: record */
565 	lock_mode		lock_mode);/*!< in: LOCK_S or LOCK_X */
566 /*********************************************************************//**
567 Releases a transaction's locks, and releases possible other transactions
568 waiting because of these locks. Change the state of the transaction to
569 TRX_STATE_COMMITTED_IN_MEMORY. */
570 void
571 lock_trx_release_locks(
572 /*===================*/
573 	trx_t*	trx);	/*!< in/out: transaction */
574 
575 /** Release read locks of a transacion. It is called during XA
576 prepare to release locks early.
577 @param[in,out]	trx		transaction
578 @param[in]	only_gap	release only GAP locks */
579 void
580 lock_trx_release_read_locks(
581 	trx_t*	trx,
582 	bool	only_gap);
583 
584 /*********************************************************************//**
585 Removes locks on a table to be dropped or truncated.
586 If remove_also_table_sx_locks is TRUE then table-level S and X locks are
587 also removed in addition to other table-level and record-level locks.
588 No lock, that is going to be removed, is allowed to be a wait lock. */
589 void
590 lock_remove_all_on_table(
591 /*=====================*/
592 	dict_table_t*	table,			/*!< in: table to be dropped
593 						or truncated */
594 	ibool		remove_also_table_sx_locks);/*!< in: also removes
595 						table S and X locks */
596 
597 /*********************************************************************//**
598 Calculates the fold value of a page file address: used in inserting or
599 searching for a lock in the hash table.
600 @return folded value */
601 UNIV_INLINE
602 ulint
603 lock_rec_fold(
604 /*==========*/
605 	ulint	space,	/*!< in: space */
606 	ulint	page_no)/*!< in: page number */
607 	MY_ATTRIBUTE((const));
608 /*********************************************************************//**
609 Calculates the hash value of a page file address: used in inserting or
610 searching for a lock in the hash table.
611 @return hashed value */
612 UNIV_INLINE
613 ulint
614 lock_rec_hash(
615 /*==========*/
616 	ulint	space,	/*!< in: space */
617 	ulint	page_no);/*!< in: page number */
618 
619 /*************************************************************//**
620 Get the lock hash table */
621 UNIV_INLINE
622 hash_table_t*
623 lock_hash_get(
624 /*==========*/
625 	ulint	mode);	/*!< in: lock mode */
626 
627 /**********************************************************************//**
628 Looks for a set bit in a record lock bitmap. Returns ULINT_UNDEFINED,
629 if none found.
630 @return bit index == heap number of the record, or ULINT_UNDEFINED if
631 none found */
632 ulint
633 lock_rec_find_set_bit(
634 /*==================*/
635 	const lock_t*	lock);	/*!< in: record lock with at least one
636 				bit set */
637 
638 /*********************************************************************//**
639 Gets the source table of an ALTER TABLE transaction.  The table must be
640 covered by an IX or IS table lock.
641 @return the source table of transaction, if it is covered by an IX or
642 IS table lock; dest if there is no source table, and NULL if the
643 transaction is locking more than two tables or an inconsistency is
644 found */
645 dict_table_t*
646 lock_get_src_table(
647 /*===============*/
648 	trx_t*		trx,	/*!< in: transaction */
649 	dict_table_t*	dest,	/*!< in: destination of ALTER TABLE */
650 	lock_mode*	mode);	/*!< out: lock mode of the source table */
651 /*********************************************************************//**
652 Determine if the given table is exclusively "owned" by the given
653 transaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INC
654 on the table.
655 @return TRUE if table is only locked by trx, with LOCK_IX, and
656 possibly LOCK_AUTO_INC */
657 ibool
658 lock_is_table_exclusive(
659 /*====================*/
660 	const dict_table_t*	table,	/*!< in: table */
661 	const trx_t*		trx);	/*!< in: transaction */
662 /*********************************************************************//**
663 Checks if a lock request lock1 has to wait for request lock2.
664 @return TRUE if lock1 has to wait for lock2 to be removed */
665 ibool
666 lock_has_to_wait(
667 /*=============*/
668 	const lock_t*	lock1,	/*!< in: waiting lock */
669 	const lock_t*	lock2);	/*!< in: another lock; NOTE that it is
670 				assumed that this has a lock bit set
671 				on the same record as in lock1 if the
672 				locks are record locks */
673 /*********************************************************************//**
674 Reports that a transaction id is insensible, i.e., in the future. */
675 void
676 lock_report_trx_id_insanity(
677 /*========================*/
678 	trx_id_t	trx_id,		/*!< in: trx id */
679 	const rec_t*	rec,		/*!< in: user record */
680 	dict_index_t*	index,		/*!< in: index */
681 	const ulint*	offsets,	/*!< in: rec_get_offsets(rec, index) */
682 	trx_id_t	max_trx_id);	/*!< in: trx_sys_get_max_trx_id() */
683 /*********************************************************************//**
684 Prints info of a table lock. */
685 void
686 lock_table_print(
687 /*=============*/
688 	FILE*		file,	/*!< in: file where to print */
689 	const lock_t*	lock);	/*!< in: table type lock */
690 /*********************************************************************//**
691 Prints info of a record lock. */
692 void
693 lock_rec_print(
694 /*===========*/
695 	FILE*		file,	/*!< in: file where to print */
696 	const lock_t*	lock);	/*!< in: record type lock */
697 /*********************************************************************//**
698 Prints info of locks for all transactions.
699 @return FALSE if not able to obtain lock mutex and exits without
700 printing info */
701 ibool
702 lock_print_info_summary(
703 /*====================*/
704 	FILE*	file,	/*!< in: file where to print */
705 	ibool   nowait)	/*!< in: whether to wait for the lock mutex */
706 	MY_ATTRIBUTE((warn_unused_result));
707 
708 /** Prints transaction lock wait and MVCC state.
709 @param[in,out]	file	file where to print
710 @param[in]	trx	transaction */
711 void
712 lock_trx_print_wait_and_mvcc_state(
713 	FILE*		file,
714 	const trx_t*	trx);
715 
716 /*********************************************************************//**
717 Prints info of locks for each transaction. This function assumes that the
718 caller holds the lock mutex and more importantly it will release the lock
719 mutex on behalf of the caller. (This should be fixed in the future). */
720 void
721 lock_print_info_all_transactions(
722 /*=============================*/
723 	FILE*	file);	/*!< in: file where to print */
724 /*********************************************************************//**
725 Return approximate number or record locks (bits set in the bitmap) for
726 this transaction. Since delete-marked records may be removed, the
727 record count will not be precise.
728 The caller must be holding lock_sys->mutex. */
729 ulint
730 lock_number_of_rows_locked(
731 /*=======================*/
732 	const trx_lock_t*	trx_lock)	/*!< in: transaction locks */
733 	MY_ATTRIBUTE((warn_unused_result));
734 
735 /*********************************************************************//**
736 Return the number of table locks for a transaction.
737 The caller must be holding lock_sys->mutex. */
738 ulint
739 lock_number_of_tables_locked(
740 /*=========================*/
741 	const trx_lock_t*	trx_lock)	/*!< in: transaction locks */
742 	MY_ATTRIBUTE((warn_unused_result));
743 
744 /*******************************************************************//**
745 Gets the type of a lock. Non-inline version for using outside of the
746 lock module.
747 @return LOCK_TABLE or LOCK_REC */
748 ulint
749 lock_get_type(
750 /*==========*/
751 	const lock_t*	lock);	/*!< in: lock */
752 
753 /*******************************************************************//**
754 Gets the id of the transaction owning a lock.
755 @return transaction id */
756 trx_id_t
757 lock_get_trx_id(
758 /*============*/
759 	const lock_t*	lock);	/*!< in: lock */
760 
761 /*******************************************************************//**
762 Gets the mode of a lock in a human readable string.
763 The string should not be free()'d or modified.
764 @return lock mode */
765 const char*
766 lock_get_mode_str(
767 /*==============*/
768 	const lock_t*	lock);	/*!< in: lock */
769 
770 /*******************************************************************//**
771 Gets the type of a lock in a human readable string.
772 The string should not be free()'d or modified.
773 @return lock type */
774 const char*
775 lock_get_type_str(
776 /*==============*/
777 	const lock_t*	lock);	/*!< in: lock */
778 
779 /*******************************************************************//**
780 Gets the id of the table on which the lock is.
781 @return id of the table */
782 table_id_t
783 lock_get_table_id(
784 /*==============*/
785 	const lock_t*	lock);	/*!< in: lock */
786 
787 /** Determine which table a lock is associated with.
788 @param[in]	lock	the lock
789 @return name of the table */
790 const table_name_t&
791 lock_get_table_name(
792 	const lock_t*	lock);
793 
794 /*******************************************************************//**
795 For a record lock, gets the index on which the lock is.
796 @return index */
797 const dict_index_t*
798 lock_rec_get_index(
799 /*===============*/
800 	const lock_t*	lock);	/*!< in: lock */
801 
802 /*******************************************************************//**
803 For a record lock, gets the name of the index on which the lock is.
804 The string should not be free()'d or modified.
805 @return name of the index */
806 const char*
807 lock_rec_get_index_name(
808 /*====================*/
809 	const lock_t*	lock);	/*!< in: lock */
810 
811 /*******************************************************************//**
812 For a record lock, gets the tablespace number on which the lock is.
813 @return tablespace number */
814 ulint
815 lock_rec_get_space_id(
816 /*==================*/
817 	const lock_t*	lock);	/*!< in: lock */
818 
819 /*******************************************************************//**
820 For a record lock, gets the page number on which the lock is.
821 @return page number */
822 ulint
823 lock_rec_get_page_no(
824 /*=================*/
825 	const lock_t*	lock);	/*!< in: lock */
826 /*******************************************************************//**
827 Check if there are any locks (table or rec) against table.
828 @return TRUE if locks exist */
829 bool
830 lock_table_has_locks(
831 /*=================*/
832 	const dict_table_t*	table);	/*!< in: check if there are any locks
833 					held on records in this table or on the
834 					table itself */
835 
836 /*********************************************************************//**
837 A thread which wakes up threads whose lock wait may have lasted too long.
838 @return a dummy parameter */
839 extern "C"
840 os_thread_ret_t
841 DECLARE_THREAD(lock_wait_timeout_thread)(
842 /*=====================================*/
843 	void*	arg);	/*!< in: a dummy parameter required by
844 			os_thread_create */
845 
846 /********************************************************************//**
847 Releases a user OS thread waiting for a lock to be released, if the
848 thread is already suspended. */
849 void
850 lock_wait_release_thread_if_suspended(
851 /*==================================*/
852 	que_thr_t*	thr);	/*!< in: query thread associated with the
853 				user OS thread	 */
854 
855 /***************************************************************//**
856 Puts a user OS thread to wait for a lock to be released. If an error
857 occurs during the wait trx->error_state associated with thr is
858 != DB_SUCCESS when we return. DB_LOCK_WAIT_TIMEOUT and DB_DEADLOCK
859 are possible errors. DB_DEADLOCK is returned if selective deadlock
860 resolution chose this transaction as a victim. */
861 void
862 lock_wait_suspend_thread(
863 /*=====================*/
864 	que_thr_t*	thr);	/*!< in: query thread associated with the
865 				user OS thread */
866 /*********************************************************************//**
867 Unlocks AUTO_INC type locks that were possibly reserved by a trx. This
868 function should be called at the the end of an SQL statement, by the
869 connection thread that owns the transaction (trx->mysql_thd). */
870 void
871 lock_unlock_table_autoinc(
872 /*======================*/
873 	trx_t*	trx);			/*!< in/out: transaction */
874 /*********************************************************************//**
875 Check whether the transaction has already been rolled back because it
876 was selected as a deadlock victim, or if it has to wait then cancel
877 the wait lock.
878 @return DB_DEADLOCK, DB_LOCK_WAIT or DB_SUCCESS */
879 dberr_t
880 lock_trx_handle_wait(
881 /*=================*/
882 	trx_t*	trx);	/*!< in/out: trx lock state */
883 /*********************************************************************//**
884 Get the number of locks on a table.
885 @return number of locks */
886 ulint
887 lock_table_get_n_locks(
888 /*===================*/
889 	const dict_table_t*	table);	/*!< in: table */
890 /*******************************************************************//**
891 Initialise the trx lock list. */
892 void
893 lock_trx_lock_list_init(
894 /*====================*/
895 	trx_lock_list_t*	lock_list);	/*!< List to initialise */
896 
897 /*******************************************************************//**
898 Set the lock system timeout event. */
899 void
900 lock_set_timeout_event();
901 /*====================*/
902 #ifdef UNIV_DEBUG
903 /*********************************************************************//**
904 Checks that a transaction id is sensible, i.e., not in the future.
905 @return true if ok */
906 bool
907 lock_check_trx_id_sanity(
908 /*=====================*/
909 	trx_id_t	trx_id,		/*!< in: trx id */
910 	const rec_t*	rec,		/*!< in: user record */
911 	dict_index_t*	index,		/*!< in: index */
912 	const ulint*	offsets)	/*!< in: rec_get_offsets(rec, index) */
913 	MY_ATTRIBUTE((warn_unused_result));
914 /*******************************************************************//**
915 Check if the transaction holds any locks on the sys tables
916 or its records.
917 @return the strongest lock found on any sys table or 0 for none */
918 const lock_t*
919 lock_trx_has_sys_table_locks(
920 /*=========================*/
921 	const trx_t*	trx)	/*!< in: transaction to check */
922 	MY_ATTRIBUTE((warn_unused_result));
923 
924 /*******************************************************************//**
925 Check if the transaction holds an exclusive lock on a record.
926 @return whether the locks are held */
927 bool
928 lock_trx_has_rec_x_lock(
929 /*====================*/
930 	const trx_t*		trx,	/*!< in: transaction to check */
931 	const dict_table_t*	table,	/*!< in: table to check */
932 	const buf_block_t*	block,	/*!< in: buffer block of the record */
933 	ulint			heap_no)/*!< in: record heap number */
934 	MY_ATTRIBUTE((warn_unused_result));
935 #endif /* UNIV_DEBUG */
936 
937 /**
938 Allocate cached locks for the transaction.
939 @param trx		allocate cached record locks for this transaction */
940 void
941 lock_trx_alloc_locks(trx_t* trx);
942 
943 /** Lock modes and types */
944 /* @{ */
945 #define LOCK_MODE_MASK	0xFUL	/*!< mask used to extract mode from the
946 				type_mode field in a lock */
947 /** Lock types */
948 /* @{ */
949 #define LOCK_TABLE	16	/*!< table lock */
950 #define	LOCK_REC	32	/*!< record lock */
951 #define LOCK_TYPE_MASK	0xF0UL	/*!< mask used to extract lock type from the
952 				type_mode field in a lock */
953 #if LOCK_MODE_MASK & LOCK_TYPE_MASK
954 # error "LOCK_MODE_MASK & LOCK_TYPE_MASK"
955 #endif
956 
957 #define LOCK_WAIT	256	/*!< Waiting lock flag; when set, it
958 				means that the lock has not yet been
959 				granted, it is just waiting for its
960 				turn in the wait queue */
961 /* Precise modes */
962 #define LOCK_ORDINARY	0	/*!< this flag denotes an ordinary
963 				next-key lock in contrast to LOCK_GAP
964 				or LOCK_REC_NOT_GAP */
965 #define LOCK_GAP	512	/*!< when this bit is set, it means that the
966 				lock holds only on the gap before the record;
967 				for instance, an x-lock on the gap does not
968 				give permission to modify the record on which
969 				the bit is set; locks of this type are created
970 				when records are removed from the index chain
971 				of records */
972 #define LOCK_REC_NOT_GAP 1024	/*!< this bit means that the lock is only on
973 				the index record and does NOT block inserts
974 				to the gap before the index record; this is
975 				used in the case when we retrieve a record
976 				with a unique key, and is also used in
977 				locking plain SELECTs (not part of UPDATE
978 				or DELETE) when the user has set the READ
979 				COMMITTED isolation level */
980 #define LOCK_INSERT_INTENTION 2048 /*!< this bit is set when we place a waiting
981 				gap type record lock request in order to let
982 				an insert of an index record to wait until
983 				there are no conflicting locks by other
984 				transactions on the gap; note that this flag
985 				remains set when the waiting lock is granted,
986 				or if the lock is inherited to a neighboring
987 				record */
988 #define LOCK_PREDICATE	8192	/*!< Predicate lock */
989 #define LOCK_PRDT_PAGE	16384	/*!< Page lock */
990 
991 
992 #if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_PREDICATE|LOCK_PRDT_PAGE)&LOCK_MODE_MASK
993 # error
994 #endif
995 #if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_PREDICATE|LOCK_PRDT_PAGE)&LOCK_TYPE_MASK
996 # error
997 #endif
998 /* @} */
999 
1000 /** Lock operation struct */
1001 struct lock_op_t{
1002 	dict_table_t*	table;	/*!< table to be locked */
1003 	lock_mode	mode;	/*!< lock mode */
1004 };
1005 
1006 typedef ib_mutex_t LockMutex;
1007 
1008 /** The lock system struct */
1009 struct lock_sys_t{
1010 	char		pad1[CACHE_LINE_SIZE];	/*!< padding to prevent other
1011 						memory update hotspots from
1012 						residing on the same memory
1013 						cache line */
1014 	LockMutex	mutex;			/*!< Mutex protecting the
1015 						locks */
1016 	hash_table_t*	rec_hash;		/*!< hash table of the record
1017 						locks */
1018 	hash_table_t*	prdt_hash;		/*!< hash table of the predicate
1019 						lock */
1020 	hash_table_t*	prdt_page_hash;		/*!< hash table of the page
1021 						lock */
1022 
1023 	char		pad2[CACHE_LINE_SIZE];	/*!< Padding */
1024 	LockMutex	wait_mutex;		/*!< Mutex protecting the
1025 						next two fields */
1026 	srv_slot_t*	waiting_threads;	/*!< Array  of user threads
1027 						suspended while waiting for
1028 						locks within InnoDB, protected
1029 						by the lock_sys->wait_mutex */
1030 	srv_slot_t*	last_slot;		/*!< highest slot ever used
1031 						in the waiting_threads array,
1032 						protected by
1033 						lock_sys->wait_mutex */
1034 	ibool		rollback_complete;
1035 						/*!< TRUE if rollback of all
1036 						recovered transactions is
1037 						complete. Protected by
1038 						lock_sys->mutex */
1039 
1040 	ulint		n_lock_max_wait_time;	/*!< Max wait time */
1041 
1042 	os_event_t	timeout_event;		/*!< Set to the event that is
1043 						created in the lock wait monitor
1044 						thread. A value of 0 means the
1045 						thread is not active */
1046 
1047 	bool		timeout_thread_active;	/*!< True if the timeout thread
1048 						is running */
1049 };
1050 
1051 /*********************************************************************//**
1052 This function is kind of wrapper to lock_rec_convert_impl_to_expl_for_trx()
1053 function with functionailty added to facilitate lock conversion from implicit
1054 to explicit for partial rollback cases */
1055 void
1056 lock_rec_convert_active_impl_to_expl(
1057 /*==================================*/
1058         const buf_block_t*      block,  /*!< in: buffer block of rec */
1059         const rec_t*            rec,    /*!< in: user record on page */
1060         dict_index_t*           index,  /*!< in: index of record */
1061         const ulint*            offsets,/*!< in: rec_get_offsets(rec, index) */
1062         trx_t*                  trx,    /*!< in/out: active transaction */
1063         ulint                   heap_no);/*!< in: rec heap number to lock */
1064 
1065 /*************************************************************//**
1066 Removes a record lock request, waiting or granted, from the queue. */
1067 void
1068 lock_rec_discard(
1069 /*=============*/
1070 	lock_t*		in_lock);	/*!< in: record lock object: all
1071 					record locks which are contained
1072 					in this lock object are removed */
1073 
1074 /*************************************************************//**
1075 Moves the explicit locks on user records to another page if a record
1076 list start is moved to another page. */
1077 void
1078 lock_rtr_move_rec_list(
1079 /*===================*/
1080 	const buf_block_t*	new_block,	/*!< in: index page to
1081 						move to */
1082 	const buf_block_t*	block,		/*!< in: index page */
1083 	rtr_rec_move_t*		rec_move,	/*!< in: recording records
1084 						moved */
1085 	ulint			num_move);	/*!< in: num of rec to move */
1086 
1087 /*************************************************************//**
1088 Removes record lock objects set on an index page which is discarded. This
1089 function does not move locks, or check for waiting locks, therefore the
1090 lock bitmaps must already be reset when this function is called. */
1091 void
1092 lock_rec_free_all_from_discard_page(
1093 /*================================*/
1094 	const buf_block_t*	block);		/*!< in: page to be discarded */
1095 
1096 /** Reset the nth bit of a record lock.
1097 @param[in,out]	lock record lock
1098 @param[in] i	index of the bit that will be reset
1099 @param[in] type	whether the lock is in wait mode  */
1100 void
1101 lock_rec_trx_wait(
1102 	lock_t*		lock,
1103 	ulint		i,
1104 	ulint		type);
1105 
1106 /** The lock system */
1107 extern lock_sys_t*	lock_sys;
1108 
1109 /** Test if lock_sys->mutex can be acquired without waiting. */
1110 #define lock_mutex_enter_nowait() 		\
1111 	(lock_sys->mutex.trylock(__FILE__, __LINE__))
1112 
1113 /** Test if lock_sys->mutex is owned. */
1114 #define lock_mutex_own() (lock_sys->mutex.is_owned())
1115 
1116 /** Acquire the lock_sys->mutex. */
1117 #define lock_mutex_enter() do {			\
1118 	mutex_enter(&lock_sys->mutex);		\
1119 } while (0)
1120 
1121 /** Release the lock_sys->mutex. */
1122 #define lock_mutex_exit() do {			\
1123 	lock_sys->mutex.exit();			\
1124 } while (0)
1125 
1126 /** Test if lock_sys->wait_mutex is owned. */
1127 #define lock_wait_mutex_own() (lock_sys->wait_mutex.is_owned())
1128 
1129 /** Acquire the lock_sys->wait_mutex. */
1130 #define lock_wait_mutex_enter() do {		\
1131 	mutex_enter(&lock_sys->wait_mutex);	\
1132 } while (0)
1133 
1134 /** Release the lock_sys->wait_mutex. */
1135 #define lock_wait_mutex_exit() do {		\
1136 	lock_sys->wait_mutex.exit();		\
1137 } while (0)
1138 
1139 #ifdef WITH_WSREP
1140 /*********************************************************************//**
1141 Cancels a waiting lock request and releases possible other transactions
1142 waiting behind it. */
1143 void
1144 lock_cancel_waiting_and_release(
1145 /*============================*/
1146 	lock_t*	lock);	/*!< in/out: waiting lock request */
1147 #endif /* WITH_WSREP */
1148 #ifndef UNIV_NONINL
1149 #include "lock0lock.ic"
1150 #endif
1151 
1152 #endif
1153