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