1 /*****************************************************************************
3 Copyright (c) 2000, 2013, Oracle and/or its affiliates. All Rights Reserved.
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free Software
7 Foundation; version 2 of the License.
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
17 *****************************************************************************/
19 /**************************************************//**
21 Interface between Innobase row operations and MySQL.
22 Contains also create table and other data dictionary operations.
24 Created 9/17/2000 Heikki Tuuri
25 *******************************************************/
27 #include "row0mysql.h"
30 #include "row0mysql.ic"
34 #include "row0merge.h"
39 #include "pars0pars.h"
40 #include "dict0dict.h"
41 #include "dict0crea.h"
42 #include "dict0load.h"
43 #include "dict0boot.h"
45 #include "trx0purge.h"
48 #include "lock0lock.h"
53 #include "ibuf0ibuf.h"
54 #include "ha_prototypes.h"
57 /* error LNK2001: unresolved external symbol _debug_sync_C_callback_ptr */
58 # define DEBUG_SYNC_C(dummy) ((void) 0)
60 # include "m_string.h" /* for my_sys.h */
61 # include "my_sys.h" /* DEBUG_SYNC_C */
64 /** Provide optional 4.x backwards compatibility for 5.0 and above */
65 UNIV_INTERN ibool row_rollback_on_timeout
= FALSE
;
67 /** Chain node of the list of tables to drop in the background. */
68 typedef struct row_mysql_drop_struct row_mysql_drop_t
;
70 /** Chain node of the list of tables to drop in the background. */
71 struct row_mysql_drop_struct
{
72 char* table_name
; /*!< table name */
73 UT_LIST_NODE_T(row_mysql_drop_t
)row_mysql_drop_list
;
74 /*!< list chain node */
77 /** @brief List of tables we should drop in background.
79 ALTER TABLE in MySQL requires that the table handler can drop the
80 table in background when there are no queries to it any
81 more. Protected by kernel_mutex. */
82 static UT_LIST_BASE_NODE_T(row_mysql_drop_t
) row_mysql_drop_list
;
83 /** Flag: has row_mysql_drop_list been initialized? */
84 static ibool row_mysql_drop_list_inited
= FALSE
;
86 /** Magic table names for invoking various monitor threads */
88 static const char S_innodb_monitor
[] = "innodb_monitor";
89 static const char S_innodb_lock_monitor
[] = "innodb_lock_monitor";
90 static const char S_innodb_tablespace_monitor
[] = "innodb_tablespace_monitor";
91 static const char S_innodb_table_monitor
[] = "innodb_table_monitor";
92 static const char S_innodb_mem_validate
[] = "innodb_mem_validate";
95 /** Evaluates to true if str1 equals str2_onstack, used for comparing
96 the magic table names.
97 @param str1 in: string to compare
98 @param str1_len in: length of str1, in bytes, including terminating NUL
99 @param str2_onstack in: char[] array containing a NUL terminated string
100 @return TRUE if str1 equals str2_onstack */
101 #define STR_EQ(str1, str1_len, str2_onstack) \
102 ((str1_len) == sizeof(str2_onstack) \
103 && memcmp(str1, str2_onstack, sizeof(str2_onstack)) == 0)
105 /*******************************************************************//**
106 Determine if the given name is a name reserved for MySQL system tables.
107 @return TRUE if name is a MySQL system table name */
110 row_mysql_is_system_table(
111 /*======================*/
114 if (strncmp(name
, "mysql/", 6) != 0) {
119 return(0 == strcmp(name
+ 6, "host")
120 || 0 == strcmp(name
+ 6, "user")
121 || 0 == strcmp(name
+ 6, "db"));
124 /*********************************************************************//**
125 If a table is not yet in the drop list, adds the table to the list of tables
126 which the master thread drops in background. We need this on Unix because in
127 ALTER TABLE MySQL may call drop table even if the table has running queries on
128 it. Also, if there are running foreign key checks on the table, we drop the
130 @return TRUE if the table was not yet in the drop list, and was added there */
133 row_add_table_to_background_drop_list(
134 /*==================================*/
135 const char* name
); /*!< in: table name */
137 /*******************************************************************//**
138 Delays an INSERT, DELETE or UPDATE operation if the purge is lagging. */
141 row_mysql_delay_if_needed(void)
142 /*===========================*/
144 if (srv_dml_needed_delay
) {
145 os_thread_sleep(srv_dml_needed_delay
);
149 /*******************************************************************//**
150 Frees the blob heap in prebuilt when no longer needed. */
153 row_mysql_prebuilt_free_blob_heap(
154 /*==============================*/
155 row_prebuilt_t
* prebuilt
) /*!< in: prebuilt struct of a
156 ha_innobase:: table handle */
158 mem_heap_free(prebuilt
->blob_heap
);
159 prebuilt
->blob_heap
= NULL
;
162 /*******************************************************************//**
163 Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL row
165 @return pointer to the data, we skip the 1 or 2 bytes at the start
166 that are used to store the len */
169 row_mysql_store_true_var_len(
170 /*=========================*/
171 byte
* dest
, /*!< in: where to store */
172 ulint len
, /*!< in: length, must fit in two bytes */
173 ulint lenlen
) /*!< in: storage length of len: either 1 or 2 bytes */
176 ut_a(len
< 256 * 256);
178 mach_write_to_2_little_endian(dest
, len
);
186 mach_write_to_1(dest
, len
);
191 /*******************************************************************//**
192 Reads a >= 5.0.3 format true VARCHAR length, in the MySQL row format, and
193 returns a pointer to the data.
194 @return pointer to the data, we skip the 1 or 2 bytes at the start
195 that are used to store the len */
198 row_mysql_read_true_varchar(
199 /*========================*/
200 ulint
* len
, /*!< out: variable-length field length */
201 const byte
* field
, /*!< in: field in the MySQL format */
202 ulint lenlen
) /*!< in: storage length of len: either 1
206 *len
= mach_read_from_2_little_endian(field
);
213 *len
= mach_read_from_1(field
);
218 /*******************************************************************//**
219 Stores a reference to a BLOB in the MySQL format. */
222 row_mysql_store_blob_ref(
223 /*=====================*/
224 byte
* dest
, /*!< in: where to store */
225 ulint col_len
,/*!< in: dest buffer size: determines into
226 how many bytes the BLOB length is stored,
227 the space for the length may vary from 1
229 const void* data
, /*!< in: BLOB data; if the value to store
230 is SQL NULL this should be NULL pointer */
231 ulint len
) /*!< in: BLOB length; if the value to store
232 is SQL NULL this should be 0; remember
233 also to set the NULL bit in the MySQL record
236 /* MySQL might assume the field is set to zero except the length and
237 the pointer fields */
239 memset(dest
, '\0', col_len
);
241 /* In dest there are 1 - 4 bytes reserved for the BLOB length,
242 and after that 8 bytes reserved for the pointer to the data.
243 In 32-bit architectures we only use the first 4 bytes of the pointer
246 ut_a(col_len
- 8 > 1 || len
< 256);
247 ut_a(col_len
- 8 > 2 || len
< 256 * 256);
248 ut_a(col_len
- 8 > 3 || len
< 256 * 256 * 256);
250 mach_write_to_n_little_endian(dest
, col_len
- 8, len
);
252 memcpy(dest
+ col_len
- 8, &data
, sizeof data
);
255 /*******************************************************************//**
256 Reads a reference to a BLOB in the MySQL format.
257 @return pointer to BLOB data */
260 row_mysql_read_blob_ref(
261 /*====================*/
262 ulint
* len
, /*!< out: BLOB length */
263 const byte
* ref
, /*!< in: BLOB reference in the
265 ulint col_len
) /*!< in: BLOB reference length
270 *len
= mach_read_from_n_little_endian(ref
, col_len
- 8);
272 memcpy(&data
, ref
+ col_len
- 8, sizeof data
);
277 /**************************************************************//**
278 Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
279 The counterpart of this function is row_sel_field_store_in_mysql_format() in
281 @return up to which byte we used buf in the conversion */
284 row_mysql_store_col_in_innobase_format(
285 /*===================================*/
286 dfield_t
* dfield
, /*!< in/out: dfield where dtype
287 information must be already set when
288 this function is called! */
289 byte
* buf
, /*!< in/out: buffer for a converted
290 integer value; this must be at least
291 col_len long then! */
292 ibool row_format_col
, /*!< TRUE if the mysql_data is from
293 a MySQL row, FALSE if from a MySQL
295 in MySQL, a true VARCHAR storage
296 format differs in a row and in a
297 key value: in a key value the length
298 is always stored in 2 bytes! */
299 const byte
* mysql_data
, /*!< in: MySQL column value, not
300 SQL NULL; NOTE that dfield may also
301 get a pointer to mysql_data,
302 therefore do not discard this as long
303 as dfield is used! */
304 ulint col_len
, /*!< in: MySQL column length; NOTE that
305 this is the storage length of the
306 column in the MySQL format row, not
307 necessarily the length of the actual
308 payload data; if the column is a true
309 VARCHAR then this is irrelevant */
310 ulint comp
) /*!< in: nonzero=compact format */
312 const byte
* ptr
= mysql_data
;
313 const dtype_t
* dtype
;
317 dtype
= dfield_get_type(dfield
);
321 if (type
== DATA_INT
) {
322 /* Store integer data in Innobase in a big-endian format,
323 sign bit negated if the data is a signed integer. In MySQL,
324 integers are stored in a little-endian format. */
326 byte
* p
= buf
+ col_len
;
337 if (!(dtype
->prtype
& DATA_UNSIGNED
)) {
344 } else if ((type
== DATA_VARCHAR
345 || type
== DATA_VARMYSQL
346 || type
== DATA_BINARY
)) {
348 if (dtype_get_mysql_type(dtype
) == DATA_MYSQL_TRUE_VARCHAR
) {
349 /* The length of the actual data is stored to 1 or 2
350 bytes at the start of the field */
352 if (row_format_col
) {
353 if (dtype
->prtype
& DATA_LONG_TRUE_VARCHAR
) {
359 /* In a MySQL key value, lenlen is always 2 */
363 ptr
= row_mysql_read_true_varchar(&col_len
, mysql_data
,
366 /* Remove trailing spaces from old style VARCHAR
369 /* Handle UCS2 strings differently. */
370 ulint mbminlen
= dtype_get_mbminlen(dtype
);
376 /* Trim "half-chars", just in case. */
379 while (col_len
>= 2 && ptr
[col_len
- 2] == 0x00
380 && ptr
[col_len
- 1] == 0x20) {
387 && ptr
[col_len
- 1] == 0x20) {
392 } else if (comp
&& type
== DATA_MYSQL
393 && dtype_get_mbminlen(dtype
) == 1
394 && dtype_get_mbmaxlen(dtype
) > 1) {
395 /* In some cases we strip trailing spaces from UTF-8 and other
396 multibyte charsets, from FIXED-length CHAR columns, to save
397 space. UTF-8 would otherwise normally use 3 * the string length
398 bytes to store an ASCII string! */
400 /* We assume that this CHAR field is encoded in a
401 variable-length character set where spaces have
402 1:1 correspondence to 0x20 bytes, such as UTF-8.
404 Consider a CHAR(n) field, a field of n characters.
405 It will contain between n * mbminlen and n * mbmaxlen bytes.
406 We will try to truncate it to n bytes by stripping
407 space padding. If the field contains single-byte
408 characters only, it will be truncated to n characters.
409 Consider a CHAR(5) field containing the string ".a "
410 where "." denotes a 3-byte character represented by
411 the bytes "$%&". After our stripping, the string will
412 be stored as "$%&a " (5 bytes). The string ".abc "
413 will be stored as "$%&abc" (6 bytes).
415 The space padding will be restored in row0sel.c, function
416 row_sel_field_store_in_mysql_format(). */
420 ut_a(!(dtype_get_len(dtype
) % dtype_get_mbmaxlen(dtype
)));
422 n_chars
= dtype_get_len(dtype
) / dtype_get_mbmaxlen(dtype
);
424 /* Strip space padding. */
425 while (col_len
> n_chars
&& ptr
[col_len
- 1] == 0x20) {
428 } else if (type
== DATA_BLOB
&& row_format_col
) {
430 ptr
= row_mysql_read_blob_ref(&col_len
, mysql_data
, col_len
);
433 dfield_set_data(dfield
, ptr
, col_len
);
438 /**************************************************************//**
439 Convert a row in the MySQL format to a row in the Innobase format. Note that
440 the function to convert a MySQL format key value to an InnoDB dtuple is
441 row_sel_convert_mysql_key_to_innobase() in row0sel.c. */
444 row_mysql_convert_row_to_innobase(
445 /*==============================*/
446 dtuple_t
* row
, /*!< in/out: Innobase row where the
447 field type information is already
449 row_prebuilt_t
* prebuilt
, /*!< in: prebuilt struct where template
450 must be of type ROW_MYSQL_WHOLE_ROW */
451 byte
* mysql_rec
) /*!< in: row in the MySQL format;
452 NOTE: do not discard as long as
453 row is used, as row may contain
454 pointers to this record! */
456 const mysql_row_templ_t
*templ
;
460 ut_ad(prebuilt
->template_type
== ROW_MYSQL_WHOLE_ROW
);
461 ut_ad(prebuilt
->mysql_template
);
463 for (i
= 0; i
< prebuilt
->n_template
; i
++) {
465 templ
= prebuilt
->mysql_template
+ i
;
466 dfield
= dtuple_get_nth_field(row
, i
);
468 if (templ
->mysql_null_bit_mask
!= 0) {
469 /* Column may be SQL NULL */
471 if (mysql_rec
[templ
->mysql_null_byte_offset
]
472 & (byte
) (templ
->mysql_null_bit_mask
)) {
476 dfield_set_null(dfield
);
482 row_mysql_store_col_in_innobase_format(
484 prebuilt
->ins_upd_rec_buff
+ templ
->mysql_col_offset
,
485 TRUE
, /* MySQL row format data */
486 mysql_rec
+ templ
->mysql_col_offset
,
487 templ
->mysql_col_len
,
488 dict_table_is_comp(prebuilt
->table
));
494 /****************************************************************//**
495 Handles user errors and lock waits detected by the database engine.
496 @return TRUE if it was a lock wait and we should continue running the
497 query thread and in that case the thr is ALREADY in the running state. */
500 row_mysql_handle_errors(
501 /*====================*/
502 ulint
* new_err
,/*!< out: possible new error encountered in
503 lock wait, or if no new error, the value
504 of trx->error_state at the entry of this
506 trx_t
* trx
, /*!< in: transaction */
507 que_thr_t
* thr
, /*!< in: query thread */
508 trx_savept_t
* savept
) /*!< in: savepoint or NULL */
513 err
= trx
->error_state
;
515 ut_a(err
!= DB_SUCCESS
);
517 trx
->error_state
= DB_SUCCESS
;
520 case DB_LOCK_WAIT_TIMEOUT
:
521 if (row_rollback_on_timeout
) {
522 trx_general_rollback_for_mysql(trx
, NULL
);
526 case DB_DUPLICATE_KEY
:
527 case DB_FOREIGN_DUPLICATE_KEY
:
528 case DB_TOO_BIG_RECORD
:
529 case DB_ROW_IS_REFERENCED
:
530 case DB_NO_REFERENCED_ROW
:
531 case DB_CANNOT_ADD_CONSTRAINT
:
532 case DB_TOO_MANY_CONCURRENT_TRXS
:
533 case DB_OUT_OF_FILE_SPACE
:
536 /* Roll back the latest, possibly incomplete
537 insertion or update */
539 trx_general_rollback_for_mysql(trx
, savept
);
541 /* MySQL will roll back the latest SQL statement */
544 srv_suspend_mysql_thread(thr
);
546 if (trx
->error_state
!= DB_SUCCESS
) {
547 que_thr_stop_for_mysql(thr
);
549 goto handle_new_error
;
557 case DB_LOCK_TABLE_FULL
:
558 /* Roll back the whole transaction; this resolution was added
559 to version 3.23.43 */
561 trx_general_rollback_for_mysql(trx
, NULL
);
564 case DB_MUST_GET_MORE_FILE_SPACE
:
565 fputs("InnoDB: The database cannot continue"
566 " operation because of\n"
567 "InnoDB: lack of space. You must add"
568 " a new data file to\n"
569 "InnoDB: my.cnf and restart the database.\n", stderr
);
574 fputs("InnoDB: We detected index corruption"
575 " in an InnoDB type table.\n"
576 "InnoDB: You have to dump + drop + reimport"
577 " the table or, in\n"
578 "InnoDB: a case of widespread corruption,"
580 "InnoDB: tables and recreate the"
581 " whole InnoDB tablespace.\n"
582 "InnoDB: If the mysqld server crashes"
583 " after the startup or when\n"
584 "InnoDB: you dump the tables, look at\n"
585 "InnoDB: " REFMAN
"forcing-innodb-recovery.html"
586 " for help.\n", stderr
);
588 case DB_FOREIGN_EXCEED_MAX_CASCADE
:
589 fprintf(stderr
, "InnoDB: Cannot delete/update rows with"
590 " cascading foreign key constraints that exceed max"
592 "Please drop excessive foreign constraints"
593 " and try again\n", (ulong
) DICT_FK_MAX_RECURSIVE_LOAD
);
596 fprintf(stderr
, "InnoDB: unknown error code %lu\n",
601 if (trx
->error_state
!= DB_SUCCESS
) {
602 *new_err
= trx
->error_state
;
607 trx
->error_state
= DB_SUCCESS
;
612 /********************************************************************//**
613 Create a prebuilt struct for a MySQL table handle.
614 @return own: a prebuilt struct */
619 dict_table_t
* table
) /*!< in: Innobase table handle */
621 row_prebuilt_t
* prebuilt
;
623 dict_index_t
* clust_index
;
627 heap
= mem_heap_create(sizeof *prebuilt
+ 128);
629 prebuilt
= mem_heap_zalloc(heap
, sizeof *prebuilt
);
631 prebuilt
->magic_n
= ROW_PREBUILT_ALLOCATED
;
632 prebuilt
->magic_n2
= ROW_PREBUILT_ALLOCATED
;
634 prebuilt
->table
= table
;
636 prebuilt
->sql_stat_start
= TRUE
;
637 prebuilt
->heap
= heap
;
639 prebuilt
->pcur
= btr_pcur_create_for_mysql();
640 prebuilt
->clust_pcur
= btr_pcur_create_for_mysql();
642 prebuilt
->select_lock_type
= LOCK_NONE
;
643 prebuilt
->stored_select_lock_type
= 99999999;
644 UNIV_MEM_INVALID(&prebuilt
->stored_select_lock_type
,
645 sizeof prebuilt
->stored_select_lock_type
);
647 prebuilt
->search_tuple
= dtuple_create(
648 heap
, 2 * dict_table_get_n_cols(table
));
650 clust_index
= dict_table_get_first_index(table
);
652 /* Make sure that search_tuple is long enough for clustered index */
653 ut_a(2 * dict_table_get_n_cols(table
) >= clust_index
->n_fields
);
655 ref_len
= dict_index_get_n_unique(clust_index
);
657 ref
= dtuple_create(heap
, ref_len
);
659 dict_index_copy_types(ref
, clust_index
, ref_len
);
661 prebuilt
->clust_ref
= ref
;
663 prebuilt
->autoinc_error
= 0;
664 prebuilt
->autoinc_offset
= 0;
666 /* Default to 1, we will set the actual value later in
667 ha_innobase::get_auto_increment(). */
668 prebuilt
->autoinc_increment
= 1;
670 prebuilt
->autoinc_last_value
= 0;
675 /********************************************************************//**
676 Free a prebuilt struct for a MySQL table handle. */
681 row_prebuilt_t
* prebuilt
, /*!< in, own: prebuilt struct */
682 ibool dict_locked
) /*!< in: TRUE=data dictionary locked */
687 (prebuilt
->magic_n
!= ROW_PREBUILT_ALLOCATED
688 || prebuilt
->magic_n2
!= ROW_PREBUILT_ALLOCATED
)) {
691 "InnoDB: Error: trying to free a corrupt\n"
692 "InnoDB: table handle. Magic n %lu,"
693 " magic n2 %lu, table name ",
694 (ulong
) prebuilt
->magic_n
,
695 (ulong
) prebuilt
->magic_n2
);
696 ut_print_name(stderr
, NULL
, TRUE
, prebuilt
->table
->name
);
699 mem_analyze_corruption(prebuilt
);
704 prebuilt
->magic_n
= ROW_PREBUILT_FREED
;
705 prebuilt
->magic_n2
= ROW_PREBUILT_FREED
;
707 btr_pcur_free_for_mysql(prebuilt
->pcur
);
708 btr_pcur_free_for_mysql(prebuilt
->clust_pcur
);
710 if (prebuilt
->mysql_template
) {
711 mem_free(prebuilt
->mysql_template
);
714 if (prebuilt
->ins_graph
) {
715 que_graph_free_recursive(prebuilt
->ins_graph
);
718 if (prebuilt
->sel_graph
) {
719 que_graph_free_recursive(prebuilt
->sel_graph
);
722 if (prebuilt
->upd_graph
) {
723 que_graph_free_recursive(prebuilt
->upd_graph
);
726 if (prebuilt
->blob_heap
) {
727 mem_heap_free(prebuilt
->blob_heap
);
730 if (prebuilt
->old_vers_heap
) {
731 mem_heap_free(prebuilt
->old_vers_heap
);
734 for (i
= 0; i
< MYSQL_FETCH_CACHE_SIZE
; i
++) {
735 if (prebuilt
->fetch_cache
[i
] != NULL
) {
737 if ((ROW_PREBUILT_FETCH_MAGIC_N
!= mach_read_from_4(
738 (prebuilt
->fetch_cache
[i
]) - 4))
739 || (ROW_PREBUILT_FETCH_MAGIC_N
!= mach_read_from_4(
740 (prebuilt
->fetch_cache
[i
])
741 + prebuilt
->mysql_row_len
))) {
742 fputs("InnoDB: Error: trying to free"
743 " a corrupt fetch buffer.\n", stderr
);
745 mem_analyze_corruption(
746 prebuilt
->fetch_cache
[i
]);
751 mem_free((prebuilt
->fetch_cache
[i
]) - 4);
755 dict_table_decrement_handle_count(prebuilt
->table
, dict_locked
);
757 mem_heap_free(prebuilt
->heap
);
760 /*********************************************************************//**
761 Updates the transaction pointers in query graphs stored in the prebuilt
765 row_update_prebuilt_trx(
766 /*====================*/
767 row_prebuilt_t
* prebuilt
, /*!< in/out: prebuilt struct
769 trx_t
* trx
) /*!< in: transaction handle */
771 if (trx
->magic_n
!= TRX_MAGIC_N
) {
773 "InnoDB: Error: trying to use a corrupt\n"
774 "InnoDB: trx handle. Magic n %lu\n",
775 (ulong
) trx
->magic_n
);
777 mem_analyze_corruption(trx
);
782 if (prebuilt
->magic_n
!= ROW_PREBUILT_ALLOCATED
) {
784 "InnoDB: Error: trying to use a corrupt\n"
785 "InnoDB: table handle. Magic n %lu, table name ",
786 (ulong
) prebuilt
->magic_n
);
787 ut_print_name(stderr
, trx
, TRUE
, prebuilt
->table
->name
);
790 mem_analyze_corruption(prebuilt
);
797 if (prebuilt
->ins_graph
) {
798 prebuilt
->ins_graph
->trx
= trx
;
801 if (prebuilt
->upd_graph
) {
802 prebuilt
->upd_graph
->trx
= trx
;
805 if (prebuilt
->sel_graph
) {
806 prebuilt
->sel_graph
->trx
= trx
;
810 /*********************************************************************//**
811 Gets pointer to a prebuilt dtuple used in insertions. If the insert graph
812 has not yet been built in the prebuilt struct, then this function first
814 @return prebuilt dtuple; the column type information is also set in it */
817 row_get_prebuilt_insert_row(
818 /*========================*/
819 row_prebuilt_t
* prebuilt
) /*!< in: prebuilt struct in MySQL
824 dict_table_t
* table
= prebuilt
->table
;
826 ut_ad(prebuilt
&& table
&& prebuilt
->trx
);
828 if (prebuilt
->ins_node
== NULL
) {
830 /* Not called before for this handle: create an insert node
831 and query graph to the prebuilt struct */
833 node
= ins_node_create(INS_DIRECT
, table
, prebuilt
->heap
);
835 prebuilt
->ins_node
= node
;
837 if (prebuilt
->ins_upd_rec_buff
== NULL
) {
838 prebuilt
->ins_upd_rec_buff
= mem_heap_alloc(
839 prebuilt
->heap
, prebuilt
->mysql_row_len
);
842 row
= dtuple_create(prebuilt
->heap
,
843 dict_table_get_n_cols(table
));
845 dict_table_copy_types(row
, table
);
847 ins_node_set_new_row(node
, row
);
849 prebuilt
->ins_graph
= que_node_get_parent(
850 pars_complete_graph_for_exec(node
,
853 prebuilt
->ins_graph
->state
= QUE_FORK_ACTIVE
;
856 return(prebuilt
->ins_node
->row
);
859 /*********************************************************************//**
860 Updates the table modification counter and calculates new estimates
861 for table and index statistics if necessary. */
864 row_update_statistics_if_needed(
865 /*============================*/
866 dict_table_t
* table
) /*!< in: table */
870 counter
= table
->stat_modified_counter
;
872 table
->stat_modified_counter
= counter
+ 1;
874 /* Calculate new statistics if 1 / 16 of table has been modified
875 since the last time a statistics batch was run, or if
876 stat_modified_counter > 2 000 000 000 (to avoid wrap-around).
877 We calculate statistics at most every 16th round, since we may have
878 a counter table which is very small and updated very often. */
880 if (counter
> 2000000000
881 || ((ib_int64_t
)counter
> 16 + table
->stat_n_rows
/ 16)) {
883 dict_update_statistics(table
, FALSE
/* update even if stats
888 /*********************************************************************//**
889 Unlocks AUTO_INC type locks that were possibly reserved by a trx. This
890 function should be called at the the end of an SQL statement, by the
891 connection thread that owns the transaction (trx->mysql_thd). */
894 row_unlock_table_autoinc_for_mysql(
895 /*===============================*/
896 trx_t
* trx
) /*!< in/out: transaction */
898 if (lock_trx_holds_autoinc_locks(trx
)) {
899 mutex_enter(&kernel_mutex
);
901 lock_release_autoinc_locks(trx
);
903 mutex_exit(&kernel_mutex
);
907 /*********************************************************************//**
908 Sets an AUTO_INC type lock on the table mentioned in prebuilt. The
909 AUTO_INC lock gives exclusive access to the auto-inc counter of the
910 table. The lock is reserved only for the duration of an SQL statement.
911 It is not compatible with another AUTO_INC or exclusive lock on the
913 @return error code or DB_SUCCESS */
916 row_lock_table_autoinc_for_mysql(
917 /*=============================*/
918 row_prebuilt_t
* prebuilt
) /*!< in: prebuilt struct in the MySQL
921 trx_t
* trx
= prebuilt
->trx
;
922 ins_node_t
* node
= prebuilt
->ins_node
;
923 const dict_table_t
* table
= prebuilt
->table
;
929 ut_ad(trx
->mysql_thread_id
== os_thread_get_curr_id());
931 /* If we already hold an AUTOINC lock on the table then do nothing.
932 Note: We peek at the value of the current owner without acquiring
933 the kernel mutex. **/
934 if (trx
== table
->autoinc_trx
) {
939 trx
->op_info
= "setting auto-inc lock";
942 row_get_prebuilt_insert_row(prebuilt
);
943 node
= prebuilt
->ins_node
;
946 /* We use the insert query graph as the dummy graph needed
947 in the lock module call */
949 thr
= que_fork_get_first_thr(prebuilt
->ins_graph
);
951 que_thr_move_to_run_state_for_mysql(thr
, trx
);
954 thr
->run_node
= node
;
955 thr
->prev_node
= node
;
957 /* It may be that the current session has not yet started
958 its transaction, or it has been committed: */
960 trx_start_if_not_started(trx
);
962 err
= lock_table(0, prebuilt
->table
, LOCK_AUTO_INC
, thr
);
964 trx
->error_state
= err
;
966 if (err
!= DB_SUCCESS
) {
967 que_thr_stop_for_mysql(thr
);
969 was_lock_wait
= row_mysql_handle_errors(&err
, trx
, thr
, NULL
);
980 que_thr_stop_for_mysql_no_error(thr
, trx
);
987 /*********************************************************************//**
988 Sets a table lock on the table mentioned in prebuilt.
989 @return error code or DB_SUCCESS */
992 row_lock_table_for_mysql(
993 /*=====================*/
994 row_prebuilt_t
* prebuilt
, /*!< in: prebuilt struct in the MySQL
996 dict_table_t
* table
, /*!< in: table to lock, or NULL
997 if prebuilt->table should be
999 prebuilt->select_lock_type */
1000 ulint mode
) /*!< in: lock mode of table
1001 (ignored if table==NULL) */
1003 trx_t
* trx
= prebuilt
->trx
;
1006 ibool was_lock_wait
;
1009 ut_ad(trx
->mysql_thread_id
== os_thread_get_curr_id());
1011 trx
->op_info
= "setting table lock";
1013 if (prebuilt
->sel_graph
== NULL
) {
1014 /* Build a dummy select query graph */
1015 row_prebuild_sel_graph(prebuilt
);
1018 /* We use the select query graph as the dummy graph needed
1019 in the lock module call */
1021 thr
= que_fork_get_first_thr(prebuilt
->sel_graph
);
1023 que_thr_move_to_run_state_for_mysql(thr
, trx
);
1026 thr
->run_node
= thr
;
1027 thr
->prev_node
= thr
->common
.parent
;
1029 /* It may be that the current session has not yet started
1030 its transaction, or it has been committed: */
1032 trx_start_if_not_started(trx
);
1035 err
= lock_table(0, table
, mode
, thr
);
1037 err
= lock_table(0, prebuilt
->table
,
1038 prebuilt
->select_lock_type
, thr
);
1041 trx
->error_state
= err
;
1043 if (err
!= DB_SUCCESS
) {
1044 que_thr_stop_for_mysql(thr
);
1046 was_lock_wait
= row_mysql_handle_errors(&err
, trx
, thr
, NULL
);
1048 if (was_lock_wait
) {
1057 que_thr_stop_for_mysql_no_error(thr
, trx
);
1064 /*********************************************************************//**
1065 Does an insert for MySQL.
1066 @return error code or DB_SUCCESS */
1069 row_insert_for_mysql(
1070 /*=================*/
1071 byte
* mysql_rec
, /*!< in: row in the MySQL format */
1072 row_prebuilt_t
* prebuilt
) /*!< in: prebuilt struct in MySQL
1075 trx_savept_t savept
;
1078 ibool was_lock_wait
;
1079 trx_t
* trx
= prebuilt
->trx
;
1080 ins_node_t
* node
= prebuilt
->ins_node
;
1083 ut_ad(trx
->mysql_thread_id
== os_thread_get_curr_id());
1085 if (prebuilt
->table
->ibd_file_missing
) {
1086 ut_print_timestamp(stderr
);
1087 fprintf(stderr
, " InnoDB: Error:\n"
1088 "InnoDB: MySQL is trying to use a table handle"
1089 " but the .ibd file for\n"
1090 "InnoDB: table %s does not exist.\n"
1091 "InnoDB: Have you deleted the .ibd file"
1092 " from the database directory under\n"
1093 "InnoDB: the MySQL datadir, or have you"
1094 " used DISCARD TABLESPACE?\n"
1095 "InnoDB: Look from\n"
1096 "InnoDB: " REFMAN
"innodb-troubleshooting.html\n"
1097 "InnoDB: how you can resolve the problem.\n",
1098 prebuilt
->table
->name
);
1102 if (UNIV_UNLIKELY(prebuilt
->magic_n
!= ROW_PREBUILT_ALLOCATED
)) {
1104 "InnoDB: Error: trying to free a corrupt\n"
1105 "InnoDB: table handle. Magic n %lu, table name ",
1106 (ulong
) prebuilt
->magic_n
);
1107 ut_print_name(stderr
, trx
, TRUE
, prebuilt
->table
->name
);
1110 mem_analyze_corruption(prebuilt
);
1115 if (UNIV_UNLIKELY(srv_created_new_raw
|| srv_force_recovery
)) {
1116 fputs("InnoDB: A new raw disk partition was initialized or\n"
1117 "InnoDB: innodb_force_recovery is on: we do not allow\n"
1118 "InnoDB: database modifications by the user. Shut down\n"
1119 "InnoDB: mysqld and edit my.cnf so that"
1120 " newraw is replaced\n"
1121 "InnoDB: with raw, and innodb_force_... is removed.\n",
1127 trx
->op_info
= "inserting";
1129 row_mysql_delay_if_needed();
1131 trx_start_if_not_started(trx
);
1134 row_get_prebuilt_insert_row(prebuilt
);
1135 node
= prebuilt
->ins_node
;
1138 row_mysql_convert_row_to_innobase(node
->row
, prebuilt
, mysql_rec
);
1140 savept
= trx_savept_take(trx
);
1142 thr
= que_fork_get_first_thr(prebuilt
->ins_graph
);
1144 if (prebuilt
->sql_stat_start
) {
1145 node
->state
= INS_NODE_SET_IX_LOCK
;
1146 prebuilt
->sql_stat_start
= FALSE
;
1148 node
->state
= INS_NODE_ALLOC_ROW_ID
;
1151 que_thr_move_to_run_state_for_mysql(thr
, trx
);
1154 thr
->run_node
= node
;
1155 thr
->prev_node
= node
;
1159 err
= trx
->error_state
;
1161 if (err
!= DB_SUCCESS
) {
1162 que_thr_stop_for_mysql(thr
);
1164 /* TODO: what is this? */ thr
->lock_state
= QUE_THR_LOCK_ROW
;
1166 was_lock_wait
= row_mysql_handle_errors(&err
, trx
, thr
,
1168 thr
->lock_state
= QUE_THR_LOCK_NOLOCK
;
1170 if (was_lock_wait
) {
1179 que_thr_stop_for_mysql_no_error(thr
, trx
);
1181 prebuilt
->table
->stat_n_rows
++;
1183 srv_n_rows_inserted
++;
1185 if (prebuilt
->table
->stat_n_rows
== 0) {
1186 /* Avoid wrap-over */
1187 prebuilt
->table
->stat_n_rows
--;
1190 row_update_statistics_if_needed(prebuilt
->table
);
1196 /*********************************************************************//**
1197 Builds a dummy query graph used in selects. */
1200 row_prebuild_sel_graph(
1201 /*===================*/
1202 row_prebuilt_t
* prebuilt
) /*!< in: prebuilt struct in MySQL
1207 ut_ad(prebuilt
&& prebuilt
->trx
);
1209 if (prebuilt
->sel_graph
== NULL
) {
1211 node
= sel_node_create(prebuilt
->heap
);
1213 prebuilt
->sel_graph
= que_node_get_parent(
1214 pars_complete_graph_for_exec(node
,
1218 prebuilt
->sel_graph
->state
= QUE_FORK_ACTIVE
;
1222 /*********************************************************************//**
1223 Creates an query graph node of 'update' type to be used in the MySQL
1225 @return own: update node */
1228 row_create_update_node_for_mysql(
1229 /*=============================*/
1230 dict_table_t
* table
, /*!< in: table to update */
1231 mem_heap_t
* heap
) /*!< in: mem heap from which allocated */
1235 node
= upd_node_create(heap
);
1237 node
->in_mysql_interface
= TRUE
;
1238 node
->is_delete
= FALSE
;
1239 node
->searched_update
= FALSE
;
1240 node
->select
= NULL
;
1241 node
->pcur
= btr_pcur_create_for_mysql();
1242 node
->table
= table
;
1244 node
->update
= upd_create(dict_table_get_n_cols(table
), heap
);
1246 node
->update_n_fields
= dict_table_get_n_cols(table
);
1248 UT_LIST_INIT(node
->columns
);
1249 node
->has_clust_rec_x_lock
= TRUE
;
1250 node
->cmpl_info
= 0;
1252 node
->table_sym
= NULL
;
1253 node
->col_assign_list
= NULL
;
1258 /*********************************************************************//**
1259 Gets pointer to a prebuilt update vector used in updates. If the update
1260 graph has not yet been built in the prebuilt struct, then this function
1262 @return prebuilt update vector */
1265 row_get_prebuilt_update_vector(
1266 /*===========================*/
1267 row_prebuilt_t
* prebuilt
) /*!< in: prebuilt struct in MySQL
1270 dict_table_t
* table
= prebuilt
->table
;
1273 ut_ad(prebuilt
&& table
&& prebuilt
->trx
);
1275 if (prebuilt
->upd_node
== NULL
) {
1277 /* Not called before for this handle: create an update node
1278 and query graph to the prebuilt struct */
1280 node
= row_create_update_node_for_mysql(table
, prebuilt
->heap
);
1282 prebuilt
->upd_node
= node
;
1284 prebuilt
->upd_graph
= que_node_get_parent(
1285 pars_complete_graph_for_exec(node
,
1288 prebuilt
->upd_graph
->state
= QUE_FORK_ACTIVE
;
1291 return(prebuilt
->upd_node
->update
);
1294 /*********************************************************************//**
1295 Does an update or delete of a row for MySQL.
1296 @return error code or DB_SUCCESS */
1299 row_update_for_mysql(
1300 /*=================*/
1301 byte
* mysql_rec
, /*!< in: the row to be updated, in
1303 row_prebuilt_t
* prebuilt
) /*!< in: prebuilt struct in MySQL
1306 trx_savept_t savept
;
1309 ibool was_lock_wait
;
1310 dict_index_t
* clust_index
;
1311 /* ulint ref_len; */
1313 dict_table_t
* table
= prebuilt
->table
;
1314 trx_t
* trx
= prebuilt
->trx
;
1316 ut_ad(prebuilt
&& trx
);
1317 ut_ad(trx
->mysql_thread_id
== os_thread_get_curr_id());
1318 UT_NOT_USED(mysql_rec
);
1320 if (prebuilt
->table
->ibd_file_missing
) {
1321 ut_print_timestamp(stderr
);
1322 fprintf(stderr
, " InnoDB: Error:\n"
1323 "InnoDB: MySQL is trying to use a table handle"
1324 " but the .ibd file for\n"
1325 "InnoDB: table %s does not exist.\n"
1326 "InnoDB: Have you deleted the .ibd file"
1327 " from the database directory under\n"
1328 "InnoDB: the MySQL datadir, or have you"
1329 " used DISCARD TABLESPACE?\n"
1330 "InnoDB: Look from\n"
1331 "InnoDB: " REFMAN
"innodb-troubleshooting.html\n"
1332 "InnoDB: how you can resolve the problem.\n",
1333 prebuilt
->table
->name
);
1337 if (UNIV_UNLIKELY(prebuilt
->magic_n
!= ROW_PREBUILT_ALLOCATED
)) {
1339 "InnoDB: Error: trying to free a corrupt\n"
1340 "InnoDB: table handle. Magic n %lu, table name ",
1341 (ulong
) prebuilt
->magic_n
);
1342 ut_print_name(stderr
, trx
, TRUE
, prebuilt
->table
->name
);
1345 mem_analyze_corruption(prebuilt
);
1350 if (UNIV_UNLIKELY(srv_created_new_raw
|| srv_force_recovery
)) {
1351 fputs("InnoDB: A new raw disk partition was initialized or\n"
1352 "InnoDB: innodb_force_recovery is on: we do not allow\n"
1353 "InnoDB: database modifications by the user. Shut down\n"
1354 "InnoDB: mysqld and edit my.cnf so that newraw"
1356 "InnoDB: with raw, and innodb_force_... is removed.\n",
1362 DEBUG_SYNC_C("innodb_row_update_for_mysql_begin");
1364 trx
->op_info
= "updating or deleting";
1366 row_mysql_delay_if_needed();
1368 trx_start_if_not_started(trx
);
1370 node
= prebuilt
->upd_node
;
1372 clust_index
= dict_table_get_first_index(table
);
1374 if (prebuilt
->pcur
->btr_cur
.index
== clust_index
) {
1375 btr_pcur_copy_stored_position(node
->pcur
, prebuilt
->pcur
);
1377 btr_pcur_copy_stored_position(node
->pcur
,
1378 prebuilt
->clust_pcur
);
1381 ut_a(node
->pcur
->rel_pos
== BTR_PCUR_ON
);
1383 /* MySQL seems to call rnd_pos before updating each row it
1384 has cached: we can get the correct cursor position from
1385 prebuilt->pcur; NOTE that we cannot build the row reference
1386 from mysql_rec if the clustered index was automatically
1387 generated for the table: MySQL does not know anything about
1388 the row id used as the clustered index key */
1390 savept
= trx_savept_take(trx
);
1392 thr
= que_fork_get_first_thr(prebuilt
->upd_graph
);
1394 node
->state
= UPD_NODE_UPDATE_CLUSTERED
;
1396 ut_ad(!prebuilt
->sql_stat_start
);
1398 que_thr_move_to_run_state_for_mysql(thr
, trx
);
1401 thr
->run_node
= node
;
1402 thr
->prev_node
= node
;
1403 thr
->fk_cascade_depth
= 0;
1407 err
= trx
->error_state
;
1409 /* Reset fk_cascade_depth back to 0 */
1410 thr
->fk_cascade_depth
= 0;
1412 if (err
!= DB_SUCCESS
) {
1413 que_thr_stop_for_mysql(thr
);
1415 if (err
== DB_RECORD_NOT_FOUND
) {
1416 trx
->error_state
= DB_SUCCESS
;
1422 thr
->lock_state
= QUE_THR_LOCK_ROW
;
1423 was_lock_wait
= row_mysql_handle_errors(&err
, trx
, thr
,
1425 thr
->lock_state
= QUE_THR_LOCK_NOLOCK
;
1427 if (was_lock_wait
) {
1436 que_thr_stop_for_mysql_no_error(thr
, trx
);
1438 if (node
->is_delete
) {
1439 if (prebuilt
->table
->stat_n_rows
> 0) {
1440 prebuilt
->table
->stat_n_rows
--;
1443 srv_n_rows_deleted
++;
1445 srv_n_rows_updated
++;
1448 /* We update table statistics only if it is a DELETE or UPDATE
1449 that changes indexed columns, UPDATEs that change only non-indexed
1450 columns would not affect statistics. */
1451 if (node
->is_delete
|| !(node
->cmpl_info
& UPD_NODE_NO_ORD_CHANGE
)) {
1452 row_update_statistics_if_needed(prebuilt
->table
);
1460 /*********************************************************************//**
1461 This can only be used when srv_locks_unsafe_for_binlog is TRUE or this
1462 session is using a READ COMMITTED or READ UNCOMMITTED isolation level.
1463 Before calling this function row_search_for_mysql() must have
1464 initialized prebuilt->new_rec_locks to store the information which new
1465 record locks really were set. This function removes a newly set
1466 clustered index record lock under prebuilt->pcur or
1467 prebuilt->clust_pcur. Thus, this implements a 'mini-rollback' that
1468 releases the latest clustered index record lock we set.
1469 @return error code or DB_SUCCESS */
1472 row_unlock_for_mysql(
1473 /*=================*/
1474 row_prebuilt_t
* prebuilt
, /*!< in/out: prebuilt struct in MySQL
1476 ibool has_latches_on_recs
)/*!< in: TRUE if called so
1477 that we have the latches on
1478 the records under pcur and
1479 clust_pcur, and we do not need
1480 to reposition the cursors. */
1482 btr_pcur_t
* pcur
= prebuilt
->pcur
;
1483 btr_pcur_t
* clust_pcur
= prebuilt
->clust_pcur
;
1484 trx_t
* trx
= prebuilt
->trx
;
1486 ut_ad(prebuilt
&& trx
);
1487 ut_ad(trx
->mysql_thread_id
== os_thread_get_curr_id());
1490 (!srv_locks_unsafe_for_binlog
1491 && trx
->isolation_level
> TRX_ISO_READ_COMMITTED
)) {
1494 "InnoDB: Error: calling row_unlock_for_mysql though\n"
1495 "InnoDB: innodb_locks_unsafe_for_binlog is FALSE and\n"
1496 "InnoDB: this session is not using"
1497 " READ COMMITTED isolation level.\n");
1502 trx
->op_info
= "unlock_row";
1504 if (prebuilt
->new_rec_locks
>= 1) {
1507 dict_index_t
* index
;
1508 trx_id_t rec_trx_id
;
1513 /* Restore the cursor position and find the record */
1515 if (!has_latches_on_recs
) {
1516 btr_pcur_restore_position(BTR_SEARCH_LEAF
, pcur
, &mtr
);
1519 rec
= btr_pcur_get_rec(pcur
);
1520 index
= btr_pcur_get_btr_cur(pcur
)->index
;
1522 if (prebuilt
->new_rec_locks
>= 2) {
1523 /* Restore the cursor position and find the record
1524 in the clustered index. */
1526 if (!has_latches_on_recs
) {
1527 btr_pcur_restore_position(BTR_SEARCH_LEAF
,
1531 rec
= btr_pcur_get_rec(clust_pcur
);
1532 index
= btr_pcur_get_btr_cur(clust_pcur
)->index
;
1535 if (UNIV_UNLIKELY(!dict_index_is_clust(index
))) {
1536 /* This is not a clustered index record. We
1537 do not know how to unlock the record. */
1541 /* If the record has been modified by this
1542 transaction, do not unlock it. */
1544 if (index
->trx_id_offset
) {
1545 rec_trx_id
= trx_read_trx_id(rec
1546 + index
->trx_id_offset
);
1548 mem_heap_t
* heap
= NULL
;
1549 ulint offsets_
[REC_OFFS_NORMAL_SIZE
];
1550 ulint
* offsets
= offsets_
;
1552 rec_offs_init(offsets_
);
1553 offsets
= rec_get_offsets(rec
, index
, offsets
,
1554 ULINT_UNDEFINED
, &heap
);
1556 rec_trx_id
= row_get_rec_trx_id(rec
, index
, offsets
);
1558 if (UNIV_LIKELY_NULL(heap
)) {
1559 mem_heap_free(heap
);
1563 if (ut_dulint_cmp(rec_trx_id
, trx
->id
) != 0) {
1564 /* We did not update the record: unlock it */
1566 rec
= btr_pcur_get_rec(pcur
);
1567 index
= btr_pcur_get_btr_cur(pcur
)->index
;
1569 lock_rec_unlock(trx
, btr_pcur_get_block(pcur
),
1570 rec
, prebuilt
->select_lock_type
);
1572 if (prebuilt
->new_rec_locks
>= 2) {
1573 rec
= btr_pcur_get_rec(clust_pcur
);
1574 index
= btr_pcur_get_btr_cur(clust_pcur
)->index
;
1576 lock_rec_unlock(trx
,
1577 btr_pcur_get_block(clust_pcur
),
1579 prebuilt
->select_lock_type
);
1591 /**********************************************************************//**
1592 Does a cascaded delete or set null in a foreign key operation.
1593 @return error code or DB_SUCCESS */
1596 row_update_cascade_for_mysql(
1597 /*=========================*/
1598 que_thr_t
* thr
, /*!< in: query thread */
1599 upd_node_t
* node
, /*!< in: update node used in the cascade
1600 or set null operation */
1601 dict_table_t
* table
) /*!< in: table where we do the operation */
1606 trx
= thr_get_trx(thr
);
1608 /* Increment fk_cascade_depth to record the recursive call depth on
1609 a single update/delete that affects multiple tables chained
1610 together with foreign key relations. */
1611 thr
->fk_cascade_depth
++;
1613 if (thr
->fk_cascade_depth
> FK_MAX_CASCADE_DEL
) {
1614 return (DB_FOREIGN_EXCEED_MAX_CASCADE
);
1617 thr
->run_node
= node
;
1618 thr
->prev_node
= node
;
1622 /* The recursive call for cascading update/delete happens
1623 in above row_upd_step(), reset the counter once we come
1624 out of the recursive call, so it does not accumulate for
1625 different row deletes */
1626 thr
->fk_cascade_depth
= 0;
1628 err
= trx
->error_state
;
1630 /* Note that the cascade node is a subnode of another InnoDB
1631 query graph node. We do a normal lock wait in this node, but
1632 all errors are handled by the parent node. */
1634 if (err
== DB_LOCK_WAIT
) {
1635 /* Handle lock wait here */
1637 que_thr_stop_for_mysql(thr
);
1639 srv_suspend_mysql_thread(thr
);
1641 /* Note that a lock wait may also end in a lock wait timeout,
1642 or this transaction is picked as a victim in selective
1643 deadlock resolution */
1645 if (trx
->error_state
!= DB_SUCCESS
) {
1647 return(trx
->error_state
);
1650 /* Retry operation after a normal lock wait */
1655 if (err
!= DB_SUCCESS
) {
1660 if (node
->is_delete
) {
1661 if (table
->stat_n_rows
> 0) {
1662 table
->stat_n_rows
--;
1665 srv_n_rows_deleted
++;
1667 srv_n_rows_updated
++;
1670 row_update_statistics_if_needed(table
);
1675 /*********************************************************************//**
1676 Checks if a table is such that we automatically created a clustered
1677 index on it (on row id).
1678 @return TRUE if the clustered index was generated automatically */
1681 row_table_got_default_clust_index(
1682 /*==============================*/
1683 const dict_table_t
* table
) /*!< in: table */
1685 const dict_index_t
* clust_index
;
1687 clust_index
= dict_table_get_first_index(table
);
1689 return(dict_index_get_nth_col(clust_index
, 0)->mtype
== DATA_SYS
);
1692 /*********************************************************************//**
1693 Locks the data dictionary in shared mode from modifications, for performing
1694 foreign key check, rollback, or other operation invisible to MySQL. */
1697 row_mysql_freeze_data_dictionary_func(
1698 /*==================================*/
1699 trx_t
* trx
, /*!< in/out: transaction */
1700 const char* file
, /*!< in: file name */
1701 ulint line
) /*!< in: line number */
1703 ut_a(trx
->dict_operation_lock_mode
== 0);
1705 rw_lock_s_lock_func(&dict_operation_lock
, 0, file
, line
);
1707 trx
->dict_operation_lock_mode
= RW_S_LATCH
;
1710 /*********************************************************************//**
1711 Unlocks the data dictionary shared lock. */
1714 row_mysql_unfreeze_data_dictionary(
1715 /*===============================*/
1716 trx_t
* trx
) /*!< in/out: transaction */
1718 ut_a(trx
->dict_operation_lock_mode
== RW_S_LATCH
);
1720 rw_lock_s_unlock(&dict_operation_lock
);
1722 trx
->dict_operation_lock_mode
= 0;
1725 /*********************************************************************//**
1726 Locks the data dictionary exclusively for performing a table create or other
1727 data dictionary modification operation. */
1730 row_mysql_lock_data_dictionary_func(
1731 /*================================*/
1732 trx_t
* trx
, /*!< in/out: transaction */
1733 const char* file
, /*!< in: file name */
1734 ulint line
) /*!< in: line number */
1736 ut_a(trx
->dict_operation_lock_mode
== 0
1737 || trx
->dict_operation_lock_mode
== RW_X_LATCH
);
1739 /* Serialize data dictionary operations with dictionary mutex:
1740 no deadlocks or lock waits can occur then in these operations */
1742 rw_lock_x_lock_func(&dict_operation_lock
, 0, file
, line
);
1743 trx
->dict_operation_lock_mode
= RW_X_LATCH
;
1745 mutex_enter(&(dict_sys
->mutex
));
1748 /*********************************************************************//**
1749 Unlocks the data dictionary exclusive lock. */
1752 row_mysql_unlock_data_dictionary(
1753 /*=============================*/
1754 trx_t
* trx
) /*!< in/out: transaction */
1756 ut_a(trx
->dict_operation_lock_mode
== RW_X_LATCH
);
1758 /* Serialize data dictionary operations with dictionary mutex:
1759 no deadlocks can occur then in these operations */
1761 mutex_exit(&(dict_sys
->mutex
));
1762 rw_lock_x_unlock(&dict_operation_lock
);
1764 trx
->dict_operation_lock_mode
= 0;
1767 /*********************************************************************//**
1768 Creates a table for MySQL. If the name of the table ends in
1769 one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
1770 "innodb_table_monitor", then this will also start the printing of monitor
1771 output by the master thread. If the table name ends in "innodb_mem_validate",
1772 InnoDB will try to invoke mem_validate(). On failure the transaction will
1773 be rolled back and the 'table' object will be freed.
1774 @return error code or DB_SUCCESS */
1777 row_create_table_for_mysql(
1778 /*=======================*/
1779 dict_table_t
* table
, /*!< in, own: table definition
1781 trx_t
* trx
) /*!< in: transaction handle */
1786 const char* table_name
;
1787 ulint table_name_len
;
1790 ut_ad(trx
->mysql_thread_id
== os_thread_get_curr_id());
1791 #ifdef UNIV_SYNC_DEBUG
1792 ut_ad(rw_lock_own(&dict_operation_lock
, RW_LOCK_EX
));
1793 #endif /* UNIV_SYNC_DEBUG */
1794 ut_ad(mutex_own(&(dict_sys
->mutex
)));
1795 ut_ad(trx
->dict_operation_lock_mode
== RW_X_LATCH
);
1797 if (srv_created_new_raw
) {
1798 fputs("InnoDB: A new raw disk partition was initialized:\n"
1799 "InnoDB: we do not allow database modifications"
1801 "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
1802 " is replaced with raw.\n", stderr
);
1804 dict_mem_table_free(table
);
1805 trx_commit_for_mysql(trx
);
1810 trx
->op_info
= "creating table";
1812 if (row_mysql_is_system_table(table
->name
)) {
1815 "InnoDB: Error: trying to create a MySQL system"
1816 " table %s of type InnoDB.\n"
1817 "InnoDB: MySQL system tables must be"
1818 " of the MyISAM type!\n",
1823 trx_start_if_not_started(trx
);
1825 /* The table name is prefixed with the database name and a '/'.
1826 Certain table names starting with 'innodb_' have their special
1827 meaning regardless of the database name. Thus, we need to
1828 ignore the database name prefix in the comparisons. */
1829 table_name
= strchr(table
->name
, '/');
1832 table_name_len
= strlen(table_name
) + 1;
1834 if (STR_EQ(table_name
, table_name_len
, S_innodb_monitor
)) {
1836 /* Table equals "innodb_monitor":
1837 start monitor prints */
1839 srv_print_innodb_monitor
= TRUE
;
1841 /* The lock timeout monitor thread also takes care
1842 of InnoDB monitor prints */
1844 os_event_set(srv_lock_timeout_thread_event
);
1845 } else if (STR_EQ(table_name
, table_name_len
,
1846 S_innodb_lock_monitor
)) {
1848 srv_print_innodb_monitor
= TRUE
;
1849 srv_print_innodb_lock_monitor
= TRUE
;
1850 os_event_set(srv_lock_timeout_thread_event
);
1851 } else if (STR_EQ(table_name
, table_name_len
,
1852 S_innodb_tablespace_monitor
)) {
1854 srv_print_innodb_tablespace_monitor
= TRUE
;
1855 os_event_set(srv_lock_timeout_thread_event
);
1856 } else if (STR_EQ(table_name
, table_name_len
,
1857 S_innodb_table_monitor
)) {
1859 srv_print_innodb_table_monitor
= TRUE
;
1860 os_event_set(srv_lock_timeout_thread_event
);
1861 } else if (STR_EQ(table_name
, table_name_len
,
1862 S_innodb_mem_validate
)) {
1863 /* We define here a debugging feature intended for
1866 fputs("Validating InnoDB memory:\n"
1867 "to use this feature you must compile InnoDB with\n"
1868 "UNIV_MEM_DEBUG defined in univ.i and"
1869 " the server must be\n"
1870 "quiet because allocation from a mem heap"
1871 " is not protected\n"
1872 "by any semaphore.\n", stderr
);
1873 #ifdef UNIV_MEM_DEBUG
1874 ut_a(mem_validate());
1875 fputs("Memory validated\n", stderr
);
1876 #else /* UNIV_MEM_DEBUG */
1877 fputs("Memory NOT validated (recompile with UNIV_MEM_DEBUG)\n",
1879 #endif /* UNIV_MEM_DEBUG */
1882 heap
= mem_heap_create(512);
1884 trx_set_dict_operation(trx
, TRX_DICT_OP_TABLE
);
1886 node
= tab_create_graph_create(table
, heap
);
1888 thr
= pars_complete_graph_for_exec(node
, trx
, heap
);
1890 ut_a(thr
== que_fork_start_command(que_node_get_parent(thr
)));
1891 que_run_threads(thr
);
1893 err
= trx
->error_state
;
1898 case DB_OUT_OF_FILE_SPACE
:
1899 trx
->error_state
= DB_SUCCESS
;
1900 trx_general_rollback_for_mysql(trx
, NULL
);
1902 ut_print_timestamp(stderr
);
1903 fputs(" InnoDB: Warning: cannot create table ",
1905 ut_print_name(stderr
, trx
, TRUE
, table
->name
);
1906 fputs(" because tablespace full\n", stderr
);
1908 if (dict_table_get_low(table
->name
)) {
1910 row_drop_table_for_mysql(table
->name
, trx
, FALSE
);
1911 trx_commit_for_mysql(trx
);
1913 dict_mem_table_free(table
);
1917 case DB_TOO_MANY_CONCURRENT_TRXS
:
1918 /* We already have .ibd file here. it should be deleted. */
1920 if (table
->space
&& !fil_delete_tablespace(table
->space
)) {
1921 ut_print_timestamp(stderr
);
1923 " InnoDB: Error: not able to"
1924 " delete tablespace %lu of table ",
1925 (ulong
) table
->space
);
1926 ut_print_name(stderr
, trx
, TRUE
, table
->name
);
1927 fputs("!\n", stderr
);
1931 case DB_DUPLICATE_KEY
:
1933 /* We may also get err == DB_ERROR if the .ibd file for the
1934 table already exists */
1936 trx
->error_state
= DB_SUCCESS
;
1937 trx_general_rollback_for_mysql(trx
, NULL
);
1938 dict_mem_table_free(table
);
1942 que_graph_free((que_t
*) que_node_get_parent(thr
));
1949 /*********************************************************************//**
1950 Does an index creation operation for MySQL. TODO: currently failure
1951 to create an index results in dropping the whole table! This is no problem
1952 currently as all indexes must be created at the same time as the table.
1953 @return error number or DB_SUCCESS */
1956 row_create_index_for_mysql(
1957 /*=======================*/
1958 dict_index_t
* index
, /*!< in, own: index definition
1960 trx_t
* trx
, /*!< in: transaction handle */
1961 const ulint
* field_lengths
) /*!< in: if not NULL, must contain
1962 dict_index_get_n_fields(index)
1963 actual field lengths for the
1964 index columns, which are
1965 then checked for not being too
1976 #ifdef UNIV_SYNC_DEBUG
1977 ut_ad(rw_lock_own(&dict_operation_lock
, RW_LOCK_EX
));
1978 #endif /* UNIV_SYNC_DEBUG */
1979 ut_ad(mutex_own(&(dict_sys
->mutex
)));
1980 ut_ad(trx
->mysql_thread_id
== os_thread_get_curr_id());
1982 trx
->op_info
= "creating index";
1984 /* Copy the table name because we may want to drop the
1985 table later, after the index object is freed (inside
1986 que_run_threads()) and thus index->table_name is not available. */
1987 table_name
= mem_strdup(index
->table_name
);
1989 trx_start_if_not_started(trx
);
1991 /* Check that the same column does not appear twice in the index.
1992 Starting from 4.0.14, InnoDB should be able to cope with that, but
1993 safer not to allow them. */
1995 for (i
= 0; i
< dict_index_get_n_fields(index
); i
++) {
1998 for (j
= 0; j
< i
; j
++) {
2000 dict_index_get_nth_field(index
, j
)->name
,
2001 dict_index_get_nth_field(index
, i
)->name
)) {
2002 ut_print_timestamp(stderr
);
2004 fputs(" InnoDB: Error: column ", stderr
);
2005 ut_print_name(stderr
, trx
, FALSE
,
2006 dict_index_get_nth_field(
2008 fputs(" appears twice in ", stderr
);
2009 dict_index_name_print(stderr
, trx
, index
);
2011 "InnoDB: This is not allowed"
2012 " in InnoDB.\n", stderr
);
2014 err
= DB_COL_APPEARS_TWICE_IN_INDEX
;
2016 goto error_handling
;
2020 /* Check also that prefix_len and actual length
2021 < DICT_MAX_INDEX_COL_LEN */
2023 len
= dict_index_get_nth_field(index
, i
)->prefix_len
;
2025 if (field_lengths
) {
2026 len
= ut_max(len
, field_lengths
[i
]);
2029 if (len
>= DICT_MAX_INDEX_COL_LEN
) {
2030 err
= DB_TOO_BIG_RECORD
;
2032 goto error_handling
;
2036 heap
= mem_heap_create(512);
2038 trx_set_dict_operation(trx
, TRX_DICT_OP_TABLE
);
2040 /* Note that the space id where we store the index is inherited from
2041 the table in dict_build_index_def_step() in dict0crea.c. */
2043 node
= ind_create_graph_create(index
, heap
);
2045 thr
= pars_complete_graph_for_exec(node
, trx
, heap
);
2047 ut_a(thr
== que_fork_start_command(que_node_get_parent(thr
)));
2048 que_run_threads(thr
);
2050 err
= trx
->error_state
;
2052 que_graph_free((que_t
*) que_node_get_parent(thr
));
2055 if (err
!= DB_SUCCESS
) {
2056 /* We have special error handling here */
2058 trx
->error_state
= DB_SUCCESS
;
2060 trx_general_rollback_for_mysql(trx
, NULL
);
2062 row_drop_table_for_mysql(table_name
, trx
, FALSE
);
2064 trx_commit_for_mysql(trx
);
2066 trx
->error_state
= DB_SUCCESS
;
2071 mem_free(table_name
);
2076 /*********************************************************************//**
2077 Scans a table create SQL string and adds to the data dictionary
2078 the foreign key constraints declared in the string. This function
2079 should be called after the indexes for a table have been created.
2080 Each foreign key constraint must be accompanied with indexes in
2081 both participating tables. The indexes are allowed to contain more
2082 fields than mentioned in the constraint. Check also that foreign key
2083 constraints which reference this table are ok.
2084 @return error code or DB_SUCCESS */
2087 row_table_add_foreign_constraints(
2088 /*==============================*/
2089 trx_t
* trx
, /*!< in: transaction */
2090 const char* sql_string
, /*!< in: table create statement where
2091 foreign keys are declared like:
2092 FOREIGN KEY (a, b) REFERENCES table2(c, d),
2093 table2 can be written also with the
2094 database name before it: test.table2 */
2095 size_t sql_length
, /*!< in: length of sql_string */
2096 const char* name
, /*!< in: table full name in the
2098 database_name/table_name */
2099 ibool reject_fks
) /*!< in: if TRUE, fail with error
2100 code DB_CANNOT_ADD_CONSTRAINT if
2101 any foreign keys are found. */
2105 ut_ad(mutex_own(&(dict_sys
->mutex
)));
2106 #ifdef UNIV_SYNC_DEBUG
2107 ut_ad(rw_lock_own(&dict_operation_lock
, RW_LOCK_EX
));
2108 #endif /* UNIV_SYNC_DEBUG */
2111 trx
->op_info
= "adding foreign keys";
2113 trx_start_if_not_started(trx
);
2115 trx_set_dict_operation(trx
, TRX_DICT_OP_TABLE
);
2117 err
= dict_create_foreign_constraints(trx
, sql_string
, sql_length
,
2119 if (err
== DB_SUCCESS
) {
2120 /* Check that also referencing constraints are ok */
2121 err
= dict_load_foreigns(name
, FALSE
, TRUE
);
2124 if (err
!= DB_SUCCESS
) {
2125 /* We have special error handling here */
2127 trx
->error_state
= DB_SUCCESS
;
2129 trx_general_rollback_for_mysql(trx
, NULL
);
2131 row_drop_table_for_mysql(name
, trx
, FALSE
);
2133 trx_commit_for_mysql(trx
);
2135 trx
->error_state
= DB_SUCCESS
;
2141 /*********************************************************************//**
2142 Drops a table for MySQL as a background operation. MySQL relies on Unix
2143 in ALTER TABLE to the fact that the table handler does not remove the
2144 table before all handles to it has been removed. Furhermore, the MySQL's
2145 call to drop table must be non-blocking. Therefore we do the drop table
2146 as a background operation, which is taken care of by the master thread
2148 @return error code or DB_SUCCESS */
2151 row_drop_table_for_mysql_in_background(
2152 /*===================================*/
2153 const char* name
) /*!< in: table name */
2158 trx
= trx_allocate_for_background();
2160 /* If the original transaction was dropping a table referenced by
2161 foreign keys, we must set the following to be able to drop the
2164 trx
->check_foreigns
= FALSE
;
2166 /* fputs("InnoDB: Error: Dropping table ", stderr);
2167 ut_print_name(stderr, trx, TRUE, name);
2168 fputs(" in background drop list\n", stderr); */
2170 /* Try to drop the table in InnoDB */
2172 error
= row_drop_table_for_mysql(name
, trx
, FALSE
);
2174 /* Flush the log to reduce probability that the .frm files and
2175 the InnoDB data dictionary get out-of-sync if the user runs
2176 with innodb_flush_log_at_trx_commit = 0 */
2178 log_buffer_flush_to_disk();
2180 trx_commit_for_mysql(trx
);
2182 trx_free_for_background(trx
);
2184 return((int) error
);
2187 /*********************************************************************//**
2188 The master thread in srv0srv.c calls this regularly to drop tables which
2189 we must drop in background after queries to them have ended. Such lazy
2190 dropping of tables is needed in ALTER TABLE on Unix.
2191 @return how many tables dropped + remaining tables in list */
2194 row_drop_tables_for_mysql_in_background(void)
2195 /*=========================================*/
2197 row_mysql_drop_t
* drop
;
2198 dict_table_t
* table
;
2200 ulint n_tables_dropped
= 0;
2202 mutex_enter(&kernel_mutex
);
2204 if (!row_mysql_drop_list_inited
) {
2206 UT_LIST_INIT(row_mysql_drop_list
);
2207 row_mysql_drop_list_inited
= TRUE
;
2210 drop
= UT_LIST_GET_FIRST(row_mysql_drop_list
);
2212 n_tables
= UT_LIST_GET_LEN(row_mysql_drop_list
);
2214 mutex_exit(&kernel_mutex
);
2217 /* All tables dropped */
2219 return(n_tables
+ n_tables_dropped
);
2222 mutex_enter(&(dict_sys
->mutex
));
2223 table
= dict_table_get_low(drop
->table_name
);
2224 mutex_exit(&(dict_sys
->mutex
));
2226 if (table
== NULL
) {
2227 /* If for some reason the table has already been dropped
2228 through some other mechanism, do not try to drop it */
2230 goto already_dropped
;
2233 if (DB_SUCCESS
!= row_drop_table_for_mysql_in_background(
2234 drop
->table_name
)) {
2235 /* If the DROP fails for some table, we return, and let the
2236 main thread retry later */
2238 return(n_tables
+ n_tables_dropped
);
2244 mutex_enter(&kernel_mutex
);
2246 UT_LIST_REMOVE(row_mysql_drop_list
, row_mysql_drop_list
, drop
);
2248 ut_print_timestamp(stderr
);
2249 fputs(" InnoDB: Dropped table ", stderr
);
2250 ut_print_name(stderr
, NULL
, TRUE
, drop
->table_name
);
2251 fputs(" in background drop queue.\n", stderr
);
2253 mem_free(drop
->table_name
);
2257 mutex_exit(&kernel_mutex
);
2262 /*********************************************************************//**
2263 Get the background drop list length. NOTE: the caller must own the kernel
2265 @return how many tables in list */
2268 row_get_background_drop_list_len_low(void)
2269 /*======================================*/
2271 ut_ad(mutex_own(&kernel_mutex
));
2273 if (!row_mysql_drop_list_inited
) {
2275 UT_LIST_INIT(row_mysql_drop_list
);
2276 row_mysql_drop_list_inited
= TRUE
;
2279 return(UT_LIST_GET_LEN(row_mysql_drop_list
));
2282 /*********************************************************************//**
2283 If a table is not yet in the drop list, adds the table to the list of tables
2284 which the master thread drops in background. We need this on Unix because in
2285 ALTER TABLE MySQL may call drop table even if the table has running queries on
2286 it. Also, if there are running foreign key checks on the table, we drop the
2288 @return TRUE if the table was not yet in the drop list, and was added there */
2291 row_add_table_to_background_drop_list(
2292 /*==================================*/
2293 const char* name
) /*!< in: table name */
2295 row_mysql_drop_t
* drop
;
2297 mutex_enter(&kernel_mutex
);
2299 if (!row_mysql_drop_list_inited
) {
2301 UT_LIST_INIT(row_mysql_drop_list
);
2302 row_mysql_drop_list_inited
= TRUE
;
2305 /* Look if the table already is in the drop list */
2306 drop
= UT_LIST_GET_FIRST(row_mysql_drop_list
);
2308 while (drop
!= NULL
) {
2309 if (strcmp(drop
->table_name
, name
) == 0) {
2310 /* Already in the list */
2312 mutex_exit(&kernel_mutex
);
2317 drop
= UT_LIST_GET_NEXT(row_mysql_drop_list
, drop
);
2320 drop
= mem_alloc(sizeof(row_mysql_drop_t
));
2322 drop
->table_name
= mem_strdup(name
);
2324 UT_LIST_ADD_LAST(row_mysql_drop_list
, row_mysql_drop_list
, drop
);
2326 /* fputs("InnoDB: Adding table ", stderr);
2327 ut_print_name(stderr, trx, TRUE, drop->table_name);
2328 fputs(" to background drop list\n", stderr); */
2330 mutex_exit(&kernel_mutex
);
2335 /*********************************************************************//**
2336 Discards the tablespace of a table which stored in an .ibd file. Discarding
2337 means that this function deletes the .ibd file and assigns a new table id for
2338 the table. Also the flag table->ibd_file_missing is set TRUE.
2339 @return error code or DB_SUCCESS */
2342 row_discard_tablespace_for_mysql(
2343 /*=============================*/
2344 const char* name
, /*!< in: table name */
2345 trx_t
* trx
) /*!< in: transaction handle */
2347 dict_foreign_t
* foreign
;
2349 dict_table_t
* table
;
2352 pars_info_t
* info
= NULL
;
2354 /* How do we prevent crashes caused by ongoing operations on
2355 the table? Old operations could try to access non-existent
2358 1) SQL queries, INSERT, SELECT, ...: we must get an exclusive
2359 MySQL table lock on the table before we can do DISCARD
2360 TABLESPACE. Then there are no running queries on the table.
2362 2) Purge and rollback: we assign a new table id for the
2363 table. Since purge and rollback look for the table based on
2364 the table id, they see the table as 'dropped' and discard
2367 3) Insert buffer: we remove all entries for the tablespace in
2368 the insert buffer tree; as long as the tablespace mem object
2369 does not exist, ongoing insert buffer page merges are
2370 discarded in buf0rea.c. If we recreate the tablespace mem
2371 object with IMPORT TABLESPACE later, then the tablespace will
2372 have the same id, but the tablespace_version field in the mem
2373 object is different, and ongoing old insert buffer page merges
2376 4) Linear readahead and random readahead: we use the same
2377 method as in 3) to discard ongoing operations.
2379 5) FOREIGN KEY operations: if
2380 table->n_foreign_key_checks_running > 0, we do not allow the
2381 discard. We also reserve the data dictionary latch. */
2383 ut_ad(trx
->mysql_thread_id
== os_thread_get_curr_id());
2385 trx
->op_info
= "discarding tablespace";
2386 trx_start_if_not_started(trx
);
2388 /* Serialize data dictionary operations with dictionary mutex:
2389 no deadlocks can occur then in these operations */
2391 row_mysql_lock_data_dictionary(trx
);
2393 table
= dict_table_get_low(name
);
2396 err
= DB_TABLE_NOT_FOUND
;
2401 if (table
->space
== 0) {
2402 ut_print_timestamp(stderr
);
2403 fputs(" InnoDB: Error: table ", stderr
);
2404 ut_print_name(stderr
, trx
, TRUE
, name
);
2406 "InnoDB: is in the system tablespace 0"
2407 " which cannot be discarded\n", stderr
);
2413 if (table
->n_foreign_key_checks_running
> 0) {
2415 ut_print_timestamp(stderr
);
2416 fputs(" InnoDB: You are trying to DISCARD table ", stderr
);
2417 ut_print_name(stderr
, trx
, TRUE
, table
->name
);
2419 "InnoDB: though there is a foreign key check"
2421 "InnoDB: Cannot discard the table.\n",
2429 /* Check if the table is referenced by foreign key constraints from
2430 some other table (not the table itself) */
2432 foreign
= UT_LIST_GET_FIRST(table
->referenced_list
);
2434 while (foreign
&& foreign
->foreign_table
== table
) {
2435 foreign
= UT_LIST_GET_NEXT(referenced_list
, foreign
);
2438 if (foreign
&& trx
->check_foreigns
) {
2440 FILE* ef
= dict_foreign_err_file
;
2442 /* We only allow discarding a referenced table if
2443 FOREIGN_KEY_CHECKS is set to 0 */
2445 err
= DB_CANNOT_DROP_CONSTRAINT
;
2447 mutex_enter(&dict_foreign_err_mutex
);
2449 ut_print_timestamp(ef
);
2451 fputs(" Cannot DISCARD table ", ef
);
2452 ut_print_name(stderr
, trx
, TRUE
, name
);
2454 "because it is referenced by ", ef
);
2455 ut_print_name(stderr
, trx
, TRUE
, foreign
->foreign_table_name
);
2457 mutex_exit(&dict_foreign_err_mutex
);
2462 dict_hdr_get_new_id(&new_id
, NULL
, NULL
);
2464 /* Remove all locks except the table-level S and X locks. */
2465 lock_remove_all_on_table(table
, FALSE
);
2467 info
= pars_info_create();
2469 pars_info_add_str_literal(info
, "table_name", name
);
2470 pars_info_add_dulint_literal(info
, "new_id", new_id
);
2472 err
= que_eval_sql(info
,
2473 "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
2476 "SELECT ID INTO old_id\n"
2478 "WHERE NAME = :table_name\n"
2479 "LOCK IN SHARE MODE;\n"
2480 "IF (SQL % NOTFOUND) THEN\n"
2484 "UPDATE SYS_TABLES SET ID = :new_id\n"
2485 " WHERE ID = old_id;\n"
2486 "UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n"
2487 " WHERE TABLE_ID = old_id;\n"
2488 "UPDATE SYS_INDEXES SET TABLE_ID = :new_id\n"
2489 " WHERE TABLE_ID = old_id;\n"
2494 if (err
!= DB_SUCCESS
) {
2495 trx
->error_state
= DB_SUCCESS
;
2496 trx_general_rollback_for_mysql(trx
, NULL
);
2497 trx
->error_state
= DB_SUCCESS
;
2499 dict_table_change_id_in_cache(table
, new_id
);
2501 success
= fil_discard_tablespace(table
->space
);
2504 trx
->error_state
= DB_SUCCESS
;
2505 trx_general_rollback_for_mysql(trx
, NULL
);
2506 trx
->error_state
= DB_SUCCESS
;
2510 /* Set the flag which tells that now it is legal to
2511 IMPORT a tablespace for this table */
2512 table
->tablespace_discarded
= TRUE
;
2513 table
->ibd_file_missing
= TRUE
;
2518 trx_commit_for_mysql(trx
);
2520 row_mysql_unlock_data_dictionary(trx
);
2527 /*****************************************************************//**
2528 Imports a tablespace. The space id in the .ibd file must match the space id
2529 of the table in the data dictionary.
2530 @return error code or DB_SUCCESS */
2533 row_import_tablespace_for_mysql(
2534 /*============================*/
2535 const char* name
, /*!< in: table name */
2536 trx_t
* trx
) /*!< in: transaction handle */
2538 dict_table_t
* table
;
2540 ib_uint64_t current_lsn
;
2541 ulint err
= DB_SUCCESS
;
2543 ut_ad(trx
->mysql_thread_id
== os_thread_get_curr_id());
2545 trx_start_if_not_started(trx
);
2547 trx
->op_info
= "importing tablespace";
2549 current_lsn
= log_get_lsn();
2551 /* It is possible, though very improbable, that the lsn's in the
2552 tablespace to be imported have risen above the current system lsn, if
2553 a lengthy purge, ibuf merge, or rollback was performed on a backup
2554 taken with ibbackup. If that is the case, reset page lsn's in the
2555 file. We assume that mysqld was shut down after it performed these
2556 cleanup operations on the .ibd file, so that it stamped the latest lsn
2557 to the FIL_PAGE_FILE_FLUSH_LSN in the first page of the .ibd file.
2559 TODO: reset also the trx id's in clustered index records and write
2560 a new space id to each data page. That would allow us to import clean
2561 .ibd files from another MySQL installation. */
2563 success
= fil_reset_too_high_lsns(name
, current_lsn
);
2566 ut_print_timestamp(stderr
);
2567 fputs(" InnoDB: Error: cannot reset lsn's in table ", stderr
);
2568 ut_print_name(stderr
, trx
, TRUE
, name
);
2570 "InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n",
2575 row_mysql_lock_data_dictionary(trx
);
2580 /* Serialize data dictionary operations with dictionary mutex:
2581 no deadlocks can occur then in these operations */
2583 row_mysql_lock_data_dictionary(trx
);
2585 table
= dict_table_get_low(name
);
2588 ut_print_timestamp(stderr
);
2589 fputs(" InnoDB: table ", stderr
);
2590 ut_print_name(stderr
, trx
, TRUE
, name
);
2592 "InnoDB: does not exist in the InnoDB data dictionary\n"
2593 "InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n",
2596 err
= DB_TABLE_NOT_FOUND
;
2601 if (table
->space
== 0) {
2602 ut_print_timestamp(stderr
);
2603 fputs(" InnoDB: Error: table ", stderr
);
2604 ut_print_name(stderr
, trx
, TRUE
, name
);
2606 "InnoDB: is in the system tablespace 0"
2607 " which cannot be imported\n", stderr
);
2613 if (!table
->tablespace_discarded
) {
2614 ut_print_timestamp(stderr
);
2615 fputs(" InnoDB: Error: you are trying to"
2616 " IMPORT a tablespace\n"
2617 "InnoDB: ", stderr
);
2618 ut_print_name(stderr
, trx
, TRUE
, name
);
2619 fputs(", though you have not called DISCARD on it yet\n"
2620 "InnoDB: during the lifetime of the mysqld process!\n",
2628 /* Play safe and remove all insert buffer entries, though we should
2629 have removed them already when DISCARD TABLESPACE was called */
2631 ibuf_delete_for_discarded_space(table
->space
);
2633 success
= fil_open_single_table_tablespace(
2635 table
->flags
== DICT_TF_COMPACT
? 0 : table
->flags
,
2638 table
->ibd_file_missing
= FALSE
;
2639 table
->tablespace_discarded
= FALSE
;
2641 if (table
->ibd_file_missing
) {
2642 ut_print_timestamp(stderr
);
2643 fputs(" InnoDB: cannot find or open in the"
2644 " database directory the .ibd file of\n"
2645 "InnoDB: table ", stderr
);
2646 ut_print_name(stderr
, trx
, TRUE
, name
);
2648 "InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n",
2656 trx_commit_for_mysql(trx
);
2658 row_mysql_unlock_data_dictionary(trx
);
2665 /*********************************************************************//**
2666 Truncates a table for MySQL.
2667 @return error code or DB_SUCCESS */
2670 row_truncate_table_for_mysql(
2671 /*=========================*/
2672 dict_table_t
* table
, /*!< in: table handle */
2673 trx_t
* trx
) /*!< in: transaction handle */
2675 dict_foreign_t
* foreign
;
2681 dict_index_t
* sys_index
;
2685 ulint recreate_space
= 0;
2686 pars_info_t
* info
= NULL
;
2688 /* How do we prevent crashes caused by ongoing operations on
2689 the table? Old operations could try to access non-existent
2692 1) SQL queries, INSERT, SELECT, ...: we must get an exclusive
2693 MySQL table lock on the table before we can do TRUNCATE
2694 TABLE. Then there are no running queries on the table. This is
2695 guaranteed, because in ha_innobase::store_lock(), we do not
2696 weaken the TL_WRITE lock requested by MySQL when executing
2699 2) Purge and rollback: we assign a new table id for the
2700 table. Since purge and rollback look for the table based on
2701 the table id, they see the table as 'dropped' and discard
2704 3) Insert buffer: TRUNCATE TABLE is analogous to DROP TABLE,
2705 so we do not have to remove insert buffer records, as the
2706 insert buffer works at a low level. If a freed page is later
2707 reallocated, the allocator will remove the ibuf entries for
2710 When we truncate *.ibd files by recreating them (analogous to
2711 DISCARD TABLESPACE), we remove all entries for the table in the
2712 insert buffer tree. This is not strictly necessary, because
2713 in 6) we will assign a new tablespace identifier, but we can
2714 free up some space in the system tablespace.
2716 4) Linear readahead and random readahead: we use the same
2717 method as in 3) to discard ongoing operations. (This is only
2718 relevant for TRUNCATE TABLE by DISCARD TABLESPACE.)
2720 5) FOREIGN KEY operations: if
2721 table->n_foreign_key_checks_running > 0, we do not allow the
2722 TRUNCATE. We also reserve the data dictionary latch.
2724 6) Crash recovery: To prevent the application of pre-truncation
2725 redo log records on the truncated tablespace, we will assign
2726 a new tablespace identifier to the truncated tablespace. */
2728 ut_ad(trx
->mysql_thread_id
== os_thread_get_curr_id());
2731 if (srv_created_new_raw
) {
2732 fputs("InnoDB: A new raw disk partition was initialized:\n"
2733 "InnoDB: we do not allow database modifications"
2735 "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
2736 " is replaced with raw.\n", stderr
);
2741 trx
->op_info
= "truncating table";
2743 trx_start_if_not_started(trx
);
2745 /* Serialize data dictionary operations with dictionary mutex:
2746 no deadlocks can occur then in these operations */
2748 ut_a(trx
->dict_operation_lock_mode
== 0);
2749 /* Prevent foreign key checks etc. while we are truncating the
2752 row_mysql_lock_data_dictionary(trx
);
2754 ut_ad(mutex_own(&(dict_sys
->mutex
)));
2755 #ifdef UNIV_SYNC_DEBUG
2756 ut_ad(rw_lock_own(&dict_operation_lock
, RW_LOCK_EX
));
2757 #endif /* UNIV_SYNC_DEBUG */
2759 /* Check if the table is referenced by foreign key constraints from
2760 some other table (not the table itself) */
2762 foreign
= UT_LIST_GET_FIRST(table
->referenced_list
);
2764 while (foreign
&& foreign
->foreign_table
== table
) {
2765 foreign
= UT_LIST_GET_NEXT(referenced_list
, foreign
);
2768 if (foreign
&& trx
->check_foreigns
) {
2769 FILE* ef
= dict_foreign_err_file
;
2771 /* We only allow truncating a referenced table if
2772 FOREIGN_KEY_CHECKS is set to 0 */
2774 mutex_enter(&dict_foreign_err_mutex
);
2776 ut_print_timestamp(ef
);
2778 fputs(" Cannot truncate table ", ef
);
2779 ut_print_name(ef
, trx
, TRUE
, table
->name
);
2780 fputs(" by DROP+CREATE\n"
2781 "InnoDB: because it is referenced by ", ef
);
2782 ut_print_name(ef
, trx
, TRUE
, foreign
->foreign_table_name
);
2784 mutex_exit(&dict_foreign_err_mutex
);
2790 /* TODO: could we replace the counter n_foreign_key_checks_running
2791 with lock checks on the table? Acquire here an exclusive lock on the
2792 table, and rewrite lock0lock.c and the lock wait in srv0srv.c so that
2793 they can cope with the table having been truncated here? Foreign key
2794 checks take an IS or IX lock on the table. */
2796 if (table
->n_foreign_key_checks_running
> 0) {
2797 ut_print_timestamp(stderr
);
2798 fputs(" InnoDB: Cannot truncate table ", stderr
);
2799 ut_print_name(stderr
, trx
, TRUE
, table
->name
);
2800 fputs(" by DROP+CREATE\n"
2801 "InnoDB: because there is a foreign key check"
2802 " running on it.\n",
2809 /* Remove all locks except the table-level S and X locks. */
2810 lock_remove_all_on_table(table
, FALSE
);
2812 trx
->table_id
= table
->id
;
2814 if (table
->space
&& !table
->dir_path_of_temp_table
) {
2815 /* Discard and create the single-table tablespace. */
2816 ulint space
= table
->space
;
2817 ulint flags
= fil_space_get_flags(space
);
2819 if (flags
!= ULINT_UNDEFINED
2820 && fil_discard_tablespace(space
)) {
2822 dict_index_t
* index
;
2824 dict_hdr_get_new_id(NULL
, NULL
, &space
);
2826 /* Lock all index trees for this table. We must
2827 do so after dict_hdr_get_new_id() to preserve
2829 dict_table_x_lock_indexes(table
);
2831 if (space
== ULINT_UNDEFINED
2832 || fil_create_new_single_table_tablespace(
2833 space
, table
->name
, FALSE
, flags
,
2834 FIL_IBD_FILE_INITIAL_SIZE
) != DB_SUCCESS
) {
2835 dict_table_x_unlock_indexes(table
);
2836 ut_print_timestamp(stderr
);
2838 " InnoDB: TRUNCATE TABLE %s failed to"
2839 " create a new tablespace\n",
2841 table
->ibd_file_missing
= 1;
2846 recreate_space
= space
;
2848 /* Replace the space_id in the data dictionary cache.
2849 The persisent data dictionary (SYS_TABLES.SPACE
2850 and SYS_INDEXES.SPACE) are updated later in this
2852 table
->space
= space
;
2853 index
= dict_table_get_first_index(table
);
2855 index
->space
= space
;
2856 index
= dict_table_get_next_index(index
);
2860 fsp_header_init(space
,
2861 FIL_IBD_FILE_INITIAL_SIZE
, &mtr
);
2865 /* Lock all index trees for this table, as we will
2866 truncate the table/index and possibly change their metadata.
2867 All DML/DDL are blocked by table level lock, with
2868 a few exceptions such as queries into information schema
2869 about the table, MySQL could try to access index stats
2870 for this kind of query, we need to use index locks to
2872 dict_table_x_lock_indexes(table
);
2875 /* scan SYS_INDEXES for all indexes of the table */
2876 heap
= mem_heap_create(800);
2878 tuple
= dtuple_create(heap
, 1);
2879 dfield
= dtuple_get_nth_field(tuple
, 0);
2881 buf
= mem_heap_alloc(heap
, 8);
2882 mach_write_to_8(buf
, table
->id
);
2884 dfield_set_data(dfield
, buf
, 8);
2885 sys_index
= dict_table_get_first_index(dict_sys
->sys_indexes
);
2886 dict_index_copy_types(tuple
, sys_index
, 1);
2889 btr_pcur_open_on_user_rec(sys_index
, tuple
, PAGE_CUR_GE
,
2890 BTR_MODIFY_LEAF
, &pcur
, &mtr
);
2897 if (!btr_pcur_is_on_user_rec(&pcur
)) {
2898 /* The end of SYS_INDEXES has been reached. */
2902 rec
= btr_pcur_get_rec(&pcur
);
2904 field
= rec_get_nth_field_old(rec
, 0, &len
);
2907 if (memcmp(buf
, field
, len
) != 0) {
2908 /* End of indexes for the table (TABLE_ID mismatch). */
2912 if (rec_get_deleted_flag(rec
, FALSE
)) {
2913 /* The index has been dropped. */
2917 /* This call may commit and restart mtr
2918 and reposition pcur. */
2919 root_page_no
= dict_truncate_index_tree(table
, recreate_space
,
2922 rec
= btr_pcur_get_rec(&pcur
);
2924 if (root_page_no
!= FIL_NULL
) {
2925 page_rec_write_index_page_no(
2926 rec
, DICT_SYS_INDEXES_PAGE_NO_FIELD
,
2927 root_page_no
, &mtr
);
2928 /* We will need to commit and restart the
2929 mini-transaction in order to avoid deadlocks.
2930 The dict_truncate_index_tree() call has allocated
2931 a page in this mini-transaction, and the rest of
2932 this loop could latch another index page. */
2935 btr_pcur_restore_position(BTR_MODIFY_LEAF
,
2940 btr_pcur_move_to_next_user_rec(&pcur
, &mtr
);
2943 btr_pcur_close(&pcur
);
2946 mem_heap_free(heap
);
2948 /* Done with index truncation, release index tree locks,
2949 subsequent work relates to table level metadata change */
2950 dict_table_x_unlock_indexes(table
);
2952 dict_hdr_get_new_id(&new_id
, NULL
, NULL
);
2954 info
= pars_info_create();
2956 pars_info_add_int4_literal(info
, "space", (lint
) table
->space
);
2957 pars_info_add_dulint_literal(info
, "old_id", table
->id
);
2958 pars_info_add_dulint_literal(info
, "new_id", new_id
);
2960 err
= que_eval_sql(info
,
2961 "PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
2964 " SET ID = :new_id, SPACE = :space\n"
2965 " WHERE ID = :old_id;\n"
2966 "UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n"
2967 " WHERE TABLE_ID = :old_id;\n"
2968 "UPDATE SYS_INDEXES"
2969 " SET TABLE_ID = :new_id, SPACE = :space\n"
2970 " WHERE TABLE_ID = :old_id;\n"
2975 if (err
!= DB_SUCCESS
) {
2976 trx
->error_state
= DB_SUCCESS
;
2977 trx_general_rollback_for_mysql(trx
, NULL
);
2978 trx
->error_state
= DB_SUCCESS
;
2979 ut_print_timestamp(stderr
);
2980 fputs(" InnoDB: Unable to assign a new identifier to table ",
2982 ut_print_name(stderr
, trx
, TRUE
, table
->name
);
2984 "InnoDB: after truncating it. Background processes"
2985 " may corrupt the table!\n", stderr
);
2988 dict_table_change_id_in_cache(table
, new_id
);
2991 /* MySQL calls ha_innobase::reset_auto_increment() which does
2993 dict_table_autoinc_lock(table
);
2994 dict_table_autoinc_initialize(table
, 1);
2995 dict_table_autoinc_unlock(table
);
2996 dict_update_statistics(table
, FALSE
/* update even if stats are
2999 trx_commit_for_mysql(trx
);
3003 row_mysql_unlock_data_dictionary(trx
);
3007 srv_wake_master_thread();
3012 /*********************************************************************//**
3013 Drops a table for MySQL. If the name of the dropped table ends in
3014 one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
3015 "innodb_table_monitor", then this will also stop the printing of monitor
3016 output by the master thread. If the data dictionary was not already locked
3017 by the transaction, the transaction will be committed. Otherwise, the
3018 data dictionary will remain locked.
3019 @return error code or DB_SUCCESS */
3022 row_drop_table_for_mysql(
3023 /*=====================*/
3024 const char* name
, /*!< in: table name */
3025 trx_t
* trx
, /*!< in: transaction handle */
3026 ibool drop_db
)/*!< in: TRUE=dropping whole database */
3028 dict_foreign_t
* foreign
;
3029 dict_table_t
* table
;
3030 dict_index_t
* index
;
3033 const char* table_name
;
3035 ibool locked_dictionary
= FALSE
;
3036 pars_info_t
* info
= NULL
;
3040 if (srv_created_new_raw
) {
3041 fputs("InnoDB: A new raw disk partition was initialized:\n"
3042 "InnoDB: we do not allow database modifications"
3044 "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
3045 " is replaced with raw.\n", stderr
);
3050 trx
->op_info
= "dropping table";
3052 trx_start_if_not_started(trx
);
3054 /* The table name is prefixed with the database name and a '/'.
3055 Certain table names starting with 'innodb_' have their special
3056 meaning regardless of the database name. Thus, we need to
3057 ignore the database name prefix in the comparisons. */
3058 table_name
= strchr(name
, '/');
3061 namelen
= strlen(table_name
) + 1;
3063 if (namelen
== sizeof S_innodb_monitor
3064 && !memcmp(table_name
, S_innodb_monitor
,
3065 sizeof S_innodb_monitor
)) {
3067 /* Table name equals "innodb_monitor":
3068 stop monitor prints */
3070 srv_print_innodb_monitor
= FALSE
;
3071 srv_print_innodb_lock_monitor
= FALSE
;
3072 } else if (namelen
== sizeof S_innodb_lock_monitor
3073 && !memcmp(table_name
, S_innodb_lock_monitor
,
3074 sizeof S_innodb_lock_monitor
)) {
3075 srv_print_innodb_monitor
= FALSE
;
3076 srv_print_innodb_lock_monitor
= FALSE
;
3077 } else if (namelen
== sizeof S_innodb_tablespace_monitor
3078 && !memcmp(table_name
, S_innodb_tablespace_monitor
,
3079 sizeof S_innodb_tablespace_monitor
)) {
3081 srv_print_innodb_tablespace_monitor
= FALSE
;
3082 } else if (namelen
== sizeof S_innodb_table_monitor
3083 && !memcmp(table_name
, S_innodb_table_monitor
,
3084 sizeof S_innodb_table_monitor
)) {
3086 srv_print_innodb_table_monitor
= FALSE
;
3089 /* Serialize data dictionary operations with dictionary mutex:
3090 no deadlocks can occur then in these operations */
3092 if (trx
->dict_operation_lock_mode
!= RW_X_LATCH
) {
3093 /* Prevent foreign key checks etc. while we are dropping the
3096 row_mysql_lock_data_dictionary(trx
);
3098 locked_dictionary
= TRUE
;
3101 ut_ad(mutex_own(&(dict_sys
->mutex
)));
3102 #ifdef UNIV_SYNC_DEBUG
3103 ut_ad(rw_lock_own(&dict_operation_lock
, RW_LOCK_EX
));
3104 #endif /* UNIV_SYNC_DEBUG */
3106 table
= dict_table_get_low(name
);
3109 err
= DB_TABLE_NOT_FOUND
;
3110 ut_print_timestamp(stderr
);
3112 fputs(" InnoDB: Error: table ", stderr
);
3113 ut_print_name(stderr
, trx
, TRUE
, name
);
3114 fputs(" does not exist in the InnoDB internal\n"
3115 "InnoDB: data dictionary though MySQL is"
3116 " trying to drop it.\n"
3117 "InnoDB: Have you copied the .frm file"
3118 " of the table to the\n"
3119 "InnoDB: MySQL database directory"
3120 " from another database?\n"
3121 "InnoDB: You can look for further help from\n"
3122 "InnoDB: " REFMAN
"innodb-troubleshooting.html\n",
3127 /* Check if the table is referenced by foreign key constraints from
3128 some other table (not the table itself) */
3130 foreign
= UT_LIST_GET_FIRST(table
->referenced_list
);
3132 while (foreign
&& foreign
->foreign_table
== table
) {
3134 foreign
= UT_LIST_GET_NEXT(referenced_list
, foreign
);
3137 if (foreign
&& trx
->check_foreigns
3138 && !(drop_db
&& dict_tables_have_same_db(
3139 name
, foreign
->foreign_table_name
))) {
3140 FILE* ef
= dict_foreign_err_file
;
3142 /* We only allow dropping a referenced table if
3143 FOREIGN_KEY_CHECKS is set to 0 */
3145 err
= DB_CANNOT_DROP_CONSTRAINT
;
3147 mutex_enter(&dict_foreign_err_mutex
);
3149 ut_print_timestamp(ef
);
3151 fputs(" Cannot drop table ", ef
);
3152 ut_print_name(ef
, trx
, TRUE
, name
);
3154 "because it is referenced by ", ef
);
3155 ut_print_name(ef
, trx
, TRUE
, foreign
->foreign_table_name
);
3157 mutex_exit(&dict_foreign_err_mutex
);
3162 if (foreign
&& trx
->check_foreigns
) {
3163 goto check_next_foreign
;
3166 if (table
->n_mysql_handles_opened
> 0) {
3169 added
= row_add_table_to_background_drop_list(table
->name
);
3172 ut_print_timestamp(stderr
);
3173 fputs(" InnoDB: Warning: MySQL is"
3174 " trying to drop table ", stderr
);
3175 ut_print_name(stderr
, trx
, TRUE
, table
->name
);
3177 "InnoDB: though there are still"
3178 " open handles to it.\n"
3179 "InnoDB: Adding the table to the"
3180 " background drop queue.\n",
3183 /* We return DB_SUCCESS to MySQL though the drop will
3184 happen lazily later */
3187 /* The table is already in the background drop list */
3194 /* TODO: could we replace the counter n_foreign_key_checks_running
3195 with lock checks on the table? Acquire here an exclusive lock on the
3196 table, and rewrite lock0lock.c and the lock wait in srv0srv.c so that
3197 they can cope with the table having been dropped here? Foreign key
3198 checks take an IS or IX lock on the table. */
3200 if (table
->n_foreign_key_checks_running
> 0) {
3202 const char* table_name
= table
->name
;
3205 added
= row_add_table_to_background_drop_list(table_name
);
3208 ut_print_timestamp(stderr
);
3209 fputs(" InnoDB: You are trying to drop table ",
3211 ut_print_name(stderr
, trx
, TRUE
, table_name
);
3213 "InnoDB: though there is a"
3214 " foreign key check running on it.\n"
3215 "InnoDB: Adding the table to"
3216 " the background drop queue.\n",
3219 /* We return DB_SUCCESS to MySQL though the drop will
3220 happen lazily later */
3224 /* The table is already in the background drop list */
3231 /* Remove all locks there are on the table or its records */
3232 lock_remove_all_on_table(table
, TRUE
);
3234 trx_set_dict_operation(trx
, TRX_DICT_OP_TABLE
);
3235 trx
->table_id
= table
->id
;
3237 /* Mark all indexes unavailable in the data dictionary cache
3238 before starting to drop the table. */
3240 for (index
= dict_table_get_first_index(table
);
3242 index
= dict_table_get_next_index(index
)) {
3243 rw_lock_x_lock(dict_index_get_lock(index
));
3244 ut_ad(!index
->to_be_dropped
);
3245 index
->to_be_dropped
= TRUE
;
3246 rw_lock_x_unlock(dict_index_get_lock(index
));
3249 /* We use the private SQL parser of Innobase to generate the
3250 query graphs needed in deleting the dictionary data from system
3251 tables in Innobase. Deleting a row from SYS_INDEXES table also
3252 frees the file segments of the B-tree associated with the index. */
3254 info
= pars_info_create();
3256 pars_info_add_str_literal(info
, "table_name", name
);
3258 err
= que_eval_sql(info
,
3259 "PROCEDURE DROP_TABLE_PROC () IS\n"
3260 "sys_foreign_id CHAR;\n"
3263 "foreign_id CHAR;\n"
3266 "DECLARE CURSOR cur_fk IS\n"
3267 "SELECT ID FROM SYS_FOREIGN\n"
3268 "WHERE FOR_NAME = :table_name\n"
3269 "AND TO_BINARY(FOR_NAME)\n"
3270 " = TO_BINARY(:table_name)\n"
3271 "LOCK IN SHARE MODE;\n"
3273 "DECLARE CURSOR cur_idx IS\n"
3274 "SELECT ID FROM SYS_INDEXES\n"
3275 "WHERE TABLE_ID = table_id\n"
3276 "LOCK IN SHARE MODE;\n"
3279 "SELECT ID INTO table_id\n"
3281 "WHERE NAME = :table_name\n"
3282 "LOCK IN SHARE MODE;\n"
3283 "IF (SQL % NOTFOUND) THEN\n"
3287 "SELECT ID INTO sys_foreign_id\n"
3289 "WHERE NAME = 'SYS_FOREIGN'\n"
3290 "LOCK IN SHARE MODE;\n"
3291 "IF (SQL % NOTFOUND) THEN\n"
3294 "IF (:table_name = 'SYS_FOREIGN') THEN\n"
3297 "IF (:table_name = 'SYS_FOREIGN_COLS') THEN\n"
3301 "WHILE found = 1 LOOP\n"
3302 " FETCH cur_fk INTO foreign_id;\n"
3303 " IF (SQL % NOTFOUND) THEN\n"
3306 " DELETE FROM SYS_FOREIGN_COLS\n"
3307 " WHERE ID = foreign_id;\n"
3308 " DELETE FROM SYS_FOREIGN\n"
3309 " WHERE ID = foreign_id;\n"
3315 "WHILE found = 1 LOOP\n"
3316 " FETCH cur_idx INTO index_id;\n"
3317 " IF (SQL % NOTFOUND) THEN\n"
3320 " DELETE FROM SYS_FIELDS\n"
3321 " WHERE INDEX_ID = index_id;\n"
3322 " DELETE FROM SYS_INDEXES\n"
3323 " WHERE ID = index_id\n"
3324 " AND TABLE_ID = table_id;\n"
3328 "DELETE FROM SYS_COLUMNS\n"
3329 "WHERE TABLE_ID = table_id;\n"
3330 "DELETE FROM SYS_TABLES\n"
3331 "WHERE ID = table_id;\n"
3337 const char* name_or_path
;
3342 heap
= mem_heap_create(200);
3344 /* Clone the name, in case it has been allocated
3345 from table->heap, which will be freed by
3346 dict_table_remove_from_cache(table) below. */
3347 name
= mem_heap_strdup(heap
, name
);
3348 space_id
= table
->space
;
3350 if (table
->dir_path_of_temp_table
!= NULL
) {
3351 name_or_path
= mem_heap_strdup(
3352 heap
, table
->dir_path_of_temp_table
);
3355 name_or_path
= name
;
3356 is_temp
= (table
->flags
>> DICT_TF2_SHIFT
)
3357 & DICT_TF2_TEMPORARY
;
3360 dict_table_remove_from_cache(table
);
3362 if (dict_load_table(name
) != NULL
) {
3363 ut_print_timestamp(stderr
);
3364 fputs(" InnoDB: Error: not able to remove table ",
3366 ut_print_name(stderr
, trx
, TRUE
, name
);
3367 fputs(" from the dictionary cache!\n", stderr
);
3371 /* Do not drop possible .ibd tablespace if something went
3372 wrong: we do not want to delete valuable data of the user */
3374 if (err
== DB_SUCCESS
&& space_id
> 0) {
3375 if (!fil_space_for_table_exists_in_mem(space_id
,
3382 "InnoDB: We removed now the InnoDB"
3383 " internal data dictionary entry\n"
3384 "InnoDB: of table ");
3385 ut_print_name(stderr
, trx
, TRUE
, name
);
3386 fprintf(stderr
, ".\n");
3387 } else if (!fil_delete_tablespace(space_id
)) {
3389 "InnoDB: We removed now the InnoDB"
3390 " internal data dictionary entry\n"
3391 "InnoDB: of table ");
3392 ut_print_name(stderr
, trx
, TRUE
, name
);
3393 fprintf(stderr
, ".\n");
3395 ut_print_timestamp(stderr
);
3397 " InnoDB: Error: not able to"
3398 " delete tablespace %lu of table ",
3400 ut_print_name(stderr
, trx
, TRUE
, name
);
3401 fputs("!\n", stderr
);
3406 mem_heap_free(heap
);
3409 case DB_TOO_MANY_CONCURRENT_TRXS
:
3410 /* Cannot even find a free slot for the
3411 the undo log. We can directly exit here
3412 and return the DB_TOO_MANY_CONCURRENT_TRXS
3415 /* Mark all indexes available in the data dictionary
3418 for (index
= dict_table_get_first_index(table
);
3420 index
= dict_table_get_next_index(index
)) {
3421 rw_lock_x_lock(dict_index_get_lock(index
));
3422 index
->to_be_dropped
= FALSE
;
3423 rw_lock_x_unlock(dict_index_get_lock(index
));
3427 case DB_OUT_OF_FILE_SPACE
:
3428 err
= DB_MUST_GET_MORE_FILE_SPACE
;
3430 row_mysql_handle_errors(&err
, trx
, NULL
, NULL
);
3432 /* Fall through to raise error */
3435 /* No other possible error returns */
3441 if (locked_dictionary
) {
3442 trx_commit_for_mysql(trx
);
3444 row_mysql_unlock_data_dictionary(trx
);
3449 srv_wake_master_thread();
3454 /*********************************************************************//**
3455 Drop all temporary tables during crash recovery. */
3458 row_mysql_drop_temp_tables(void)
3459 /*============================*/
3466 trx
= trx_allocate_for_background();
3467 trx
->op_info
= "dropping temporary tables";
3468 row_mysql_lock_data_dictionary(trx
);
3470 heap
= mem_heap_create(200);
3474 btr_pcur_open_at_index_side(
3476 dict_table_get_first_index(dict_sys
->sys_tables
),
3477 BTR_SEARCH_LEAF
, &pcur
, TRUE
, &mtr
);
3483 const char* table_name
;
3484 dict_table_t
* table
;
3486 btr_pcur_move_to_next_user_rec(&pcur
, &mtr
);
3488 if (!btr_pcur_is_on_user_rec(&pcur
)) {
3492 rec
= btr_pcur_get_rec(&pcur
);
3493 field
= rec_get_nth_field_old(rec
, 4/*N_COLS*/, &len
);
3494 if (len
!= 4 || !(mach_read_from_4(field
) & 0x80000000UL
)) {
3498 /* Because this is not a ROW_FORMAT=REDUNDANT table,
3499 the is_temp flag is valid. Examine it. */
3501 field
= rec_get_nth_field_old(rec
, 7/*MIX_LEN*/, &len
);
3503 || !(mach_read_from_4(field
) & DICT_TF2_TEMPORARY
)) {
3507 /* This is a temporary table. */
3508 field
= rec_get_nth_field_old(rec
, 0/*NAME*/, &len
);
3509 if (len
== UNIV_SQL_NULL
|| len
== 0) {
3510 /* Corrupted SYS_TABLES.NAME */
3514 table_name
= mem_heap_strdupl(heap
, (const char*) field
, len
);
3516 btr_pcur_store_position(&pcur
, &mtr
);
3517 btr_pcur_commit_specify_mtr(&pcur
, &mtr
);
3519 table
= dict_load_table(table_name
);
3522 row_drop_table_for_mysql(table_name
, trx
, FALSE
);
3523 trx_commit_for_mysql(trx
);
3527 btr_pcur_restore_position(BTR_SEARCH_LEAF
,
3531 btr_pcur_close(&pcur
);
3533 mem_heap_free(heap
);
3534 row_mysql_unlock_data_dictionary(trx
);
3535 trx_free_for_background(trx
);
3538 /*******************************************************************//**
3539 Drop all foreign keys in a database, see Bug#18942.
3540 Called at the end of row_drop_database_for_mysql().
3541 @return error code or DB_SUCCESS */
3544 drop_all_foreign_keys_in_db(
3545 /*========================*/
3546 const char* name
, /*!< in: database name which ends to '/' */
3547 trx_t
* trx
) /*!< in: transaction handle */
3552 ut_a(name
[strlen(name
) - 1] == '/');
3554 pinfo
= pars_info_create();
3556 pars_info_add_str_literal(pinfo
, "dbname", name
);
3558 /** true if for_name is not prefixed with dbname */
3559 #define TABLE_NOT_IN_THIS_DB \
3560 "SUBSTR(for_name, 0, LENGTH(:dbname)) <> :dbname"
3562 err
= que_eval_sql(pinfo
,
3563 "PROCEDURE DROP_ALL_FOREIGN_KEYS_PROC () IS\n"
3564 "foreign_id CHAR;\n"
3567 "DECLARE CURSOR cur IS\n"
3568 "SELECT ID, FOR_NAME FROM SYS_FOREIGN\n"
3569 "WHERE FOR_NAME >= :dbname\n"
3570 "LOCK IN SHARE MODE\n"
3571 "ORDER BY FOR_NAME;\n"
3575 "WHILE found = 1 LOOP\n"
3576 " FETCH cur INTO foreign_id, for_name;\n"
3577 " IF (SQL % NOTFOUND) THEN\n"
3579 " ELSIF (" TABLE_NOT_IN_THIS_DB
") THEN\n"
3581 " ELSIF (1=1) THEN\n"
3582 " DELETE FROM SYS_FOREIGN_COLS\n"
3583 " WHERE ID = foreign_id;\n"
3584 " DELETE FROM SYS_FOREIGN\n"
3585 " WHERE ID = foreign_id;\n"
3591 FALSE
, /* do not reserve dict mutex,
3592 we are already holding it */
3598 /*********************************************************************//**
3599 Drops a database for MySQL.
3600 @return error code or DB_SUCCESS */
3603 row_drop_database_for_mysql(
3604 /*========================*/
3605 const char* name
, /*!< in: database name which ends to '/' */
3606 trx_t
* trx
) /*!< in: transaction handle */
3608 dict_table_t
* table
;
3610 int err
= DB_SUCCESS
;
3611 ulint namelen
= strlen(name
);
3613 ut_ad(trx
->mysql_thread_id
== os_thread_get_curr_id());
3615 ut_a(name
[namelen
- 1] == '/');
3617 trx
->op_info
= "dropping database";
3619 trx_start_if_not_started(trx
);
3621 row_mysql_lock_data_dictionary(trx
);
3623 while ((table_name
= dict_get_first_table_name_in_db(name
))) {
3624 ut_a(memcmp(table_name
, name
, namelen
) == 0);
3626 table
= dict_table_get_low(table_name
);
3630 /* Wait until MySQL does not have any queries running on
3633 if (table
->n_mysql_handles_opened
> 0) {
3634 row_mysql_unlock_data_dictionary(trx
);
3636 ut_print_timestamp(stderr
);
3637 fputs(" InnoDB: Warning: MySQL is trying to"
3638 " drop database ", stderr
);
3639 ut_print_name(stderr
, trx
, TRUE
, name
);
3641 "InnoDB: though there are still"
3642 " open handles to table ", stderr
);
3643 ut_print_name(stderr
, trx
, TRUE
, table_name
);
3644 fputs(".\n", stderr
);
3646 os_thread_sleep(1000000);
3648 mem_free(table_name
);
3653 err
= row_drop_table_for_mysql(table_name
, trx
, TRUE
);
3654 trx_commit_for_mysql(trx
);
3656 if (err
!= DB_SUCCESS
) {
3657 fputs("InnoDB: DROP DATABASE ", stderr
);
3658 ut_print_name(stderr
, trx
, TRUE
, name
);
3659 fprintf(stderr
, " failed with error %lu for table ",
3661 ut_print_name(stderr
, trx
, TRUE
, table_name
);
3663 mem_free(table_name
);
3667 mem_free(table_name
);
3670 if (err
== DB_SUCCESS
) {
3671 /* after dropping all tables try to drop all leftover
3672 foreign keys in case orphaned ones exist */
3673 err
= (int) drop_all_foreign_keys_in_db(name
, trx
);
3675 if (err
!= DB_SUCCESS
) {
3676 fputs("InnoDB: DROP DATABASE ", stderr
);
3677 ut_print_name(stderr
, trx
, TRUE
, name
);
3678 fprintf(stderr
, " failed with error %d while "
3679 "dropping all foreign keys", err
);
3683 trx_commit_for_mysql(trx
);
3685 row_mysql_unlock_data_dictionary(trx
);
3692 /*********************************************************************//**
3693 Checks if a table name contains the string "/#sql" which denotes temporary
3695 @return TRUE if temporary table */
3698 row_is_mysql_tmp_table_name(
3699 /*========================*/
3700 const char* name
) /*!< in: table name in the form
3701 'database/tablename' */
3703 return(strstr(name
, "/#sql") != NULL
);
3704 /* return(strstr(name, "/@0023sql") != NULL); */
3707 /****************************************************************//**
3708 Delete a single constraint.
3709 @return error code or DB_SUCCESS */
3712 row_delete_constraint_low(
3713 /*======================*/
3714 const char* id
, /*!< in: constraint id */
3715 trx_t
* trx
) /*!< in: transaction handle */
3717 pars_info_t
* info
= pars_info_create();
3719 pars_info_add_str_literal(info
, "id", id
);
3721 return((int) que_eval_sql(info
,
3722 "PROCEDURE DELETE_CONSTRAINT () IS\n"
3724 "DELETE FROM SYS_FOREIGN_COLS WHERE ID = :id;\n"
3725 "DELETE FROM SYS_FOREIGN WHERE ID = :id;\n"
3730 /****************************************************************//**
3731 Delete a single constraint.
3732 @return error code or DB_SUCCESS */
3735 row_delete_constraint(
3736 /*==================*/
3737 const char* id
, /*!< in: constraint id */
3738 const char* database_name
, /*!< in: database name, with the
3740 mem_heap_t
* heap
, /*!< in: memory heap */
3741 trx_t
* trx
) /*!< in: transaction handle */
3745 /* New format constraints have ids <databasename>/<constraintname>. */
3746 err
= row_delete_constraint_low(
3747 mem_heap_strcat(heap
, database_name
, id
), trx
);
3749 if ((err
== DB_SUCCESS
) && !strchr(id
, '/')) {
3750 /* Old format < 4.0.18 constraints have constraint ids
3751 NUMBER_NUMBER. We only try deleting them if the
3752 constraint name does not contain a '/' character, otherwise
3753 deleting a new format constraint named 'foo/bar' from
3754 database 'baz' would remove constraint 'bar' from database
3755 'foo', if it existed. */
3757 err
= row_delete_constraint_low(id
, trx
);
3763 /*********************************************************************//**
3764 Renames a table for MySQL.
3765 @return error code or DB_SUCCESS */
3768 row_rename_table_for_mysql(
3769 /*=======================*/
3770 const char* old_name
, /*!< in: old table name */
3771 const char* new_name
, /*!< in: new table name */
3772 trx_t
* trx
, /*!< in: transaction handle */
3773 ibool commit
) /*!< in: if TRUE then commit trx */
3775 dict_table_t
* table
;
3776 ulint err
= DB_ERROR
;
3777 mem_heap_t
* heap
= NULL
;
3778 const char** constraints_to_drop
= NULL
;
3779 ulint n_constraints_to_drop
= 0;
3780 ibool old_is_tmp
, new_is_tmp
;
3781 pars_info_t
* info
= NULL
;
3784 ut_ad(trx
->mysql_thread_id
== os_thread_get_curr_id());
3785 ut_a(old_name
!= NULL
);
3786 ut_a(new_name
!= NULL
);
3788 if (srv_created_new_raw
|| srv_force_recovery
) {
3789 fputs("InnoDB: A new raw disk partition was initialized or\n"
3790 "InnoDB: innodb_force_recovery is on: we do not allow\n"
3791 "InnoDB: database modifications by the user. Shut down\n"
3792 "InnoDB: mysqld and edit my.cnf so that newraw"
3794 "InnoDB: with raw, and innodb_force_... is removed.\n",
3798 } else if (row_mysql_is_system_table(new_name
)) {
3801 "InnoDB: Error: trying to create a MySQL"
3802 " system table %s of type InnoDB.\n"
3803 "InnoDB: MySQL system tables must be"
3804 " of the MyISAM type!\n",
3810 trx
->op_info
= "renaming table";
3811 trx_start_if_not_started(trx
);
3813 old_is_tmp
= row_is_mysql_tmp_table_name(old_name
);
3814 new_is_tmp
= row_is_mysql_tmp_table_name(new_name
);
3816 table
= dict_table_get_low(old_name
);
3819 err
= DB_TABLE_NOT_FOUND
;
3820 ut_print_timestamp(stderr
);
3822 fputs(" InnoDB: Error: table ", stderr
);
3823 ut_print_name(stderr
, trx
, TRUE
, old_name
);
3824 fputs(" does not exist in the InnoDB internal\n"
3825 "InnoDB: data dictionary though MySQL is"
3826 " trying to rename the table.\n"
3827 "InnoDB: Have you copied the .frm file"
3828 " of the table to the\n"
3829 "InnoDB: MySQL database directory"
3830 " from another database?\n"
3831 "InnoDB: You can look for further help from\n"
3832 "InnoDB: " REFMAN
"innodb-troubleshooting.html\n",
3835 } else if (table
->ibd_file_missing
) {
3836 err
= DB_TABLE_NOT_FOUND
;
3837 ut_print_timestamp(stderr
);
3839 fputs(" InnoDB: Error: table ", stderr
);
3840 ut_print_name(stderr
, trx
, TRUE
, old_name
);
3841 fputs(" does not have an .ibd file"
3842 " in the database directory.\n"
3843 "InnoDB: You can look for further help from\n"
3844 "InnoDB: " REFMAN
"innodb-troubleshooting.html\n",
3847 } else if (new_is_tmp
) {
3848 /* MySQL is doing an ALTER TABLE command and it renames the
3849 original table to a temporary table name. We want to preserve
3850 the original foreign key constraint definitions despite the
3851 name change. An exception is those constraints for which
3852 the ALTER TABLE contained DROP FOREIGN KEY <foreign key id>.*/
3854 heap
= mem_heap_create(100);
3856 err
= dict_foreign_parse_drop_constraints(
3857 heap
, trx
, table
, &n_constraints_to_drop
,
3858 &constraints_to_drop
);
3860 if (err
!= DB_SUCCESS
) {
3866 /* Is a foreign key check running on this table? */
3867 for (retry
= 0; retry
< 100
3868 && table
->n_foreign_key_checks_running
> 0; ++retry
) {
3869 row_mysql_unlock_data_dictionary(trx
);
3871 row_mysql_lock_data_dictionary(trx
);
3874 if (table
->n_foreign_key_checks_running
> 0) {
3875 ut_print_timestamp(stderr
);
3876 fputs(" InnoDB: Error: in ALTER TABLE ", stderr
);
3877 ut_print_name(stderr
, trx
, TRUE
, old_name
);
3878 fprintf(stderr
, "\n"
3879 "InnoDB: a FOREIGN KEY check is running.\n"
3880 "InnoDB: Cannot rename table.\n");
3881 err
= DB_TABLE_IN_FK_CHECK
;
3885 /* We use the private SQL parser of Innobase to generate the query
3886 graphs needed in updating the dictionary data from system tables. */
3888 info
= pars_info_create();
3890 pars_info_add_str_literal(info
, "new_table_name", new_name
);
3891 pars_info_add_str_literal(info
, "old_table_name", old_name
);
3893 err
= que_eval_sql(info
,
3894 "PROCEDURE RENAME_TABLE () IS\n"
3896 "UPDATE SYS_TABLES SET NAME = :new_table_name\n"
3897 " WHERE NAME = :old_table_name;\n"
3901 if (err
!= DB_SUCCESS
) {
3904 } else if (!new_is_tmp
) {
3905 /* Rename all constraints. */
3906 char new_table_name
[MAX_TABLE_NAME_LEN
] = "";
3907 char old_table_utf8
[MAX_TABLE_NAME_LEN
] = "";
3910 strncpy(old_table_utf8
, old_name
, MAX_TABLE_NAME_LEN
);
3911 innobase_convert_to_system_charset(
3912 strchr(old_table_utf8
, '/') + 1,
3913 strchr(old_name
, '/') +1,
3914 MAX_TABLE_NAME_LEN
, &errors
);
3917 /* Table name could not be converted from charset
3918 my_charset_filename to UTF-8. This means that the
3919 table name is already in UTF-8 (#mysql#50). */
3920 strncpy(old_table_utf8
, old_name
, MAX_TABLE_NAME_LEN
);
3923 info
= pars_info_create();
3925 pars_info_add_str_literal(info
, "new_table_name", new_name
);
3926 pars_info_add_str_literal(info
, "old_table_name", old_name
);
3927 pars_info_add_str_literal(info
, "old_table_name_utf8",
3930 strncpy(new_table_name
, new_name
, MAX_TABLE_NAME_LEN
);
3931 innobase_convert_to_system_charset(
3932 strchr(new_table_name
, '/') + 1,
3933 strchr(new_name
, '/') +1,
3934 MAX_TABLE_NAME_LEN
, &errors
);
3937 /* Table name could not be converted from charset
3938 my_charset_filename to UTF-8. This means that the
3939 table name is already in UTF-8 (#mysql#50). */
3940 strncpy(new_table_name
, new_name
, MAX_TABLE_NAME_LEN
);
3943 pars_info_add_str_literal(info
, "new_table_utf8", new_table_name
);
3947 "PROCEDURE RENAME_CONSTRAINT_IDS () IS\n"
3948 "gen_constr_prefix CHAR;\n"
3949 "new_db_name CHAR;\n"
3950 "foreign_id CHAR;\n"
3951 "new_foreign_id CHAR;\n"
3952 "old_db_name_len INT;\n"
3953 "old_t_name_len INT;\n"
3954 "new_db_name_len INT;\n"
3960 "old_db_name_len := INSTR(:old_table_name, '/')-1;\n"
3961 "new_db_name_len := INSTR(:new_table_name, '/')-1;\n"
3962 "new_db_name := SUBSTR(:new_table_name, 0,\n"
3963 " new_db_name_len);\n"
3964 "old_t_name_len := LENGTH(:old_table_name);\n"
3965 "gen_constr_prefix := CONCAT(:old_table_name_utf8,\n"
3967 "WHILE found = 1 LOOP\n"
3968 " SELECT ID INTO foreign_id\n"
3969 " FROM SYS_FOREIGN\n"
3970 " WHERE FOR_NAME = :old_table_name\n"
3971 " AND TO_BINARY(FOR_NAME)\n"
3972 " = TO_BINARY(:old_table_name)\n"
3973 " LOCK IN SHARE MODE;\n"
3974 " IF (SQL % NOTFOUND) THEN\n"
3977 " UPDATE SYS_FOREIGN\n"
3978 " SET FOR_NAME = :new_table_name\n"
3979 " WHERE ID = foreign_id;\n"
3980 " id_len := LENGTH(foreign_id);\n"
3981 " IF (INSTR(foreign_id, '/') > 0) THEN\n"
3982 " IF (INSTR(foreign_id,\n"
3983 " gen_constr_prefix) > 0)\n"
3985 " offset := INSTR(foreign_id, '_ibfk_') - 1;\n"
3986 " new_foreign_id :=\n"
3987 " CONCAT(:new_table_utf8,\n"
3988 " SUBSTR(foreign_id, offset,\n"
3989 " id_len - offset));\n"
3991 " new_foreign_id :=\n"
3992 " CONCAT(new_db_name,\n"
3993 " SUBSTR(foreign_id,\n"
3994 " old_db_name_len,\n"
3995 " id_len - old_db_name_len));\n"
3997 " UPDATE SYS_FOREIGN\n"
3998 " SET ID = new_foreign_id\n"
3999 " WHERE ID = foreign_id;\n"
4000 " UPDATE SYS_FOREIGN_COLS\n"
4001 " SET ID = new_foreign_id\n"
4002 " WHERE ID = foreign_id;\n"
4006 "UPDATE SYS_FOREIGN SET REF_NAME = :new_table_name\n"
4007 "WHERE REF_NAME = :old_table_name\n"
4008 " AND TO_BINARY(REF_NAME)\n"
4009 " = TO_BINARY(:old_table_name);\n"
4013 } else if (n_constraints_to_drop
> 0) {
4014 /* Drop some constraints of tmp tables. */
4016 ulint db_name_len
= dict_get_db_name_len(old_name
) + 1;
4017 char* db_name
= mem_heap_strdupl(heap
, old_name
,
4021 for (i
= 0; i
< n_constraints_to_drop
; i
++) {
4022 err
= row_delete_constraint(constraints_to_drop
[i
],
4023 db_name
, heap
, trx
);
4025 if (err
!= DB_SUCCESS
) {
4032 if (err
!= DB_SUCCESS
) {
4033 if (err
== DB_DUPLICATE_KEY
) {
4034 ut_print_timestamp(stderr
);
4035 fputs(" InnoDB: Error; possible reasons:\n"
4036 "InnoDB: 1) Table rename would cause"
4037 " two FOREIGN KEY constraints\n"
4038 "InnoDB: to have the same internal name"
4039 " in case-insensitive comparison.\n"
4040 "InnoDB: 2) table ", stderr
);
4041 ut_print_name(stderr
, trx
, TRUE
, new_name
);
4042 fputs(" exists in the InnoDB internal data\n"
4043 "InnoDB: dictionary though MySQL is"
4044 " trying to rename table ", stderr
);
4045 ut_print_name(stderr
, trx
, TRUE
, old_name
);
4047 "InnoDB: Have you deleted the .frm file"
4048 " and not used DROP TABLE?\n"
4049 "InnoDB: You can look for further help from\n"
4050 "InnoDB: " REFMAN
"innodb-troubleshooting.html\n"
4051 "InnoDB: If table ", stderr
);
4052 ut_print_name(stderr
, trx
, TRUE
, new_name
);
4053 fputs(" is a temporary table #sql..., then"
4055 "InnoDB: there are still queries running"
4056 " on the table, and it will be\n"
4057 "InnoDB: dropped automatically when"
4058 " the queries end.\n"
4059 "InnoDB: You can drop the orphaned table"
4060 " inside InnoDB by\n"
4061 "InnoDB: creating an InnoDB table with"
4062 " the same name in another\n"
4063 "InnoDB: database and copying the .frm file"
4064 " to the current database.\n"
4065 "InnoDB: Then MySQL thinks the table exists,"
4066 " and DROP TABLE will\n"
4067 "InnoDB: succeed.\n", stderr
);
4069 trx
->error_state
= DB_SUCCESS
;
4070 trx_general_rollback_for_mysql(trx
, NULL
);
4071 trx
->error_state
= DB_SUCCESS
;
4073 /* The following call will also rename the .ibd data file if
4074 the table is stored in a single-table tablespace */
4076 if (!dict_table_rename_in_cache(table
, new_name
,
4078 trx
->error_state
= DB_SUCCESS
;
4079 trx_general_rollback_for_mysql(trx
, NULL
);
4080 trx
->error_state
= DB_SUCCESS
;
4085 /* We only want to switch off some of the type checking in
4086 an ALTER, not in a RENAME. */
4088 err
= dict_load_foreigns(
4089 new_name
, FALSE
, !old_is_tmp
|| trx
->check_foreigns
);
4091 if (err
!= DB_SUCCESS
) {
4092 ut_print_timestamp(stderr
);
4095 fputs(" InnoDB: Error: in ALTER TABLE ",
4097 ut_print_name(stderr
, trx
, TRUE
, new_name
);
4099 "InnoDB: has or is referenced"
4100 " in foreign key constraints\n"
4101 "InnoDB: which are not compatible"
4102 " with the new table definition.\n",
4105 fputs(" InnoDB: Error: in RENAME TABLE"
4108 ut_print_name(stderr
, trx
, TRUE
, new_name
);
4110 "InnoDB: is referenced in"
4111 " foreign key constraints\n"
4112 "InnoDB: which are not compatible"
4113 " with the new table definition.\n",
4117 ut_a(dict_table_rename_in_cache(table
,
4119 trx
->error_state
= DB_SUCCESS
;
4120 trx_general_rollback_for_mysql(trx
, NULL
);
4121 trx
->error_state
= DB_SUCCESS
;
4123 if (old_is_tmp
&& !new_is_tmp
) {
4124 /* After ALTER TABLE the table statistics
4125 needs to be rebuilt. It will be rebuilt
4126 when the table is loaded again. */
4127 table
->stat_initialized
= FALSE
;
4135 trx_commit_for_mysql(trx
);
4138 if (UNIV_LIKELY_NULL(heap
)) {
4139 mem_heap_free(heap
);
4147 /*********************************************************************//**
4148 Checks that the index contains entries in an ascending order, unique
4149 constraint is not broken, and calculates the number of index entries
4150 in the read view of the current transaction.
4151 @return TRUE if ok */
4154 row_check_index_for_mysql(
4155 /*======================*/
4156 row_prebuilt_t
* prebuilt
, /*!< in: prebuilt struct
4158 const dict_index_t
* index
, /*!< in: index */
4159 ulint
* n_rows
) /*!< out: number of entries
4160 seen in the consistent read */
4162 dtuple_t
* prev_entry
= NULL
;
4163 ulint matched_fields
;
4164 ulint matched_bytes
;
4170 ibool contains_null
;
4173 mem_heap_t
* heap
= NULL
;
4175 ulint offsets_
[REC_OFFS_NORMAL_SIZE
];
4177 rec_offs_init(offsets_
);
4181 buf
= mem_alloc(UNIV_PAGE_SIZE
);
4182 heap
= mem_heap_create(100);
4186 ret
= row_search_for_mysql(buf
, PAGE_CUR_G
, prebuilt
, 0, 0);
4188 /* Check thd->killed every 1,000 scanned rows */
4190 if (trx_is_interrupted(prebuilt
->trx
)) {
4200 ut_print_timestamp(stderr
);
4201 fputs(" InnoDB: Warning: CHECK TABLE on ", stderr
);
4202 dict_index_name_print(stderr
, prebuilt
->trx
, index
);
4203 fprintf(stderr
, " returned %lu\n", ret
);
4204 /* fall through (this error is ignored by CHECK TABLE) */
4205 case DB_END_OF_INDEX
:
4208 mem_heap_free(heap
);
4213 *n_rows
= *n_rows
+ 1;
4215 /* row_search... returns the index record in buf, record origin offset
4216 within buf stored in the first 4 bytes, because we have built a dummy
4219 rec
= buf
+ mach_read_from_4(buf
);
4221 offsets
= rec_get_offsets(rec
, index
, offsets_
,
4222 ULINT_UNDEFINED
, &heap
);
4224 if (prev_entry
!= NULL
) {
4228 cmp
= cmp_dtuple_rec_with_match(prev_entry
, rec
, offsets
,
4231 contains_null
= FALSE
;
4233 /* In a unique secondary index we allow equal key values if
4234 they contain SQL NULLs */
4237 i
< dict_index_get_n_ordering_defined_by_user(index
);
4239 if (UNIV_SQL_NULL
== dfield_get_len(
4240 dtuple_get_nth_field(prev_entry
, i
))) {
4242 contains_null
= TRUE
;
4247 fputs("InnoDB: index records in a wrong order in ",
4250 dict_index_name_print(stderr
,
4251 prebuilt
->trx
, index
);
4253 "InnoDB: prev record ", stderr
);
4254 dtuple_print(stderr
, prev_entry
);
4256 "InnoDB: record ", stderr
);
4257 rec_print_new(stderr
, rec
, offsets
);
4260 } else if (dict_index_is_unique(index
)
4263 >= dict_index_get_n_ordering_defined_by_user(
4266 fputs("InnoDB: duplicate key in ", stderr
);
4272 mem_heap_t
* tmp_heap
= NULL
;
4274 /* Empty the heap on each round. But preserve offsets[]
4275 for the row_rec_to_index_entry() call, by copying them
4276 into a separate memory heap when needed. */
4277 if (UNIV_UNLIKELY(offsets
!= offsets_
)) {
4278 ulint size
= rec_offs_get_n_alloc(offsets
)
4281 tmp_heap
= mem_heap_create(size
);
4282 offsets
= mem_heap_dup(tmp_heap
, offsets
, size
);
4285 mem_heap_empty(heap
);
4287 prev_entry
= row_rec_to_index_entry(ROW_COPY_DATA
, rec
,
4291 if (UNIV_LIKELY_NULL(tmp_heap
)) {
4292 mem_heap_free(tmp_heap
);
4296 ret
= row_search_for_mysql(buf
, PAGE_CUR_G
, prebuilt
, 0, ROW_SEL_NEXT
);
4301 /*********************************************************************//**
4302 Determines if a table is a magic monitor table.
4303 @return TRUE if monitor table */
4306 row_is_magic_monitor_table(
4307 /*=======================*/
4308 const char* table_name
) /*!< in: name of the table, in the
4309 form database/table_name */
4311 const char* name
; /* table_name without database/ */
4314 name
= strchr(table_name
, '/');
4317 len
= strlen(name
) + 1;
4319 if (STR_EQ(name
, len
, S_innodb_monitor
)
4320 || STR_EQ(name
, len
, S_innodb_lock_monitor
)
4321 || STR_EQ(name
, len
, S_innodb_tablespace_monitor
)
4322 || STR_EQ(name
, len
, S_innodb_table_monitor
)
4323 || STR_EQ(name
, len
, S_innodb_mem_validate
)) {