30 #include "row0mysql.ic"
77 static ibool row_mysql_drop_list_inited = FALSE;
81 static const
char S_innodb_monitor[] = "innodb_monitor";
82 static const
char S_innodb_lock_monitor[] = "innodb_lock_monitor";
83 static const
char S_innodb_tablespace_monitor[] = "innodb_tablespace_monitor";
84 static const
char S_innodb_table_monitor[] = "innodb_table_monitor";
85 static const
char S_innodb_mem_validate[] = "innodb_mem_validate";
94 #define STR_EQ(str1, str1_len, str2_onstack) \
95 ((str1_len) == sizeof(str2_onstack) \
96 && memcmp(str1, str2_onstack, sizeof(str2_onstack)) == 0)
107 row_add_table_to_background_drop_list(
115 row_mysql_delay_if_needed(
void)
118 if (srv_dml_needed_delay) {
150 ut_a(len < 256 * 256);
213 memset(dest,
'\0', col_len);
220 ut_a(col_len - 8 > 1 || len < 256);
221 ut_a(col_len - 8 > 2 || len < 256 * 256);
222 ut_a(col_len - 8 > 3 || len < 256 * 256 * 256);
226 memcpy(dest + col_len - 8, &data,
sizeof data);
246 memcpy(&data, ref + col_len - 8,
sizeof data);
264 switch (UNIV_EXPECT(mbminlen, 1)) {
269 memset(pad, 0x20, len);
278 }
while (pad < pad_end);
289 }
while (pad < pad_end);
309 ibool row_format_col,
316 const byte* mysql_data,
329 const byte* ptr = mysql_data;
334 dtype = dfield_get_type(dfield);
338 if (type == DATA_INT) {
343 byte* p = buf + col_len;
354 if (!(dtype->
prtype & DATA_UNSIGNED)) {
361 }
else if ((type == DATA_VARCHAR
362 || type == DATA_VARMYSQL
363 || type == DATA_BINARY)) {
369 if (row_format_col) {
370 if (dtype->
prtype & DATA_LONG_TRUE_VARCHAR) {
400 && ptr[col_len - 4] == 0x00
401 && ptr[col_len - 3] == 0x00
402 && ptr[col_len - 2] == 0x00
403 && ptr[col_len - 1] == 0x20) {
412 while (col_len >= 2 && ptr[col_len - 2] == 0x00
413 && ptr[col_len - 1] == 0x20) {
420 && ptr[col_len - 1] == 0x20) {
425 }
else if (comp && type == DATA_MYSQL
458 while (col_len > n_chars && ptr[col_len - 1] == 0x20) {
461 }
else if (type == DATA_BLOB && row_format_col) {
477 row_mysql_convert_row_to_innobase(
499 dfield = dtuple_get_nth_field(row, i);
548 ut_a(err != DB_SUCCESS);
553 case DB_LOCK_WAIT_TIMEOUT:
559 case DB_DUPLICATE_KEY:
560 case DB_FOREIGN_DUPLICATE_KEY:
561 case DB_TOO_BIG_RECORD:
562 case DB_ROW_IS_REFERENCED:
563 case DB_NO_REFERENCED_ROW:
564 case DB_CANNOT_ADD_CONSTRAINT:
565 case DB_TOO_MANY_CONCURRENT_TRXS:
566 case DB_OUT_OF_FILE_SPACE:
582 goto handle_new_error;
590 case DB_LOCK_TABLE_FULL:
597 case DB_MUST_GET_MORE_FILE_SPACE:
598 fputs(
"InnoDB: The database cannot continue"
599 " operation because of\n"
600 "InnoDB: lack of space. You must add"
601 " a new data file to\n"
602 "InnoDB: my.cnf and restart the database.\n", stderr);
607 fputs(
"InnoDB: We detected index corruption"
608 " in an InnoDB type table.\n"
609 "InnoDB: You have to dump + drop + reimport"
610 " the table or, in\n"
611 "InnoDB: a case of widespread corruption,"
613 "InnoDB: tables and recreate the"
614 " whole InnoDB tablespace.\n"
615 "InnoDB: If the mysqld server crashes"
616 " after the startup or when\n"
617 "InnoDB: you dump the tables, look at\n"
618 "InnoDB: " REFMAN
"forcing-innodb-recovery.html"
619 " for help.\n", stderr);
621 case DB_FOREIGN_EXCEED_MAX_CASCADE:
622 fprintf(stderr,
"InnoDB: Cannot delete/update rows with"
623 " cascading foreign key constraints that exceed max"
625 "Please drop excessive foreign constraints"
629 fprintf(stderr,
"InnoDB: unknown error code %lu\n",
664 prebuilt->
magic_n = ROW_PREBUILT_ALLOCATED;
665 prebuilt->
magic_n2 = ROW_PREBUILT_ALLOCATED;
667 prebuilt->
table = table;
670 prebuilt->
heap = heap;
672 prebuilt->
pcur = btr_pcur_create_for_mysql();
673 prebuilt->
clust_pcur = btr_pcur_create_for_mysql();
683 clust_index = dict_table_get_first_index(table);
692 dict_index_copy_types(ref, clust_index, ref_len);
697 prebuilt->autoinc_offset = 0;
720 (prebuilt->
magic_n != ROW_PREBUILT_ALLOCATED
721 || prebuilt->
magic_n2 != ROW_PREBUILT_ALLOCATED)) {
724 "InnoDB: Error: trying to free a corrupt\n"
725 "InnoDB: table handle. Magic n %lu,"
726 " magic n2 %lu, table name ",
737 prebuilt->
magic_n = ROW_PREBUILT_FREED;
738 prebuilt->
magic_n2 = ROW_PREBUILT_FREED;
740 btr_pcur_free_for_mysql(prebuilt->
pcur);
741 btr_pcur_free_for_mysql(prebuilt->
clust_pcur);
767 for (i = 0; i < MYSQL_FETCH_CACHE_SIZE; i++) {
775 fputs(
"InnoDB: Error: trying to free"
776 " a corrupt fetch buffer.\n", stderr);
788 dict_table_decrement_handle_count(prebuilt->
table, dict_locked);
804 if (trx->magic_n != TRX_MAGIC_N) {
806 "InnoDB: Error: trying to use a corrupt\n"
807 "InnoDB: trx handle. Magic n %lu\n",
808 (ulong) trx->magic_n);
815 if (prebuilt->
magic_n != ROW_PREBUILT_ALLOCATED) {
817 "InnoDB: Error: trying to use a corrupt\n"
818 "InnoDB: table handle. Magic n %lu, table name ",
851 row_get_prebuilt_insert_row(
860 ut_ad(prebuilt && table && prebuilt->
trx);
879 dict_table_copy_types(row, table);
898 row_update_statistics_if_needed(
914 if (counter > 2000000000
915 || ((ib_int64_t)counter > 16 + table->
stat_n_rows / 16)) {
917 dict_update_statistics(table, FALSE
933 mutex_enter(&kernel_mutex);
937 mutex_exit(&kernel_mutex);
973 trx->
op_info =
"setting auto-inc lock";
976 row_get_prebuilt_insert_row(prebuilt);
1000 if (err != DB_SUCCESS) {
1005 if (was_lock_wait) {
1040 ibool was_lock_wait;
1045 trx->
op_info =
"setting table lock";
1069 err =
lock_table(0, table, static_cast<lock_mode>(mode), thr);
1077 if (err != DB_SUCCESS) {
1082 if (was_lock_wait) {
1112 ibool was_lock_wait;
1121 fprintf(stderr,
" InnoDB: Error:\n"
1122 "InnoDB: MySQL is trying to use a table handle"
1123 " but the .ibd file for\n"
1124 "InnoDB: table %s does not exist.\n"
1125 "InnoDB: Have you deleted the .ibd file"
1126 " from the database directory under\n"
1127 "InnoDB: the MySQL datadir, or have you"
1128 " used DISCARD TABLESPACE?\n"
1129 "InnoDB: Look from\n"
1130 "InnoDB: " REFMAN
"innodb-troubleshooting.html\n"
1131 "InnoDB: how you can resolve the problem.\n",
1136 if (UNIV_UNLIKELY(prebuilt->
magic_n != ROW_PREBUILT_ALLOCATED)) {
1138 "InnoDB: Error: trying to free a corrupt\n"
1139 "InnoDB: table handle. Magic n %lu, table name ",
1149 if (UNIV_UNLIKELY(srv_created_new_raw || srv_force_recovery)) {
1150 fputs(
"InnoDB: A new raw disk partition was initialized or\n"
1151 "InnoDB: innodb_force_recovery is on: we do not allow\n"
1152 "InnoDB: database modifications by the user. Shut down\n"
1153 "InnoDB: mysqld and edit my.cnf so that"
1154 " newraw is replaced\n"
1155 "InnoDB: with raw, and innodb_force_... is removed.\n",
1163 row_mysql_delay_if_needed();
1168 row_get_prebuilt_insert_row(prebuilt);
1172 row_mysql_convert_row_to_innobase(node->
row, prebuilt, mysql_rec);
1179 node->
state = INS_NODE_SET_IX_LOCK;
1182 node->
state = INS_NODE_ALLOC_ROW_ID;
1195 if (err != DB_SUCCESS) {
1204 if (was_lock_wait) {
1217 srv_n_rows_inserted++;
1224 row_update_statistics_if_needed(prebuilt->
table);
1271 node->in_mysql_interface = TRUE;
1272 node->is_delete = FALSE;
1273 node->searched_update = FALSE;
1275 node->
pcur = btr_pcur_create_for_mysql();
1276 node->
table = table;
1283 node->has_clust_rec_x_lock = TRUE;
1284 node->cmpl_info = 0;
1286 node->table_sym = NULL;
1287 node->col_assign_list = NULL;
1307 ut_ad(prebuilt && table && prebuilt->
trx);
1343 ibool was_lock_wait;
1350 ut_ad(prebuilt && trx);
1356 fprintf(stderr,
" InnoDB: Error:\n"
1357 "InnoDB: MySQL is trying to use a table handle"
1358 " but the .ibd file for\n"
1359 "InnoDB: table %s does not exist.\n"
1360 "InnoDB: Have you deleted the .ibd file"
1361 " from the database directory under\n"
1362 "InnoDB: the MySQL datadir, or have you"
1363 " used DISCARD TABLESPACE?\n"
1364 "InnoDB: Look from\n"
1365 "InnoDB: " REFMAN
"innodb-troubleshooting.html\n"
1366 "InnoDB: how you can resolve the problem.\n",
1371 if (UNIV_UNLIKELY(prebuilt->
magic_n != ROW_PREBUILT_ALLOCATED)) {
1373 "InnoDB: Error: trying to free a corrupt\n"
1374 "InnoDB: table handle. Magic n %lu, table name ",
1384 if (UNIV_UNLIKELY(srv_created_new_raw || srv_force_recovery)) {
1385 fputs(
"InnoDB: A new raw disk partition was initialized or\n"
1386 "InnoDB: innodb_force_recovery is on: we do not allow\n"
1387 "InnoDB: database modifications by the user. Shut down\n"
1388 "InnoDB: mysqld and edit my.cnf so that newraw"
1390 "InnoDB: with raw, and innodb_force_... is removed.\n",
1396 trx->
op_info =
"updating or deleting";
1398 row_mysql_delay_if_needed();
1404 clust_index = dict_table_get_first_index(table);
1407 btr_pcur_copy_stored_position(node->
pcur, prebuilt->
pcur);
1409 btr_pcur_copy_stored_position(node->
pcur,
1426 node->
state = UPD_NODE_UPDATE_CLUSTERED;
1450 if (err != DB_SUCCESS) {
1453 if (err == DB_RECORD_NOT_FOUND) {
1465 if (was_lock_wait) {
1476 if (node->is_delete) {
1481 srv_n_rows_deleted++;
1483 srv_n_rows_updated++;
1489 if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
1490 row_update_statistics_if_needed(prebuilt->
table);
1514 ibool has_latches_on_recs)
1524 ut_ad(prebuilt && trx);
1529 && trx->isolation_level > TRX_ISO_READ_COMMITTED)) {
1532 "InnoDB: Error: calling row_unlock_for_mysql though\n"
1533 "InnoDB: innodb_locks_unsafe_for_binlog is FALSE and\n"
1534 "InnoDB: this session is not using"
1535 " READ COMMITTED isolation level.\n");
1553 if (!has_latches_on_recs) {
1557 rec = btr_pcur_get_rec(pcur);
1558 index = btr_pcur_get_btr_cur(pcur)->index;
1564 if (!has_latches_on_recs) {
1569 rec = btr_pcur_get_rec(clust_pcur);
1570 index = btr_pcur_get_btr_cur(clust_pcur)->index;
1587 ulint offsets_[REC_OFFS_NORMAL_SIZE];
1588 ulint* offsets = offsets_;
1590 rec_offs_init(offsets_);
1591 offsets = rec_get_offsets(rec, index, offsets,
1592 ULINT_UNDEFINED, &heap);
1596 if (UNIV_LIKELY_NULL(heap)) {
1601 if (rec_trx_id != trx->
id) {
1604 rec = btr_pcur_get_rec(pcur);
1605 index = btr_pcur_get_btr_cur(pcur)->index;
1611 rec = btr_pcur_get_rec(clust_pcur);
1612 index = btr_pcur_get_btr_cur(clust_pcur)->index;
1615 btr_pcur_get_block(clust_pcur),
1652 return (DB_FOREIGN_EXCEED_MAX_CASCADE);
1672 if (err == DB_LOCK_WAIT) {
1693 if (err != DB_SUCCESS) {
1698 if (node->is_delete) {
1703 srv_n_rows_deleted++;
1705 srv_n_rows_updated++;
1708 row_update_statistics_if_needed(table);
1725 clust_index = dict_table_get_first_index(table);
1758 rw_lock_s_unlock(&dict_operation_lock);
1783 mutex_enter(&(dict_sys->
mutex));
1799 mutex_exit(&(dict_sys->
mutex));
1800 rw_lock_x_unlock(&dict_operation_lock);
1824 ulint table_name_len;
1828 #ifdef UNIV_SYNC_DEBUG
1829 ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
1834 if (srv_created_new_raw) {
1835 fputs(
"InnoDB: A new raw disk partition was initialized:\n"
1836 "InnoDB: we do not allow database modifications"
1838 "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
1839 " is replaced with raw.\n", stderr);
1840 dict_mem_table_free(table);
1846 trx->
op_info =
"creating table";
1854 table_name = strchr(table->
name,
'/');
1857 table_name_len = strlen(table_name) + 1;
1859 if (STR_EQ(table_name, table_name_len, S_innodb_monitor)) {
1864 srv_print_innodb_monitor = TRUE;
1870 }
else if (STR_EQ(table_name, table_name_len,
1871 S_innodb_lock_monitor)) {
1873 srv_print_innodb_monitor = TRUE;
1874 srv_print_innodb_lock_monitor = TRUE;
1876 }
else if (STR_EQ(table_name, table_name_len,
1877 S_innodb_tablespace_monitor)) {
1879 srv_print_innodb_tablespace_monitor = TRUE;
1881 }
else if (STR_EQ(table_name, table_name_len,
1882 S_innodb_table_monitor)) {
1884 srv_print_innodb_table_monitor = TRUE;
1886 }
else if (STR_EQ(table_name, table_name_len,
1887 S_innodb_mem_validate)) {
1891 fputs(
"Validating InnoDB memory:\n"
1892 "to use this feature you must compile InnoDB with\n"
1893 "UNIV_MEM_DEBUG defined in univ.i and"
1894 " the server must be\n"
1895 "quiet because allocation from a mem heap"
1896 " is not protected\n"
1897 "by any semaphore.\n", stderr);
1898 #ifdef UNIV_MEM_DEBUG
1899 ut_a(mem_validate());
1900 fputs(
"Memory validated\n", stderr);
1902 fputs(
"Memory NOT validated (recompile with UNIV_MEM_DEBUG)\n",
1911 node = tab_create_graph_create(table, heap);
1923 case DB_OUT_OF_FILE_SPACE:
1928 fputs(
" InnoDB: Warning: cannot create table ",
1931 fputs(
" because tablespace full\n", stderr);
1940 case DB_DUPLICATE_KEY:
1947 dict_mem_table_free(table);
1970 const ulint* field_lengths)
1985 #ifdef UNIV_SYNC_DEBUG
1986 ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
1991 trx->
op_info =
"creating index";
2007 for (j = 0; j < i; j++) {
2009 dict_index_get_nth_field(index, j)->name,
2010 dict_index_get_nth_field(index, i)->name)) {
2013 fputs(
" InnoDB: Error: column ", stderr);
2015 dict_index_get_nth_field(
2017 fputs(
" appears twice in ", stderr);
2018 dict_index_name_print(stderr, trx, index);
2020 "InnoDB: This is not allowed"
2021 " in InnoDB.\n", stderr);
2023 err = DB_COL_APPEARS_TWICE_IN_INDEX;
2025 goto error_handling;
2032 len = dict_index_get_nth_field(index, i)->prefix_len;
2034 if (field_lengths) {
2035 len =
ut_max(len, field_lengths[i]);
2039 err = DB_TOO_BIG_RECORD;
2041 goto error_handling;
2052 node = ind_create_graph_create(index, heap);
2064 if (err != DB_SUCCESS) {
2099 const char* sql_string,
2115 #ifdef UNIV_SYNC_DEBUG
2116 ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
2120 trx->
op_info =
"adding foreign keys";
2126 err = dict_create_foreign_constraints(trx, sql_string, sql_length,
2128 if (err == DB_SUCCESS) {
2130 err = dict_load_foreigns(name, FALSE, TRUE);
2133 if (err != DB_SUCCESS) {
2160 row_drop_table_for_mysql_in_background(
2173 trx->check_foreigns = FALSE;
2193 return((
int) error);
2209 ulint n_tables_dropped = 0;
2211 mutex_enter(&kernel_mutex);
2213 if (!row_mysql_drop_list_inited) {
2216 row_mysql_drop_list_inited = TRUE;
2223 mutex_exit(&kernel_mutex);
2228 return(n_tables + n_tables_dropped);
2231 mutex_enter(&(dict_sys->
mutex));
2233 mutex_exit(&(dict_sys->
mutex));
2235 if (table == NULL) {
2239 goto already_dropped;
2242 if (DB_SUCCESS != row_drop_table_for_mysql_in_background(
2247 return(n_tables + n_tables_dropped);
2253 mutex_enter(&kernel_mutex);
2258 fputs(
" InnoDB: Dropped table ", stderr);
2260 fputs(
" in background drop queue.\n", stderr);
2266 mutex_exit(&kernel_mutex);
2280 ut_ad(mutex_own(&kernel_mutex));
2282 if (!row_mysql_drop_list_inited) {
2285 row_mysql_drop_list_inited = TRUE;
2300 row_add_table_to_background_drop_list(
2306 mutex_enter(&kernel_mutex);
2308 if (!row_mysql_drop_list_inited) {
2311 row_mysql_drop_list_inited = TRUE;
2317 while (drop != NULL) {
2321 mutex_exit(&kernel_mutex);
2339 mutex_exit(&kernel_mutex);
2394 trx->
op_info =
"discarding tablespace";
2400 row_mysql_lock_data_dictionary(trx);
2405 err = DB_TABLE_NOT_FOUND;
2410 if (table->
space == 0) {
2412 fputs(
" InnoDB: Error: table ", stderr);
2415 "InnoDB: is in the system tablespace 0"
2416 " which cannot be discarded\n", stderr);
2425 fputs(
" InnoDB: You are trying to DISCARD table ", stderr);
2428 "InnoDB: though there is a foreign key check"
2430 "InnoDB: Cannot discard the table.\n",
2447 if (foreign && trx->check_foreigns) {
2449 FILE* ef = dict_foreign_err_file;
2454 err = DB_CANNOT_DROP_CONSTRAINT;
2456 mutex_enter(&dict_foreign_err_mutex);
2460 fputs(
" Cannot DISCARD table ", ef);
2463 "because it is referenced by ", ef);
2466 mutex_exit(&dict_foreign_err_mutex);
2471 dict_hdr_get_new_id(&new_id, NULL, NULL);
2482 "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
2485 "SELECT ID INTO old_id\n"
2487 "WHERE NAME = :table_name\n"
2488 "LOCK IN SHARE MODE;\n"
2489 "IF (SQL % NOTFOUND) THEN\n"
2493 "UPDATE SYS_TABLES SET ID = :new_id\n"
2494 " WHERE ID = old_id;\n"
2495 "UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n"
2496 " WHERE TABLE_ID = old_id;\n"
2497 "UPDATE SYS_INDEXES SET TABLE_ID = :new_id\n"
2498 " WHERE TABLE_ID = old_id;\n"
2503 if (err != DB_SUCCESS) {
2508 dict_table_change_id_in_cache(table, new_id);
2510 success = fil_discard_tablespace(table->
space);
2549 ib_uint64_t current_lsn;
2550 ulint err = DB_SUCCESS;
2556 trx->
op_info =
"importing tablespace";
2572 success = fil_reset_too_high_lsns(name, current_lsn);
2576 fputs(
" InnoDB: Error: cannot reset lsn's in table ", stderr);
2579 "InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n",
2584 row_mysql_lock_data_dictionary(trx);
2592 row_mysql_lock_data_dictionary(trx);
2598 fputs(
" InnoDB: table ", stderr);
2601 "InnoDB: does not exist in the InnoDB data dictionary\n"
2602 "InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n",
2605 err = DB_TABLE_NOT_FOUND;
2610 if (table->
space == 0) {
2612 fputs(
" InnoDB: Error: table ", stderr);
2615 "InnoDB: is in the system tablespace 0"
2616 " which cannot be imported\n", stderr);
2624 fputs(
" InnoDB: Error: you are trying to"
2625 " IMPORT a tablespace\n"
2626 "InnoDB: ", stderr);
2628 fputs(
", though you have not called DISCARD on it yet\n"
2629 "InnoDB: during the lifetime of the mysqld process!\n",
2640 ibuf_delete_for_discarded_space(table->
space);
2642 success = fil_open_single_table_tablespace(
2652 fputs(
" InnoDB: cannot find or open in the"
2653 " database directory the .ibd file of\n"
2654 "InnoDB: table ", stderr);
2657 "InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n",
2694 ulint recreate_space = 0;
2740 if (srv_created_new_raw) {
2741 fputs(
"InnoDB: A new raw disk partition was initialized:\n"
2742 "InnoDB: we do not allow database modifications"
2744 "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
2745 " is replaced with raw.\n", stderr);
2750 trx->
op_info =
"truncating table";
2761 row_mysql_lock_data_dictionary(trx);
2764 #ifdef UNIV_SYNC_DEBUG
2765 ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
2777 if (foreign && trx->check_foreigns) {
2778 FILE* ef = dict_foreign_err_file;
2783 mutex_enter(&dict_foreign_err_mutex);
2787 fputs(
" Cannot truncate table ", ef);
2789 fputs(
" by DROP+CREATE\n"
2790 "InnoDB: because it is referenced by ", ef);
2793 mutex_exit(&dict_foreign_err_mutex);
2807 fputs(
" InnoDB: Cannot truncate table ", stderr);
2809 fputs(
" by DROP+CREATE\n"
2810 "InnoDB: because there is a foreign key check"
2811 " running on it.\n",
2825 ulint space = table->
space;
2826 ulint flags = fil_space_get_flags(space);
2828 if (flags != ULINT_UNDEFINED
2829 && fil_discard_tablespace(space)) {
2833 dict_hdr_get_new_id(NULL, NULL, &space);
2840 if (space == ULINT_UNDEFINED
2841 || fil_create_new_single_table_tablespace(
2842 space, table->
name, FALSE, flags,
2847 " InnoDB: TRUNCATE TABLE %s failed to"
2848 " create a new tablespace\n",
2855 recreate_space = space;
2861 table->
space = space;
2862 index = dict_table_get_first_index(table);
2864 index->
space = space;
2865 index = dict_table_get_next_index(index);
2869 fsp_header_init(space,
2888 dfield = dtuple_get_nth_field(tuple, 0);
2894 sys_index = dict_table_get_first_index(dict_sys->
sys_indexes);
2895 dict_index_copy_types(tuple, sys_index, 1);
2898 btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
2911 rec = btr_pcur_get_rec(&pcur);
2913 field = rec_get_nth_field_old(rec, 0, &len);
2916 if (memcmp(buf, field, len) != 0) {
2928 root_page_no = dict_truncate_index_tree(table, recreate_space,
2931 rec = btr_pcur_get_rec(&pcur);
2935 rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
2936 root_page_no, &mtr);
2961 dict_hdr_get_new_id(&new_id, NULL, NULL);
2970 "PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
2973 " SET ID = :new_id, SPACE = :space\n"
2974 " WHERE ID = :old_id;\n"
2975 "UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n"
2976 " WHERE TABLE_ID = :old_id;\n"
2977 "UPDATE SYS_INDEXES"
2978 " SET TABLE_ID = :new_id, SPACE = :space\n"
2979 " WHERE TABLE_ID = :old_id;\n"
2984 if (err != DB_SUCCESS) {
2989 fputs(
" InnoDB: Unable to assign a new identifier to table ",
2993 "InnoDB: after truncating it. Background processes"
2994 " may corrupt the table!\n", stderr);
2997 dict_table_change_id_in_cache(table, new_id);
3004 dict_table_autoinc_lock(table);
3005 dict_table_autoinc_initialize(table, 1);
3006 dict_table_autoinc_unlock(table);
3007 dict_update_statistics(table, FALSE
3045 ibool locked_dictionary = FALSE;
3050 if (srv_created_new_raw) {
3051 fputs(
"InnoDB: A new raw disk partition was initialized:\n"
3052 "InnoDB: we do not allow database modifications"
3054 "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
3055 " is replaced with raw.\n", stderr);
3060 trx->
op_info =
"dropping table";
3068 table_name = strchr(name,
'/');
3071 namelen = strlen(table_name) + 1;
3073 if (namelen ==
sizeof S_innodb_monitor
3074 && !memcmp(table_name, S_innodb_monitor,
3075 sizeof S_innodb_monitor)) {
3080 srv_print_innodb_monitor = FALSE;
3081 srv_print_innodb_lock_monitor = FALSE;
3082 }
else if (namelen ==
sizeof S_innodb_lock_monitor
3083 && !memcmp(table_name, S_innodb_lock_monitor,
3084 sizeof S_innodb_lock_monitor)) {
3085 srv_print_innodb_monitor = FALSE;
3086 srv_print_innodb_lock_monitor = FALSE;
3087 }
else if (namelen ==
sizeof S_innodb_tablespace_monitor
3088 && !memcmp(table_name, S_innodb_tablespace_monitor,
3089 sizeof S_innodb_tablespace_monitor)) {
3091 srv_print_innodb_tablespace_monitor = FALSE;
3092 }
else if (namelen ==
sizeof S_innodb_table_monitor
3093 && !memcmp(table_name, S_innodb_table_monitor,
3094 sizeof S_innodb_table_monitor)) {
3096 srv_print_innodb_table_monitor = FALSE;
3106 row_mysql_lock_data_dictionary(trx);
3108 locked_dictionary = TRUE;
3112 #ifdef UNIV_SYNC_DEBUG
3113 ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
3119 #if defined(BUILD_DRIZZLE)
3122 err = DB_TABLE_NOT_FOUND;
3125 fputs(
" InnoDB: Error: table ", stderr);
3127 fputs(
" does not exist in the InnoDB internal\n"
3128 "InnoDB: data dictionary though MySQL is"
3129 " trying to drop it.\n"
3130 "InnoDB: Have you copied the .frm file"
3131 " of the table to the\n"
3132 "InnoDB: MySQL database directory"
3133 " from another database?\n"
3134 "InnoDB: You can look for further help from\n"
3135 "InnoDB: " REFMAN
"innodb-troubleshooting.html\n",
3151 if (foreign && trx->check_foreigns
3152 && !(drop_db && dict_tables_have_same_db(
3154 FILE* ef = dict_foreign_err_file;
3159 err = DB_CANNOT_DROP_CONSTRAINT;
3161 mutex_enter(&dict_foreign_err_mutex);
3165 fputs(
" Cannot drop table ", ef);
3168 "because it is referenced by ", ef);
3171 mutex_exit(&dict_foreign_err_mutex);
3176 if (foreign && trx->check_foreigns) {
3177 goto check_next_foreign;
3183 added = row_add_table_to_background_drop_list(table->
name);
3187 fputs(
" InnoDB: Warning: MySQL is"
3188 " trying to drop table ", stderr);
3191 "InnoDB: though there are still"
3192 " open handles to it.\n"
3193 "InnoDB: Adding the table to the"
3194 " background drop queue.\n",
3216 const char* i_table_name = table->
name;
3219 added = row_add_table_to_background_drop_list(i_table_name);
3223 fputs(
" InnoDB: You are trying to drop table ",
3227 "InnoDB: though there is a"
3228 " foreign key check running on it.\n"
3229 "InnoDB: Adding the table to"
3230 " the background drop queue.\n",
3261 "PROCEDURE DROP_TABLE_PROC () IS\n"
3262 "sys_foreign_id CHAR;\n"
3265 "foreign_id CHAR;\n"
3268 "SELECT ID INTO table_id\n"
3270 "WHERE NAME = :table_name\n"
3271 "LOCK IN SHARE MODE;\n"
3272 "IF (SQL % NOTFOUND) THEN\n"
3276 "SELECT ID INTO sys_foreign_id\n"
3278 "WHERE NAME = 'SYS_FOREIGN'\n"
3279 "LOCK IN SHARE MODE;\n"
3280 "IF (SQL % NOTFOUND) THEN\n"
3283 "IF (:table_name = 'SYS_FOREIGN') THEN\n"
3286 "IF (:table_name = 'SYS_FOREIGN_COLS') THEN\n"
3289 "WHILE found = 1 LOOP\n"
3290 " SELECT ID INTO foreign_id\n"
3291 " FROM SYS_FOREIGN\n"
3292 " WHERE FOR_NAME = :table_name\n"
3293 " AND TO_BINARY(FOR_NAME)\n"
3294 " = TO_BINARY(:table_name)\n"
3295 " LOCK IN SHARE MODE;\n"
3296 " IF (SQL % NOTFOUND) THEN\n"
3299 " DELETE FROM SYS_FOREIGN_COLS\n"
3300 " WHERE ID = foreign_id;\n"
3301 " DELETE FROM SYS_FOREIGN\n"
3302 " WHERE ID = foreign_id;\n"
3306 "WHILE found = 1 LOOP\n"
3307 " SELECT ID INTO index_id\n"
3308 " FROM SYS_INDEXES\n"
3309 " WHERE TABLE_ID = table_id\n"
3310 " LOCK IN SHARE MODE;\n"
3311 " IF (SQL % NOTFOUND) THEN\n"
3314 " DELETE FROM SYS_FIELDS\n"
3315 " WHERE INDEX_ID = index_id;\n"
3316 " DELETE FROM SYS_INDEXES\n"
3317 " WHERE ID = index_id\n"
3318 " AND TABLE_ID = table_id;\n"
3321 "DELETE FROM SYS_COLUMNS\n"
3322 "WHERE TABLE_ID = table_id;\n"
3323 "DELETE FROM SYS_TABLES\n"
3324 "WHERE ID = table_id;\n"
3330 const char* name_or_path;
3341 space_id = table->
space;
3348 name_or_path = name;
3353 dict_table_remove_from_cache(table);
3357 fputs(
" InnoDB: Error: not able to remove table ",
3360 fputs(
" from the dictionary cache!\n", stderr);
3367 if (err == DB_SUCCESS && space_id > 0) {
3368 if (!fil_space_for_table_exists_in_mem(space_id,
3375 "InnoDB: We removed now the InnoDB"
3376 " internal data dictionary entry\n"
3377 "InnoDB: of table ");
3379 fprintf(stderr,
".\n");
3380 }
else if (!fil_delete_tablespace(space_id)) {
3382 "InnoDB: We removed now the InnoDB"
3383 " internal data dictionary entry\n"
3384 "InnoDB: of table ");
3386 fprintf(stderr,
".\n");
3390 " InnoDB: Error: not able to"
3391 " delete tablespace %lu of table ",
3394 fputs(
"!\n", stderr);
3402 case DB_TOO_MANY_CONCURRENT_TRXS:
3409 case DB_OUT_OF_FILE_SPACE:
3410 err = DB_MUST_GET_MORE_FILE_SPACE;
3423 if (locked_dictionary) {
3449 trx->
op_info =
"dropping temporary tables";
3450 row_mysql_lock_data_dictionary(trx);
3458 dict_table_get_first_index(dict_sys->
sys_tables),
3474 rec = btr_pcur_get_rec(&pcur);
3475 field = rec_get_nth_field_old(rec, 4, &len);
3483 field = rec_get_nth_field_old(rec, 7, &len);
3490 field = rec_get_nth_field_old(rec, 0, &len);
3491 if (len == UNIV_SQL_NULL || len == 0) {
3498 btr_pcur_store_position(&pcur, &mtr);
3526 drop_all_foreign_keys_in_db(
3534 ut_a(name[strlen(name) - 1] ==
'/');
3541 #define TABLE_NOT_IN_THIS_DB \
3542 "SUBSTR(for_name, 0, LENGTH(:dbname)) <> :dbname"
3545 "PROCEDURE DROP_ALL_FOREIGN_KEYS_PROC () IS\n"
3546 "foreign_id CHAR;\n"
3549 "DECLARE CURSOR cur IS\n"
3550 "SELECT ID, FOR_NAME FROM SYS_FOREIGN\n"
3551 "WHERE FOR_NAME >= :dbname\n"
3552 "LOCK IN SHARE MODE\n"
3553 "ORDER BY FOR_NAME;\n"
3557 "WHILE found = 1 LOOP\n"
3558 " FETCH cur INTO foreign_id, for_name;\n"
3559 " IF (SQL % NOTFOUND) THEN\n"
3561 " ELSIF (" TABLE_NOT_IN_THIS_DB
") THEN\n"
3563 " ELSIF (1=1) THEN\n"
3564 " DELETE FROM SYS_FOREIGN_COLS\n"
3565 " WHERE ID = foreign_id;\n"
3566 " DELETE FROM SYS_FOREIGN\n"
3567 " WHERE ID = foreign_id;\n"
3592 int err = DB_SUCCESS;
3593 ulint namelen = strlen(name);
3597 ut_a(name[namelen - 1] ==
'/');
3599 trx->
op_info =
"dropping database";
3603 row_mysql_lock_data_dictionary(trx);
3605 while ((table_name = dict_get_first_table_name_in_db(name))) {
3606 ut_a(memcmp(table_name, name, namelen) == 0);
3610 fprintf(stderr,
"Dropping lost temporary table %s\n", table_name);
3623 fputs(
" InnoDB: Warning: MySQL is trying to"
3624 " drop database ", stderr);
3627 "InnoDB: though there are still"
3628 " open handles to table ", stderr);
3630 fputs(
".\n", stderr);
3642 if (err != DB_SUCCESS) {
3643 fputs(
"InnoDB: DROP DATABASE ", stderr);
3645 fprintf(stderr,
" failed with error %lu for table ",
3656 if (err == DB_SUCCESS) {
3659 err = (int) drop_all_foreign_keys_in_db(name, trx);
3661 if (err != DB_SUCCESS) {
3662 fputs(
"InnoDB: DROP DATABASE ", stderr);
3664 fprintf(stderr,
" failed with error %d while "
3665 "dropping all foreign keys", err);
3684 row_is_mysql_tmp_table_name(
3689 return(strstr(name,
"/#sql") != NULL);
3698 row_delete_constraint_low(
3708 "PROCEDURE DELETE_CONSTRAINT () IS\n"
3710 "DELETE FROM SYS_FOREIGN_COLS WHERE ID = :id;\n"
3711 "DELETE FROM SYS_FOREIGN WHERE ID = :id;\n"
3721 row_delete_constraint(
3724 const char* database_name,
3732 err = row_delete_constraint_low(
3735 if ((err == DB_SUCCESS) && !strchr(
id,
'/')) {
3743 err = row_delete_constraint_low(
id, trx);
3756 const char* old_name,
3757 const char* new_name,
3762 ulint err = DB_ERROR;
3764 const char** constraints_to_drop = NULL;
3765 ulint n_constraints_to_drop = 0;
3766 ibool old_is_tmp, new_is_tmp;
3770 ut_a(old_name != NULL);
3771 ut_a(new_name != NULL);
3773 if (srv_created_new_raw || srv_force_recovery) {
3774 fputs(
"InnoDB: A new raw disk partition was initialized or\n"
3775 "InnoDB: innodb_force_recovery is on: we do not allow\n"
3776 "InnoDB: database modifications by the user. Shut down\n"
3777 "InnoDB: mysqld and edit my.cnf so that newraw"
3779 "InnoDB: with raw, and innodb_force_... is removed.\n",
3785 trx->
op_info =
"renaming table";
3788 old_is_tmp = row_is_mysql_tmp_table_name(old_name);
3789 new_is_tmp = row_is_mysql_tmp_table_name(new_name);
3794 #if defined(BUILD_DRIZZLE)
3797 err = DB_TABLE_NOT_FOUND;
3800 fputs(
" InnoDB: Error: table ", stderr);
3802 fputs(
" does not exist in the InnoDB internal\n"
3803 "InnoDB: data dictionary though MySQL is"
3804 " trying to rename the table.\n"
3805 "InnoDB: Have you copied the .frm file"
3806 " of the table to the\n"
3807 "InnoDB: MySQL database directory"
3808 " from another database?\n"
3809 "InnoDB: You can look for further help from\n"
3810 "InnoDB: " REFMAN
"innodb-troubleshooting.html\n",
3815 err = DB_TABLE_NOT_FOUND;
3818 fputs(
" InnoDB: Error: table ", stderr);
3820 fputs(
" does not have an .ibd file"
3821 " in the database directory.\n"
3822 "InnoDB: You can look for further help from\n"
3823 "InnoDB: " REFMAN
"innodb-troubleshooting.html\n",
3826 }
else if (new_is_tmp) {
3835 err = dict_foreign_parse_drop_constraints(
3836 heap, trx, table, &n_constraints_to_drop,
3837 &constraints_to_drop);
3839 if (err != DB_SUCCESS) {
3854 "PROCEDURE RENAME_TABLE () IS\n"
3856 "UPDATE SYS_TABLES SET NAME = :new_table_name\n"
3857 " WHERE NAME = :old_table_name;\n"
3861 if (err != DB_SUCCESS) {
3864 }
else if (!new_is_tmp) {
3874 "PROCEDURE RENAME_CONSTRAINT_IDS () IS\n"
3875 "gen_constr_prefix CHAR;\n"
3876 "new_db_name CHAR;\n"
3877 "foreign_id CHAR;\n"
3878 "new_foreign_id CHAR;\n"
3879 "old_db_name_len INT;\n"
3880 "old_t_name_len INT;\n"
3881 "new_db_name_len INT;\n"
3886 "old_db_name_len := INSTR(:old_table_name, '/')-1;\n"
3887 "new_db_name_len := INSTR(:new_table_name, '/')-1;\n"
3888 "new_db_name := SUBSTR(:new_table_name, 0,\n"
3889 " new_db_name_len);\n"
3890 "old_t_name_len := LENGTH(:old_table_name);\n"
3891 "gen_constr_prefix := CONCAT(:old_table_name,\n"
3893 "WHILE found = 1 LOOP\n"
3894 " SELECT ID INTO foreign_id\n"
3895 " FROM SYS_FOREIGN\n"
3896 " WHERE FOR_NAME = :old_table_name\n"
3897 " AND TO_BINARY(FOR_NAME)\n"
3898 " = TO_BINARY(:old_table_name)\n"
3899 " LOCK IN SHARE MODE;\n"
3900 " IF (SQL % NOTFOUND) THEN\n"
3903 " UPDATE SYS_FOREIGN\n"
3904 " SET FOR_NAME = :new_table_name\n"
3905 " WHERE ID = foreign_id;\n"
3906 " id_len := LENGTH(foreign_id);\n"
3907 " IF (INSTR(foreign_id, '/') > 0) THEN\n"
3908 " IF (INSTR(foreign_id,\n"
3909 " gen_constr_prefix) > 0)\n"
3911 " new_foreign_id :=\n"
3912 " CONCAT(:new_table_name,\n"
3913 " SUBSTR(foreign_id, old_t_name_len,\n"
3914 " id_len - old_t_name_len));\n"
3916 " new_foreign_id :=\n"
3917 " CONCAT(new_db_name,\n"
3918 " SUBSTR(foreign_id,\n"
3919 " old_db_name_len,\n"
3920 " id_len - old_db_name_len));\n"
3922 " UPDATE SYS_FOREIGN\n"
3923 " SET ID = new_foreign_id\n"
3924 " WHERE ID = foreign_id;\n"
3925 " UPDATE SYS_FOREIGN_COLS\n"
3926 " SET ID = new_foreign_id\n"
3927 " WHERE ID = foreign_id;\n"
3931 "UPDATE SYS_FOREIGN SET REF_NAME = :new_table_name\n"
3932 "WHERE REF_NAME = :old_table_name\n"
3933 " AND TO_BINARY(REF_NAME)\n"
3934 " = TO_BINARY(:old_table_name);\n"
3938 }
else if (n_constraints_to_drop > 0) {
3941 ulint db_name_len = dict_get_db_name_len(old_name) + 1;
3946 for (i = 0; i < n_constraints_to_drop; i++) {
3947 err = row_delete_constraint(constraints_to_drop[i],
3948 db_name, heap, trx);
3950 if (err != DB_SUCCESS) {
3957 if (err != DB_SUCCESS) {
3958 if (err == DB_DUPLICATE_KEY) {
3960 fputs(
" InnoDB: Error; possible reasons:\n"
3961 "InnoDB: 1) Table rename would cause"
3962 " two FOREIGN KEY constraints\n"
3963 "InnoDB: to have the same internal name"
3964 " in case-insensitive comparison.\n"
3965 "InnoDB: 2) table ", stderr);
3967 fputs(
" exists in the InnoDB internal data\n"
3968 "InnoDB: dictionary though MySQL is"
3969 " trying to rename table ", stderr);
3972 "InnoDB: Have you deleted the .frm file"
3973 " and not used DROP TABLE?\n"
3974 "InnoDB: You can look for further help from\n"
3975 "InnoDB: " REFMAN
"innodb-troubleshooting.html\n"
3976 "InnoDB: If table ", stderr);
3978 fputs(
" is a temporary table #sql..., then"
3980 "InnoDB: there are still queries running"
3981 " on the table, and it will be\n"
3982 "InnoDB: dropped automatically when"
3983 " the queries end.\n"
3984 "InnoDB: You can drop the orphaned table"
3985 " inside InnoDB by\n"
3986 "InnoDB: creating an InnoDB table with"
3987 " the same name in another\n"
3988 "InnoDB: database and copying the .frm file"
3989 " to the current database.\n"
3990 "InnoDB: Then MySQL thinks the table exists,"
3991 " and DROP TABLE will\n"
3992 "InnoDB: succeed.\n", stderr);
4001 if (!dict_table_rename_in_cache(table, new_name,
4012 err = dict_load_foreigns(
4013 new_name, FALSE, !old_is_tmp || trx->check_foreigns);
4015 if (err != DB_SUCCESS) {
4019 fputs(
" InnoDB: Error: in ALTER TABLE ",
4023 "InnoDB: has or is referenced"
4024 " in foreign key constraints\n"
4025 "InnoDB: which are not compatible"
4026 " with the new table definition.\n",
4029 fputs(
" InnoDB: Error: in RENAME TABLE"
4034 "InnoDB: is referenced in"
4035 " foreign key constraints\n"
4036 "InnoDB: which are not compatible"
4037 " with the new table definition.\n",
4041 ut_a(dict_table_rename_in_cache(table,
4055 if (UNIV_LIKELY_NULL(heap)) {
4080 ulint matched_fields;
4081 ulint matched_bytes;
4087 ibool contains_null;
4092 ulint offsets_[REC_OFFS_NORMAL_SIZE];
4094 rec_offs_init(offsets_);
4098 buf =
static_cast<byte *
>(mem_alloc(UNIV_PAGE_SIZE));
4118 fputs(
" InnoDB: Warning: CHECK TABLE on ", stderr);
4119 dict_index_name_print(stderr, prebuilt->
trx, index);
4120 fprintf(stderr,
" returned %lu\n", ret);
4122 case DB_END_OF_INDEX:
4130 *n_rows = *n_rows + 1;
4138 offsets = rec_get_offsets(rec, index, offsets_,
4139 ULINT_UNDEFINED, &heap);
4141 if (prev_entry != NULL) {
4148 contains_null = FALSE;
4157 dtuple_get_nth_field(prev_entry, i))) {
4159 contains_null = TRUE;
4164 fputs(
"InnoDB: index records in a wrong order in ",
4167 dict_index_name_print(stderr,
4168 prebuilt->
trx, index);
4170 "InnoDB: prev record ", stderr);
4171 dtuple_print(stderr, prev_entry);
4173 "InnoDB: record ", stderr);
4183 fputs(
"InnoDB: duplicate key in ", stderr);
4194 if (UNIV_UNLIKELY(offsets != offsets_)) {
4199 offsets =
static_cast<ulint *
>(
mem_heap_dup(tmp_heap, offsets, size));
4208 if (UNIV_LIKELY_NULL(tmp_heap)) {
4231 name = strchr(table_name,
'/');
4234 len = strlen(name) + 1;
4236 if (STR_EQ(name, len, S_innodb_monitor)
4237 || STR_EQ(name, len, S_innodb_lock_monitor)
4238 || STR_EQ(name, len, S_innodb_tablespace_monitor)
4239 || STR_EQ(name, len, S_innodb_table_monitor)
4240 || STR_EQ(name, len, S_innodb_mem_validate)) {