From: kevin.lewis Date: May 27 2012 12:59am Subject: bzr push into mysql-trunk branch (kevin.lewis:3902 to 3904) List-Archive: http://lists.mysql.com/commits/143964 Message-Id: <20120527005928.4012A223C76A@kevin-lewis-macbook.local> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3904 kevin.lewis@stripped 2012-05-26 Changes requested from Sunny modified: storage/innobase/dict/dict0crea.cc storage/innobase/dict/dict0load.cc storage/innobase/fil/fil0fil.cc storage/innobase/handler/ha_innodb.cc 3903 kevin.lewis@stripped 2012-05-26 [merge] Merge modified: storage/innobase/handler/ha_innodb.cc storage/innobase/handler/ha_innodb.h storage/innobase/handler/handler0alter.cc storage/innobase/include/trx0trx.h storage/innobase/include/trx0types.h storage/innobase/trx/trx0trx.cc 3902 kevin.lewis@stripped 2012-05-25 Full 5980 commit. added: mysql-test/include/shutdown_mysqld.inc mysql-test/include/start_mysqld.inc mysql-test/r/partition_innodb_tablespace.result mysql-test/suite/innodb/r/innodb-multiple-tablespaces.result mysql-test/suite/innodb/r/innodb-tablespace.result mysql-test/suite/innodb/r/innodb_wl5980_linux.result mysql-test/suite/innodb/t/innodb-multiple-tablespaces.test mysql-test/suite/innodb/t/innodb-tablespace.test mysql-test/suite/innodb/t/innodb_wl5980_linux.test mysql-test/suite/innodb/t/portability_wl5980_linux.zip mysql-test/suite/parts/r/partition_reorganize_innodb.result mysql-test/suite/parts/r/partition_reorganize_myisam.result mysql-test/suite/parts/t/partition_reorganize_innodb.test mysql-test/suite/parts/t/partition_reorganize_myisam.test mysql-test/t/partition_innodb_tablespace.test modified: include/my_base.h mysql-test/r/mysqlshow.result mysql-test/suite/innodb/r/innodb-alter-discard.result mysql-test/suite/innodb/r/innodb-restart.result mysql-test/suite/innodb/r/innodb-system-table-view.result mysql-test/suite/innodb/r/innodb_16k.result mysql-test/suite/innodb/r/innodb_4k.result mysql-test/suite/innodb/r/innodb_8k.result mysql-test/suite/innodb/t/innodb-alter-discard.test mysql-test/suite/innodb/t/innodb-restart.test mysql-test/suite/innodb/t/innodb-system-table-view.test mysql-test/suite/innodb/t/innodb_16k.test mysql-test/suite/innodb/t/innodb_4k.test mysql-test/suite/innodb/t/innodb_8k.test mysql-test/suite/parts/r/partition_basic_symlink_innodb.result mysql-test/suite/parts/t/partition_basic_symlink_innodb.test mysys/my_handler_errors.h sql/ha_partition.cc sql/ha_partition.h sql/handler.cc sql/sql_partition.cc sql/sql_partition.h sql/sql_table.cc storage/innobase/dict/dict0boot.cc storage/innobase/dict/dict0crea.cc storage/innobase/dict/dict0dict.cc storage/innobase/dict/dict0load.cc storage/innobase/fil/fil0fil.cc storage/innobase/handler/ha_innodb.cc storage/innobase/handler/ha_innodb.h storage/innobase/handler/handler0alter.cc storage/innobase/handler/i_s.cc storage/innobase/handler/i_s.h storage/innobase/include/db0err.h storage/innobase/include/dict0boot.h storage/innobase/include/dict0crea.h storage/innobase/include/dict0dict.h storage/innobase/include/dict0dict.ic storage/innobase/include/dict0load.h storage/innobase/include/dict0mem.h storage/innobase/include/fil0fil.h storage/innobase/include/fsp0fsp.h storage/innobase/include/fsp0fsp.ic storage/innobase/include/os0file.h storage/innobase/include/row0merge.h storage/innobase/lock/lock0lock.cc storage/innobase/os/os0file.cc storage/innobase/row/row0import.cc storage/innobase/row/row0merge.cc storage/innobase/row/row0mysql.cc storage/innobase/srv/srv0start.cc storage/innobase/trx/trx0rec.cc storage/innobase/ut/ut0ut.cc === modified file 'storage/innobase/dict/dict0crea.cc' --- a/storage/innobase/dict/dict0crea.cc revid:kevin.lewis@stripped +++ b/storage/innobase/dict/dict0crea.cc revid:kevin.lewis@stripped @@ -286,8 +286,8 @@ dict_build_table_def_step( - page 3 will contain the root of the clustered index of the table we create here. */ - path = table->data_dir_path ? table->data_dir_path : - table->dir_path_of_temp_table; + path = table->data_dir_path ? table->data_dir_path + : table->dir_path_of_temp_table; ut_ad(dict_table_get_format(table) <= UNIV_FORMAT_MAX); ut_ad(!dict_table_zip_size(table) @@ -1211,7 +1211,7 @@ function_exit: Check whether a system table exists. Additionally, if it exists, move it to the non-LRU end of the table LRU list. This is oly used for system tables that can be upgraded or added to an older database, -which include SYS_FOREIGN, SYS_FOREIGN_COLS, SYS_TABLESPACES and +which include SYS_FOREIGN, SYS_FOREIGN_COLS, SYS_TABLESPACES and SYS_DATAFILES. @return TRUE if they exist. */ static @@ -1264,22 +1264,22 @@ dict_create_or_check_foreign_constraint_ { trx_t* trx; my_bool srv_file_per_table_backup; - dberr_t error; - dberr_t sys_foreign_ok; - dberr_t sys_foreign_cols_ok; + dberr_t err; + dberr_t sys_foreign_err; + dberr_t sys_foreign_cols_err; ut_a(srv_get_active_thread_type() == SRV_NONE); /* Note: The master thread has not been started at this point. */ - sys_foreign_ok = dict_check_if_system_table_exists( + sys_foreign_err = dict_check_if_system_table_exists( "SYS_FOREIGN", DICT_NUM_FIELDS__SYS_FOREIGN + 1, 3); - sys_foreign_cols_ok = dict_check_if_system_table_exists( + sys_foreign_cols_err = dict_check_if_system_table_exists( "SYS_FOREIGN_COLS", DICT_NUM_FIELDS__SYS_FOREIGN_COLS + 1, 1); - if (sys_foreign_ok == DB_SUCCESS - && sys_foreign_cols_ok == DB_SUCCESS) { + if (sys_foreign_err == DB_SUCCESS + && sys_foreign_cols_err == DB_SUCCESS) { return(DB_SUCCESS); } @@ -1291,23 +1291,23 @@ dict_create_or_check_foreign_constraint_ /* Check which incomplete table definition to drop. */ - if (sys_foreign_ok == DB_CORRUPTION) { - fprintf(stderr, - "InnoDB: dropping incompletely created " - "SYS_FOREIGN table\n"); + if (sys_foreign_err == DB_CORRUPTION) { + ib_logf(IB_LOG_LEVEL_WARN, + "Dropping incompletely created " + "SYS_FOREIGN table.\n"); row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE); } - if (sys_foreign_cols_ok == DB_CORRUPTION) { - fprintf(stderr, - "InnoDB: dropping incompletely created " - "SYS_FOREIGN_COLS table\n"); + if (sys_foreign_cols_err == DB_CORRUPTION) { + ib_logf(IB_LOG_LEVEL_WARN, + "Dropping incompletely created " + "SYS_FOREIGN_COLS table.\n"); row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE); } - fprintf(stderr, - "InnoDB: Creating foreign key constraint system tables\n"); + ib_logf(IB_LOG_LEVEL_WARN, + "Creating foreign key constraint system tables.\n"); /* NOTE: in dict_load_foreigns we use the fact that there are 2 secondary indexes on SYS_FOREIGN, and they @@ -1326,7 +1326,7 @@ dict_create_or_check_foreign_constraint_ srv_file_per_table = 0; - error = que_eval_sql( + err = que_eval_sql( NULL, "PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n" "BEGIN\n" @@ -1347,23 +1347,20 @@ dict_create_or_check_foreign_constraint_ "END;\n", FALSE, trx); - if (error != DB_SUCCESS) { - fprintf(stderr, "InnoDB: error %lu in creation\n", - (ulong) error); - - ut_a(error == DB_OUT_OF_FILE_SPACE - || error == DB_TOO_MANY_CONCURRENT_TRXS); + if (err != DB_SUCCESS) { + ib_logf(IB_LOG_LEVEL_ERROR, + "Creation of SYS_FOREIGN and SYS_FOREIGN_COLS " + "has failed with error %lu. Tablespace is full. " + "Dropping incompletely created tables.\n", + (ulong) err); - fprintf(stderr, - "InnoDB: creation failed\n" - "InnoDB: tablespace is full\n" - "InnoDB: dropping incompletely created" - " SYS_FOREIGN tables\n"); + ut_ad(err == DB_OUT_OF_FILE_SPACE + || err == DB_TOO_MANY_CONCURRENT_TRXS); row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE); row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE); - error = DB_MUST_GET_MORE_FILE_SPACE; + err = DB_MUST_GET_MORE_FILE_SPACE; } trx_commit_for_mysql(trx); @@ -1374,23 +1371,22 @@ dict_create_or_check_foreign_constraint_ srv_file_per_table = srv_file_per_table_backup; - if (error == DB_SUCCESS) { - fprintf(stderr, - "InnoDB: Foreign key constraint system tables" - " created\n"); + if (err == DB_SUCCESS) { + ib_logf(IB_LOG_LEVEL_INFO, + "Foreign key constraint system tables created\n"); } /* Note: The master thread has not been started at this point. */ /* Confirm and move to the non-LRU part of the table LRU list. */ - sys_foreign_ok = dict_check_if_system_table_exists( + sys_foreign_err = dict_check_if_system_table_exists( "SYS_FOREIGN", DICT_NUM_FIELDS__SYS_FOREIGN + 1, 3); - ut_a(sys_foreign_ok == DB_SUCCESS); + ut_a(sys_foreign_err == DB_SUCCESS); - sys_foreign_cols_ok = dict_check_if_system_table_exists( + sys_foreign_cols_err = dict_check_if_system_table_exists( "SYS_FOREIGN_COLS", DICT_NUM_FIELDS__SYS_FOREIGN_COLS + 1, 1); - ut_a(sys_foreign_cols_ok == DB_SUCCESS); + ut_a(sys_foreign_cols_err == DB_SUCCESS); - return(error); + return(err); } /****************************************************************//** @@ -1631,21 +1627,21 @@ dict_create_or_check_sys_tablespace(void { trx_t* trx; my_bool srv_file_per_table_backup; - dberr_t error; - dberr_t sys_tablespaces_ok; - dberr_t sys_datafiles_ok; + dberr_t err; + dberr_t sys_tablespaces_err; + dberr_t sys_datafiles_err; ut_a(srv_get_active_thread_type() == SRV_NONE); /* Note: The master thread has not been started at this point. */ - sys_tablespaces_ok = dict_check_if_system_table_exists( + sys_tablespaces_err = dict_check_if_system_table_exists( "SYS_TABLESPACES", DICT_NUM_FIELDS__SYS_TABLESPACES + 1, 1); - sys_datafiles_ok = dict_check_if_system_table_exists( + sys_datafiles_err = dict_check_if_system_table_exists( "SYS_DATAFILES", DICT_NUM_FIELDS__SYS_DATAFILES + 1, 1); - if (sys_tablespaces_ok == DB_SUCCESS - && sys_datafiles_ok == DB_SUCCESS) { + if (sys_tablespaces_err == DB_SUCCESS + && sys_datafiles_err == DB_SUCCESS) { return(DB_SUCCESS); } @@ -1657,30 +1653,30 @@ dict_create_or_check_sys_tablespace(void /* Check which incomplete table definition to drop. */ - if (sys_tablespaces_ok == DB_CORRUPTION) { - fprintf(stderr, - "InnoDB: dropping incompletely created" - " SYS_TABLESPACES table\n"); + if (sys_tablespaces_err == DB_CORRUPTION) { + ib_logf(IB_LOG_LEVEL_WARN, + "Dropping incompletely created " + "SYS_TABLESPACES table.\n"); row_drop_table_for_mysql("SYS_TABLESPACES", trx, TRUE); } - if (sys_datafiles_ok == DB_CORRUPTION) { - fprintf(stderr, - "InnoDB: dropping incompletely created" - " SYS_DATAFILES table\n"); + if (sys_datafiles_err == DB_CORRUPTION) { + ib_logf(IB_LOG_LEVEL_WARN, + "Dropping incompletely created " + "SYS_DATAFILES table.\n"); row_drop_table_for_mysql("SYS_DATAFILES", trx, TRUE); } - fprintf(stderr, - "InnoDB: Creating tablespace and datafile system tables\n"); + ib_logf(IB_LOG_LEVEL_INFO, + "Creating tablespace and datafile system tables.\n"); /* We always want SYSTEM tables to be created inside the system tablespace. */ srv_file_per_table_backup = srv_file_per_table; srv_file_per_table = 0; - error = que_eval_sql( + err = que_eval_sql( NULL, "PROCEDURE CREATE_SYS_TABLESPACE_PROC () IS\n" "BEGIN\n" @@ -1695,23 +1691,20 @@ dict_create_or_check_sys_tablespace(void "END;\n", FALSE, trx); - if (error != DB_SUCCESS) { - fprintf(stderr, - "InnoDB: error %lu in creating SYS_TABLESPACES\n", - (ulong) error); + if (err != DB_SUCCESS) { + ib_logf(IB_LOG_LEVEL_ERROR, + "Creation of SYS_TABLESPACES and SYS_DATAFILES " + "has failed with error %lu. Tablespace is full. " + "Dropping incompletely created tables.\n", + (ulong) err); - ut_a(error == DB_OUT_OF_FILE_SPACE - || error == DB_TOO_MANY_CONCURRENT_TRXS); - - fprintf(stderr, - "InnoDB: Creation failed, tablespace is full\n" - "InnoDB: dropping incompletely created" - " SYS_TABLESPACE and SYS_DATAFILES tables\n"); + ut_a(err == DB_OUT_OF_FILE_SPACE + || err == DB_TOO_MANY_CONCURRENT_TRXS); row_drop_table_for_mysql("SYS_TABLESPACES", trx, TRUE); row_drop_table_for_mysql("SYS_DATAFILES", trx, TRUE); - error = DB_MUST_GET_MORE_FILE_SPACE; + err = DB_MUST_GET_MORE_FILE_SPACE; } trx_commit_for_mysql(trx); @@ -1722,24 +1715,23 @@ dict_create_or_check_sys_tablespace(void srv_file_per_table = srv_file_per_table_backup; - if (error == DB_SUCCESS) { - fprintf(stderr, - "InnoDB: System tables for Tablespaces and " - "Datafiles created\n"); + if (err == DB_SUCCESS) { + ib_logf(IB_LOG_LEVEL_INFO, + "Tablespace and datafile system tables created\n"); } /* Note: The master thread has not been started at this point. */ /* Confirm and move to the non-LRU part of the table LRU list. */ - sys_tablespaces_ok = dict_check_if_system_table_exists( + sys_tablespaces_err = dict_check_if_system_table_exists( "SYS_TABLESPACES", DICT_NUM_FIELDS__SYS_TABLESPACES + 1, 1); - ut_a(sys_tablespaces_ok == DB_SUCCESS); + ut_a(sys_tablespaces_err == DB_SUCCESS); - sys_datafiles_ok = dict_check_if_system_table_exists( + sys_datafiles_err = dict_check_if_system_table_exists( "SYS_DATAFILES", DICT_NUM_FIELDS__SYS_DATAFILES + 1, 1); - ut_a(sys_datafiles_ok == DB_SUCCESS); + ut_a(sys_datafiles_err == DB_SUCCESS); - return(error); + return(err); } /********************************************************************//** @@ -1760,7 +1752,7 @@ dict_create_add_tablespace_to_dictionary pars_info_t* info = pars_info_create(); - ut_a(space > 0); + ut_a(space > TRX_SYS_SPACE); pars_info_add_int4_literal(info, "space", space); === modified file 'storage/innobase/dict/dict0load.cc' --- a/storage/innobase/dict/dict0load.cc revid:kevin.lewis@stripped +++ b/storage/innobase/dict/dict0load.cc revid:kevin.lewis@stripped @@ -489,7 +489,7 @@ dict_process_sys_foreign_rec( const byte* field; ulint n_fields_and_type; - if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) { + if (rec_get_deleted_flag(rec, 0)) { return("delete-marked record in SYS_FOREIGN"); } @@ -499,7 +499,7 @@ dict_process_sys_foreign_rec( field = rec_get_nth_field_old( rec, DICT_FLD__SYS_FOREIGN__ID, &len); - if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) { + if (len == 0 || len == UNIV_SQL_NULL) { err_len: return("incorrect column length in SYS_FOREIGN"); } @@ -526,7 +526,7 @@ err_len: field = rec_get_nth_field_old( rec, DICT_FLD__SYS_FOREIGN__FOR_NAME, &len); - if (len < 1 || len == UNIV_SQL_NULL) { + if (len == 0 || len == UNIV_SQL_NULL) { goto err_len; } foreign->foreign_table_name = mem_heap_strdupl( @@ -534,7 +534,7 @@ err_len: field = rec_get_nth_field_old( rec, DICT_FLD__SYS_FOREIGN__REF_NAME, &len); - if (len < 1 || len == UNIV_SQL_NULL) { + if (len == 0 || len == UNIV_SQL_NULL) { goto err_len; } foreign->referenced_table_name = mem_heap_strdupl( @@ -582,7 +582,7 @@ dict_process_sys_foreign_col_rec( field = rec_get_nth_field_old( rec, DICT_FLD__SYS_FOREIGN_COLS__ID, &len); - if (len < 1 || len == UNIV_SQL_NULL) { + if (len == 0 || len == UNIV_SQL_NULL) { err_len: return("incorrect column length in SYS_FOREIGN_COLS"); } @@ -608,14 +608,14 @@ err_len: field = rec_get_nth_field_old( rec, DICT_FLD__SYS_FOREIGN_COLS__FOR_COL_NAME, &len); - if (len < 1 || len == UNIV_SQL_NULL) { + if (len == 0 || len == UNIV_SQL_NULL) { goto err_len; } *for_col_name = mem_heap_strdupl(heap, (char*) field, len); field = rec_get_nth_field_old( rec, DICT_FLD__SYS_FOREIGN_COLS__REF_COL_NAME, &len); - if (len < 1 || len == UNIV_SQL_NULL) { + if (len == 0 || len == UNIV_SQL_NULL) { goto err_len; } *ref_col_name = mem_heap_strdupl(heap, (char*) field, len); @@ -640,6 +640,11 @@ dict_process_sys_tablespaces( ulint len; const byte* field; + /* Initialize the output values */ + *space = ULINT_UNDEFINED; + *name = NULL; + *flags = ULINT_UNDEFINED; + if (rec_get_deleted_flag(rec, 0)) { return("delete-marked record in SYS_TABLESPACES"); } @@ -670,7 +675,7 @@ err_len: field = rec_get_nth_field_old( rec, DICT_FLD__SYS_TABLESPACES__NAME, &len); - if (len < 1 || len == UNIV_SQL_NULL) { + if (len == 0 || len == UNIV_SQL_NULL) { goto err_len; } *name = mem_heap_strdupl(heap, (char*) field, len); @@ -732,7 +737,7 @@ err_len: field = rec_get_nth_field_old( rec, DICT_FLD__SYS_DATAFILES__PATH, &len); - if (len < 1 || len == UNIV_SQL_NULL) { + if (len == 0 || len == UNIV_SQL_NULL) { goto err_len; } *path = mem_heap_strdupl(heap, (char*) field, len); @@ -897,10 +902,9 @@ dict_update_filepath( if (err == DB_SUCCESS) { /* We just updated SYS_DATAFILES due to the contents in a link file. Make a note that we did this. */ - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: The InnoDB data dictionary" - " table SYS_DATAFILES for tablespace ID %lu" - " was updated to use file %s.\n", + ib_logf(IB_LOG_LEVEL_INFO, + "The InnoDB data dictionary table SYS_DATAFILES " + "for tablespace ID %lu was updated to use file %s.\n", (ulong) space_id, filepath); } @@ -1211,7 +1215,7 @@ err_len: field = rec_get_nth_field_old( rec, DICT_FLD__SYS_COLUMNS__NAME, &len); - if (len < 1 || len == UNIV_SQL_NULL) { + if (len == 0 || len == UNIV_SQL_NULL) { goto err_len; } @@ -1486,7 +1490,7 @@ err_len: field = rec_get_nth_field_old( rec, DICT_FLD__SYS_FIELDS__COL_NAME, &len); - if (len < 1 || len == UNIV_SQL_NULL) { + if (len == 0 || len == UNIV_SQL_NULL) { goto err_len; } @@ -1964,7 +1968,7 @@ dict_load_table_low( rec_get_nth_field_offs_old( rec, DICT_FLD__SYS_TABLES__NAME, &len); - if (len < 1 || len == UNIV_SQL_NULL) { + if (len == 0 || len == UNIV_SQL_NULL) { err_len: return("incorrect column length in SYS_TABLES"); } === modified file 'storage/innobase/fil/fil0fil.cc' --- a/storage/innobase/fil/fil0fil.cc revid:kevin.lewis@stripped +++ b/storage/innobase/fil/fil0fil.cc revid:kevin.lewis@stripped @@ -2339,7 +2339,7 @@ fil_ibuf_check_pending_ops( if (space->n_pending_ops != 0) { - if (count > 5000) { + if (count > 5000) { ib_logf(IB_LOG_LEVEL_WARN, "Trying to close/delete tablespace " "'%s' but there are %lu pending change " @@ -3243,10 +3243,10 @@ fil_create_new_single_table_tablespace( if (is_temp) { /* Temporary table filepath */ - ut_a(dir_path); + ut_ad(dir_path); path = fil_make_ibd_name(dir_path, TRUE); } else if (has_data_dir) { - ut_a(dir_path); + ut_ad(dir_path); path = os_file_make_remote_pathname(dir_path, tablename); /* Since this tablespace file will be created in a === modified file 'storage/innobase/handler/ha_innodb.cc' --- a/storage/innobase/handler/ha_innodb.cc revid:kevin.lewis@stripped +++ b/storage/innobase/handler/ha_innodb.cc revid:kevin.lewis@stripped @@ -96,6 +96,9 @@ this program; if not, write to the Free # ifndef MYSQL_PLUGIN_IMPORT # define MYSQL_PLUGIN_IMPORT /* nothing */ # endif /* MYSQL_PLUGIN_IMPORT */ + +/** to protect innobase_open_files */ +static mysql_mutex_t innobase_share_mutex; /** to force correct commit order in binlog */ static ulong commit_threads = 0; static mysql_mutex_t commit_threads_m; @@ -231,6 +234,8 @@ it every INNOBASE_WAKE_INTERVAL'th step. #define INNOBASE_WAKE_INTERVAL 32 static ulong innobase_active_counter = 0; +static hash_table_t* innobase_open_tables; + /** Allowed values of innodb_change_buffering */ static const char* innobase_change_buffering_values[IBUF_USE_COUNT] = { "none", /* IBUF_USE_NONE */ @@ -257,6 +262,7 @@ const struct _ft_vft_ext ft_vft_ext_resu #ifdef HAVE_PSI_INTERFACE /* Keys to register pthread mutexes/cond in the current file with performance schema */ +static mysql_pfs_key_t innobase_share_mutex_key; static mysql_pfs_key_t commit_threads_m_key; static mysql_pfs_key_t commit_cond_mutex_key; static mysql_pfs_key_t commit_cond_key; @@ -264,6 +270,7 @@ static mysql_pfs_key_t commit_cond_key; static PSI_mutex_info all_pthread_mutexes[] = { {&commit_threads_m_key, "commit_threads_m", 0}, {&commit_cond_mutex_key, "commit_cond_mutex", 0}, + {&innobase_share_mutex_key, "innobase_share_mutex", 0} }; static PSI_cond_info all_innodb_conds[] = { @@ -620,6 +627,23 @@ static SHOW_VAR innodb_status_variables[ {NullS, NullS, SHOW_LONG} }; +/************************************************************************//** +Handling the shared INNOBASE_SHARE structure that is needed to provide table +locking. Register the table name if it doesn't exist in the hash table. */ +static +INNOBASE_SHARE* +get_share( +/*======*/ + const char* table_name); /*!< in: table to lookup */ + +/************************************************************************//** +Free the shared object that was registered with get_share(). */ +static +void +free_share( +/*=======*/ + INNOBASE_SHARE* share); /*!< in/own: share to free */ + /*****************************************************************//** Frees a possible InnoDB trx object associated with the current THD. @return 0 or error number */ @@ -3103,6 +3127,10 @@ innobase_change_buffering_inited_ok: ibuf_max_size_update(innobase_change_buffer_max_size); + innobase_open_tables = hash_create(200); + mysql_mutex_init(innobase_share_mutex_key, + &innobase_share_mutex, + MY_MUTEX_INIT_FAST); mysql_mutex_init(commit_threads_m_key, &commit_threads_m, MY_MUTEX_INIT_FAST); mysql_mutex_init(commit_cond_mutex_key, @@ -3161,11 +3189,14 @@ innobase_end( srv_fast_shutdown = (ulint) innobase_fast_shutdown; innodb_inited = 0; + hash_table_free(innobase_open_tables); + innobase_open_tables = NULL; if (innobase_shutdown_for_mysql() != DB_SUCCESS) { err = 1; } srv_free_paths_and_sizes(); my_free(internal_innobase_data_file_path); + mysql_mutex_destroy(&innobase_share_mutex); mysql_mutex_destroy(&commit_threads_m); mysql_mutex_destroy(&commit_cond_m); mysql_cond_destroy(&commit_cond); @@ -4195,8 +4226,8 @@ innobase_match_index_columns( } /*******************************************************************//** -This function builds a translation table in Innobase_share -object for fast index location with mysql array number from its +This function builds a translation table in INNOBASE_SHARE +structure for fast index location with mysql array number from its table->key_info structure. This also provides the necessary translation between the key order in mysql key_info and Innodb ib_table->indexes if they are not fully matched with each other. @@ -4213,7 +4244,7 @@ innobase_build_index_translation( dictionary */ dict_table_t* ib_table,/*!< in: table in Innodb data dictionary */ - Innobase_share* share) /*!< in/out: share object + INNOBASE_SHARE* share) /*!< in/out: share structure where index translation table will be constructed in. */ { @@ -4333,7 +4364,7 @@ static dict_index_t* innobase_index_lookup( /*==================*/ - Innobase_share* share, /*!< in: share object for index + INNOBASE_SHARE* share, /*!< in: share structure for index translation table. */ uint keynr) /*!< in: index number for the requested index */ @@ -4488,7 +4519,7 @@ ha_innobase::open( user_thd = NULL; - if (!(share=get_share())) { + if (!(share=get_share(name))) { DBUG_RETURN(1); } @@ -4599,6 +4630,7 @@ retry: REFMAN "innodb-troubleshooting.html for how " "you can resolve the problem.", norm_name); + free_share(share); my_errno = ENOENT; DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); @@ -4643,6 +4675,7 @@ table_opened: } if (!thd_tablespace_op(thd) && no_tablespace) { + free_share(share); my_errno = ENOENT; dict_table_close(ib_table, FALSE, FALSE); @@ -4879,6 +4912,8 @@ ha_innobase::close() upd_buf_size = 0; } + free_share(share); + MONITOR_INC(MONITOR_TABLE_CLOSE); /* Tell InnoDB server that there might be work for @@ -8929,7 +8964,7 @@ ha_innobase::parse_table_name( } if (create_info->data_file_name) { - ibool ignore = FALSE; + bool ignore = false; /* Use DATA DIRECTORY only with file-per-table. */ if (!use_tablespace) { @@ -8938,7 +8973,7 @@ ha_innobase::parse_table_name( ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: DATA DIRECTORY requires" " innodb_file_per_table."); - ignore = TRUE; + ignore = true; } /* Do not use DATA DIRECTORY with TEMPORARY TABLE. */ @@ -8948,7 +8983,7 @@ ha_innobase::parse_table_name( ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: DATA DIRECTORY cannot be" " used for TEMPORARY tables."); - ignore = TRUE; + ignore = true; } if (ignore) { @@ -10334,7 +10369,7 @@ static int innobase_get_mysql_key_number_for_index( /*====================================*/ - Innobase_share* share, /*!< in: share object for index + INNOBASE_SHARE* share, /*!< in: share structure for index translation table. */ const TABLE* table, /*!< in: table in MySQL data dictionary */ @@ -12314,31 +12349,94 @@ innobase_show_status( } /************************************************************************//** -Handling the shared Innobase_share object that is needed to provide table -locking. */ -Innobase_share* -ha_innobase::get_share(void) -/*========================*/ +Handling the shared INNOBASE_SHARE structure that is needed to provide table +locking. Register the table name if it doesn't exist in the hash table. */ +static +INNOBASE_SHARE* +get_share( +/*======*/ + const char* table_name) { - Innobase_share *tmp_share; + INNOBASE_SHARE* share; - lock_shared_ha_data(); - tmp_share= static_cast(get_ha_share_ptr()); + mysql_mutex_lock(&innobase_share_mutex); - if (!tmp_share) - { - tmp_share= new Innobase_share; - if (!tmp_share) - { - unlock_shared_ha_data(); - return(NULL); - } + ulint fold = ut_fold_string(table_name); + + HASH_SEARCH(table_name_hash, innobase_open_tables, fold, + INNOBASE_SHARE*, share, + ut_ad(share->use_count > 0), + !strcmp(share->table_name, table_name)); + + if (!share) { + + uint length = (uint) strlen(table_name); + + /* TODO: invoke HASH_MIGRATE if innobase_open_tables + grows too big */ + + share = (INNOBASE_SHARE*) my_malloc(sizeof(*share)+length+1, + MYF(MY_FAE | MY_ZEROFILL)); + + share->table_name = (char*) memcpy(share + 1, + table_name, length + 1); + + HASH_INSERT(INNOBASE_SHARE, table_name_hash, + innobase_open_tables, fold, share); - set_ha_share_ptr(static_cast(tmp_share)); + thr_lock_init(&share->lock); + + /* Index translation table initialization */ + share->idx_trans_tbl.index_mapping = NULL; + share->idx_trans_tbl.index_count = 0; + share->idx_trans_tbl.array_size = 0; + } + + share->use_count++; + mysql_mutex_unlock(&innobase_share_mutex); + + return(share); +} + +/************************************************************************//** +Free the shared object that was registered with get_share(). */ +static +void +free_share( +/*=======*/ + INNOBASE_SHARE* share) /*!< in/own: table share to free */ +{ + mysql_mutex_lock(&innobase_share_mutex); + +#ifdef UNIV_DEBUG + INNOBASE_SHARE* share2; + ulint fold = ut_fold_string(share->table_name); + + HASH_SEARCH(table_name_hash, innobase_open_tables, fold, + INNOBASE_SHARE*, share2, + ut_ad(share->use_count > 0), + !strcmp(share->table_name, share2->table_name)); + + ut_a(share2 == share); +#endif /* UNIV_DEBUG */ + + if (!--share->use_count) { + ulint fold = ut_fold_string(share->table_name); + + HASH_DELETE(INNOBASE_SHARE, table_name_hash, + innobase_open_tables, fold, share); + thr_lock_delete(&share->lock); + + /* Free any memory from index translation table */ + my_free(share->idx_trans_tbl.index_mapping); + + my_free(share); + + /* TODO: invoke HASH_MIGRATE if innobase_open_tables + shrinks too much */ } - unlock_shared_ha_data(); - ut_ad(tmp_share); - return(tmp_share); + + mysql_mutex_unlock(&innobase_share_mutex); } /*****************************************************************//** === modified file 'storage/innobase/handler/ha_innodb.h' --- a/storage/innobase/handler/ha_innodb.h revid:kevin.lewis@stripped +++ b/storage/innobase/handler/ha_innodb.h revid:kevin.lewis@stripped @@ -38,29 +38,19 @@ typedef struct innodb_idx_translate_stru /** InnoDB table share */ -class Innobase_share : public Handler_share -{ -public: +typedef struct st_innobase_share { THR_LOCK lock; /*!< MySQL lock protecting this structure */ + const char* table_name; /*!< InnoDB table name */ + uint use_count; /*!< reference count, + incremented in get_share() + and decremented in + free_share() */ + void* table_name_hash;/*!< hash table chain node */ innodb_idx_translate_t idx_trans_tbl; /*!< index translation table between MySQL and Innodb */ - Innobase_share() - { - thr_lock_init(&lock); - idx_trans_tbl.index_mapping = NULL; - idx_trans_tbl.index_count = 0; - idx_trans_tbl.array_size = 0; - } - ~Innobase_share() - { - thr_lock_delete(&lock); - - /* Free any memory from index translation table */ - my_free(idx_trans_tbl.index_mapping); - } -}; +} INNOBASE_SHARE; /** InnoDB B-tree index */ @@ -83,7 +73,7 @@ class ha_innobase: public handler currently using the handle; this is set in external_lock function */ THR_LOCK_DATA lock; - Innobase_share* share; /*!< information for MySQL + INNOBASE_SHARE* share; /*!< information for MySQL table locking */ uchar* upd_buf; /*!< buffer used in updates */ @@ -368,8 +358,6 @@ public: private: /** The multi range read session object */ DsMrr_impl ds_mrr; - /** Connects/gets Innobase_share in TABLE_SHARE */ - Innobase_share* get_share(); /* @} */ }; === modified file 'storage/innobase/handler/handler0alter.cc' --- a/storage/innobase/handler/handler0alter.cc revid:kevin.lewis@stripped +++ b/storage/innobase/handler/handler0alter.cc revid:kevin.lewis@stripped @@ -1290,14 +1290,11 @@ online_retry_drop_indexes( THD* user_thd) /*!< in/out: MySQL connection */ { if (table->drop_aborted) { - trx_t* trx = innobase_trx_allocate(user_thd); - trx_start_if_not_started(trx); - trx->will_lock = 1; + trx_t* trx = innobase_trx_allocate(user_thd); + + trx_start_for_ddl(trx, TRX_DICT_OP_INDEX); row_mysql_lock_data_dictionary(trx); - /* Flag this transaction as a dictionary operation, so that - the data dictionary will be locked in crash recovery. */ - trx_set_dict_operation(trx, TRX_DICT_OP_INDEX); online_retry_drop_indexes_low(table, trx); trx_commit_for_mysql(trx); row_mysql_unlock_data_dictionary(trx); @@ -1329,13 +1326,11 @@ online_retry_drop_indexes_with_trx( drop any incompletely created indexes that may have been left behind in rollback_inplace_alter_table() earlier. */ if (table->drop_aborted) { - /* Re-use the dictionary transaction object - to avoid some memory allocation overhead. */ - ut_ad(trx_get_dict_operation(trx) == TRX_DICT_OP_TABLE); - trx->dict_operation = TRX_DICT_OP_INDEX; + trx->table_id = 0; - trx_start_if_not_started(trx); - trx->will_lock = 1; + + trx_start_for_ddl(trx, TRX_DICT_OP_INDEX); + online_retry_drop_indexes_low(table, trx); trx_commit_for_mysql(trx); } @@ -1404,8 +1399,9 @@ prepare_inplace_alter_table_dict( /* Create a background transaction for the operations on the data dictionary tables. */ trx = innobase_trx_allocate(user_thd); - trx_start_if_not_started(trx); - trx->will_lock = 1; + + trx_start_for_ddl(trx, TRX_DICT_OP_INDEX); + if (!heap) { heap = mem_heap_create(1024); } @@ -1443,9 +1439,10 @@ prepare_inplace_alter_table_dict( add_key_nums = (ulint*) mem_heap_alloc( heap, n_add_index * sizeof *add_key_nums); - /* Flag this transaction as a dictionary operation, so that - the data dictionary will be locked in crash recovery. */ - trx_set_dict_operation(trx, TRX_DICT_OP_INDEX); + /* This transaction should be dictionary operation, so that + the data dictionary will be locked during crash recovery. */ + + ut_ad(trx->dict_operation == TRX_DICT_OP_INDEX); const bool exclusive = ha_alter_info->alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE; @@ -1697,11 +1694,11 @@ col_fail: } if (fts_index) { -#ifdef UNIV_DEBUG /* Ensure that the dictionary operation mode will not change while creating the auxiliary tables. */ enum trx_dict_op op = trx_get_dict_operation(trx); +#ifdef UNIV_DEBUG switch (op) { case TRX_DICT_OP_NONE: break; @@ -1720,12 +1717,17 @@ op_ok: DICT_TF2_FLAG_SET(indexed_table, DICT_TF2_FTS); + /* This function will commit the transaction and reset + the trx_t::dict_operation flag on success. */ + error = fts_create_index_tables(trx, fts_index); if (error != DB_SUCCESS) { goto error_handling; } + trx_start_for_ddl(trx, op); + if (!indexed_table->fts || ib_vector_size(indexed_table->fts->indexes) == 0) { error = fts_create_common_tables( @@ -2529,6 +2531,9 @@ rollback_inplace_alter_table( } else { DBUG_ASSERT(!(ha_alter_info->handler_flags & Alter_inplace_info::ADD_PK_INDEX)); + + trx_start_for_ddl(ctx->trx, TRX_DICT_OP_INDEX); + row_merge_drop_indexes(ctx->trx, prebuilt->table, FALSE); } @@ -2845,15 +2850,20 @@ ha_innobase::commit_inplace_alter_table( /* Create a background transaction for the operations on the data dictionary tables. */ trx = innobase_trx_allocate(user_thd); - trx_start_if_not_started(trx); - trx->will_lock = 1; - /* Flag this transaction as a dictionary operation, so that - the data dictionary will be locked in crash recovery. */ - trx_set_dict_operation(trx, TRX_DICT_OP_INDEX); + + trx_start_for_ddl(trx, TRX_DICT_OP_INDEX); + new_clustered = false; } else { + trx_dict_op_t op; + trx = ctx->trx; + new_clustered = ctx->indexed_table != prebuilt->table; + + op = (new_clustered) ? TRX_DICT_OP_TABLE : TRX_DICT_OP_INDEX; + + trx_start_for_ddl(trx, op); } /* Latch the InnoDB data dictionary exclusively so that no deadlocks @@ -2923,10 +2933,10 @@ ha_innobase::commit_inplace_alter_table( } } else if (ctx) { dberr_t error; + /* We altered the table in place. */ - ulint i; /* Lose the TEMP_INDEX_PREFIX. */ - for (i = 0; i < ctx->num_to_add; i++) { + for (ulint i = 0; i < ctx->num_to_add; i++) { dict_index_t* index = ctx->add[i]; DBUG_ASSERT(*index->name == TEMP_INDEX_PREFIX); @@ -2948,7 +2958,7 @@ ha_innobase::commit_inplace_alter_table( index->name in the dictionary cache, because the index is about to be freed after row_merge_drop_indexes_dict(). */ - for (i = 0; i < ctx->num_to_drop; i++) { + for (ulint i = 0; i < ctx->num_to_drop; i++) { dict_index_t* index = ctx->drop[i]; DBUG_ASSERT(*index->name != TEMP_INDEX_PREFIX); DBUG_ASSERT(index->table == prebuilt->table); @@ -3044,6 +3054,7 @@ trx_commit: } if (!new_clustered && ha_alter_info->index_drop_count) { + /* Really drop the indexes that were dropped. The transaction had to be committed first (after renaming the indexes), so that in the @@ -3053,10 +3064,7 @@ trx_commit: have started dropping an index tree, there is no way to roll it back. */ - trx_start_if_not_started(trx); - DBUG_ASSERT(trx_get_dict_operation(trx) - == TRX_DICT_OP_INDEX); - trx->will_lock = 1; + trx_start_for_ddl(trx, TRX_DICT_OP_INDEX); for (ulint i = 0; i < ctx->num_to_drop; i++) { dict_index_t* index = ctx->drop[i]; === modified file 'storage/innobase/include/trx0trx.h' --- a/storage/innobase/include/trx0trx.h revid:kevin.lewis@stripped +++ b/storage/innobase/include/trx0trx.h revid:kevin.lewis@stripped @@ -148,6 +148,28 @@ trx_start_if_not_started_low( trx_start_if_not_started_low((t)) #endif /* UNIV_DEBUG */ +/*************************************************************//** +Starts the transaction for a DDL operation. */ +UNIV_INTERN +void +trx_start_for_ddl_low( +/*==================*/ + trx_t* trx, /*!< in/out: transaction */ + trx_dict_op_t op) /*!< in: dictionary operation type */ + __attribute__((nonnull)); + +#ifdef UNIV_DEBUG +#define trx_start_for_ddl(t, o) \ + { \ + (t)->start_line = __LINE__; \ + (t)->start_file = __FILE__; \ + trx_start_for_ddl_low((t), (o)); \ + } +#else +#define trx_start_for_ddl(t, o) \ + trx_start_for_ddl_low((t), (o)) +#endif /* UNIV_DEBUG */ + /****************************************************************//** Commits a transaction. */ UNIV_INTERN @@ -299,21 +321,6 @@ trx_print( or 0 to use the default max length */ __attribute__((nonnull)); -/** Type of data dictionary operation */ -typedef enum trx_dict_op { - /** The transaction is not modifying the data dictionary. */ - TRX_DICT_OP_NONE = 0, - /** The transaction is creating a table or an index, or - dropping a table. The table must be dropped in crash - recovery. This and TRX_DICT_OP_NONE are the only possible - operation modes in crash recovery. */ - TRX_DICT_OP_TABLE = 1, - /** The transaction is creating or dropping an index in an - existing table. In crash recovery, the data dictionary - must be locked, but the table must not be dropped. */ - TRX_DICT_OP_INDEX = 2 -} trx_dict_op_t; - /**********************************************************************//** Determine if a transaction is a dictionary operation. @return dictionary operation mode */ === modified file 'storage/innobase/include/trx0types.h' --- a/storage/innobase/include/trx0types.h revid:kevin.lewis@stripped +++ b/storage/innobase/include/trx0types.h revid:kevin.lewis@stripped @@ -52,6 +52,21 @@ enum trx_state_enum { TRX_STATE_COMMITTED_IN_MEMORY }; +/** Type of data dictionary operation */ +typedef enum trx_dict_op { + /** The transaction is not modifying the data dictionary. */ + TRX_DICT_OP_NONE = 0, + /** The transaction is creating a table or an index, or + dropping a table. The table must be dropped in crash + recovery. This and TRX_DICT_OP_NONE are the only possible + operation modes in crash recovery. */ + TRX_DICT_OP_TABLE = 1, + /** The transaction is creating or dropping an index in an + existing table. In crash recovery, the data dictionary + must be locked, but the table must not be dropped. */ + TRX_DICT_OP_INDEX = 2 +} trx_dict_op_t; + /** Memory objects */ /* @{ */ /** Transaction */ === modified file 'storage/innobase/trx/trx0trx.cc' --- a/storage/innobase/trx/trx0trx.cc revid:kevin.lewis@stripped +++ b/storage/innobase/trx/trx0trx.cc revid:kevin.lewis@stripped @@ -1196,6 +1196,8 @@ trx_commit( ut_ad(!trx->in_ro_trx_list); ut_ad(!trx->in_rw_trx_list); + trx->dict_operation = TRX_DICT_OP_NONE; + trx->error_state = DB_SUCCESS; /* trx->in_mysql_trx_list would hold between @@ -2093,3 +2095,24 @@ trx_start_if_not_started_low( ut_error; } + +/*************************************************************//** +Starts the transaction for a DDL operation. */ +UNIV_INTERN +void +trx_start_for_ddl_low( +/*==================*/ + trx_t* trx, /*!< in/out: transaction */ + trx_dict_op_t op) /*!< in: dictionary operation type */ +{ + /* Flag this transaction as a dictionary operation, so that + the data dictionary will be locked in crash recovery. */ + + trx_set_dict_operation(trx, op); + + /* Ensure it is not flagged as an auto-commit-non-locking transation. */ + trx->will_lock = 1; + + trx_start_low(trx); +} + No bundle (reason: useless for push emails).