diff options
author | unknown <aivanov@mysql.com> | 2006-01-16 14:32:43 +0300 |
---|---|---|
committer | unknown <aivanov@mysql.com> | 2006-01-16 14:32:43 +0300 |
commit | 7bafd119a3f73c39306a133936501a433e80bcf9 (patch) | |
tree | 42a4966dcc1d1565033773730d0782e22ce4570b /innobase | |
parent | fe1970d4b9084de6e883b0dae50ab4d5d3957e54 (diff) | |
download | mariadb-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.h | 3 | ||||
-rw-r--r-- | innobase/include/data0type.ic | 39 | ||||
-rw-r--r-- | innobase/include/lock0lock.h | 20 | ||||
-rw-r--r-- | innobase/include/os0file.h | 5 | ||||
-rw-r--r-- | innobase/include/row0mysql.h | 5 | ||||
-rw-r--r-- | innobase/lock/lock0lock.c | 71 | ||||
-rw-r--r-- | innobase/os/os0file.c | 112 | ||||
-rw-r--r-- | innobase/row/row0ins.c | 9 | ||||
-rw-r--r-- | innobase/row/row0mysql.c | 26 | ||||
-rw-r--r-- | innobase/row/row0sel.c | 12 | ||||
-rw-r--r-- | innobase/trx/trx0trx.c | 3 |
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, |