summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--storage/innobase/dict/dict0dict.c2
-rw-r--r--storage/innobase/handler/ha_innodb.cc2
-rw-r--r--storage/innobase/include/row0mysql.h2
-rw-r--r--storage/innobase/include/srv0srv.h6
-rw-r--r--storage/innobase/include/trx0undo.h1
-rw-r--r--storage/innobase/os/os0file.c61
-rw-r--r--storage/innobase/row/row0sel.c23
-rw-r--r--storage/innobase/srv/srv0srv.c2
-rw-r--r--storage/innobase/srv/srv0start.c6
-rw-r--r--storage/innobase/trx/trx0trx.c6
-rw-r--r--storage/innobase/trx/trx0undo.c26
11 files changed, 108 insertions, 29 deletions
diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
index 10cef688705..5eaa44b4615 100644
--- a/storage/innobase/dict/dict0dict.c
+++ b/storage/innobase/dict/dict0dict.c
@@ -3395,7 +3395,7 @@ loop:
ptr = dict_accept(cs, ptr, "FOREIGN", &success);
- if (!success) {
+ if (!success || !my_isspace(cs, *ptr)) {
goto loop;
}
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index a181ecf1612..665171927e0 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -7935,7 +7935,7 @@ bool ha_innobase::check_if_incompatible_data(
}
/* Check that row format didn't change */
- if ((info->used_fields & HA_CREATE_USED_AUTO) &&
+ if ((info->used_fields & HA_CREATE_USED_ROW_FORMAT) &&
get_row_type() != info->row_type) {
return COMPATIBLE_DATA_NO;
diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index f486caa874d..ca9d9c6b8f8 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -679,7 +679,7 @@ struct row_prebuilt_struct {
fetched row in fetch_cache */
ulint n_fetch_cached; /* number of not yet fetched rows
in fetch_cache */
- mem_heap_t* blob_heap; /* in SELECTS BLOB fie lds are copied
+ mem_heap_t* blob_heap; /* in SELECTS BLOB fields are copied
to this heap */
mem_heap_t* old_vers_heap; /* memory heap where a previous
version is built in consistent read */
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index 1ad695f700c..f0bfd3b07ce 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -249,11 +249,7 @@ extern srv_sys_t* srv_sys;
/* Alternatives for the file flush option in Unix; see the InnoDB manual
about what these mean */
-#define SRV_UNIX_FDATASYNC 1 /* This is the default; it is
- currently mapped to a call of
- fsync() because fdatasync() seemed
- to corrupt files in Linux and
- Solaris */
+#define SRV_UNIX_FSYNC 1 /* This is the default */
#define SRV_UNIX_O_DSYNC 2
#define SRV_UNIX_LITTLESYNC 3
#define SRV_UNIX_NOSYNC 4
diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h
index f53c6b01be4..7f10e407746 100644
--- a/storage/innobase/include/trx0undo.h
+++ b/storage/innobase/include/trx0undo.h
@@ -240,6 +240,7 @@ trx_undo_set_state_at_finish(
/*=========================*/
/* out: undo log segment header page,
x-latched */
+ trx_rseg_t* rseg, /* in: rollback segment memory object */
trx_t* trx, /* in: transaction */
trx_undo_t* undo, /* in: undo log memory copy */
mtr_t* mtr); /* in: mtr */
diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c
index 78140cc5ecf..9adb9ddac50 100644
--- a/storage/innobase/os/os0file.c
+++ b/storage/innobase/os/os0file.c
@@ -22,8 +22,6 @@ Created 10/21/1995 Heikki Tuuri
#include <errno.h>
#endif /* UNIV_HOTBACKUP */
-#undef HAVE_FDATASYNC
-
#ifdef POSIX_ASYNC_IO
/* We assume in this case that the OS has standard Posix aio (at least SunOS
2.6, HP-UX 11i and AIX 4.3 have) */
@@ -1812,6 +1810,55 @@ os_file_set_eof(
#endif /* __WIN__ */
}
+#ifndef __WIN__
+/***************************************************************************
+Wrapper to fsync(2) that retries the call on some errors.
+Returns the value 0 if successful; otherwise the value -1 is returned and
+the global variable errno is set to indicate the error. */
+
+static
+int
+os_file_fsync(
+/*==========*/
+ /* out: 0 if success, -1 otherwise */
+ os_file_t file) /* in: handle to a file */
+{
+ int ret;
+ int failures;
+ ibool retry;
+
+ failures = 0;
+
+ do {
+ ret = fsync(file);
+
+ os_n_fsyncs++;
+
+ if (ret == -1 && errno == ENOLCK) {
+
+ if (failures % 100 == 0) {
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: fsync(): "
+ "No locks available; retrying\n");
+ }
+
+ os_thread_sleep(200000 /* 0.2 sec */);
+
+ failures++;
+
+ retry = TRUE;
+ } else {
+
+ retry = FALSE;
+ }
+ } while (retry);
+
+ return(ret);
+}
+#endif /* !__WIN__ */
+
/***************************************************************************
Flushes the write buffers of a given file to the disk. */
@@ -1869,23 +1916,19 @@ os_file_flush(
/* If we are not on an operating system that supports this,
then fall back to a plain fsync. */
- ret = fsync(file);
+ ret = os_file_fsync(file);
} else {
ret = fcntl(file, F_FULLFSYNC, NULL);
if (ret) {
/* If we are not on a file system that supports this,
then fall back to a plain fsync. */
- ret = fsync(file);
+ ret = os_file_fsync(file);
}
}
-#elif HAVE_FDATASYNC
- ret = fdatasync(file);
#else
- /* fprintf(stderr, "Flushing to file %p\n", file); */
- ret = fsync(file);
+ ret = os_file_fsync(file);
#endif
- os_n_fsyncs++;
if (ret == 0) {
return(TRUE);
diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c
index b050838aad2..9d2e08e0929 100644
--- a/storage/innobase/row/row0sel.c
+++ b/storage/innobase/row/row0sel.c
@@ -2643,6 +2643,25 @@ row_sel_store_mysql_rec(
data = rec_get_nth_field(rec, offsets,
templ->rec_field_no, &len);
+
+ if (UNIV_UNLIKELY(templ->type == DATA_BLOB)
+ && len != UNIV_SQL_NULL) {
+
+ /* It is a BLOB field locally stored in the
+ InnoDB record: we MUST copy its contents to
+ prebuilt->blob_heap here because later code
+ assumes all BLOB values have been copied to a
+ safe place. */
+
+ if (prebuilt->blob_heap == NULL) {
+ prebuilt->blob_heap = mem_heap_create(
+ UNIV_PAGE_SIZE);
+ }
+
+ data = memcpy(mem_heap_alloc(
+ prebuilt->blob_heap, len),
+ data, len);
+ }
}
if (len != UNIV_SQL_NULL) {
@@ -3558,7 +3577,9 @@ shortcut_fails_too_big_rec:
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
&& prebuilt->select_lock_type != LOCK_NONE
- && trx->mysql_query_str && trx->mysql_thd) {
+ && trx->mysql_query_str != NULL
+ && *trx->mysql_query_str != NULL
+ && trx->mysql_thd != NULL) {
/* Scan the MySQL query string; check if SELECT is the first
word there */
diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
index 1b13b19783e..53fa5c58ded 100644
--- a/storage/innobase/srv/srv0srv.c
+++ b/storage/innobase/srv/srv0srv.c
@@ -192,7 +192,7 @@ a heavier load on the I/O sub system. */
ulong srv_insert_buffer_batch_size = 20;
char* srv_file_flush_method_str = NULL;
-ulint srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
+ulint srv_unix_file_flush_method = SRV_UNIX_FSYNC;
ulint srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
ulint srv_max_n_open_files = 300;
diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c
index dac84e1410d..979d882307a 100644
--- a/storage/innobase/srv/srv0start.c
+++ b/storage/innobase/srv/srv0start.c
@@ -1122,12 +1122,12 @@ innobase_start_or_create_for_mysql(void)
if (srv_file_flush_method_str == NULL) {
/* These are the default options */
- srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
+ srv_unix_file_flush_method = SRV_UNIX_FSYNC;
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
#ifndef __WIN__
- } else if (0 == ut_strcmp(srv_file_flush_method_str, "fdatasync")) {
- srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "fsync")) {
+ srv_unix_file_flush_method = SRV_UNIX_FSYNC;
} else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) {
srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c
index 55b244abb0a..69b72451f2b 100644
--- a/storage/innobase/trx/trx0trx.c
+++ b/storage/innobase/trx/trx0trx.c
@@ -757,8 +757,8 @@ trx_commit_off_kernel(
mutex_enter(&(rseg->mutex));
if (trx->insert_undo != NULL) {
- trx_undo_set_state_at_finish(trx, trx->insert_undo,
- &mtr);
+ trx_undo_set_state_at_finish(
+ rseg, trx, trx->insert_undo, &mtr);
}
undo = trx->update_undo;
@@ -774,7 +774,7 @@ trx_commit_off_kernel(
transaction commit for this transaction. */
update_hdr_page = trx_undo_set_state_at_finish(
- trx, undo, &mtr);
+ rseg, trx, undo, &mtr);
/* We have to do the cleanup for the update log while
holding the rseg mutex because update log headers
diff --git a/storage/innobase/trx/trx0undo.c b/storage/innobase/trx/trx0undo.c
index 64e5ad3c9a8..2aa7752d292 100644
--- a/storage/innobase/trx/trx0undo.c
+++ b/storage/innobase/trx/trx0undo.c
@@ -1725,6 +1725,7 @@ trx_undo_set_state_at_finish(
/*=========================*/
/* out: undo log segment header page,
x-latched */
+ trx_rseg_t* rseg, /* in: rollback segment memory object */
trx_t* trx __attribute__((unused)), /* in: transaction */
trx_undo_t* undo, /* in: undo log memory copy */
mtr_t* mtr) /* in: mtr */
@@ -1734,7 +1735,10 @@ trx_undo_set_state_at_finish(
page_t* undo_page;
ulint state;
- ut_ad(trx && undo && mtr);
+ ut_ad(trx);
+ ut_ad(undo);
+ ut_ad(mtr);
+ ut_ad(mutex_own(&rseg->mutex));
if (undo->id >= TRX_RSEG_N_SLOTS) {
fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
@@ -1748,9 +1752,23 @@ trx_undo_set_state_at_finish(
seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
- if (undo->size == 1 && mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE)
- < TRX_UNDO_PAGE_REUSE_LIMIT) {
- state = TRX_UNDO_CACHED;
+ if (undo->size == 1
+ && mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE)
+ < TRX_UNDO_PAGE_REUSE_LIMIT) {
+
+ /* This is a heuristic to avoid the problem of all UNDO
+ slots ending up in one of the UNDO lists. Previously if
+ the server crashed with all the slots in one of the lists,
+ transactions that required the slots of a different type
+ would fail for lack of slots. */
+
+ if (UT_LIST_GET_LEN(rseg->update_undo_list) < 500
+ && UT_LIST_GET_LEN(rseg->insert_undo_list) < 500) {
+
+ state = TRX_UNDO_CACHED;
+ } else {
+ state = TRX_UNDO_TO_FREE;
+ }
} else if (undo->type == TRX_UNDO_INSERT) {