From ec8257216e5b25ed82d63f074254b9454e0a0df3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 10 Jan 2014 12:11:36 +0200 Subject: [PATCH] Enhancement: Change atomic_writes table option to enum type. Now every file can either use atomic writes, not use it or use default. SYNTAX: ATOMIC_WRITES=['DEFAULT','ON','OFF'] Idea here is to be able to define innodb_doublewrite = 1 but with following rules: ATOMIC_WRITES='DEFAULT' - if innodb_use_atomic_writes = 1, we do not write to doublewrite buffer the changes if innodb_use_atomic_writes = 0, we write to doublewrite buffer ATOMIC_WRITES='ON' - do not write to doublewrite buffer ATOMIC_WRITES='OFF' - write to doublewrite buffer Note that doublewrite buffer can't be used if innodb_doublewrite = 0. --- storage/innobase/buf/buf0flu.cc | 24 +++++++- storage/innobase/fil/fil0fil.cc | 10 ++-- storage/innobase/fil/fil0pagecompress.cc | 8 +-- storage/innobase/handler/ha_innodb.cc | 8 ++- storage/innobase/handler/ha_innodb.h | 8 ++- storage/innobase/handler/handler0alter.cc | 2 +- storage/innobase/include/dict0dict.h | 4 +- storage/innobase/include/dict0dict.ic | 15 +++-- storage/innobase/include/dict0mem.h | 3 +- storage/innobase/include/dict0pagecompress.h | 4 +- storage/innobase/include/dict0pagecompress.ic | 12 ++-- storage/innobase/include/dict0types.h | 8 +++ storage/innobase/include/fil0pagecompress.h | 4 +- storage/innobase/include/fsp0fsp.h | 2 +- storage/innobase/include/fsp0fsp.ic | 5 +- storage/innobase/include/fsp0pagecompress.h | 9 +++ storage/innobase/include/fsp0pagecompress.ic | 4 +- storage/innobase/include/os0file.h | 34 ++++++----- storage/innobase/include/os0file.ic | 9 +-- storage/innobase/os/os0file.cc | 58 ++++++++----------- 20 files changed, 137 insertions(+), 94 deletions(-) diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index b5f1aeef597..d159ddbe23f 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -50,6 +50,7 @@ Created 11/11/1995 Heikki Tuuri #include "srv0mon.h" #include "mysql/plugin.h" #include "mysql/service_thd_wait.h" +#include "fil0pagecompress.h" /** Number of pages flushed through non flush_list flushes. */ static ulint buf_lru_flush_page_count = 0; @@ -866,6 +867,8 @@ buf_flush_write_block_low( { ulint zip_size = buf_page_get_zip_size(bpage); page_t* frame = NULL; + ulint space_id = buf_page_get_space(bpage); + atomic_writes_t awrites = fil_space_get_atomic_writes(space_id); #ifdef UNIV_DEBUG buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); @@ -943,10 +946,25 @@ buf_flush_write_block_low( buf_page_get_page_no(bpage), 0, zip_size ? zip_size : UNIV_PAGE_SIZE, frame, bpage, &bpage->write_size); - } else if (flush_type == BUF_FLUSH_SINGLE_PAGE) { - buf_dblwr_write_single_page(bpage); } else { - buf_dblwr_add_to_batch(bpage); + /* InnoDB uses doublewrite buffer and doublewrite buffer + is initialized. User can define do we use atomic writes + on a file space (table) or not. If atomic writes are + not used we should use doublewrite buffer and if + atomic writes should be used, no doublewrite buffer + is used. */ + + if (awrites == ATOMIC_WRITES_ON) { + fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, + FALSE, buf_page_get_space(bpage), zip_size, + buf_page_get_page_no(bpage), 0, + zip_size ? zip_size : UNIV_PAGE_SIZE, + frame, bpage, &bpage->write_size); + } else if (flush_type == BUF_FLUSH_SINGLE_PAGE) { + buf_dblwr_write_single_page(bpage); + } else { + buf_dblwr_add_to_batch(bpage); + } } } diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 0bec85c699a..2f56936ae04 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -756,7 +756,7 @@ fil_node_open_file( node->handle = os_file_create_simple_no_error_handling( innodb_file_data_key, node->name, OS_FILE_OPEN, - OS_FILE_READ_ONLY, &success, FALSE); + OS_FILE_READ_ONLY, &success, 0); if (!success) { /* The following call prints an error message */ os_file_get_last_error(true); @@ -3159,7 +3159,7 @@ fil_create_link_file( file = os_file_create_simple_no_error_handling( innodb_file_data_key, link_filepath, - OS_FILE_CREATE, OS_FILE_READ_WRITE, &success, FALSE); + OS_FILE_CREATE, OS_FILE_READ_WRITE, &success, 0); if (!success) { /* The following call will print an error message */ @@ -3269,8 +3269,8 @@ fil_open_linked_file( const char* tablename, /*!< in: database/tablename */ char** remote_filepath,/*!< out: remote filepath */ os_file_t* remote_file, /*!< out: remote file handle */ - ibool atomic_writes) /*!< in: should atomic writes be - used */ + ulint atomic_writes) /*!< in: atomic writes table option + value */ { ibool success; @@ -4861,7 +4861,7 @@ retry: #ifdef HAVE_POSIX_FALLOCATE if (srv_use_posix_fallocate) { - ulint n_pages = size_after_extend - start_page_no; + ulint n_pages = size_after_extend; success = os_file_set_size(node->name, node->handle, n_pages * page_size); diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc index 3926b23c677..b67f583b53b 100644 --- a/storage/innobase/fil/fil0pagecompress.cc +++ b/storage/innobase/fil/fil0pagecompress.cc @@ -350,8 +350,8 @@ fil_get_compression_alg_name( /*******************************************************************//** Returns the atomic writes flag of the space, or false if the space is not using atomic writes. The tablespace must be cached in the memory cache. -@return true if space using atomic writes, false if not */ -ibool +@return atomic writes table option value */ +atomic_writes_t fil_space_get_atomic_writes( /*========================*/ ulint id) /*!< in: space id */ @@ -362,8 +362,8 @@ fil_space_get_atomic_writes( if (flags && flags != ULINT_UNDEFINED) { - return(fsp_flags_get_atomic_writes(flags)); + return((atomic_writes_t)fsp_flags_get_atomic_writes(flags)); } - return(flags); + return((atomic_writes_t)0); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 085521ac7e5..074f8c3fc2c 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -503,7 +503,7 @@ ha_create_table_option innodb_table_option_list[]= compression for this table*/ HA_TOPTION_NUMBER("PAGE_COMPRESSION_LEVEL", page_compression_level, ULINT_UNDEFINED, 0, 9, 1), /* With this option user can enable atomic writes feature for this table */ - HA_TOPTION_BOOL("ATOMIC_WRITES", atomic_writes, 0), + HA_TOPTION_ENUM("ATOMIC_WRITES", atomic_writes, "DEFAULT,ON,OFF", 0), HA_TOPTION_END }; @@ -9738,6 +9738,7 @@ ha_innobase::check_table_options( { enum row_type row_format = table->s->row_type;; ha_table_option_struct *options= table->s->option_struct; + atomic_writes_t awrites = (atomic_writes_t)options->atomic_writes; /* Check page compression requirements */ if (options->page_compressed) { @@ -9811,8 +9812,9 @@ ha_innobase::check_table_options( } /* Check atomic writes requirements */ - if (options->atomic_writes) { - if (!srv_use_atomic_writes && !use_tablespace) { + if (awrites == ATOMIC_WRITES_ON || + (awrites == ATOMIC_WRITES_DEFAULT && srv_use_atomic_writes)) { + if (!use_tablespace) { push_warning( thd, Sql_condition::WARN_LEVEL_WARN, HA_WRONG_CREATE_OPTION, diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 5eb460072bb..9e133ea1023 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -64,8 +64,12 @@ struct ha_table_option_struct if this option is true. */ int page_compression_level; /*!< Table page compression level or UNIV_UNSPECIFIED. */ - bool atomic_writes; /*!< Use atomic writes for this - table if this options is true. */ + uint atomic_writes; /*!< Use atomic writes for this + table if this options is ON or + in DEFAULT if + srv_use_atomic_writes=1. + Atomic writes are not used if + value OFF.*/ }; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 49f8a05d11a..244e7d19586 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -258,7 +258,7 @@ ha_innobase::check_if_supported_inplace_alter( if (new_options->page_compressed != old_options->page_compressed || new_options->page_compression_level != old_options->page_compression_level || - new_options->atomic_writes != old_options->page_compression_level) { + new_options->atomic_writes != old_options->atomic_writes) { ha_alter_info->unsupported_reason = innobase_get_err_msg( ER_ALTER_OPERATION_NOT_SUPPORTED_REASON); DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 0ca64956a2e..3208a764fe1 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -887,8 +887,8 @@ dict_tf_set( pages */ ulint page_compression_level, /*!< in: table page compression level */ - bool atomic_writes) /*!< in: table uses atomic - writes */ + ulint atomic_writes) /*!< in: table atomic + writes option value*/ __attribute__((nonnull)); /********************************************************************//** Convert a 32 bit integer table flags to the 32 bit integer that is diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index 65c1bfca24f..f9d548681a8 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -670,6 +670,7 @@ dict_sys_tables_type_validate( ulint page_compression = DICT_TF_GET_PAGE_COMPRESSION(type); ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(type); ulint atomic_writes = DICT_TF_GET_ATOMIC_WRITES(type); + atomic_writes_t awrites = (atomic_writes_t)atomic_writes; /* The low order bit of SYS_TABLES.TYPE is always set to 1. If the format is UNIV_FORMAT_B or higher, this field is the same @@ -734,7 +735,8 @@ dict_sys_tables_type_validate( } } - if (atomic_writes) { + if (awrites == ATOMIC_WRITES_ON || + (awrites == ATOMIC_WRITES_DEFAULT && srv_use_atomic_writes)) { if (!atomic_blobs) { return(ULINT_UNDEFINED); } @@ -818,9 +820,10 @@ dict_tf_set( pages */ ulint page_compression_level, /*!< in: table page compression level */ - bool atomic_writes) /*!< in: table uses atomic - writes */ + ulint atomic_writes) /*!< in: table atomic writes setup */ { + atomic_writes_t awrites = (atomic_writes_t)atomic_writes; + switch (format) { case REC_FORMAT_REDUNDANT: *flags = 0; @@ -853,9 +856,9 @@ dict_tf_set( ut_ad(dict_tf_get_page_compression_level(*flags) == page_compression_level); } - if (atomic_writes) { - *flags |= (1 << DICT_TF_POS_ATOMIC_WRITES); - ut_ad(dict_tf_get_atomic_writes(*flags) == TRUE); + if (awrites != ATOMIC_WRITES_DEFAULT) { + *flags |= (atomic_writes << DICT_TF_POS_ATOMIC_WRITES); + ut_ad(dict_tf_get_atomic_writes(*flags) == awrites); *flags |= (1 << DICT_TF_POS_ATOMIC_BLOBS); } diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 6cfcb81bcd5..f4e5e558488 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -129,8 +129,9 @@ Width of the page compression flag /** Width of atomic writes flag +DEFAULT=0, ON = 1, OFF = 2 */ -#define DICT_TF_WIDTH_ATOMIC_WRITES 1 +#define DICT_TF_WIDTH_ATOMIC_WRITES 2 /** Width of all the currently known table flags */ #define DICT_TF_BITS (DICT_TF_WIDTH_COMPACT \ diff --git a/storage/innobase/include/dict0pagecompress.h b/storage/innobase/include/dict0pagecompress.h index 236924758f1..19a2a6c52f3 100644 --- a/storage/innobase/include/dict0pagecompress.h +++ b/storage/innobase/include/dict0pagecompress.h @@ -71,7 +71,7 @@ dict_tf_verify_flags( Extract the atomic writes flag from table flags. @return true if atomic writes are used, false if not used */ UNIV_INLINE -ibool +atomic_writes_t dict_tf_get_atomic_writes( /*======================*/ ulint flags) /*!< in: flags */ @@ -81,7 +81,7 @@ dict_tf_get_atomic_writes( Check whether the table uses the atomic writes. @return true if atomic writes is used, false if not */ UNIV_INLINE -ibool +atomic_writes_t dict_table_get_atomic_writes( /*=========================*/ const dict_table_t* table); /*!< in: table */ diff --git a/storage/innobase/include/dict0pagecompress.ic b/storage/innobase/include/dict0pagecompress.ic index 98b64723542..fb9581fc657 100644 --- a/storage/innobase/include/dict0pagecompress.ic +++ b/storage/innobase/include/dict0pagecompress.ic @@ -168,24 +168,24 @@ dict_table_is_page_compressed( /********************************************************************//** Extract the atomic writes flag from table flags. -@return true if atomic writes are used, false if not used */ +@return enumerated value of atomic writes */ UNIV_INLINE -ibool +atomic_writes_t dict_tf_get_atomic_writes( /*======================*/ ulint flags) /*!< in: flags */ { - return(DICT_TF_GET_ATOMIC_WRITES(flags)); + return((atomic_writes_t)DICT_TF_GET_ATOMIC_WRITES(flags)); } /********************************************************************//** Check whether the table uses the atomic writes. -@return true if atomic writes is used, false if not */ +@return enumerated value of atomic writes */ UNIV_INLINE -ibool +atomic_writes_t dict_table_get_atomic_writes( /*=========================*/ const dict_table_t* table) /*!< in: table */ { - return (dict_tf_get_atomic_writes(table->flags)); + return ((atomic_writes_t)dict_tf_get_atomic_writes(table->flags)); } diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h index b7f7c2d9df9..a398ccfe7ea 100644 --- a/storage/innobase/include/dict0types.h +++ b/storage/innobase/include/dict0types.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2013, SkySQL Ab. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -67,4 +68,11 @@ enum ib_quiesce_t { QUIESCE_COMPLETE /*!< All done */ }; +/** Enum values for atomic_writes table option */ +typedef enum { + ATOMIC_WRITES_DEFAULT = 0, + ATOMIC_WRITES_ON = 1, + ATOMIC_WRITES_OFF = 2 +} atomic_writes_t; + #endif diff --git a/storage/innobase/include/fil0pagecompress.h b/storage/innobase/include/fil0pagecompress.h index e21eae7a5ee..bf5caf98a75 100644 --- a/storage/innobase/include/fil0pagecompress.h +++ b/storage/innobase/include/fil0pagecompress.h @@ -49,8 +49,8 @@ fil_space_is_page_compressed( /*******************************************************************//** Returns the atomic writes flag of the space, or false if the space is not using atomic writes. The tablespace must be cached in the memory cache. -@return true if space using atomic writes, false if not */ -ibool +@return atomic write table option value */ +atomic_writes_t fil_space_get_atomic_writes( /*=========================*/ ulint id); /*!< in: space id */ diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index 31c34cdafca..87f1f5a636d 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -58,7 +58,7 @@ is found in a remote location, not the default data directory. */ #define FSP_FLAGS_WIDTH_PAGE_COMPRESSION 1 #define FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL 4 /** Number of flag bits used to indicate atomic writes for this tablespace */ -#define FSP_FLAGS_WIDTH_ATOMIC_WRITES 1 +#define FSP_FLAGS_WIDTH_ATOMIC_WRITES 2 /** Width of all the currently known tablespace flags */ #define FSP_FLAGS_WIDTH (FSP_FLAGS_WIDTH_POST_ANTELOPE \ diff --git a/storage/innobase/include/fsp0fsp.ic b/storage/innobase/include/fsp0fsp.ic index 0ca02a5652d..cb12d556ec4 100644 --- a/storage/innobase/include/fsp0fsp.ic +++ b/storage/innobase/include/fsp0fsp.ic @@ -67,6 +67,7 @@ fsp_flags_is_valid( ulint page_compression = FSP_FLAGS_GET_PAGE_COMPRESSION(flags); ulint page_compression_level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags); ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(flags); + atomic_writes_t awrites = (atomic_writes_t)atomic_writes; DBUG_EXECUTE_IF("fsp_flags_is_valid_failure", return(false);); @@ -116,7 +117,9 @@ fsp_flags_is_valid( } } - if (atomic_writes && !atomic_blobs) { + if ((awrites == ATOMIC_WRITES_ON || + (awrites == ATOMIC_WRITES_DEFAULT && srv_use_atomic_writes)) + && !atomic_blobs) { return (false); } diff --git a/storage/innobase/include/fsp0pagecompress.h b/storage/innobase/include/fsp0pagecompress.h index 417d4a6879e..4913f1d6b29 100644 --- a/storage/innobase/include/fsp0pagecompress.h +++ b/storage/innobase/include/fsp0pagecompress.h @@ -57,6 +57,15 @@ fsp_flags_get_page_compression_level( /*=================================*/ ulint flags); /*!< in: tablespace flags */ +/********************************************************************//** +Determine the tablespace is using atomic writes from dict_table_t::flags. +@return true if atomic writes is used, false if not */ +UNIV_INLINE +atomic_writes_t +fsp_flags_get_atomic_writes( +/*========================*/ + ulint flags); /*!< in: tablespace flags */ + #ifndef UNIV_NONINL #include "fsp0pagecompress.ic" #endif diff --git a/storage/innobase/include/fsp0pagecompress.ic b/storage/innobase/include/fsp0pagecompress.ic index 1dffd1bedf1..4859012428a 100644 --- a/storage/innobase/include/fsp0pagecompress.ic +++ b/storage/innobase/include/fsp0pagecompress.ic @@ -52,10 +52,10 @@ fsp_flags_get_page_compression_level( Determine the tablespace is using atomic writes from dict_table_t::flags. @return true if atomic writes is used, false if not */ UNIV_INLINE -ibool +atomic_writes_t fsp_flags_get_atomic_writes( /*========================*/ ulint flags) /*!< in: tablespace flags */ { - return(FSP_FLAGS_GET_ATOMIC_WRITES(flags)); + return((atomic_writes_t)FSP_FLAGS_GET_ATOMIC_WRITES(flags)); } diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index eb5e1dddaf5..8b798b6d34f 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -275,12 +275,12 @@ The wrapper functions have the prefix of "innodb_". */ pfs_os_file_create_func(key, name, create, purpose, type, \ success, atomic_writes, __FILE__, __LINE__) -# define os_file_create_simple(key, name, create, access, success, atomic_writes) \ +# define os_file_create_simple(key, name, create, access, success) \ pfs_os_file_create_simple_func(key, name, create, access, \ - success, atomic_writes, __FILE__, __LINE__) + success, __FILE__, __LINE__) # define os_file_create_simple_no_error_handling( \ - key, name, create_mode, access, success, atomic_writes) \ + key, name, create_mode, access, success, atomic_writes) \ pfs_os_file_create_simple_no_error_handling_func( \ key, name, create_mode, access, success, atomic_writes, __FILE__, __LINE__) @@ -315,13 +315,13 @@ to original un-instrumented file I/O APIs */ # define os_file_create(key, name, create, purpose, type, success, atomic_writes) \ os_file_create_func(name, create, purpose, type, success, atomic_writes) -# define os_file_create_simple(key, name, create_mode, access, success, atomic_writes) \ - os_file_create_simple_func(name, create_mode, access, success, atomic_writes) +# define os_file_create_simple(key, name, create_mode, access, success) \ + os_file_create_simple_func(name, create_mode, access, success) # define os_file_create_simple_no_error_handling( \ - key, name, create_mode, access, success, atomic_writes) \ - os_file_create_simple_no_error_handling_func( \ - name, create_mode, access, success, atomic_writes) + key, name, create_mode, access, success, atomic_writes) \ + os_file_create_simple_no_error_handling_func( \ + name, create_mode, access, success, atomic_writes) # define os_file_close(file) os_file_close_func(file) @@ -470,8 +470,7 @@ os_file_create_simple_func( ulint create_mode,/*!< in: create mode */ ulint access_type,/*!< in: OS_FILE_READ_ONLY or OS_FILE_READ_WRITE */ - ibool* success,/*!< out: TRUE if succeed, FALSE if error */ - ibool atomic_writes); /*!