summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
authorunknown <aivanov@mysql.com>2006-01-16 14:32:43 +0300
committerunknown <aivanov@mysql.com>2006-01-16 14:32:43 +0300
commit7bafd119a3f73c39306a133936501a433e80bcf9 (patch)
tree42a4966dcc1d1565033773730d0782e22ce4570b /innobase
parentfe1970d4b9084de6e883b0dae50ab4d5d3957e54 (diff)
downloadmariadb-git-7bafd119a3f73c39306a133936501a433e80bcf9.tar.gz
Changes from the innodb-5.0-ss115 snapshot.
Fixed bugs: BUG#15991: "innodb-file-per-table + symlink database + rename = crash" BUG#15650: "DELETE with LEFT JOIN crashes server" BUG#15308: "Problem of Order with Enum Column in Primary Key" BUG#14189: "VARBINARY and BINARY variables: trailing space ignored" innobase/include/data0type.h: Changes from the innodb-5.0-ss115 snapshot. innobase/include/data0type.ic: Changes from the innodb-5.0-ss115 snapshot. Fixed bug #14189. dtype_get_pad_char(): Do not pad VARBINARY or BINARY cloumns. innobase/include/lock0lock.h: Changes from the innodb-5.0-ss115 snapshot. innobase/include/os0file.h: Changes from the innodb-5.0-ss115 snapshot. os_file_handle_error(): Map the error codes EXDEV, ENOTDIR, and EISDIR to the new code OS_FILE_PATH_ERROR. Treat this code as OS_FILE_PATH_ERROR. This fixes the crash on RENAME TABLE when the .ibd file is a symbolic link to a different file system (bug#15991). innobase/include/row0mysql.h: Changes from the innodb-5.0-ss115 snapshot. innobase/lock/lock0lock.c: Changes from the innodb-5.0-ss115 snapshot. lock_rec_unlock(): Initialize local variable release_lock, in order to avoid dereferencing an uninitialized pointer when no lock exists on rec. innobase/os/os0file.c: Changes from the innodb-5.0-ss115 snapshot. os_file_handle_error(): Map the error codes EXDEV, ENOTDIR, and EISDIR to the new code OS_FILE_PATH_ERROR. Treat this code as OS_FILE_PATH_ERROR. This fixes the crash on RENAME TABLE when the .ibd file is a symbolic link to a different file system (bug#15991). Protect the increment and decrement operations on the statistic variables os_n_pending_writes/reads with os_file_count_mutes. innobase/row/row0ins.c: Changes from the innodb-5.0-ss115 snapshot. Fixed bug #14189. row_ins_cascade_calc_update_vec(): Refuse ON UPDATE_CASCADE when trying to change the length of of a VARBINARY column that refers to or is referenced by a BINARY column. BINARY columns are no longer padded on comparison, and thus they cannot be padded on storage either. innobase/row/row0mysql.c: Changes from the innodb-5.0-ss115 snapshot. Fixed bug on unlock_row. In a unlock_row we may unlock only the latest lock granted to this transaction to the row. innobase/row/row0sel.c: Changes from the innodb-5.0-ss115 snapshot. Fixed bug #15308. Fixed bug #14189: innobase_init(): Assert that DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number. After review fixes for unlock bug where unlock released all locks transaction requested for a row. Only a latest requested lock to a row should be released. Update function comments to reflect current state. Persistent cursor should be stored whenever select lock type != LOCK_NONE. innobase/trx/trx0trx.c: Changes from the innodb-5.0-ss115 snapshot. trx_commit_off_kernel(): Do not write empty trx->mysql_log_file_name. mysql-test/r/innodb.result: Changes from the innodb-5.0-ss115 snapshot. mysql-test/t/innodb.test: Changes from the innodb-5.0-ss115 snapshot. sql/ha_innodb.cc: Changes from the innodb-5.0-ss115 snapshot. Fixed bug #15308. Fixed bug #14189: innobase_init(): Assert that DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number. After review fixes for unlock bug where unlock released all locks transaction requested for a row. Only a latest requested lock to a row should be released. Update function comments to reflect current state. Persistent cursor should be stored whenever select lock type != LOCK_NONE. mysql-test/r/innodb_unsafe_binlog.result: Changes from the innodb-5.0-ss115 snapshot. mysql-test/t/innodb_unsafe_binlog-master.opt: Changes from the innodb-5.0-ss115 snapshot. mysql-test/t/innodb_unsafe_binlog.test: Changes from the innodb-5.0-ss115 snapshot. Added testcases for bug #15650.
Diffstat (limited to 'innobase')
-rw-r--r--innobase/include/data0type.h3
-rw-r--r--innobase/include/data0type.ic39
-rw-r--r--innobase/include/lock0lock.h20
-rw-r--r--innobase/include/os0file.h5
-rw-r--r--innobase/include/row0mysql.h5
-rw-r--r--innobase/lock/lock0lock.c71
-rw-r--r--innobase/os/os0file.c112
-rw-r--r--innobase/row/row0ins.c9
-rw-r--r--innobase/row/row0mysql.c26
-rw-r--r--innobase/row/row0sel.c12
-rw-r--r--innobase/trx/trx0trx.c3
11 files changed, 216 insertions, 89 deletions
diff --git a/innobase/include/data0type.h b/innobase/include/data0type.h
index 7e9692eca5a..30c0f732c34 100644
--- a/innobase/include/data0type.h
+++ b/innobase/include/data0type.h
@@ -13,6 +13,7 @@ Created 1/16/1996 Heikki Tuuri
extern ulint data_mysql_default_charset_coll;
#define DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL 8
+#define DATA_MYSQL_BINARY_CHARSET_COLL 63
/* SQL data type struct */
typedef struct dtype_struct dtype_t;
@@ -311,7 +312,7 @@ dtype_get_pad_char(
/*===============*/
/* out: padding character code, or
ULINT_UNDEFINED if no padding specified */
- dtype_t* type); /* in: type */
+ const dtype_t* type); /* in: type */
/***************************************************************************
Returns the size of a fixed size data type, 0 if not a fixed size type. */
UNIV_INLINE
diff --git a/innobase/include/data0type.ic b/innobase/include/data0type.ic
index d4a7b3c64b8..ad0f02fa63d 100644
--- a/innobase/include/data0type.ic
+++ b/innobase/include/data0type.ic
@@ -188,26 +188,35 @@ dtype_get_pad_char(
/*===============*/
/* out: padding character code, or
ULINT_UNDEFINED if no padding specified */
- dtype_t* type) /* in: type */
+ const dtype_t* type) /* in: type */
{
- if (type->mtype == DATA_CHAR
- || type->mtype == DATA_VARCHAR
- || type->mtype == DATA_BINARY
- || type->mtype == DATA_FIXBINARY
- || type->mtype == DATA_MYSQL
- || type->mtype == DATA_VARMYSQL
- || (type->mtype == DATA_BLOB
- && (type->prtype & DATA_BINARY_TYPE) == 0)) {
-
+ switch (type->mtype) {
+ case DATA_FIXBINARY:
+ case DATA_BINARY:
+ if (UNIV_UNLIKELY(dtype_get_charset_coll(type->prtype)
+ == DATA_MYSQL_BINARY_CHARSET_COLL)) {
+ /* Starting from 5.0.18, do not pad
+ VARBINARY or BINARY columns. */
+ return(ULINT_UNDEFINED);
+ }
+ /* Fall through */
+ case DATA_CHAR:
+ case DATA_VARCHAR:
+ case DATA_MYSQL:
+ case DATA_VARMYSQL:
/* Space is the padding character for all char and binary
strings, and starting from 5.0.3, also for TEXT strings. */
- return((ulint)' ');
+ return(0x20);
+ case DATA_BLOB:
+ if ((type->prtype & DATA_BINARY_TYPE) == 0) {
+ return(0x20);
+ }
+ /* Fall through */
+ default:
+ /* No padding specified */
+ return(ULINT_UNDEFINED);
}
-
- /* No padding specified */
-
- return(ULINT_UNDEFINED);
}
/**************************************************************************
diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h
index 20b1f1d7145..86e579bc007 100644
--- a/innobase/include/lock0lock.h
+++ b/innobase/include/lock0lock.h
@@ -64,14 +64,6 @@ lock_clust_rec_some_has_impl(
dict_index_t* index, /* in: clustered index */
const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*****************************************************************
-Resets the lock bits for a single record. Releases transactions
-waiting for lock requests here. */
-
-void
-lock_rec_reset_and_release_wait(
-/*============================*/
- rec_t* rec); /* in: record whose locks bits should be reset */
-/*****************************************************************
Makes a record to inherit the locks of another record as gap type
locks, but does not reset the lock bits of the other record. Also
waiting lock requests on rec are inherited as GRANTED gap locks. */
@@ -427,6 +419,18 @@ lock_is_on_table(
/*=============*/
/* out: TRUE if there are lock(s) */
dict_table_t* table); /* in: database table in dictionary cache */
+/*****************************************************************
+Removes a granted record lock of a transaction from the queue and grants
+locks to other transactions waiting in the queue if they now are entitled
+to a lock. */
+
+void
+lock_rec_unlock(
+/*============*/
+ trx_t* trx, /* in: transaction that has set a record
+ lock */
+ rec_t* rec, /* in: record */
+ ulint lock_mode); /* in: LOCK_S or LOCK_X */
/*************************************************************************
Releases a table lock.
Releases possible other transactions waiting for this lock. */
diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h
index 02a38dd49ef..d5bc5a2b115 100644
--- a/innobase/include/os0file.h
+++ b/innobase/include/os0file.h
@@ -91,9 +91,10 @@ log. */
#define OS_FILE_NOT_FOUND 71
#define OS_FILE_DISK_FULL 72
#define OS_FILE_ALREADY_EXISTS 73
-#define OS_FILE_AIO_RESOURCES_RESERVED 74 /* wait for OS aio resources
+#define OS_FILE_PATH_ERROR 74
+#define OS_FILE_AIO_RESOURCES_RESERVED 75 /* wait for OS aio resources
to become available again */
-#define OS_FILE_ERROR_NOT_SPECIFIED 75
+#define OS_FILE_ERROR_NOT_SPECIFIED 76
/* Types for aio operations */
#define OS_FILE_READ 10
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index b5da4634d98..7d8740db044 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -250,8 +250,9 @@ trx_register_new_rec_lock() to store the information which new record locks
really were set. This function removes a newly set lock under prebuilt->pcur,
and also under prebuilt->clust_pcur. Currently, this is only used and tested
in the case of an UPDATE or a DELETE statement, where the row lock is of the
-LOCK_X type.
-Thus, this implements a 'mini-rollback' that releases the latest record
+LOCK_X or LOCK_S type.
+
+Thus, this implements a 'mini-rollback' that releases the latest record
locks we set. */
int
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 7844991613f..06475c8ef7e 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -2392,7 +2392,7 @@ lock_rec_free_all_from_discard_page(
/*****************************************************************
Resets the lock bits for a single record. Releases transactions waiting for
lock requests here. */
-
+static
void
lock_rec_reset_and_release_wait(
/*============================*/
@@ -3760,6 +3760,75 @@ lock_table_dequeue(
/*=========================== LOCK RELEASE ==============================*/
+/*****************************************************************
+Removes a granted record lock of a transaction from the queue and grants
+locks to other transactions waiting in the queue if they now are entitled
+to a lock. */
+
+void
+lock_rec_unlock(
+/*============*/
+ trx_t* trx, /* in: transaction that has set a record
+ lock */
+ rec_t* rec, /* in: record */
+ ulint lock_mode) /* in: LOCK_S or LOCK_X */
+{
+ lock_t* lock;
+ lock_t* release_lock = NULL;
+ ulint heap_no;
+
+ ut_ad(trx && rec);
+
+ mutex_enter(&kernel_mutex);
+
+ heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
+
+ lock = lock_rec_get_first(rec);
+
+ /* Find the last lock with the same lock_mode and transaction
+ from the record. */
+
+ while (lock != NULL) {
+ if (lock->trx == trx && lock_get_mode(lock) == lock_mode) {
+ release_lock = lock;
+ ut_a(!lock_get_wait(lock));
+ }
+
+ lock = lock_rec_get_next(rec, lock);
+ }
+
+ /* If a record lock is found, release the record lock */
+
+ if (UNIV_LIKELY(release_lock != NULL)) {
+ lock_rec_reset_nth_bit(release_lock, heap_no);
+ } else {
+ mutex_exit(&kernel_mutex);
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: Error: unlock row could not find a %lu mode lock on the record\n",
+ (ulong)lock_mode);
+
+ return;
+ }
+
+ /* Check if we can now grant waiting lock requests */
+
+ lock = lock_rec_get_first(rec);
+
+ while (lock != NULL) {
+ if (lock_get_wait(lock)
+ && !lock_rec_has_to_wait_in_queue(lock)) {
+
+ /* Grant the lock */
+ lock_grant(lock);
+ }
+
+ lock = lock_rec_get_next(rec, lock);
+ }
+
+ mutex_exit(&kernel_mutex);
+}
+
/*************************************************************************
Releases a table lock.
Releases possible other transactions waiting for this lock. */
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 20a3303d12d..3b8f7576049 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -160,15 +160,12 @@ time_t os_last_printout;
ibool os_has_said_disk_full = FALSE;
-/* The mutex protecting the following counts of pending pread and pwrite
-operations */
+/* The mutex protecting the following counts of pending I/O operations */
static os_mutex_t os_file_count_mutex;
ulint os_file_n_pending_preads = 0;
ulint os_file_n_pending_pwrites = 0;
-
-/* These are not protected by any mutex */
-ulint os_n_pending_writes = 0;
-ulint os_n_pending_reads = 0;
+ulint os_n_pending_writes = 0;
+ulint os_n_pending_reads = 0;
/***************************************************************************
Gets the operating system version. Currently works only on Windows. */
@@ -314,6 +311,8 @@ os_file_get_last_error(
return(OS_FILE_NOT_FOUND);
} else if (err == EEXIST) {
return(OS_FILE_ALREADY_EXISTS);
+ } else if (err == EXDEV || err == ENOTDIR || err == EISDIR) {
+ return(OS_FILE_PATH_ERROR);
} else {
return(100 + err);
}
@@ -363,7 +362,8 @@ os_file_handle_error(
return(TRUE);
- } else if (err == OS_FILE_ALREADY_EXISTS) {
+ } else if (err == OS_FILE_ALREADY_EXISTS
+ || err == OS_FILE_PATH_ERROR) {
return(FALSE);
} else {
@@ -467,7 +467,8 @@ os_file_handle_error_no_exit(
return(TRUE);
- } else if (err == OS_FILE_ALREADY_EXISTS) {
+ } else if (err == OS_FILE_ALREADY_EXISTS
+ || err == OS_FILE_PATH_ERROR) {
return(FALSE);
} else {
@@ -1905,12 +1906,14 @@ os_file_pread(
#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
os_mutex_enter(os_file_count_mutex);
os_file_n_pending_preads++;
+ os_n_pending_reads++;
os_mutex_exit(os_file_count_mutex);
n_bytes = pread(file, buf, (ssize_t)n, offs);
os_mutex_enter(os_file_count_mutex);
os_file_n_pending_preads--;
+ os_n_pending_reads--;
os_mutex_exit(os_file_count_mutex);
return(n_bytes);
@@ -1920,6 +1923,10 @@ os_file_pread(
ssize_t ret;
ulint i;
+ os_mutex_enter(os_file_count_mutex);
+ os_n_pending_reads++;
+ os_mutex_exit(os_file_count_mutex);
+
/* Protect the seek / read operation with a mutex */
i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
@@ -1928,15 +1935,17 @@ os_file_pread(
ret_offset = lseek(file, offs, SEEK_SET);
if (ret_offset < 0) {
- os_mutex_exit(os_file_seek_mutexes[i]);
-
- return(-1);
+ ret = -1;
+ } else {
+ ret = read(file, buf, (ssize_t)n);
}
-
- ret = read(file, buf, (ssize_t)n);
os_mutex_exit(os_file_seek_mutexes[i]);
+ os_mutex_enter(os_file_count_mutex);
+ os_n_pending_reads--;
+ os_mutex_exit(os_file_count_mutex);
+
return(ret);
}
#endif
@@ -1981,12 +1990,14 @@ os_file_pwrite(
#if defined(HAVE_PWRITE) && !defined(HAVE_BROKEN_PREAD)
os_mutex_enter(os_file_count_mutex);
os_file_n_pending_pwrites++;
+ os_n_pending_writes++;
os_mutex_exit(os_file_count_mutex);
ret = pwrite(file, buf, (ssize_t)n, offs);
os_mutex_enter(os_file_count_mutex);
os_file_n_pending_pwrites--;
+ os_n_pending_writes--;
os_mutex_exit(os_file_count_mutex);
# ifdef UNIV_DO_FLUSH
@@ -2008,6 +2019,10 @@ os_file_pwrite(
off_t ret_offset;
ulint i;
+ os_mutex_enter(os_file_count_mutex);
+ os_n_pending_writes++;
+ os_mutex_exit(os_file_count_mutex);
+
/* Protect the seek / write operation with a mutex */
i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
@@ -2016,9 +2031,9 @@ os_file_pwrite(
ret_offset = lseek(file, offs, SEEK_SET);
if (ret_offset < 0) {
- os_mutex_exit(os_file_seek_mutexes[i]);
+ ret = -1;
- return(-1);
+ goto func_exit;
}
ret = write(file, buf, (ssize_t)n);
@@ -2036,8 +2051,13 @@ os_file_pwrite(
}
# endif /* UNIV_DO_FLUSH */
+func_exit:
os_mutex_exit(os_file_seek_mutexes[i]);
+ os_mutex_enter(os_file_count_mutex);
+ os_n_pending_writes--;
+ os_mutex_exit(os_file_count_mutex);
+
return(ret);
}
#endif
@@ -2082,9 +2102,13 @@ try_again:
low = (DWORD) offset;
high = (DWORD) offset_high;
+ os_mutex_enter(os_file_count_mutex);
+ os_n_pending_reads++;
+ os_mutex_exit(os_file_count_mutex);
+
/* Protect the seek / read operation with a mutex */
i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
-
+
os_mutex_enter(os_file_seek_mutexes[i]);
ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
@@ -2093,17 +2117,21 @@ try_again:
os_mutex_exit(os_file_seek_mutexes[i]);
+ os_mutex_enter(os_file_count_mutex);
+ os_n_pending_reads--;
+ os_mutex_exit(os_file_count_mutex);
+
goto error_handling;
}
- os_n_pending_reads++;
-
ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
- os_n_pending_reads--;
-
os_mutex_exit(os_file_seek_mutexes[i]);
+ os_mutex_enter(os_file_count_mutex);
+ os_n_pending_reads--;
+ os_mutex_exit(os_file_count_mutex);
+
if (ret && len == n) {
return(TRUE);
}
@@ -2114,12 +2142,8 @@ try_again:
os_bytes_read_since_printout += n;
try_again:
- os_n_pending_reads++;
-
ret = os_file_pread(file, buf, n, offset, offset_high);
- os_n_pending_reads--;
-
if ((ulint)ret == n) {
return(TRUE);
@@ -2193,6 +2217,10 @@ try_again:
low = (DWORD) offset;
high = (DWORD) offset_high;
+ os_mutex_enter(os_file_count_mutex);
+ os_n_pending_reads++;
+ os_mutex_exit(os_file_count_mutex);
+
/* Protect the seek / read operation with a mutex */
i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
@@ -2204,17 +2232,21 @@ try_again:
os_mutex_exit(os_file_seek_mutexes[i]);
+ os_mutex_enter(os_file_count_mutex);
+ os_n_pending_reads--;
+ os_mutex_exit(os_file_count_mutex);
+
goto error_handling;
}
- os_n_pending_reads++;
-
ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
- os_n_pending_reads--;
-
os_mutex_exit(os_file_seek_mutexes[i]);
+ os_mutex_enter(os_file_count_mutex);
+ os_n_pending_reads--;
+ os_mutex_exit(os_file_count_mutex);
+
if (ret && len == n) {
return(TRUE);
}
@@ -2225,12 +2257,8 @@ try_again:
os_bytes_read_since_printout += n;
try_again:
- os_n_pending_reads++;
-
ret = os_file_pread(file, buf, n, offset, offset_high);
- os_n_pending_reads--;
-
if ((ulint)ret == n) {
return(TRUE);
@@ -2310,6 +2338,10 @@ retry:
low = (DWORD) offset;
high = (DWORD) offset_high;
+ os_mutex_enter(os_file_count_mutex);
+ os_n_pending_writes++;
+ os_mutex_exit(os_file_count_mutex);
+
/* Protect the seek / write operation with a mutex */
i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
@@ -2321,6 +2353,10 @@ retry:
os_mutex_exit(os_file_seek_mutexes[i]);
+ os_mutex_enter(os_file_count_mutex);
+ os_n_pending_writes--;
+ os_mutex_exit(os_file_count_mutex);
+
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -2335,12 +2371,8 @@ retry:
return(FALSE);
}
- os_n_pending_writes++;
-
ret = WriteFile(file, buf, (DWORD) n, &len, NULL);
- os_n_pending_writes--;
-
/* Always do fsync to reduce the probability that when the OS crashes,
a database page is only partially physically written to disk. */
@@ -2352,6 +2384,10 @@ retry:
os_mutex_exit(os_file_seek_mutexes[i]);
+ os_mutex_enter(os_file_count_mutex);
+ os_n_pending_writes--;
+ os_mutex_exit(os_file_count_mutex);
+
if (ret && len == n) {
return(TRUE);
@@ -2402,11 +2438,7 @@ retry:
#else
ssize_t ret;
- os_n_pending_writes++;
-
ret = os_file_pwrite(file, buf, n, offset, offset_high);
-
- os_n_pending_writes--;
if ((ulint)ret == n) {
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 32aa0385596..be1a48a4b46 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -549,6 +549,15 @@ row_ins_cascade_calc_update_vec(
default:
ut_error;
case 1:
+ if (UNIV_UNLIKELY(
+ dtype_get_charset_coll(
+ dtype_get_prtype(type))
+ == DATA_MYSQL_BINARY_CHARSET_COLL)) {
+ /* Do not pad BINARY
+ columns. */
+ return(ULINT_UNDEFINED);
+ }
+
/* space=0x20 */
memset(pad_start, 0x20,
pad_end - pad_start);
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 723e305b2ab..937056c300e 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -1436,8 +1436,9 @@ trx_register_new_rec_lock() to store the information which new record locks
really were set. This function removes a newly set lock under prebuilt->pcur,
and also under prebuilt->clust_pcur. Currently, this is only used and tested
in the case of an UPDATE or a DELETE statement, where the row lock is of the
-LOCK_X type.
-Thus, this implements a 'mini-rollback' that releases the latest record
+LOCK_X or LOCK_S type.
+
+Thus, this implements a 'mini-rollback' that releases the latest record
locks we set. */
int
@@ -1474,7 +1475,14 @@ row_unlock_for_mysql(
index = btr_pcur_get_btr_cur(pcur)->index;
- if (index != NULL && trx_new_rec_locks_contain(trx, index)) {
+ if (UNIV_UNLIKELY(index == NULL)) {
+ fprintf(stderr,
+"InnoDB: Error: Index is not set for persistent cursor.\n");
+ ut_print_buf(stderr, (const byte*)pcur, sizeof(btr_pcur_t));
+ ut_error;
+ }
+
+ if (trx_new_rec_locks_contain(trx, index)) {
mtr_start(&mtr);
@@ -1486,11 +1494,7 @@ row_unlock_for_mysql(
rec = btr_pcur_get_rec(pcur);
- mutex_enter(&kernel_mutex);
-
- lock_rec_reset_and_release_wait(rec);
-
- mutex_exit(&kernel_mutex);
+ lock_rec_unlock(trx, rec, prebuilt->select_lock_type);
mtr_commit(&mtr);
@@ -1520,11 +1524,7 @@ row_unlock_for_mysql(
rec = btr_pcur_get_rec(clust_pcur);
- mutex_enter(&kernel_mutex);
-
- lock_rec_reset_and_release_wait(rec);
-
- mutex_exit(&kernel_mutex);
+ lock_rec_unlock(trx, rec, prebuilt->select_lock_type);
mtr_commit(&mtr);
}
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 1b66f14f5d7..d25023dc6be 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -2771,8 +2771,8 @@ row_sel_get_clust_rec_for_mysql(
func_exit:
*out_rec = clust_rec;
- if (prebuilt->select_lock_type == LOCK_X) {
- /* We may use the cursor in update: store its position */
+ if (prebuilt->select_lock_type != LOCK_NONE) {
+ /* We may use the cursor in unlock: store its position */
btr_pcur_store_position(prebuilt->clust_pcur, mtr);
}
@@ -3972,12 +3972,12 @@ got_row:
/* We have an optimization to save CPU time: if this is a consistent
read on a unique condition on the clustered index, then we do not
store the pcur position, because any fetch next or prev will anyway
- return 'end of file'. An exception is the MySQL HANDLER command
- where the user can move the cursor with PREV or NEXT even after
- a unique search. */
+ return 'end of file'. Exceptions are locking reads and the MySQL
+ HANDLER command where the user can move the cursor with PREV or NEXT
+ even after a unique search. */
if (!unique_search_from_clust_index
- || prebuilt->select_lock_type == LOCK_X
+ || prebuilt->select_lock_type != LOCK_NONE
|| prebuilt->used_in_HANDLER) {
/* Inside an update always store the cursor position */
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 090057f5d46..2637b28ef90 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -794,7 +794,8 @@ trx_commit_off_kernel(
in trx sys header if MySQL binlogging is on or the database
server is a MySQL replication slave */
- if (trx->mysql_log_file_name) {
+ if (trx->mysql_log_file_name
+ && trx->mysql_log_file_name[0] != '\0') {
trx_sys_update_mysql_binlog_offset(
trx->mysql_log_file_name,
trx->mysql_log_offset,