diff options
author | unknown <jan@hundin.mysql.fi> | 2004-08-11 13:01:30 +0300 |
---|---|---|
committer | unknown <jan@hundin.mysql.fi> | 2004-08-11 13:01:30 +0300 |
commit | 11b255796818bda5f271b83d5123aba6b4a0b625 (patch) | |
tree | 63cadfc89162ff40d87519543eb9fb079a155625 /innobase/row/row0ins.c | |
parent | ce4e83e31deee668b035346729d2a79a5c9521be (diff) | |
download | mariadb-git-11b255796818bda5f271b83d5123aba6b4a0b625.tar.gz |
Take X-lock for duplicate keys in REPLACE command.
innobase/lock/lock0lock.c:
Made change where lock on the supremum record is really a 'gap' type lock and
gap type lock do not need to wait if it is not LOCK_INSERT_INTENSION type.
innobase/row/row0ins.c:
Added fuction row_ins_set_exclusive_rec_lock to set exclusive lock on a record.
This function is used for locking possible duplicate key records when
user has issued REPLACE-command.
Because manual defines the REPLACE semantics that it is either an INSERT or
DELETE(s) for duplicate key + INSERT, we take X-lock directly for duplicate
records to avoid unnecessary lock upgrades and deadlocks caused by lock
upgrades.
Diffstat (limited to 'innobase/row/row0ins.c')
-rw-r--r-- | innobase/row/row0ins.c | 104 |
1 files changed, 97 insertions, 7 deletions
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 0da749212d2..58ef7d1685c 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -1022,6 +1022,33 @@ row_ins_set_shared_rec_lock( return(err); } + +/************************************************************************* +Sets a exclusive lock on a record. Used in locking possible duplicate key +records */ +static +ulint +row_ins_set_exclusive_rec_lock( +/*========================*/ + /* out: DB_SUCCESS or error code */ + ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or + LOCK_REC_NOT_GAP type lock */ + rec_t* rec, /* in: record */ + dict_index_t* index, /* in: index */ + que_thr_t* thr) /* in: query thread */ +{ + ulint err; + + if (index->type & DICT_CLUSTERED) { + err = lock_clust_rec_read_check_and_lock(0, rec, index, LOCK_X, + type, thr); + } else { + err = lock_sec_rec_read_check_and_lock(0, rec, index, LOCK_X, + type, thr); + } + + return(err); +} /******************************************************************* Checks if foreign key constraint fails for an index entry. Sets shared locks @@ -1451,6 +1478,8 @@ row_ins_scan_sec_index_for_duplicate( ulint err = DB_SUCCESS; ibool moved; mtr_t mtr; + trx_t *trx; + ibool success; n_unique = dict_index_get_n_unique(index); @@ -1488,8 +1517,29 @@ row_ins_scan_sec_index_for_duplicate( /* Try to place a lock on the index record */ - err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, rec, index, - thr); + /* The manual defines the REPLACE semantics that it + is either an INSERT or DELETE(s) for duplicate key + + INSERT. Therefore, we should take X-lock for + duplicates. + */ + + trx = thr_get_trx(thr);*/* Get Transaction */ + + /* Is the first word in MySQL query REPLACE ? */ + + ut_ad(trx) + dict_accept(*trx->mysql_query_str, "REPLACE", &success); + + if (success) { + + err = row_ins_set_exclusive_rec_lock( + LOCK_ORDINARY,rec,index,thr); + } else { + + err = row_ins_set_shared_rec_lock( + LOCK_ORDINARY, rec, index,thr); + } + if (err != DB_SUCCESS) { @@ -1556,6 +1606,7 @@ row_ins_duplicate_error_in_clust( page_t* page; ulint n_unique; trx_t* trx = thr_get_trx(thr); + ibool success; UT_NOT_USED(mtr); @@ -1588,9 +1639,28 @@ row_ins_duplicate_error_in_clust( is needed in logical logging of MySQL to make sure that in roll-forward we get the same duplicate errors as in original execution */ - - err = row_ins_set_shared_rec_lock(LOCK_REC_NOT_GAP, - rec, cursor->index, thr); + + /* The manual defines the REPLACE semantics that it + is either an INSERT or DELETE(s) for duplicate key + + INSERT. Therefore, we should take X-lock for + duplicates. + */ + + + /* Is the first word in MySQL query REPLACE ? */ + + dict_accept(*trx->mysql_query_str, "REPLACE", &success); + + if (success) { + + err = row_ins_set_exclusive_rec_lock( + LOCK_REC_NOT_GAP,rec,cursor->index,thr); + } else { + + err = row_ins_set_shared_rec_lock( + LOCK_REC_NOT_GAP,rec, cursor->index, thr); + } + if (err != DB_SUCCESS) { return(err); @@ -1611,8 +1681,28 @@ row_ins_duplicate_error_in_clust( if (rec != page_get_supremum_rec(page)) { - err = row_ins_set_shared_rec_lock(LOCK_REC_NOT_GAP, - rec, cursor->index, thr); + + /* The manual defines the REPLACE semantics that it + is either an INSERT or DELETE(s) for duplicate key + + INSERT. Therefore, we should take X-lock for + duplicates. + */ + + + /* Is the first word in MySQL query REPLACE ? */ + + dict_accept(*trx->mysql_query_str, "REPLACE", &success); + + if (success) { + + err = row_ins_set_exclusive_rec_lock( + LOCK_REC_NOT_GAP,rec,cursor->index,thr); + } else { + + err = row_ins_set_shared_rec_lock( + LOCK_REC_NOT_GAP,rec, cursor->index, thr); + } + if (err != DB_SUCCESS) { return(err); |