summaryrefslogtreecommitdiff
path: root/innobase/row/row0mysql.c
diff options
context:
space:
mode:
Diffstat (limited to 'innobase/row/row0mysql.c')
-rw-r--r--innobase/row/row0mysql.c210
1 files changed, 152 insertions, 58 deletions
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 2e8c3adf94f..241ddc310e8 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -92,6 +92,19 @@ row_mysql_is_system_table(
|| 0 == strcmp(name + 6, "user")
|| 0 == strcmp(name + 6, "db"));
}
+
+/***********************************************************************
+Delays an INSERT, DELETE or UPDATE operation if the purge is lagging. */
+static
+void
+row_mysql_delay_if_needed(void)
+/*===========================*/
+{
+ if (srv_dml_needed_delay) {
+ os_thread_sleep(srv_dml_needed_delay);
+ }
+}
+
/***********************************************************************
Reads a MySQL format variable-length field (like VARCHAR) length and
returns pointer to the field data. */
@@ -326,8 +339,9 @@ handle_new_error:
"InnoDB: a case of widespread corruption, dump all InnoDB\n"
"InnoDB: tables and recreate the whole InnoDB tablespace.\n"
"InnoDB: If the mysqld server crashes after the startup or when\n"
- "InnoDB: you dump the tables, look at section 6.1 of\n"
- "InnoDB: http://www.innodb.com/ibman.html for help.\n", stderr);
+ "InnoDB: you dump the tables, look at\n"
+ "InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html"
+ " for help.\n", stderr);
} else {
fprintf(stderr, "InnoDB: unknown error code %lu\n",
@@ -444,7 +458,7 @@ row_prebuilt_free(
"InnoDB: table handle. Magic n %lu, magic n2 %lu, table name",
(ulong) prebuilt->magic_n,
(ulong) prebuilt->magic_n2);
- ut_print_name(stderr, prebuilt->table->name);
+ ut_print_name(stderr, NULL, prebuilt->table->name);
putc('\n', stderr);
mem_analyze_corruption((byte*)prebuilt);
@@ -537,7 +551,7 @@ row_update_prebuilt_trx(
"InnoDB: Error: trying to use a corrupt\n"
"InnoDB: table handle. Magic n %lu, table name",
(ulong) prebuilt->magic_n);
- ut_print_name(stderr, prebuilt->table->name);
+ ut_print_name(stderr, NULL, prebuilt->table->name);
putc('\n', stderr);
mem_analyze_corruption((byte*)prebuilt);
@@ -851,7 +865,7 @@ row_insert_for_mysql(
"InnoDB: Error: trying to free a corrupt\n"
"InnoDB: table handle. Magic n %lu, table name",
(ulong) prebuilt->magic_n);
- ut_print_name(stderr, prebuilt->table->name);
+ ut_print_name(stderr, prebuilt->trx, prebuilt->table->name);
putc('\n', stderr);
mem_analyze_corruption((byte*)prebuilt);
@@ -873,6 +887,8 @@ row_insert_for_mysql(
trx->op_info = "inserting";
+ row_mysql_delay_if_needed();
+
trx_start_if_not_started(trx);
if (node == NULL) {
@@ -1066,7 +1082,7 @@ row_update_for_mysql(
"InnoDB: Error: trying to free a corrupt\n"
"InnoDB: table handle. Magic n %lu, table name",
(ulong) prebuilt->magic_n);
- ut_print_name(stderr, prebuilt->table->name);
+ ut_print_name(stderr, prebuilt->trx, prebuilt->table->name);
putc('\n', stderr);
mem_analyze_corruption((byte*)prebuilt);
@@ -1088,6 +1104,8 @@ row_update_for_mysql(
trx->op_info = "updating or deleting";
+ row_mysql_delay_if_needed();
+
trx_start_if_not_started(trx);
node = prebuilt->upd_node;
@@ -1551,7 +1569,7 @@ row_create_table_for_mysql(
if (err == DB_OUT_OF_FILE_SPACE) {
fputs("InnoDB: Warning: cannot create table ", stderr);
- ut_print_name(stderr, table->name);
+ ut_print_name(stderr, trx, table->name);
fputs(" because tablespace full\n", stderr);
row_drop_table_for_mysql(table->name, trx, FALSE);
@@ -1559,7 +1577,7 @@ row_create_table_for_mysql(
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: table ", stderr);
- ut_print_name(stderr, table->name);
+ ut_print_name(stderr, trx, table->name);
fputs(" already exists in InnoDB internal\n"
"InnoDB: data dictionary. Have you deleted the .frm file\n"
"InnoDB: and not used DROP TABLE? Have you used DROP DATABASE\n"
@@ -1567,11 +1585,12 @@ row_create_table_for_mysql(
"InnoDB: See the Restrictions section of the InnoDB manual.\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: database and copying the .frm file to the current database.\n"
"InnoDB: Then MySQL thinks the table exists, and DROP TABLE will\n"
"InnoDB: succeed.\n"
- "InnoDB: You can look for further help from section 15.1 of\n"
- "InnoDB: http://www.innodb.com/ibman.php\n", stderr);
+ "InnoDB: You can look for further help from\n"
+ "InnoDB: http://dev.mysql.com/doc/mysql/en/"
+ "InnoDB_troubleshooting_datadict.html\n", stderr);
}
/* We may also get err == DB_ERROR if the .ibd file for the
@@ -1613,6 +1632,8 @@ row_create_index_for_mysql(
trx->op_info = "creating index";
+ trx_start_if_not_started(trx);
+
/* 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
safer not to allow them. */
@@ -1626,10 +1647,10 @@ row_create_index_for_mysql(
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: column ", stderr);
- ut_print_name(stderr,
+ ut_print_name(stderr, trx,
dict_index_get_nth_field(index, i)->name);
fputs(" appears twice in ", stderr);
- dict_index_name_print(stderr, index);
+ dict_index_name_print(stderr, trx, index);
fputs("\n"
"InnoDB: This is not allowed in InnoDB.\n",
stderr);
@@ -1639,9 +1660,16 @@ row_create_index_for_mysql(
goto error_handling;
}
}
- }
+
+ /* Check also that prefix_len < DICT_MAX_COL_PREFIX_LEN */
- trx_start_if_not_started(trx);
+ if (dict_index_get_nth_field(index, i)->prefix_len
+ >= DICT_MAX_COL_PREFIX_LEN) {
+ err = DB_TOO_BIG_RECORD;
+
+ goto error_handling;
+ }
+ }
if (row_mysql_is_recovered_tmp_table(index->table_name)) {
@@ -1778,7 +1806,7 @@ row_drop_table_for_mysql_in_background(
if (error != DB_SUCCESS) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: Dropping table ", stderr);
- ut_print_name(stderr, name);
+ ut_print_name(stderr, trx, name);
fputs(" in background drop list failed\n", stderr);
}
@@ -1857,9 +1885,9 @@ already_dropped:
UT_LIST_REMOVE(row_mysql_drop_list, row_mysql_drop_list, drop);
ut_print_timestamp(stderr);
- fputs(" InnoDB: Dropped table ", stderr);
- ut_print_name(stderr, drop->table_name);
- fputs(" in background drop queue.\n", stderr);
+ fprintf(stderr,
+ " InnoDB: Dropped table %s in background drop queue.\n",
+ drop->table_name);
mem_free(drop->table_name);
@@ -1971,9 +1999,9 @@ row_discard_tablespace_for_mysql(
"new_id_high INT;\n"
"table_name CHAR;\n"
"BEGIN\n"
- "table_name := ";
+ "table_name := '";
static const char discard_tablespace_proc2[] =
- ";\n"
+ "';\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"
@@ -2014,7 +2042,7 @@ row_discard_tablespace_for_mysql(
if (table->space == 0) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: table ", stderr);
- ut_print_name(stderr, name);
+ ut_print_name(stderr, trx, name);
fputs("\n"
"InnoDB: is in the system tablespace 0 which cannot be discarded\n", stderr);
err = DB_ERROR;
@@ -2125,6 +2153,12 @@ row_import_tablespace_for_mysql(
success = fil_reset_too_high_lsns(name, current_lsn);
if (!success) {
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: Error: cannot reset lsn's in table ", stderr);
+ ut_print_name(stderr, trx, name);
+ fputs("\n"
+ "InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n", stderr);
+
err = DB_ERROR;
row_mysql_lock_data_dictionary(trx);
@@ -2140,6 +2174,14 @@ row_import_tablespace_for_mysql(
table = dict_table_get_low(name);
if (!table) {
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: table ", stderr);
+ ut_print_name(stderr, trx, name);
+ fputs("\n"
+"InnoDB: does not exist in the InnoDB data dictionary\n"
+"InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n",
+ stderr);
+
err = DB_TABLE_NOT_FOUND;
goto funct_exit;
@@ -2148,7 +2190,7 @@ row_import_tablespace_for_mysql(
if (table->space == 0) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: table ", stderr);
- ut_print_name(stderr, name);
+ ut_print_name(stderr, trx, name);
fputs("\n"
"InnoDB: is in the system tablespace 0 which cannot be imported\n", stderr);
err = DB_ERROR;
@@ -2161,7 +2203,7 @@ row_import_tablespace_for_mysql(
fputs(
" InnoDB: Error: you are trying to IMPORT a tablespace\n"
"InnoDB: ", stderr);
- ut_print_name(stderr, name);
+ ut_print_name(stderr, trx, name);
fputs(", though you have not called DISCARD on it yet\n"
"InnoDB: during the lifetime of the mysqld process!\n", stderr);
@@ -2181,6 +2223,17 @@ row_import_tablespace_for_mysql(
table->ibd_file_missing = FALSE;
table->tablespace_discarded = FALSE;
} else {
+ if (table->ibd_file_missing) {
+ ut_print_timestamp(stderr);
+ fputs(
+" InnoDB: cannot find of open in the database directory the .ibd file of\n"
+"InnoDB: table ", stderr);
+ ut_print_name(stderr, trx, name);
+ fputs("\n"
+"InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n",
+ stderr);
+ }
+
err = DB_ERROR;
}
@@ -2215,14 +2268,17 @@ row_drop_table_for_mysql(
ulint err;
const char* table_name;
ulint namelen;
+ char* dir_path_of_temp_table = NULL;
ibool success;
ibool locked_dictionary = FALSE;
char* quoted_name;
char* sql;
+
/* We use the private SQL parser of Innobase to generate the
query graphs needed in deleting the dictionary data from system
tables in Innobase. Deleting a row from SYS_INDEXES table also
frees the file segments of the B-tree associated with the index. */
+
static const char str1[] =
"PROCEDURE DROP_TABLE_PROC () IS\n"
"table_name CHAR;\n"
@@ -2343,6 +2399,7 @@ row_drop_table_for_mysql(
memcpy(sql, str1, (sizeof str1) - 1);
memcpy(sql + (sizeof str1) - 1, quoted_name, namelen);
memcpy(sql + (sizeof str1) - 1 + namelen, str2, sizeof str2);
+ mem_free(quoted_name);
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
@@ -2378,13 +2435,14 @@ row_drop_table_for_mysql(
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: table ", stderr);
- ut_print_name(stderr, name);
+ ut_print_name(stderr, trx, name);
fputs(" does not exist in the InnoDB internal\n"
"InnoDB: data dictionary though MySQL is trying to drop it.\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.php\n", stderr);
+ "InnoDB: You can look for further help from\n"
+ "InnoDB: http://dev.mysql.com/doc/mysql/en/"
+ "InnoDB_troubleshooting_datadict.html\n", stderr);
goto funct_exit;
}
@@ -2412,10 +2470,10 @@ row_drop_table_for_mysql(
ut_print_timestamp(ef);
fputs(" Cannot drop table ", ef);
- ut_print_name(ef, name);
+ ut_print_name(ef, trx, name);
fputs("\n"
"because it is referenced by ", ef);
- ut_print_name(ef, foreign->foreign_table_name);
+ ut_print_name(ef, trx, foreign->foreign_table_name);
putc('\n', ef);
mutex_exit(&dict_foreign_err_mutex);
@@ -2427,7 +2485,7 @@ row_drop_table_for_mysql(
ut_print_timestamp(stderr);
fputs(" InnoDB: Warning: MySQL is trying to drop table ",
stderr);
- ut_print_name(stderr, table->name);
+ ut_print_name(stderr, trx, table->name);
fputs("\n"
"InnoDB: though there are still open handles to it.\n"
"InnoDB: Adding the table to the background drop queue.\n",
@@ -2444,10 +2502,10 @@ row_drop_table_for_mysql(
ut_print_timestamp(stderr);
fputs(" InnoDB: You are trying to drop table ", stderr);
- ut_print_name(stderr, table->name);
+ ut_print_name(stderr, trx, table->name);
fputs("\n"
- "InnoDB: though there are foreign key check running on it.\n"
- "InnoDB: Adding the table to the background drop queue.\n",
+ "InnoDB: though there is a foreign key check running on it.\n"
+ "InnoDB: Adding the table to the background drop queue.\n",
stderr);
row_add_table_to_background_drop_list(table);
@@ -2479,14 +2537,28 @@ row_drop_table_for_mysql(
ut_error;
} else {
+ ibool is_path;
+ const char* name_or_path;
+
space_id = table->space;
+
+ if (table->dir_path_of_temp_table != NULL) {
+ dir_path_of_temp_table =
+ mem_strdup(table->dir_path_of_temp_table);
+ is_path = TRUE;
+ name_or_path = dir_path_of_temp_table;
+ } else {
+ is_path = FALSE;
+ name_or_path = name;
+ }
+
dict_table_remove_from_cache(table);
if (dict_load_table(name) != NULL) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: not able to remove table ",
stderr);
- ut_print_name(stderr, name);
+ ut_print_name(stderr, trx, name);
fputs(" from the dictionary cache!\n", stderr);
err = DB_ERROR;
}
@@ -2495,9 +2567,17 @@ row_drop_table_for_mysql(
wrong: we do not want to delete valuable data of the user */
if (err == DB_SUCCESS && space_id > 0) {
- if (!fil_space_for_table_exists_in_mem(space_id, name,
+ if (!fil_space_for_table_exists_in_mem(space_id,
+ name_or_path,
+ is_path,
FALSE, TRUE)) {
- err = DB_ERROR;
+ err = DB_SUCCESS;
+
+ fprintf(stderr,
+"InnoDB: We removed now the InnoDB internal data dictionary entry\n"
+"InnoDB: of table ");
+ ut_print_name(stderr, trx, name);
+ fprintf(stderr, ".\n");
goto funct_exit;
}
@@ -2505,11 +2585,17 @@ row_drop_table_for_mysql(
success = fil_delete_tablespace(space_id);
if (!success) {
+ fprintf(stderr,
+"InnoDB: We removed now the InnoDB internal data dictionary entry\n"
+"InnoDB: of table ");
+ ut_print_name(stderr, trx, name);
+ fprintf(stderr, ".\n");
+
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Error: not able to delete tablespace %lu of table ",
(ulong) space_id);
- ut_print_name(stderr, name);
+ ut_print_name(stderr, trx, name);
fputs("!\n", stderr);
err = DB_ERROR;
}
@@ -2521,6 +2607,10 @@ funct_exit:
row_mysql_unlock_data_dictionary(trx);
}
+ if (dir_path_of_temp_table) {
+ mem_free(dir_path_of_temp_table);
+ }
+
que_graph_free(graph);
trx_commit_for_mysql(trx);
@@ -2573,10 +2663,10 @@ loop:
ut_print_timestamp(stderr);
fputs(
" InnoDB: Warning: MySQL is trying to drop database ", stderr);
- ut_print_name(stderr, name);
+ ut_print_name(stderr, trx, name);
fputs("\n"
"InnoDB: though there are still open handles to table ", stderr);
- ut_print_name(stderr, table_name);
+ ut_print_name(stderr, trx, table_name);
fputs(".\n", stderr);
os_thread_sleep(1000000);
@@ -2592,10 +2682,10 @@ loop:
if (err != DB_SUCCESS) {
fputs("InnoDB: DROP DATABASE ", stderr);
- ut_print_name(stderr, name);
+ ut_print_name(stderr, trx, name);
fprintf(stderr, " failed with error %lu for table ",
(ulint) err);
- ut_print_name(stderr, table_name);
+ ut_print_name(stderr, trx, table_name);
putc('\n', stderr);
break;
}
@@ -2776,7 +2866,7 @@ row_rename_table_for_mysql(
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: table ", stderr);
- ut_print_name(stderr, old_name);
+ ut_print_name(stderr, trx, 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"
@@ -2791,7 +2881,7 @@ row_rename_table_for_mysql(
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: table ", stderr);
- ut_print_name(stderr, old_name);
+ ut_print_name(stderr, trx, 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"
@@ -2923,22 +3013,24 @@ row_rename_table_for_mysql(
if (err == DB_DUPLICATE_KEY) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: table ", stderr);
- ut_print_name(stderr, new_name);
+ ut_print_name(stderr, trx, 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);
+ ut_print_name(stderr, trx, 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.php\n"
+ "InnoDB: You can look for further help from\n"
+ "InnoDB: http://dev.mysql.com/doc/mysql/en/"
+ "InnoDB_troubleshooting_datadict.html\n"
"InnoDB: If table ", stderr);
- ut_print_name(stderr, new_name);
- fputs(" is a temporary table #sql..., then it can be that\n"
+ ut_print_name(stderr, trx, 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"
"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: database and copying the .frm file to the current database.\n"
"InnoDB: Then MySQL thinks the table exists, and DROP TABLE will\n"
"InnoDB: succeed.\n", stderr);
}
@@ -2958,9 +3050,9 @@ row_rename_table_for_mysql(
ut_print_timestamp(stderr);
fputs(" InnoDB: Error in table rename, cannot rename ",
stderr);
- ut_print_name(stderr, old_name);
+ ut_print_name(stderr, trx, old_name);
fputs(" to ", stderr);
- ut_print_name(stderr, new_name);
+ ut_print_name(stderr, trx, new_name);
putc('\n', stderr);
err = DB_ERROR;
@@ -2982,14 +3074,14 @@ row_rename_table_for_mysql(
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: in ALTER TABLE ",
stderr);
- ut_print_name(stderr, new_name);
+ ut_print_name(stderr, trx, 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));
+ old_name, FALSE));
trx->error_state = DB_SUCCESS;
trx_general_rollback_for_mysql(trx, FALSE,
NULL);
@@ -3005,14 +3097,14 @@ row_rename_table_for_mysql(
fputs(
" InnoDB: Error: in RENAME TABLE table ",
stderr);
- ut_print_name(stderr, new_name);
+ ut_print_name(stderr, trx, new_name);
fputs("\n"
"InnoDB: 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));
+ old_name, FALSE));
trx->error_state = DB_SUCCESS;
trx_general_rollback_for_mysql(trx, FALSE,
@@ -3129,7 +3221,8 @@ loop:
fputs("InnoDB: index records in a wrong order in ",
stderr);
not_ok:
- dict_index_name_print(stderr, index);
+ dict_index_name_print(stderr,
+ prebuilt->trx, index);
fputs("\n"
"InnoDB: prev record ", stderr);
dtuple_print(stderr, prev_entry);
@@ -3215,7 +3308,8 @@ row_check_table_for_mysql(
ret = DB_ERROR;
fputs("Error: ", stderr);
- dict_index_name_print(stderr, index);
+ dict_index_name_print(stderr,
+ prebuilt->trx, index);
fprintf(stderr,
" contains %lu entries, should be %lu\n",
(ulong) n_rows,