diff options
-rw-r--r-- | storage/innobase/dict/dict0dict.c | 2 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 2 | ||||
-rw-r--r-- | storage/innobase/include/row0mysql.h | 2 | ||||
-rw-r--r-- | storage/innobase/include/srv0srv.h | 6 | ||||
-rw-r--r-- | storage/innobase/include/trx0undo.h | 1 | ||||
-rw-r--r-- | storage/innobase/os/os0file.c | 61 | ||||
-rw-r--r-- | storage/innobase/row/row0sel.c | 23 | ||||
-rw-r--r-- | storage/innobase/srv/srv0srv.c | 2 | ||||
-rw-r--r-- | storage/innobase/srv/srv0start.c | 6 | ||||
-rw-r--r-- | storage/innobase/trx/trx0trx.c | 6 | ||||
-rw-r--r-- | storage/innobase/trx/trx0undo.c | 26 |
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) { |