diff options
Diffstat (limited to 'innobase/row/row0mysql.c')
-rw-r--r-- | innobase/row/row0mysql.c | 284 |
1 files changed, 163 insertions, 121 deletions
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 61be3a7248e..c4408de2a85 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -397,6 +397,7 @@ row_create_prebuilt( prebuilt->clust_pcur = btr_pcur_create_for_mysql(); prebuilt->select_lock_type = LOCK_NONE; + prebuilt->stored_select_lock_type = 99999999; prebuilt->sel_graph = NULL; @@ -691,7 +692,7 @@ row_lock_table_autoinc_for_mysql( return(DB_SUCCESS); } - trx->op_info = (char *) "setting auto-inc lock"; + trx->op_info = "setting auto-inc lock"; if (node == NULL) { row_get_prebuilt_insert_row(prebuilt); @@ -727,14 +728,14 @@ run_again: goto run_again; } - trx->op_info = (char *) ""; + trx->op_info = ""; return(err); } que_thr_stop_for_mysql_no_error(thr, trx); - trx->op_info = (char *) ""; + trx->op_info = ""; return((int) err); } @@ -774,7 +775,7 @@ row_lock_table_for_mysql( ut_ad(trx); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); - trx->op_info = (char *) "setting table lock"; + trx->op_info = "setting table lock"; if (prebuilt->sel_graph == NULL) { /* Build a dummy select query graph */ @@ -811,14 +812,14 @@ run_again: goto run_again; } - trx->op_info = (char *) ""; + trx->op_info = ""; return(err); } que_thr_stop_for_mysql_no_error(thr, trx); - trx->op_info = (char *) ""; + trx->op_info = ""; return((int) err); } @@ -869,7 +870,7 @@ row_insert_for_mysql( return(DB_ERROR); } - trx->op_info = (char *) "inserting"; + trx->op_info = "inserting"; trx_start_if_not_started(trx); @@ -910,7 +911,7 @@ run_again: goto run_again; } - trx->op_info = (char *) ""; + trx->op_info = ""; return(err); } @@ -927,7 +928,7 @@ run_again: } row_update_statistics_if_needed(prebuilt->table); - trx->op_info = (char *) ""; + trx->op_info = ""; return((int) err); } @@ -1084,7 +1085,7 @@ row_update_for_mysql( return(DB_ERROR); } - trx->op_info = (char *) "updating or deleting"; + trx->op_info = "updating or deleting"; trx_start_if_not_started(trx); @@ -1131,7 +1132,7 @@ run_again: if (err == DB_RECORD_NOT_FOUND) { trx->error_state = DB_SUCCESS; - trx->op_info = (char *) ""; + trx->op_info = ""; return((int) err); } @@ -1142,7 +1143,7 @@ run_again: goto run_again; } - trx->op_info = (char *) ""; + trx->op_info = ""; return(err); } @@ -1161,7 +1162,7 @@ run_again: row_update_statistics_if_needed(prebuilt->table); - trx->op_info = (char *) ""; + trx->op_info = ""; return((int) err); } @@ -1413,7 +1414,8 @@ row_create_table_for_mysql( tab_node_t* node; mem_heap_t* heap; que_thr_t* thr; - ulint namelen; + const char* table_name; + ulint table_name_len; ulint err; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); @@ -1437,7 +1439,7 @@ row_create_table_for_mysql( return(DB_ERROR); } - trx->op_info = (char *) "creating table"; + trx->op_info = "creating table"; if (row_mysql_is_system_table(table->name)) { @@ -1465,10 +1467,17 @@ row_create_table_for_mysql( return(row_mysql_recover_tmp_table(table, trx)); } - namelen = strlen(table->name) + 1; + /* The table name is prefixed with the database name and a '/'. + Certain table names starting with 'innodb_' have their special + meaning regardless of the database name. Thus, we need to + ignore the database name prefix in the comparisons. */ + table_name = strchr(table->name, '/'); + ut_a(table_name); + table_name++; + table_name_len = strlen(table_name) + 1; - if (namelen == sizeof S_innodb_monitor - && !memcmp(table->name, S_innodb_monitor, + if (table_name_len == sizeof S_innodb_monitor + && !memcmp(table_name, S_innodb_monitor, sizeof S_innodb_monitor)) { /* Table equals "innodb_monitor": @@ -1480,27 +1489,27 @@ row_create_table_for_mysql( of InnoDB monitor prints */ os_event_set(srv_lock_timeout_thread_event); - } else if (namelen == sizeof S_innodb_lock_monitor - && !memcmp(table->name, S_innodb_lock_monitor, + } else if (table_name_len == sizeof S_innodb_lock_monitor + && !memcmp(table_name, S_innodb_lock_monitor, sizeof S_innodb_lock_monitor)) { srv_print_innodb_monitor = TRUE; srv_print_innodb_lock_monitor = TRUE; os_event_set(srv_lock_timeout_thread_event); - } else if (namelen == sizeof S_innodb_tablespace_monitor - && !memcmp(table->name, S_innodb_tablespace_monitor, + } else if (table_name_len == sizeof S_innodb_tablespace_monitor + && !memcmp(table_name, S_innodb_tablespace_monitor, sizeof S_innodb_tablespace_monitor)) { srv_print_innodb_tablespace_monitor = TRUE; os_event_set(srv_lock_timeout_thread_event); - } else if (namelen == sizeof S_innodb_table_monitor - && !memcmp(table->name, S_innodb_table_monitor, + } else if (table_name_len == sizeof S_innodb_table_monitor + && !memcmp(table_name, S_innodb_table_monitor, sizeof S_innodb_table_monitor)) { srv_print_innodb_table_monitor = TRUE; os_event_set(srv_lock_timeout_thread_event); - } else if (namelen == sizeof S_innodb_mem_validate - && !memcmp(table->name, S_innodb_mem_validate, + } else if (table_name_len == sizeof S_innodb_mem_validate + && !memcmp(table_name, S_innodb_mem_validate, sizeof S_innodb_mem_validate)) { /* We define here a debugging feature intended for developers */ @@ -1572,7 +1581,7 @@ row_create_table_for_mysql( que_graph_free((que_t*) que_node_get_parent(thr)); - trx->op_info = (char *) ""; + trx->op_info = ""; return((int) err); } @@ -1601,7 +1610,7 @@ row_create_index_for_mysql( #endif /* UNIV_SYNC_DEBUG */ ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); - trx->op_info = (char *) "creating index"; + trx->op_info = "creating index"; /* Check that the same column does not appear twice in the index. Starting from 4.0.14, InnoDB should be able to cope with that, but @@ -1669,7 +1678,7 @@ error_handling: trx->error_state = DB_SUCCESS; } - trx->op_info = (char *) ""; + trx->op_info = ""; return((int) err); } @@ -1705,7 +1714,7 @@ row_table_add_foreign_constraints( #endif /* UNIV_SYNC_DEBUG */ ut_a(sql_string); - trx->op_info = (char *) "adding foreign keys"; + trx->op_info = "adding foreign keys"; trx_start_if_not_started(trx); @@ -1749,8 +1758,8 @@ static int row_drop_table_for_mysql_in_background( /*===================================*/ - /* out: error code or DB_SUCCESS */ - char* name) /* in: table name */ + /* out: error code or DB_SUCCESS */ + const char* name) /* in: table name */ { ulint error; trx_t* trx; @@ -1951,11 +1960,41 @@ row_discard_tablespace_for_mysql( que_t* graph = NULL; ibool success; ulint err; - char buf[2 * OS_FILE_MAX_PATH]; + char* buf; + + static const char discard_tablespace_proc1[] = + "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n" + "old_id CHAR;\n" + "new_id CHAR;\n" + "new_id_low INT;\n" + "new_id_high INT;\n" + "table_name CHAR;\n" + "BEGIN\n" + "table_name := "; + static const char discard_tablespace_proc2[] = + ";\n" + "new_id_high := %lu;\n" + "new_id_low := %lu;\n" + "new_id := CONCAT(TO_BINARY(new_id_high, 4), TO_BINARY(new_id_low, 4));\n" + "SELECT ID INTO old_id\n" + "FROM SYS_TABLES\n" + "WHERE NAME = table_name;\n" + "IF (SQL %% NOTFOUND) THEN\n" + " COMMIT WORK;\n" + " RETURN;\n" + "END IF;\n" + "UPDATE SYS_TABLES SET ID = new_id\n" + "WHERE ID = old_id;\n" + "UPDATE SYS_COLUMNS SET TABLE_ID = new_id\n" + "WHERE TABLE_ID = old_id;\n" + "UPDATE SYS_INDEXES SET TABLE_ID = new_id\n" + "WHERE TABLE_ID = old_id;\n" + "COMMIT WORK;\n" + "END;\n"; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); - trx->op_info = (char *) "discarding tablespace"; + trx->op_info = "discarding tablespace"; trx_start_if_not_started(trx); /* Serialize data dictionary operations with dictionary mutex: @@ -1973,9 +2012,10 @@ row_discard_tablespace_for_mysql( if (table->space == 0) { ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Error: table %s\n" -"InnoDB: is in the system tablespace 0 which cannot be discarded\n", name); + fputs(" InnoDB: Error: table ", stderr); + ut_print_name(stderr, name); + fputs("\n" +"InnoDB: is in the system tablespace 0 which cannot be discarded\n", stderr); err = DB_ERROR; goto funct_exit; @@ -1983,36 +2023,16 @@ row_discard_tablespace_for_mysql( new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID); - sprintf(buf, - "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n" - "old_id CHAR;\n" - "new_id CHAR;\n" - "new_id_low INT;\n" - "new_id_high INT;\n" - "table_name CHAR;\n" - "BEGIN\n" - "table_name :='%s';\n" - "new_id_high := %lu;\n" - "new_id_low := %lu;\n" - "new_id := CONCAT(TO_BINARY(new_id_high, 4), TO_BINARY(new_id_low, 4));\n" - "SELECT ID INTO old_id\n" - "FROM SYS_TABLES\n" - "WHERE NAME = table_name;\n" - "IF (SQL %% NOTFOUND) THEN\n" - " COMMIT WORK;\n" - " RETURN;\n" - "END IF;\n" - "UPDATE SYS_TABLES SET ID = new_id\n" - "WHERE ID = old_id;\n" - "UPDATE SYS_COLUMNS SET TABLE_ID = new_id\n" - "WHERE TABLE_ID = old_id;\n" - "UPDATE SYS_INDEXES SET TABLE_ID = new_id\n" - "WHERE TABLE_ID = old_id;\n" - "COMMIT WORK;\n" - "END;\n", name, (ulong) ut_dulint_get_high(new_id), - (ulong) ut_dulint_get_low(new_id)); + buf = mem_alloc((sizeof discard_tablespace_proc1) + + (sizeof discard_tablespace_proc2) + + 20 + ut_strlenq(name, '\'')); - ut_a(strlen(buf) < 2 * OS_FILE_MAX_PATH); + memcpy(buf, discard_tablespace_proc1, sizeof discard_tablespace_proc1); + sprintf(ut_strcpyq(buf + (sizeof discard_tablespace_proc1 - 1), + '\'', name), + discard_tablespace_proc2, + (ulong) ut_dulint_get_high(new_id), + (ulong) ut_dulint_get_low(new_id)); graph = pars_sql(buf); @@ -2060,7 +2080,7 @@ funct_exit: trx_commit_for_mysql(trx); - trx->op_info = (char *) ""; + trx->op_info = ""; return((int) err); } @@ -2085,7 +2105,7 @@ row_import_tablespace_for_mysql( trx_start_if_not_started(trx); - trx->op_info = (char*) "importing tablespace"; + trx->op_info = "importing tablespace"; current_lsn = log_get_lsn(); @@ -2126,9 +2146,10 @@ row_import_tablespace_for_mysql( if (table->space == 0) { ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Error: table %s\n" -"InnoDB: is in the system tablespace 0 which cannot be imported\n", name); + fputs(" InnoDB: Error: table ", stderr); + ut_print_name(stderr, name); + fputs("\n" +"InnoDB: is in the system tablespace 0 which cannot be imported\n", stderr); err = DB_ERROR; goto funct_exit; @@ -2136,10 +2157,12 @@ row_import_tablespace_for_mysql( if (!table->tablespace_discarded) { ut_print_timestamp(stderr); - fprintf(stderr, + fputs( " InnoDB: Error: you are trying to IMPORT a tablespace\n" -"InnoDB: %s, though you have not called DISCARD on it yet\n" -"InnoDB: during the lifetime of the mysqld process!\n", name); +"InnoDB: ", stderr); + ut_print_name(stderr, name); + fputs(", though you have not called DISCARD on it yet\n" +"InnoDB: during the lifetime of the mysqld process!\n", stderr); err = DB_ERROR; @@ -2165,7 +2188,7 @@ funct_exit: trx_commit_for_mysql(trx); - trx->op_info = (char *) ""; + trx->op_info = ""; return((int) err); } @@ -2189,6 +2212,7 @@ row_drop_table_for_mysql( que_thr_t* thr; que_t* graph; ulint err; + const char* table_name; ulint namelen; ibool success; ibool locked_dictionary = FALSE; @@ -2274,14 +2298,21 @@ row_drop_table_for_mysql( return(DB_ERROR); } - trx->op_info = (char *) "dropping table"; + trx->op_info = "dropping table"; trx_start_if_not_started(trx); - namelen = strlen(name) + 1; + /* The table name is prefixed with the database name and a '/'. + Certain table names starting with 'innodb_' have their special + meaning regardless of the database name. Thus, we need to + ignore the database name prefix in the comparisons. */ + table_name = strchr(name, '/'); + ut_a(table_name); + table_name++; + namelen = strlen(table_name) + 1; if (namelen == sizeof S_innodb_monitor - && !memcmp(name, S_innodb_monitor, + && !memcmp(table_name, S_innodb_monitor, sizeof S_innodb_monitor)) { /* Table name equals "innodb_monitor": @@ -2290,17 +2321,17 @@ row_drop_table_for_mysql( srv_print_innodb_monitor = FALSE; srv_print_innodb_lock_monitor = FALSE; } else if (namelen == sizeof S_innodb_lock_monitor - && !memcmp(name, S_innodb_lock_monitor, + && !memcmp(table_name, S_innodb_lock_monitor, sizeof S_innodb_lock_monitor)) { srv_print_innodb_monitor = FALSE; srv_print_innodb_lock_monitor = FALSE; } else if (namelen == sizeof S_innodb_tablespace_monitor - && !memcmp(name, S_innodb_tablespace_monitor, + && !memcmp(table_name, S_innodb_tablespace_monitor, sizeof S_innodb_tablespace_monitor)) { srv_print_innodb_tablespace_monitor = FALSE; } else if (namelen == sizeof S_innodb_table_monitor - && !memcmp(name, S_innodb_table_monitor, + && !memcmp(table_name, S_innodb_table_monitor, sizeof S_innodb_table_monitor)) { srv_print_innodb_table_monitor = FALSE; @@ -2469,7 +2500,7 @@ row_drop_table_for_mysql( if (dict_load_table(name) != NULL) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: not able to remove table ", - stderr); + stderr); ut_print_name(stderr, name); fputs(" from the dictionary cache!\n", stderr); err = DB_ERROR; @@ -2491,8 +2522,10 @@ row_drop_table_for_mysql( if (!success) { ut_print_timestamp(stderr); fprintf(stderr, -" InnoDB: Error: not able to delete tablespace %lu of table %s!\n", - (ulong) space_id, name); +" InnoDB: Error: not able to delete tablespace %lu of table ", + (ulong) space_id); + ut_print_name(stderr, name); + fputs("!\n", stderr); err = DB_ERROR; } } @@ -2507,7 +2540,7 @@ funct_exit: trx_commit_for_mysql(trx); - trx->op_info = (char *) ""; + trx->op_info = ""; srv_wake_master_thread(); @@ -2533,7 +2566,7 @@ row_drop_database_for_mysql( ut_a(name != NULL); ut_a(name[namelen - 1] == '/'); - trx->op_info = (char *) "dropping database"; + trx->op_info = "dropping database"; trx_start_if_not_started(trx); loop: @@ -2587,7 +2620,7 @@ loop: trx_commit_for_mysql(trx); - trx->op_info = (char *) ""; + trx->op_info = ""; return(err); } @@ -2738,7 +2771,7 @@ row_rename_table_for_mysql( return(DB_ERROR); } - trx->op_info = (char *) "renaming table"; + trx->op_info = "renaming table"; trx_start_if_not_started(trx); if (row_mysql_is_recovered_tmp_table(new_name)) { @@ -2757,15 +2790,14 @@ row_rename_table_for_mysql( err = DB_TABLE_NOT_FOUND; ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: table %s\n" - "InnoDB: does not exist in the InnoDB internal\n" + fputs(" InnoDB: Error: table ", stderr); + ut_print_name(stderr, old_name); + fputs(" does not exist in the InnoDB internal\n" "InnoDB: data dictionary though MySQL is trying to rename the table.\n" "InnoDB: Have you copied the .frm file of the table to the\n" "InnoDB: MySQL database directory from another database?\n" "InnoDB: You can look for further help from section 15.1 of\n" - "InnoDB: http://www.innodb.com/ibman.html\n", - old_name); + "InnoDB: http://www.innodb.com/ibman.php\n", stderr); goto funct_exit; } @@ -2773,12 +2805,12 @@ row_rename_table_for_mysql( err = DB_TABLE_NOT_FOUND; ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: table %s\n" - "InnoDB: does not have an .ibd file in the database directory.\n" + fputs(" InnoDB: Error: table ", stderr); + ut_print_name(stderr, old_name); + fputs( + " does not have an .ibd file in the database directory.\n" "InnoDB: You can look for further help from section 15.1 of\n" - "InnoDB: http://www.innodb.com/ibman.html\n", - old_name); + "InnoDB: http://www.innodb.com/ibman.php\n", stderr); goto funct_exit; } @@ -2905,23 +2937,25 @@ row_rename_table_for_mysql( if (err != DB_SUCCESS) { if (err == DB_DUPLICATE_KEY) { ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: table %s exists in the InnoDB internal data\n" - "InnoDB: dictionary though MySQL is trying rename table %s to it.\n" + fputs(" InnoDB: Error: table ", stderr); + ut_print_name(stderr, new_name); + fputs(" exists in the InnoDB internal data\n" + "InnoDB: dictionary though MySQL is trying rename table ", stderr); + ut_print_name(stderr, old_name); + fputs(" to it.\n" "InnoDB: Have you deleted the .frm file and not used DROP TABLE?\n" "InnoDB: You can look for further help from section 15.1 of\n" - "InnoDB: http://www.innodb.com/ibman.html\n", - new_name, old_name); - fprintf(stderr, - "InnoDB: If table %s is a temporary table #sql..., then it can be that\n" + "InnoDB: http://www.innodb.com/ibman.php\n" + "InnoDB: If table ", stderr); + ut_print_name(stderr, new_name); + fputs(" is a temporary table #sql..., then it can be that\n" "InnoDB: there are still queries running on the table, and it will be\n" - "InnoDB: dropped automatically when the queries end.\n", new_name); - fprintf(stderr, + "InnoDB: dropped automatically when the queries end.\n" "InnoDB: You can drop the orphaned table inside InnoDB by\n" "InnoDB: creating an InnoDB table with the same name in another\n" "InnoDB: database and moving the .frm file to the current database.\n" "InnoDB: Then MySQL thinks the table exists, and DROP TABLE will\n" - "InnoDB: succeed.\n"); + "InnoDB: succeed.\n", stderr); } trx->error_state = DB_SUCCESS; trx_general_rollback_for_mysql(trx, FALSE, NULL); @@ -2937,9 +2971,12 @@ row_rename_table_for_mysql( trx_general_rollback_for_mysql(trx, FALSE, NULL); trx->error_state = DB_SUCCESS; ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Error in table rename, cannot rename %s to %s\n", old_name, - new_name); + fputs(" InnoDB: Error in table rename, cannot rename ", + stderr); + ut_print_name(stderr, old_name); + fputs(" to ", stderr); + ut_print_name(stderr, new_name); + putc('\n', stderr); err = DB_ERROR; goto funct_exit; @@ -2958,11 +2995,14 @@ row_rename_table_for_mysql( if (err != DB_SUCCESS) { ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: in ALTER TABLE table %s\n" - "InnoDB: has or is referenced in foreign key constraints\n" - "InnoDB: which are not compatible with the new table definition.\n", - new_name); + fputs(" InnoDB: Error: in ALTER TABLE ", + stderr); + ut_print_name(stderr, new_name); + fputs("\n" + "InnoDB: has or is referenced in foreign key constraints\n" + "InnoDB: which are not compatible with the new table definition.\n", + stderr); + ut_a(dict_table_rename_in_cache(table, old_name, FALSE)); trx->error_state = DB_SUCCESS; @@ -2987,7 +3027,7 @@ funct_exit: trx_commit_for_mysql(trx); - trx->op_info = (char *) ""; + trx->op_info = ""; return((int) err); } @@ -3125,7 +3165,7 @@ row_check_table_for_mysql( ulint ret = DB_SUCCESS; ulint old_isolation_level; - prebuilt->trx->op_info = (char *) "checking table"; + prebuilt->trx->op_info = "checking table"; old_isolation_level = prebuilt->trx->isolation_level; @@ -3160,9 +3200,11 @@ row_check_table_for_mysql( ret = DB_ERROR; + fputs("Error: ", stderr); + dict_index_name_print(stderr, index); fprintf(stderr, - "Error: index %s contains %lu entries, should be %lu\n", - index->name, (ulong) n_rows, + " contains %lu entries, should be %lu\n", + (ulong) n_rows, (ulong) n_rows_in_table); } } @@ -3181,7 +3223,7 @@ row_check_table_for_mysql( ret = DB_ERROR; } - prebuilt->trx->op_info = (char *) ""; + prebuilt->trx->op_info = ""; return(ret); } |