summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--innobase/include/row0mysql.h11
-rw-r--r--innobase/include/trx0trx.h2
-rw-r--r--innobase/lock/lock0lock.c30
-rw-r--r--innobase/row/row0mysql.c51
-rw-r--r--sql/ha_innodb.cc26
-rw-r--r--sql/ha_innodb.h1
6 files changed, 119 insertions, 2 deletions
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index 6e1865dae1d..581f1bcade3 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -233,6 +233,17 @@ row_update_for_mysql(
the MySQL format */
row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL
handle */
+
+/*************************************************************************
+Does an unlock of a row for MySQL. */
+
+int
+row_unlock_for_mysql(
+/*=================*/
+ /* out: error code or DB_SUCCESS */
+ row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL
+ handle */
+
/*************************************************************************
Creates an query graph node of 'update' type to be used in the MySQL
interface. */
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 7eb91048684..602291f946a 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -423,6 +423,8 @@ struct trx_struct{
lock_t* auto_inc_lock; /* possible auto-inc lock reserved by
the transaction; note that it is also
in the lock list trx_locks */
+ ibool trx_create_lock;/* this is TRUE if we have created a
+ new lock for a record accessed */
ulint n_lock_table_exp;/* number of explicit table locks
(LOCK TABLES) reserved by the
transaction, stored in trx_locks */
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 68073647248..44eee53212a 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -1617,6 +1617,9 @@ lock_rec_create(
HASH_INSERT(lock_t, hash, lock_sys->rec_hash,
lock_rec_fold(space, page_no), lock);
+ /* Note that we have create a new lock */
+ trx->trx_create_lock = TRUE;
+
if (type_mode & LOCK_WAIT) {
lock_set_lock_and_trx_wait(lock, trx);
@@ -1791,6 +1794,15 @@ lock_rec_add_to_queue(
if (similar_lock && !somebody_waits && !(type_mode & LOCK_WAIT)) {
+ /* If the nth bit of a record lock is already set then we
+ do not set a new lock bit, otherwice we set */
+
+ if (lock_rec_get_nth_bit(similar_lock, heap_no)) {
+ trx->trx_create_lock = FALSE;
+ } else {
+ trx->trx_create_lock = TRUE;
+ }
+
lock_rec_set_nth_bit(similar_lock, heap_no);
return(similar_lock);
@@ -1822,6 +1834,7 @@ lock_rec_lock_fast(
{
lock_t* lock;
ulint heap_no;
+ trx_t* trx;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -1840,9 +1853,12 @@ lock_rec_lock_fast(
lock = lock_rec_get_first_on_page(rec);
+ trx = thr_get_trx(thr);
+ trx->trx_create_lock = FALSE;
+
if (lock == NULL) {
if (!impl) {
- lock_rec_create(mode, rec, index, thr_get_trx(thr));
+ lock_rec_create(mode, rec, index, trx);
}
return(TRUE);
@@ -1853,13 +1869,23 @@ lock_rec_lock_fast(
return(FALSE);
}
- if (lock->trx != thr_get_trx(thr)
+ if (lock->trx != trx
|| lock->type_mode != (mode | LOCK_REC)
|| lock_rec_get_n_bits(lock) <= heap_no) {
return(FALSE);
}
if (!impl) {
+
+ /* If the nth bit of a record lock is already set then we
+ do not set a new lock bit, otherwice we set */
+
+ if (lock_rec_get_nth_bit(lock, heap_no)) {
+ trx->trx_create_lock = FALSE;
+ } else {
+ trx->trx_create_lock = TRUE;
+ }
+
lock_rec_set_nth_bit(lock, heap_no);
}
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 241ddc310e8..9ca0b7306fc 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -1186,6 +1186,57 @@ run_again:
return((int) err);
}
+/*************************************************************************
+Does an unlock of a row for MySQL. */
+
+int
+row_unlock_for_mysql(
+/*=================*/
+ /* out: error code or DB_SUCCESS */
+ row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
+ handle */
+{
+ rec_t* rec;
+ btr_pcur_t* cur = prebuilt->pcur;
+ trx_t* trx = prebuilt->trx;
+ mtr_t mtr;
+
+ ut_ad(prebuilt && trx);
+ ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
+
+ trx->op_info = "unlock_row";
+
+ if (srv_locks_unsafe_for_binlog) {
+ if (trx->trx_create_lock == TRUE) {
+
+ mtr_start(&mtr);
+
+ /* Restore a cursor position and find a record */
+ btr_pcur_restore_position(BTR_SEARCH_LEAF, cur, &mtr);
+ rec = btr_pcur_get_rec(cur);
+
+ if (rec) {
+
+ lock_rec_reset_and_release_wait(rec);
+ } else {
+ fputs("InnoDB: Error: "
+ "Record for the lock not found\n",
+ stderr);
+ mem_analyze_corruption((byte*) trx);
+ ut_error;
+ }
+
+ trx->trx_create_lock = FALSE;
+ mtr_commit(&mtr);
+ }
+
+ }
+
+ trx->op_info = "";
+
+ return(DB_SUCCESS);
+}
+
/**************************************************************************
Does a cascaded delete or set null in a foreign key operation. */
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index efd74a543c2..722a6259d3d 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -2690,6 +2690,32 @@ ha_innobase::delete_row(
DBUG_RETURN(error);
}
+/**************************************************************************
+Deletes a lock set to a row */
+
+void
+ha_innobase::unlock_row(void)
+/*=========================*/
+{
+ row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+
+ DBUG_ENTER("ha_innobase::unlock_row");
+
+ ut_ad(prebuilt->trx ==
+ (trx_t*) current_thd->transaction.all.innobase_tid);
+
+ if (last_query_id != user_thd->query_id) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: Error: last_query_id is %lu != user_thd_query_id is %lu\n",
+ (ulong)last_query_id, (ulong)user_thd->query_id);
+ mem_analyze_corruption((byte *) prebuilt->trx);
+ ut_error;
+ }
+
+ row_unlock_for_mysql(prebuilt);
+}
+
/**********************************************************************
Initializes a handle to use an index. */
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index 57e136a8fba..b74af1db90b 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -120,6 +120,7 @@ class ha_innobase: public handler
int write_row(byte * buf);
int update_row(const byte * old_data, byte * new_data);
int delete_row(const byte * buf);
+ void unlock_row();
int index_init(uint index);
int index_end();