1
/*****************************************************************************
3
Copyright (c) 2000, 2010, Innobase Oy. 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., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 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"
57
/** Provide optional 4.x backwards compatibility for 5.0 and above */
58
UNIV_INTERN ibool row_rollback_on_timeout = FALSE;
60
/** Chain node of the list of tables to drop in the background. */
61
typedef struct row_mysql_drop_struct row_mysql_drop_t;
63
/** Chain node of the list of tables to drop in the background. */
64
struct row_mysql_drop_struct{
65
char* table_name; /*!< table name */
66
UT_LIST_NODE_T(row_mysql_drop_t)row_mysql_drop_list;
67
/*!< list chain node */
70
/** @brief List of tables we should drop in background.
72
ALTER TABLE in MySQL requires that the table handler can drop the
73
table in background when there are no queries to it any
74
more. Protected by kernel_mutex. */
75
static UT_LIST_BASE_NODE_T(row_mysql_drop_t) row_mysql_drop_list;
76
/** Flag: has row_mysql_drop_list been initialized? */
77
static ibool row_mysql_drop_list_inited = FALSE;
79
/** Magic table names for invoking various monitor threads */
81
static const char S_innodb_monitor[] = "innodb_monitor";
82
static const char S_innodb_lock_monitor[] = "innodb_lock_monitor";
83
static const char S_innodb_tablespace_monitor[] = "innodb_tablespace_monitor";
84
static const char S_innodb_table_monitor[] = "innodb_table_monitor";
85
static const char S_innodb_mem_validate[] = "innodb_mem_validate";
88
/** Evaluates to true if str1 equals str2_onstack, used for comparing
89
the magic table names.
90
@param str1 in: string to compare
91
@param str1_len in: length of str1, in bytes, including terminating NUL
92
@param str2_onstack in: char[] array containing a NUL terminated string
93
@return TRUE if str1 equals str2_onstack */
94
#define STR_EQ(str1, str1_len, str2_onstack) \
95
((str1_len) == sizeof(str2_onstack) \
96
&& memcmp(str1, str2_onstack, sizeof(str2_onstack)) == 0)
98
/*********************************************************************//**
99
If a table is not yet in the drop list, adds the table to the list of tables
100
which the master thread drops in background. We need this on Unix because in
101
ALTER TABLE MySQL may call drop table even if the table has running queries on
102
it. Also, if there are running foreign key checks on the table, we drop the
104
@return TRUE if the table was not yet in the drop list, and was added there */
107
row_add_table_to_background_drop_list(
108
/*==================================*/
109
const char* name); /*!< in: table name */
111
/*******************************************************************//**
112
Delays an INSERT, DELETE or UPDATE operation if the purge is lagging. */
115
row_mysql_delay_if_needed(void)
116
/*===========================*/
118
if (srv_dml_needed_delay) {
119
os_thread_sleep(srv_dml_needed_delay);
123
/*******************************************************************//**
124
Frees the blob heap in prebuilt when no longer needed. */
127
row_mysql_prebuilt_free_blob_heap(
128
/*==============================*/
129
row_prebuilt_t* prebuilt) /*!< in: prebuilt struct of a
130
ha_innobase:: table handle */
132
mem_heap_free(prebuilt->blob_heap);
133
prebuilt->blob_heap = NULL;
136
/*******************************************************************//**
137
Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL row
139
@return pointer to the data, we skip the 1 or 2 bytes at the start
140
that are used to store the len */
143
row_mysql_store_true_var_len(
144
/*=========================*/
145
byte* dest, /*!< in: where to store */
146
ulint len, /*!< in: length, must fit in two bytes */
147
ulint lenlen) /*!< in: storage length of len: either 1 or 2 bytes */
150
ut_a(len < 256 * 256);
152
mach_write_to_2_little_endian(dest, len);
160
mach_write_to_1(dest, len);
165
/*******************************************************************//**
166
Reads a >= 5.0.3 format true VARCHAR length, in the MySQL row format, and
167
returns a pointer to the data.
168
@return pointer to the data, we skip the 1 or 2 bytes at the start
169
that are used to store the len */
172
row_mysql_read_true_varchar(
173
/*========================*/
174
ulint* len, /*!< out: variable-length field length */
175
const byte* field, /*!< in: field in the MySQL format */
176
ulint lenlen) /*!< in: storage length of len: either 1
180
*len = mach_read_from_2_little_endian(field);
187
*len = mach_read_from_1(field);
192
/*******************************************************************//**
193
Stores a reference to a BLOB in the MySQL format. */
196
row_mysql_store_blob_ref(
197
/*=====================*/
198
byte* dest, /*!< in: where to store */
199
ulint col_len,/*!< in: dest buffer size: determines into
200
how many bytes the BLOB length is stored,
201
the space for the length may vary from 1
203
const void* data, /*!< in: BLOB data; if the value to store
204
is SQL NULL this should be NULL pointer */
205
ulint len) /*!< in: BLOB length; if the value to store
206
is SQL NULL this should be 0; remember
207
also to set the NULL bit in the MySQL record
210
/* MySQL might assume the field is set to zero except the length and
211
the pointer fields */
213
memset(dest, '\0', col_len);
215
/* In dest there are 1 - 4 bytes reserved for the BLOB length,
216
and after that 8 bytes reserved for the pointer to the data.
217
In 32-bit architectures we only use the first 4 bytes of the pointer
220
ut_a(col_len - 8 > 1 || len < 256);
221
ut_a(col_len - 8 > 2 || len < 256 * 256);
222
ut_a(col_len - 8 > 3 || len < 256 * 256 * 256);
224
mach_write_to_n_little_endian(dest, col_len - 8, len);
226
memcpy(dest + col_len - 8, &data, sizeof data);
229
/*******************************************************************//**
230
Reads a reference to a BLOB in the MySQL format.
231
@return pointer to BLOB data */
234
row_mysql_read_blob_ref(
235
/*====================*/
236
ulint* len, /*!< out: BLOB length */
237
const byte* ref, /*!< in: BLOB reference in the
239
ulint col_len) /*!< in: BLOB reference length
244
*len = mach_read_from_n_little_endian(ref, col_len - 8);
246
memcpy(&data, ref + col_len - 8, sizeof data);
251
/**************************************************************//**
252
Pad a column with spaces. */
257
ulint mbminlen, /*!< in: minimum size of a character,
259
byte* pad, /*!< out: padded buffer */
260
ulint len) /*!< in: number of bytes to pad */
264
switch (UNIV_EXPECT(mbminlen, 1)) {
269
memset(pad, 0x20, len);
278
} while (pad < pad_end);
281
/* space=0x00000020 */
289
} while (pad < pad_end);
294
/**************************************************************//**
295
Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
296
The counterpart of this function is row_sel_field_store_in_mysql_format() in
298
@return up to which byte we used buf in the conversion */
301
row_mysql_store_col_in_innobase_format(
302
/*===================================*/
303
dfield_t* dfield, /*!< in/out: dfield where dtype
304
information must be already set when
305
this function is called! */
306
byte* buf, /*!< in/out: buffer for a converted
307
integer value; this must be at least
308
col_len long then! */
309
ibool row_format_col, /*!< TRUE if the mysql_data is from
310
a MySQL row, FALSE if from a MySQL
312
in MySQL, a true VARCHAR storage
313
format differs in a row and in a
314
key value: in a key value the length
315
is always stored in 2 bytes! */
316
const byte* mysql_data, /*!< in: MySQL column value, not
317
SQL NULL; NOTE that dfield may also
318
get a pointer to mysql_data,
319
therefore do not discard this as long
320
as dfield is used! */
321
ulint col_len, /*!< in: MySQL column length; NOTE that
322
this is the storage length of the
323
column in the MySQL format row, not
324
necessarily the length of the actual
325
payload data; if the column is a true
326
VARCHAR then this is irrelevant */
327
ulint comp) /*!< in: nonzero=compact format */
329
const byte* ptr = mysql_data;
330
const dtype_t* dtype;
334
dtype = dfield_get_type(dfield);
338
if (type == DATA_INT) {
339
/* Store integer data in Innobase in a big-endian format,
340
sign bit negated if the data is a signed integer. In MySQL,
341
integers are stored in a little-endian format. */
343
byte* p = buf + col_len;
354
if (!(dtype->prtype & DATA_UNSIGNED)) {
361
} else if ((type == DATA_VARCHAR
362
|| type == DATA_VARMYSQL
363
|| type == DATA_BINARY)) {
365
if (dtype_get_mysql_type(dtype) == DATA_MYSQL_TRUE_VARCHAR) {
366
/* The length of the actual data is stored to 1 or 2
367
bytes at the start of the field */
369
if (row_format_col) {
370
if (dtype->prtype & DATA_LONG_TRUE_VARCHAR) {
376
/* In a MySQL key value, lenlen is always 2 */
380
ptr = row_mysql_read_true_varchar(&col_len, mysql_data,
383
/* Remove trailing spaces from old style VARCHAR
386
/* Handle Unicode strings differently. */
387
ulint mbminlen = dtype_get_mbminlen(dtype);
395
/* space=0x00000020 */
396
/* Trim "half-chars", just in case. */
400
&& ptr[col_len - 4] == 0x00
401
&& ptr[col_len - 3] == 0x00
402
&& ptr[col_len - 2] == 0x00
403
&& ptr[col_len - 1] == 0x20) {
409
/* Trim "half-chars", just in case. */
412
while (col_len >= 2 && ptr[col_len - 2] == 0x00
413
&& ptr[col_len - 1] == 0x20) {
420
&& ptr[col_len - 1] == 0x20) {
425
} else if (comp && type == DATA_MYSQL
426
&& dtype_get_mbminlen(dtype) == 1
427
&& dtype_get_mbmaxlen(dtype) > 1) {
428
/* In some cases we strip trailing spaces from UTF-8 and other
429
multibyte charsets, from FIXED-length CHAR columns, to save
430
space. UTF-8 would otherwise normally use 3 * the string length
431
bytes to store an ASCII string! */
433
/* We assume that this CHAR field is encoded in a
434
variable-length character set where spaces have
435
1:1 correspondence to 0x20 bytes, such as UTF-8.
437
Consider a CHAR(n) field, a field of n characters.
438
It will contain between n * mbminlen and n * mbmaxlen bytes.
439
We will try to truncate it to n bytes by stripping
440
space padding. If the field contains single-byte
441
characters only, it will be truncated to n characters.
442
Consider a CHAR(5) field containing the string ".a "
443
where "." denotes a 3-byte character represented by
444
the bytes "$%&". After our stripping, the string will
445
be stored as "$%&a " (5 bytes). The string ".abc "
446
will be stored as "$%&abc" (6 bytes).
448
The space padding will be restored in row0sel.c, function
449
row_sel_field_store_in_mysql_format(). */
453
ut_a(!(dtype_get_len(dtype) % dtype_get_mbmaxlen(dtype)));
455
n_chars = dtype_get_len(dtype) / dtype_get_mbmaxlen(dtype);
457
/* Strip space padding. */
458
while (col_len > n_chars && ptr[col_len - 1] == 0x20) {
461
} else if (type == DATA_BLOB && row_format_col) {
463
ptr = row_mysql_read_blob_ref(&col_len, mysql_data, col_len);
466
dfield_set_data(dfield, ptr, col_len);
471
/**************************************************************//**
472
Convert a row in the MySQL format to a row in the Innobase format. Note that
473
the function to convert a MySQL format key value to an InnoDB dtuple is
474
row_sel_convert_mysql_key_to_innobase() in row0sel.c. */
477
row_mysql_convert_row_to_innobase(
478
/*==============================*/
479
dtuple_t* row, /*!< in/out: Innobase row where the
480
field type information is already
482
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct where template
483
must be of type ROW_MYSQL_WHOLE_ROW */
484
byte* mysql_rec) /*!< in: row in the MySQL format;
485
NOTE: do not discard as long as
486
row is used, as row may contain
487
pointers to this record! */
489
mysql_row_templ_t* templ;
493
ut_ad(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
494
ut_ad(prebuilt->mysql_template);
496
for (i = 0; i < prebuilt->n_template; i++) {
498
templ = prebuilt->mysql_template + i;
499
dfield = dtuple_get_nth_field(row, i);
501
if (templ->mysql_null_bit_mask != 0) {
502
/* Column may be SQL NULL */
504
if (mysql_rec[templ->mysql_null_byte_offset]
505
& (byte) (templ->mysql_null_bit_mask)) {
509
dfield_set_null(dfield);
515
row_mysql_store_col_in_innobase_format(
517
prebuilt->ins_upd_rec_buff + templ->mysql_col_offset,
518
TRUE, /* MySQL row format data */
519
mysql_rec + templ->mysql_col_offset,
520
templ->mysql_col_len,
521
dict_table_is_comp(prebuilt->table));
527
/****************************************************************//**
528
Handles user errors and lock waits detected by the database engine.
529
@return TRUE if it was a lock wait and we should continue running the
530
query thread and in that case the thr is ALREADY in the running state. */
533
row_mysql_handle_errors(
534
/*====================*/
535
ulint* new_err,/*!< out: possible new error encountered in
536
lock wait, or if no new error, the value
537
of trx->error_state at the entry of this
539
trx_t* trx, /*!< in: transaction */
540
que_thr_t* thr, /*!< in: query thread */
541
trx_savept_t* savept) /*!< in: savepoint or NULL */
546
err = trx->error_state;
548
ut_a(err != DB_SUCCESS);
550
trx->error_state = DB_SUCCESS;
553
case DB_LOCK_WAIT_TIMEOUT:
554
if (row_rollback_on_timeout) {
555
trx_general_rollback_for_mysql(trx, NULL);
559
case DB_DUPLICATE_KEY:
560
case DB_FOREIGN_DUPLICATE_KEY:
561
case DB_TOO_BIG_RECORD:
562
case DB_ROW_IS_REFERENCED:
563
case DB_NO_REFERENCED_ROW:
564
case DB_CANNOT_ADD_CONSTRAINT:
565
case DB_TOO_MANY_CONCURRENT_TRXS:
566
case DB_OUT_OF_FILE_SPACE:
569
/* Roll back the latest, possibly incomplete
570
insertion or update */
572
trx_general_rollback_for_mysql(trx, savept);
574
/* MySQL will roll back the latest SQL statement */
577
srv_suspend_mysql_thread(thr);
579
if (trx->error_state != DB_SUCCESS) {
580
que_thr_stop_for_mysql(thr);
582
goto handle_new_error;
590
case DB_LOCK_TABLE_FULL:
591
/* Roll back the whole transaction; this resolution was added
592
to version 3.23.43 */
594
trx_general_rollback_for_mysql(trx, NULL);
597
case DB_MUST_GET_MORE_FILE_SPACE:
598
fputs("InnoDB: The database cannot continue"
599
" operation because of\n"
600
"InnoDB: lack of space. You must add"
601
" a new data file to\n"
602
"InnoDB: my.cnf and restart the database.\n", stderr);
607
fputs("InnoDB: We detected index corruption"
608
" in an InnoDB type table.\n"
609
"InnoDB: You have to dump + drop + reimport"
610
" the table or, in\n"
611
"InnoDB: a case of widespread corruption,"
613
"InnoDB: tables and recreate the"
614
" whole InnoDB tablespace.\n"
615
"InnoDB: If the mysqld server crashes"
616
" after the startup or when\n"
617
"InnoDB: you dump the tables, look at\n"
618
"InnoDB: " REFMAN "forcing-recovery.html"
619
" for help.\n", stderr);
621
case DB_FOREIGN_EXCEED_MAX_CASCADE:
622
fprintf(stderr, "InnoDB: Cannot delete/update rows with"
623
" cascading foreign key constraints that exceed max"
625
"Please drop excessive foreign constraints"
626
" and try again\n", (ulong) DICT_FK_MAX_RECURSIVE_LOAD);
629
fprintf(stderr, "InnoDB: unknown error code %lu\n",
634
if (trx->error_state != DB_SUCCESS) {
635
*new_err = trx->error_state;
640
trx->error_state = DB_SUCCESS;
645
/********************************************************************//**
646
Create a prebuilt struct for a MySQL table handle.
647
@return own: a prebuilt struct */
652
dict_table_t* table) /*!< in: Innobase table handle */
654
row_prebuilt_t* prebuilt;
656
dict_index_t* clust_index;
660
heap = mem_heap_create(sizeof *prebuilt + 128);
662
prebuilt = mem_heap_zalloc(heap, sizeof *prebuilt);
664
prebuilt->magic_n = ROW_PREBUILT_ALLOCATED;
665
prebuilt->magic_n2 = ROW_PREBUILT_ALLOCATED;
667
prebuilt->table = table;
669
prebuilt->sql_stat_start = TRUE;
670
prebuilt->heap = heap;
672
prebuilt->pcur = btr_pcur_create_for_mysql();
673
prebuilt->clust_pcur = btr_pcur_create_for_mysql();
675
prebuilt->select_lock_type = LOCK_NONE;
676
prebuilt->stored_select_lock_type = 99999999;
677
UNIV_MEM_INVALID(&prebuilt->stored_select_lock_type,
678
sizeof prebuilt->stored_select_lock_type);
680
prebuilt->search_tuple = dtuple_create(
681
heap, 2 * dict_table_get_n_cols(table));
683
clust_index = dict_table_get_first_index(table);
685
/* Make sure that search_tuple is long enough for clustered index */
686
ut_a(2 * dict_table_get_n_cols(table) >= clust_index->n_fields);
688
ref_len = dict_index_get_n_unique(clust_index);
690
ref = dtuple_create(heap, ref_len);
692
dict_index_copy_types(ref, clust_index, ref_len);
694
prebuilt->clust_ref = ref;
696
prebuilt->autoinc_error = 0;
697
prebuilt->autoinc_offset = 0;
699
/* Default to 1, we will set the actual value later in
700
ha_innobase::get_auto_increment(). */
701
prebuilt->autoinc_increment = 1;
703
prebuilt->autoinc_last_value = 0;
708
/********************************************************************//**
709
Free a prebuilt struct for a MySQL table handle. */
714
row_prebuilt_t* prebuilt, /*!< in, own: prebuilt struct */
715
ibool dict_locked) /*!< in: TRUE=data dictionary locked */
720
(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED
721
|| prebuilt->magic_n2 != ROW_PREBUILT_ALLOCATED)) {
724
"InnoDB: Error: trying to free a corrupt\n"
725
"InnoDB: table handle. Magic n %lu,"
726
" magic n2 %lu, table name ",
727
(ulong) prebuilt->magic_n,
728
(ulong) prebuilt->magic_n2);
729
ut_print_name(stderr, NULL, TRUE, prebuilt->table->name);
732
mem_analyze_corruption(prebuilt);
737
prebuilt->magic_n = ROW_PREBUILT_FREED;
738
prebuilt->magic_n2 = ROW_PREBUILT_FREED;
740
btr_pcur_free_for_mysql(prebuilt->pcur);
741
btr_pcur_free_for_mysql(prebuilt->clust_pcur);
743
if (prebuilt->mysql_template) {
744
mem_free(prebuilt->mysql_template);
747
if (prebuilt->ins_graph) {
748
que_graph_free_recursive(prebuilt->ins_graph);
751
if (prebuilt->sel_graph) {
752
que_graph_free_recursive(prebuilt->sel_graph);
755
if (prebuilt->upd_graph) {
756
que_graph_free_recursive(prebuilt->upd_graph);
759
if (prebuilt->blob_heap) {
760
mem_heap_free(prebuilt->blob_heap);
763
if (prebuilt->old_vers_heap) {
764
mem_heap_free(prebuilt->old_vers_heap);
767
for (i = 0; i < MYSQL_FETCH_CACHE_SIZE; i++) {
768
if (prebuilt->fetch_cache[i] != NULL) {
770
if ((ROW_PREBUILT_FETCH_MAGIC_N != mach_read_from_4(
771
(prebuilt->fetch_cache[i]) - 4))
772
|| (ROW_PREBUILT_FETCH_MAGIC_N != mach_read_from_4(
773
(prebuilt->fetch_cache[i])
774
+ prebuilt->mysql_row_len))) {
775
fputs("InnoDB: Error: trying to free"
776
" a corrupt fetch buffer.\n", stderr);
778
mem_analyze_corruption(
779
prebuilt->fetch_cache[i]);
784
mem_free((prebuilt->fetch_cache[i]) - 4);
788
dict_table_decrement_handle_count(prebuilt->table, dict_locked);
790
mem_heap_free(prebuilt->heap);
793
/*********************************************************************//**
794
Updates the transaction pointers in query graphs stored in the prebuilt
798
row_update_prebuilt_trx(
799
/*====================*/
800
row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct
802
trx_t* trx) /*!< in: transaction handle */
804
if (trx->magic_n != TRX_MAGIC_N) {
806
"InnoDB: Error: trying to use a corrupt\n"
807
"InnoDB: trx handle. Magic n %lu\n",
808
(ulong) trx->magic_n);
810
mem_analyze_corruption(trx);
815
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
817
"InnoDB: Error: trying to use a corrupt\n"
818
"InnoDB: table handle. Magic n %lu, table name ",
819
(ulong) prebuilt->magic_n);
820
ut_print_name(stderr, trx, TRUE, prebuilt->table->name);
823
mem_analyze_corruption(prebuilt);
830
if (prebuilt->ins_graph) {
831
prebuilt->ins_graph->trx = trx;
834
if (prebuilt->upd_graph) {
835
prebuilt->upd_graph->trx = trx;
838
if (prebuilt->sel_graph) {
839
prebuilt->sel_graph->trx = trx;
843
dtuple_t* row_get_prebuilt_insert_row(row_prebuilt_t* prebuilt);
845
/*********************************************************************//**
846
Gets pointer to a prebuilt dtuple used in insertions. If the insert graph
847
has not yet been built in the prebuilt struct, then this function first
849
@return prebuilt dtuple; the column type information is also set in it */
851
row_get_prebuilt_insert_row(
852
/*========================*/
853
row_prebuilt_t* prebuilt) /*!< in: prebuilt struct in MySQL
858
dict_table_t* table = prebuilt->table;
860
ut_ad(prebuilt && table && prebuilt->trx);
862
if (prebuilt->ins_node == NULL) {
864
/* Not called before for this handle: create an insert node
865
and query graph to the prebuilt struct */
867
node = ins_node_create(INS_DIRECT, table, prebuilt->heap);
869
prebuilt->ins_node = node;
871
if (prebuilt->ins_upd_rec_buff == NULL) {
872
prebuilt->ins_upd_rec_buff = mem_heap_alloc(
873
prebuilt->heap, prebuilt->mysql_row_len);
876
row = dtuple_create(prebuilt->heap,
877
dict_table_get_n_cols(table));
879
dict_table_copy_types(row, table);
881
ins_node_set_new_row(node, row);
883
prebuilt->ins_graph = que_node_get_parent(
884
pars_complete_graph_for_exec(node,
887
prebuilt->ins_graph->state = QUE_FORK_ACTIVE;
890
return(prebuilt->ins_node->row);
893
/*********************************************************************//**
894
Updates the table modification counter and calculates new estimates
895
for table and index statistics if necessary. */
898
row_update_statistics_if_needed(
899
/*============================*/
900
dict_table_t* table) /*!< in: table */
904
counter = table->stat_modified_counter;
906
table->stat_modified_counter = counter + 1;
908
/* Calculate new statistics if 1 / 16 of table has been modified
909
since the last time a statistics batch was run, or if
910
stat_modified_counter > 2 000 000 000 (to avoid wrap-around).
911
We calculate statistics at most every 16th round, since we may have
912
a counter table which is very small and updated very often. */
914
if (counter > 2000000000
915
|| ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) {
917
dict_update_statistics(table);
921
/*********************************************************************//**
922
Unlocks AUTO_INC type locks that were possibly reserved by a trx. This
923
function should be called at the the end of an SQL statement, by the
924
connection thread that owns the transaction (trx->mysql_thd). */
927
row_unlock_table_autoinc_for_mysql(
928
/*===============================*/
929
trx_t* trx) /*!< in/out: transaction */
931
if (lock_trx_holds_autoinc_locks(trx)) {
932
mutex_enter(&kernel_mutex);
934
lock_release_autoinc_locks(trx);
936
mutex_exit(&kernel_mutex);
940
/*********************************************************************//**
941
Sets an AUTO_INC type lock on the table mentioned in prebuilt. The
942
AUTO_INC lock gives exclusive access to the auto-inc counter of the
943
table. The lock is reserved only for the duration of an SQL statement.
944
It is not compatible with another AUTO_INC or exclusive lock on the
946
@return error code or DB_SUCCESS */
949
row_lock_table_autoinc_for_mysql(
950
/*=============================*/
951
row_prebuilt_t* prebuilt) /*!< in: prebuilt struct in the MySQL
954
trx_t* trx = prebuilt->trx;
955
ins_node_t* node = prebuilt->ins_node;
956
const dict_table_t* table = prebuilt->table;
962
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
964
/* If we already hold an AUTOINC lock on the table then do nothing.
965
Note: We peek at the value of the current owner without acquiring
966
the kernel mutex. **/
967
if (trx == table->autoinc_trx) {
972
trx->op_info = "setting auto-inc lock";
975
row_get_prebuilt_insert_row(prebuilt);
976
node = prebuilt->ins_node;
979
/* We use the insert query graph as the dummy graph needed
980
in the lock module call */
982
thr = que_fork_get_first_thr(prebuilt->ins_graph);
984
que_thr_move_to_run_state_for_mysql(thr, trx);
987
thr->run_node = node;
988
thr->prev_node = node;
990
/* It may be that the current session has not yet started
991
its transaction, or it has been committed: */
993
trx_start_if_not_started(trx);
995
err = lock_table(0, prebuilt->table, LOCK_AUTO_INC, thr);
997
trx->error_state = err;
999
if (err != DB_SUCCESS) {
1000
que_thr_stop_for_mysql(thr);
1002
was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL);
1004
if (was_lock_wait) {
1013
que_thr_stop_for_mysql_no_error(thr, trx);
1020
/*********************************************************************//**
1021
Sets a table lock on the table mentioned in prebuilt.
1022
@return error code or DB_SUCCESS */
1025
row_lock_table_for_mysql(
1026
/*=====================*/
1027
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct in the MySQL
1029
dict_table_t* table, /*!< in: table to lock, or NULL
1030
if prebuilt->table should be
1032
prebuilt->select_lock_type */
1033
ulint mode) /*!< in: lock mode of table
1034
(ignored if table==NULL) */
1036
trx_t* trx = prebuilt->trx;
1039
ibool was_lock_wait;
1042
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1044
trx->op_info = "setting table lock";
1046
if (prebuilt->sel_graph == NULL) {
1047
/* Build a dummy select query graph */
1048
row_prebuild_sel_graph(prebuilt);
1051
/* We use the select query graph as the dummy graph needed
1052
in the lock module call */
1054
thr = que_fork_get_first_thr(prebuilt->sel_graph);
1056
que_thr_move_to_run_state_for_mysql(thr, trx);
1059
thr->run_node = thr;
1060
thr->prev_node = thr->common.parent;
1062
/* It may be that the current session has not yet started
1063
its transaction, or it has been committed: */
1065
trx_start_if_not_started(trx);
1068
err = lock_table(0, table, mode, thr);
1070
err = lock_table(0, prebuilt->table,
1071
prebuilt->select_lock_type, thr);
1074
trx->error_state = err;
1076
if (err != DB_SUCCESS) {
1077
que_thr_stop_for_mysql(thr);
1079
was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL);
1081
if (was_lock_wait) {
1090
que_thr_stop_for_mysql_no_error(thr, trx);
1097
/*********************************************************************//**
1098
Does an insert for MySQL.
1099
@return error code or DB_SUCCESS */
1102
row_insert_for_mysql(
1103
/*=================*/
1104
byte* mysql_rec, /*!< in: row in the MySQL format */
1105
row_prebuilt_t* prebuilt) /*!< in: prebuilt struct in MySQL
1108
trx_savept_t savept;
1111
ibool was_lock_wait;
1112
trx_t* trx = prebuilt->trx;
1113
ins_node_t* node = prebuilt->ins_node;
1116
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1118
if (prebuilt->table->ibd_file_missing) {
1119
ut_print_timestamp(stderr);
1120
fprintf(stderr, " InnoDB: Error:\n"
1121
"InnoDB: MySQL is trying to use a table handle"
1122
" but the .ibd file for\n"
1123
"InnoDB: table %s does not exist.\n"
1124
"InnoDB: Have you deleted the .ibd file"
1125
" from the database directory under\n"
1126
"InnoDB: the MySQL datadir, or have you"
1127
" used DISCARD TABLESPACE?\n"
1128
"InnoDB: Look from\n"
1129
"InnoDB: " REFMAN "innodb-troubleshooting.html\n"
1130
"InnoDB: how you can resolve the problem.\n",
1131
prebuilt->table->name);
1135
if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
1137
"InnoDB: Error: trying to free a corrupt\n"
1138
"InnoDB: table handle. Magic n %lu, table name ",
1139
(ulong) prebuilt->magic_n);
1140
ut_print_name(stderr, trx, TRUE, prebuilt->table->name);
1143
mem_analyze_corruption(prebuilt);
1148
if (UNIV_UNLIKELY(srv_created_new_raw || srv_force_recovery)) {
1149
fputs("InnoDB: A new raw disk partition was initialized or\n"
1150
"InnoDB: innodb_force_recovery is on: we do not allow\n"
1151
"InnoDB: database modifications by the user. Shut down\n"
1152
"InnoDB: mysqld and edit my.cnf so that"
1153
" newraw is replaced\n"
1154
"InnoDB: with raw, and innodb_force_... is removed.\n",
1160
trx->op_info = "inserting";
1162
row_mysql_delay_if_needed();
1164
trx_start_if_not_started(trx);
1167
row_get_prebuilt_insert_row(prebuilt);
1168
node = prebuilt->ins_node;
1171
row_mysql_convert_row_to_innobase(node->row, prebuilt, mysql_rec);
1173
savept = trx_savept_take(trx);
1175
thr = que_fork_get_first_thr(prebuilt->ins_graph);
1177
if (prebuilt->sql_stat_start) {
1178
node->state = INS_NODE_SET_IX_LOCK;
1179
prebuilt->sql_stat_start = FALSE;
1181
node->state = INS_NODE_ALLOC_ROW_ID;
1184
que_thr_move_to_run_state_for_mysql(thr, trx);
1187
thr->run_node = node;
1188
thr->prev_node = node;
1192
err = trx->error_state;
1194
if (err != DB_SUCCESS) {
1195
que_thr_stop_for_mysql(thr);
1197
/* TODO: what is this? */ thr->lock_state= QUE_THR_LOCK_ROW;
1199
was_lock_wait = row_mysql_handle_errors(&err, trx, thr,
1201
thr->lock_state= QUE_THR_LOCK_NOLOCK;
1203
if (was_lock_wait) {
1212
que_thr_stop_for_mysql_no_error(thr, trx);
1214
prebuilt->table->stat_n_rows++;
1216
srv_n_rows_inserted++;
1218
if (prebuilt->table->stat_n_rows == 0) {
1219
/* Avoid wrap-over */
1220
prebuilt->table->stat_n_rows--;
1223
row_update_statistics_if_needed(prebuilt->table);
1229
/*********************************************************************//**
1230
Builds a dummy query graph used in selects. */
1233
row_prebuild_sel_graph(
1234
/*===================*/
1235
row_prebuilt_t* prebuilt) /*!< in: prebuilt struct in MySQL
1240
ut_ad(prebuilt && prebuilt->trx);
1242
if (prebuilt->sel_graph == NULL) {
1244
node = sel_node_create(prebuilt->heap);
1246
prebuilt->sel_graph = que_node_get_parent(
1247
pars_complete_graph_for_exec(node,
1251
prebuilt->sel_graph->state = QUE_FORK_ACTIVE;
1255
/*********************************************************************//**
1256
Creates an query graph node of 'update' type to be used in the MySQL
1258
@return own: update node */
1261
row_create_update_node_for_mysql(
1262
/*=============================*/
1263
dict_table_t* table, /*!< in: table to update */
1264
mem_heap_t* heap) /*!< in: mem heap from which allocated */
1268
node = upd_node_create(heap);
1270
node->in_mysql_interface = TRUE;
1271
node->is_delete = FALSE;
1272
node->searched_update = FALSE;
1273
node->select = NULL;
1274
node->pcur = btr_pcur_create_for_mysql();
1275
node->table = table;
1277
node->update = upd_create(dict_table_get_n_cols(table), heap);
1279
node->update_n_fields = dict_table_get_n_cols(table);
1281
UT_LIST_INIT(node->columns);
1282
node->has_clust_rec_x_lock = TRUE;
1283
node->cmpl_info = 0;
1285
node->table_sym = NULL;
1286
node->col_assign_list = NULL;
1291
/*********************************************************************//**
1292
Gets pointer to a prebuilt update vector used in updates. If the update
1293
graph has not yet been built in the prebuilt struct, then this function
1295
@return prebuilt update vector */
1298
row_get_prebuilt_update_vector(
1299
/*===========================*/
1300
row_prebuilt_t* prebuilt) /*!< in: prebuilt struct in MySQL
1303
dict_table_t* table = prebuilt->table;
1306
ut_ad(prebuilt && table && prebuilt->trx);
1308
if (prebuilt->upd_node == NULL) {
1310
/* Not called before for this handle: create an update node
1311
and query graph to the prebuilt struct */
1313
node = row_create_update_node_for_mysql(table, prebuilt->heap);
1315
prebuilt->upd_node = node;
1317
prebuilt->upd_graph = que_node_get_parent(
1318
pars_complete_graph_for_exec(node,
1321
prebuilt->upd_graph->state = QUE_FORK_ACTIVE;
1324
return(prebuilt->upd_node->update);
1327
/*********************************************************************//**
1328
Does an update or delete of a row for MySQL.
1329
@return error code or DB_SUCCESS */
1332
row_update_for_mysql(
1333
/*=================*/
1334
byte* mysql_rec, /*!< in: the row to be updated, in
1336
row_prebuilt_t* prebuilt) /*!< in: prebuilt struct in MySQL
1339
trx_savept_t savept;
1342
ibool was_lock_wait;
1343
dict_index_t* clust_index;
1344
/* ulint ref_len; */
1346
dict_table_t* table = prebuilt->table;
1347
trx_t* trx = prebuilt->trx;
1349
ut_ad(prebuilt && trx);
1350
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1351
UT_NOT_USED(mysql_rec);
1353
if (prebuilt->table->ibd_file_missing) {
1354
ut_print_timestamp(stderr);
1355
fprintf(stderr, " InnoDB: Error:\n"
1356
"InnoDB: MySQL is trying to use a table handle"
1357
" but the .ibd file for\n"
1358
"InnoDB: table %s does not exist.\n"
1359
"InnoDB: Have you deleted the .ibd file"
1360
" from the database directory under\n"
1361
"InnoDB: the MySQL datadir, or have you"
1362
" used DISCARD TABLESPACE?\n"
1363
"InnoDB: Look from\n"
1364
"InnoDB: " REFMAN "innodb-troubleshooting.html\n"
1365
"InnoDB: how you can resolve the problem.\n",
1366
prebuilt->table->name);
1370
if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
1372
"InnoDB: Error: trying to free a corrupt\n"
1373
"InnoDB: table handle. Magic n %lu, table name ",
1374
(ulong) prebuilt->magic_n);
1375
ut_print_name(stderr, trx, TRUE, prebuilt->table->name);
1378
mem_analyze_corruption(prebuilt);
1383
if (UNIV_UNLIKELY(srv_created_new_raw || srv_force_recovery)) {
1384
fputs("InnoDB: A new raw disk partition was initialized or\n"
1385
"InnoDB: innodb_force_recovery is on: we do not allow\n"
1386
"InnoDB: database modifications by the user. Shut down\n"
1387
"InnoDB: mysqld and edit my.cnf so that newraw"
1389
"InnoDB: with raw, and innodb_force_... is removed.\n",
1395
trx->op_info = "updating or deleting";
1397
row_mysql_delay_if_needed();
1399
trx_start_if_not_started(trx);
1401
node = prebuilt->upd_node;
1403
clust_index = dict_table_get_first_index(table);
1405
if (prebuilt->pcur->btr_cur.index == clust_index) {
1406
btr_pcur_copy_stored_position(node->pcur, prebuilt->pcur);
1408
btr_pcur_copy_stored_position(node->pcur,
1409
prebuilt->clust_pcur);
1412
ut_a(node->pcur->rel_pos == BTR_PCUR_ON);
1414
/* MySQL seems to call rnd_pos before updating each row it
1415
has cached: we can get the correct cursor position from
1416
prebuilt->pcur; NOTE that we cannot build the row reference
1417
from mysql_rec if the clustered index was automatically
1418
generated for the table: MySQL does not know anything about
1419
the row id used as the clustered index key */
1421
savept = trx_savept_take(trx);
1423
thr = que_fork_get_first_thr(prebuilt->upd_graph);
1425
node->state = UPD_NODE_UPDATE_CLUSTERED;
1427
ut_ad(!prebuilt->sql_stat_start);
1429
que_thr_move_to_run_state_for_mysql(thr, trx);
1432
thr->run_node = node;
1433
thr->prev_node = node;
1434
thr->fk_cascade_depth = 0;
1438
/* The recursive call for cascading update/delete happens
1439
in above row_upd_step(), reset the counter once we come
1440
out of the recursive call, so it does not accumulate for
1441
different row deletes */
1442
thr->fk_cascade_depth = 0;
1444
err = trx->error_state;
1446
/* Reset fk_cascade_depth back to 0 */
1447
thr->fk_cascade_depth = 0;
1449
if (err != DB_SUCCESS) {
1450
que_thr_stop_for_mysql(thr);
1452
if (err == DB_RECORD_NOT_FOUND) {
1453
trx->error_state = DB_SUCCESS;
1459
thr->lock_state= QUE_THR_LOCK_ROW;
1460
was_lock_wait = row_mysql_handle_errors(&err, trx, thr,
1462
thr->lock_state= QUE_THR_LOCK_NOLOCK;
1464
if (was_lock_wait) {
1473
que_thr_stop_for_mysql_no_error(thr, trx);
1475
if (node->is_delete) {
1476
if (prebuilt->table->stat_n_rows > 0) {
1477
prebuilt->table->stat_n_rows--;
1480
srv_n_rows_deleted++;
1482
srv_n_rows_updated++;
1485
/* We update table statistics only if it is a DELETE or UPDATE
1486
that changes indexed columns, UPDATEs that change only non-indexed
1487
columns would not affect statistics. */
1488
if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
1489
row_update_statistics_if_needed(prebuilt->table);
1497
/*********************************************************************//**
1498
This can only be used when srv_locks_unsafe_for_binlog is TRUE or this
1499
session is using a READ COMMITTED or READ UNCOMMITTED isolation level.
1500
Before calling this function row_search_for_mysql() must have
1501
initialized prebuilt->new_rec_locks to store the information which new
1502
record locks really were set. This function removes a newly set
1503
clustered index record lock under prebuilt->pcur or
1504
prebuilt->clust_pcur. Thus, this implements a 'mini-rollback' that
1505
releases the latest clustered index record lock we set.
1506
@return error code or DB_SUCCESS */
1509
row_unlock_for_mysql(
1510
/*=================*/
1511
row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct in MySQL
1513
ibool has_latches_on_recs)/*!< in: TRUE if called so
1514
that we have the latches on
1515
the records under pcur and
1516
clust_pcur, and we do not need
1517
to reposition the cursors. */
1519
btr_pcur_t* pcur = prebuilt->pcur;
1520
btr_pcur_t* clust_pcur = prebuilt->clust_pcur;
1521
trx_t* trx = prebuilt->trx;
1523
ut_ad(prebuilt && trx);
1524
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1527
(!srv_locks_unsafe_for_binlog
1528
&& trx->isolation_level > TRX_ISO_READ_COMMITTED)) {
1531
"InnoDB: Error: calling row_unlock_for_mysql though\n"
1532
"InnoDB: innodb_locks_unsafe_for_binlog is FALSE and\n"
1533
"InnoDB: this session is not using"
1534
" READ COMMITTED isolation level.\n");
1539
trx->op_info = "unlock_row";
1541
if (prebuilt->new_rec_locks >= 1) {
1544
dict_index_t* index;
1545
trx_id_t rec_trx_id;
1550
/* Restore the cursor position and find the record */
1552
if (!has_latches_on_recs) {
1553
btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, &mtr);
1556
rec = btr_pcur_get_rec(pcur);
1557
index = btr_pcur_get_btr_cur(pcur)->index;
1559
if (prebuilt->new_rec_locks >= 2) {
1560
/* Restore the cursor position and find the record
1561
in the clustered index. */
1563
if (!has_latches_on_recs) {
1564
btr_pcur_restore_position(BTR_SEARCH_LEAF,
1568
rec = btr_pcur_get_rec(clust_pcur);
1569
index = btr_pcur_get_btr_cur(clust_pcur)->index;
1572
if (UNIV_UNLIKELY(!dict_index_is_clust(index))) {
1573
/* This is not a clustered index record. We
1574
do not know how to unlock the record. */
1578
/* If the record has been modified by this
1579
transaction, do not unlock it. */
1581
if (index->trx_id_offset) {
1582
rec_trx_id = trx_read_trx_id(rec
1583
+ index->trx_id_offset);
1585
mem_heap_t* heap = NULL;
1586
ulint offsets_[REC_OFFS_NORMAL_SIZE];
1587
ulint* offsets = offsets_;
1589
rec_offs_init(offsets_);
1590
offsets = rec_get_offsets(rec, index, offsets,
1591
ULINT_UNDEFINED, &heap);
1593
rec_trx_id = row_get_rec_trx_id(rec, index, offsets);
1595
if (UNIV_LIKELY_NULL(heap)) {
1596
mem_heap_free(heap);
1600
if (rec_trx_id != trx->id) {
1601
/* We did not update the record: unlock it */
1603
rec = btr_pcur_get_rec(pcur);
1604
index = btr_pcur_get_btr_cur(pcur)->index;
1606
lock_rec_unlock(trx, btr_pcur_get_block(pcur),
1607
rec, prebuilt->select_lock_type);
1609
if (prebuilt->new_rec_locks >= 2) {
1610
rec = btr_pcur_get_rec(clust_pcur);
1611
index = btr_pcur_get_btr_cur(clust_pcur)->index;
1613
lock_rec_unlock(trx,
1614
btr_pcur_get_block(clust_pcur),
1616
prebuilt->select_lock_type);
1628
/**********************************************************************//**
1629
Does a cascaded delete or set null in a foreign key operation.
1630
@return error code or DB_SUCCESS */
1633
row_update_cascade_for_mysql(
1634
/*=========================*/
1635
que_thr_t* thr, /*!< in: query thread */
1636
upd_node_t* node, /*!< in: update node used in the cascade
1637
or set null operation */
1638
dict_table_t* table) /*!< in: table where we do the operation */
1643
trx = thr_get_trx(thr);
1645
/* Increment fk_cascade_depth to record the recursive call depth on
1646
a single update/delete that affects multiple tables chained
1647
together with foreign key relations. */
1648
thr->fk_cascade_depth++;
1650
if (thr->fk_cascade_depth > FK_MAX_CASCADE_DEL) {
1651
return (DB_FOREIGN_EXCEED_MAX_CASCADE);
1654
thr->run_node = node;
1655
thr->prev_node = node;
1659
/* The recursive call for cascading update/delete happens
1660
in above row_upd_step(), reset the counter once we come
1661
out of the recursive call, so it does not accumulate for
1662
different row deletes */
1663
thr->fk_cascade_depth = 0;
1665
err = trx->error_state;
1667
/* Note that the cascade node is a subnode of another InnoDB
1668
query graph node. We do a normal lock wait in this node, but
1669
all errors are handled by the parent node. */
1671
if (err == DB_LOCK_WAIT) {
1672
/* Handle lock wait here */
1674
que_thr_stop_for_mysql(thr);
1676
srv_suspend_mysql_thread(thr);
1678
/* Note that a lock wait may also end in a lock wait timeout,
1679
or this transaction is picked as a victim in selective
1680
deadlock resolution */
1682
if (trx->error_state != DB_SUCCESS) {
1684
return(trx->error_state);
1687
/* Retry operation after a normal lock wait */
1692
if (err != DB_SUCCESS) {
1697
if (node->is_delete) {
1698
if (table->stat_n_rows > 0) {
1699
table->stat_n_rows--;
1702
srv_n_rows_deleted++;
1704
srv_n_rows_updated++;
1707
row_update_statistics_if_needed(table);
1712
/*********************************************************************//**
1713
Checks if a table is such that we automatically created a clustered
1714
index on it (on row id).
1715
@return TRUE if the clustered index was generated automatically */
1718
row_table_got_default_clust_index(
1719
/*==============================*/
1720
const dict_table_t* table) /*!< in: table */
1722
const dict_index_t* clust_index;
1724
clust_index = dict_table_get_first_index(table);
1726
return(dict_index_get_nth_col(clust_index, 0)->mtype == DATA_SYS);
1729
/*********************************************************************//**
1730
Locks the data dictionary in shared mode from modifications, for performing
1731
foreign key check, rollback, or other operation invisible to MySQL. */
1734
row_mysql_freeze_data_dictionary_func(
1735
/*==================================*/
1736
trx_t* trx, /*!< in/out: transaction */
1737
const char* file, /*!< in: file name */
1738
ulint line) /*!< in: line number */
1740
ut_a(trx->dict_operation_lock_mode == 0);
1742
rw_lock_s_lock_func(&dict_operation_lock, 0, file, line);
1744
trx->dict_operation_lock_mode = RW_S_LATCH;
1747
/*********************************************************************//**
1748
Unlocks the data dictionary shared lock. */
1751
row_mysql_unfreeze_data_dictionary(
1752
/*===============================*/
1753
trx_t* trx) /*!< in/out: transaction */
1755
ut_a(trx->dict_operation_lock_mode == RW_S_LATCH);
1757
rw_lock_s_unlock(&dict_operation_lock);
1759
trx->dict_operation_lock_mode = 0;
1762
/*********************************************************************//**
1763
Locks the data dictionary exclusively for performing a table create or other
1764
data dictionary modification operation. */
1767
row_mysql_lock_data_dictionary_func(
1768
/*================================*/
1769
trx_t* trx, /*!< in/out: transaction */
1770
const char* file, /*!< in: file name */
1771
ulint line) /*!< in: line number */
1773
ut_a(trx->dict_operation_lock_mode == 0
1774
|| trx->dict_operation_lock_mode == RW_X_LATCH);
1776
/* Serialize data dictionary operations with dictionary mutex:
1777
no deadlocks or lock waits can occur then in these operations */
1779
rw_lock_x_lock_func(&dict_operation_lock, 0, file, line);
1780
trx->dict_operation_lock_mode = RW_X_LATCH;
1782
mutex_enter(&(dict_sys->mutex));
1785
/*********************************************************************//**
1786
Unlocks the data dictionary exclusive lock. */
1789
row_mysql_unlock_data_dictionary(
1790
/*=============================*/
1791
trx_t* trx) /*!< in/out: transaction */
1793
ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
1795
/* Serialize data dictionary operations with dictionary mutex:
1796
no deadlocks can occur then in these operations */
1798
mutex_exit(&(dict_sys->mutex));
1799
rw_lock_x_unlock(&dict_operation_lock);
1801
trx->dict_operation_lock_mode = 0;
1804
/*********************************************************************//**
1805
Creates a table for MySQL. If the name of the table ends in
1806
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
1807
"innodb_table_monitor", then this will also start the printing of monitor
1808
output by the master thread. If the table name ends in "innodb_mem_validate",
1809
InnoDB will try to invoke mem_validate().
1810
@return error code or DB_SUCCESS */
1813
row_create_table_for_mysql(
1814
/*=======================*/
1815
dict_table_t* table, /*!< in, own: table definition
1817
trx_t* trx) /*!< in: transaction handle */
1822
const char* table_name;
1823
ulint table_name_len;
1826
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1827
#ifdef UNIV_SYNC_DEBUG
1828
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
1829
#endif /* UNIV_SYNC_DEBUG */
1830
ut_ad(mutex_own(&(dict_sys->mutex)));
1831
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
1833
if (srv_created_new_raw) {
1834
fputs("InnoDB: A new raw disk partition was initialized:\n"
1835
"InnoDB: we do not allow database modifications"
1837
"InnoDB: Shut down mysqld and edit my.cnf so that newraw"
1838
" is replaced with raw.\n", stderr);
1839
dict_mem_table_free(table);
1840
trx_commit_for_mysql(trx);
1845
trx->op_info = "creating table";
1847
trx_start_if_not_started(trx);
1849
/* The table name is prefixed with the database name and a '/'.
1850
Certain table names starting with 'innodb_' have their special
1851
meaning regardless of the database name. Thus, we need to
1852
ignore the database name prefix in the comparisons. */
1853
table_name = strchr(table->name, '/');
1856
table_name_len = strlen(table_name) + 1;
1858
if (STR_EQ(table_name, table_name_len, S_innodb_monitor)) {
1860
/* Table equals "innodb_monitor":
1861
start monitor prints */
1863
srv_print_innodb_monitor = TRUE;
1865
/* The lock timeout monitor thread also takes care
1866
of InnoDB monitor prints */
1868
os_event_set(srv_lock_timeout_thread_event);
1869
} else if (STR_EQ(table_name, table_name_len,
1870
S_innodb_lock_monitor)) {
1872
srv_print_innodb_monitor = TRUE;
1873
srv_print_innodb_lock_monitor = TRUE;
1874
os_event_set(srv_lock_timeout_thread_event);
1875
} else if (STR_EQ(table_name, table_name_len,
1876
S_innodb_tablespace_monitor)) {
1878
srv_print_innodb_tablespace_monitor = TRUE;
1879
os_event_set(srv_lock_timeout_thread_event);
1880
} else if (STR_EQ(table_name, table_name_len,
1881
S_innodb_table_monitor)) {
1883
srv_print_innodb_table_monitor = TRUE;
1884
os_event_set(srv_lock_timeout_thread_event);
1885
} else if (STR_EQ(table_name, table_name_len,
1886
S_innodb_mem_validate)) {
1887
/* We define here a debugging feature intended for
1890
fputs("Validating InnoDB memory:\n"
1891
"to use this feature you must compile InnoDB with\n"
1892
"UNIV_MEM_DEBUG defined in univ.i and"
1893
" the server must be\n"
1894
"quiet because allocation from a mem heap"
1895
" is not protected\n"
1896
"by any semaphore.\n", stderr);
1897
#ifdef UNIV_MEM_DEBUG
1898
ut_a(mem_validate());
1899
fputs("Memory validated\n", stderr);
1900
#else /* UNIV_MEM_DEBUG */
1901
fputs("Memory NOT validated (recompile with UNIV_MEM_DEBUG)\n",
1903
#endif /* UNIV_MEM_DEBUG */
1906
heap = mem_heap_create(512);
1908
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
1910
node = tab_create_graph_create(table, heap);
1912
thr = pars_complete_graph_for_exec(node, trx, heap);
1914
ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
1915
que_run_threads(thr);
1917
err = trx->error_state;
1919
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
1920
trx->error_state = DB_SUCCESS;
1921
trx_general_rollback_for_mysql(trx, NULL);
1922
/* TO DO: free table? The code below will dereference
1923
table->name, though. */
1927
case DB_OUT_OF_FILE_SPACE:
1928
ut_print_timestamp(stderr);
1929
fputs(" InnoDB: Warning: cannot create table ",
1931
ut_print_name(stderr, trx, TRUE, table->name);
1932
fputs(" because tablespace full\n", stderr);
1934
if (dict_table_get_low(table->name)) {
1936
row_drop_table_for_mysql(table->name, trx, FALSE);
1937
trx_commit_for_mysql(trx);
1941
case DB_DUPLICATE_KEY:
1942
/* We may also get err == DB_ERROR if the .ibd file for the
1943
table already exists */
1948
que_graph_free((que_t*) que_node_get_parent(thr));
1955
/*********************************************************************//**
1956
Does an index creation operation for MySQL. TODO: currently failure
1957
to create an index results in dropping the whole table! This is no problem
1958
currently as all indexes must be created at the same time as the table.
1959
@return error number or DB_SUCCESS */
1962
row_create_index_for_mysql(
1963
/*=======================*/
1964
dict_index_t* index, /*!< in, own: index definition
1966
trx_t* trx, /*!< in: transaction handle */
1967
const ulint* field_lengths) /*!< in: if not NULL, must contain
1968
dict_index_get_n_fields(index)
1969
actual field lengths for the
1970
index columns, which are
1971
then checked for not being too
1982
#ifdef UNIV_SYNC_DEBUG
1983
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
1984
#endif /* UNIV_SYNC_DEBUG */
1985
ut_ad(mutex_own(&(dict_sys->mutex)));
1986
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1988
trx->op_info = "creating index";
1990
/* Copy the table name because we may want to drop the
1991
table later, after the index object is freed (inside
1992
que_run_threads()) and thus index->table_name is not available. */
1993
table_name = mem_strdup(index->table_name);
1995
trx_start_if_not_started(trx);
1997
/* Check that the same column does not appear twice in the index.
1998
Starting from 4.0.14, InnoDB should be able to cope with that, but
1999
safer not to allow them. */
2001
for (i = 0; i < dict_index_get_n_fields(index); i++) {
2004
for (j = 0; j < i; j++) {
2006
dict_index_get_nth_field(index, j)->name,
2007
dict_index_get_nth_field(index, i)->name)) {
2008
ut_print_timestamp(stderr);
2010
fputs(" InnoDB: Error: column ", stderr);
2011
ut_print_name(stderr, trx, FALSE,
2012
dict_index_get_nth_field(
2014
fputs(" appears twice in ", stderr);
2015
dict_index_name_print(stderr, trx, index);
2017
"InnoDB: This is not allowed"
2018
" in InnoDB.\n", stderr);
2020
err = DB_COL_APPEARS_TWICE_IN_INDEX;
2022
goto error_handling;
2026
/* Check also that prefix_len and actual length
2027
< DICT_MAX_INDEX_COL_LEN */
2029
len = dict_index_get_nth_field(index, i)->prefix_len;
2031
if (field_lengths) {
2032
len = ut_max(len, field_lengths[i]);
2035
if (len >= DICT_MAX_INDEX_COL_LEN) {
2036
err = DB_TOO_BIG_RECORD;
2038
goto error_handling;
2042
heap = mem_heap_create(512);
2044
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
2046
/* Note that the space id where we store the index is inherited from
2047
the table in dict_build_index_def_step() in dict0crea.c. */
2049
node = ind_create_graph_create(index, heap);
2051
thr = pars_complete_graph_for_exec(node, trx, heap);
2053
ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
2054
que_run_threads(thr);
2056
err = trx->error_state;
2058
que_graph_free((que_t*) que_node_get_parent(thr));
2061
if (err != DB_SUCCESS) {
2062
/* We have special error handling here */
2064
trx->error_state = DB_SUCCESS;
2066
trx_general_rollback_for_mysql(trx, NULL);
2068
row_drop_table_for_mysql(table_name, trx, FALSE);
2070
trx_commit_for_mysql(trx);
2072
trx->error_state = DB_SUCCESS;
2077
mem_free(table_name);
2082
/*********************************************************************//**
2083
Scans a table create SQL string and adds to the data dictionary
2084
the foreign key constraints declared in the string. This function
2085
should be called after the indexes for a table have been created.
2086
Each foreign key constraint must be accompanied with indexes in
2087
both participating tables. The indexes are allowed to contain more
2088
fields than mentioned in the constraint. Check also that foreign key
2089
constraints which reference this table are ok.
2090
@return error code or DB_SUCCESS */
2093
row_table_add_foreign_constraints(
2094
/*==============================*/
2095
trx_t* trx, /*!< in: transaction */
2096
const char* sql_string, /*!< in: table create statement where
2097
foreign keys are declared like:
2098
FOREIGN KEY (a, b) REFERENCES table2(c, d),
2099
table2 can be written also with the
2100
database name before it: test.table2 */
2101
size_t sql_length, /*!< in: length of sql_string */
2102
const char* name, /*!< in: table full name in the
2104
database_name/table_name */
2105
ibool reject_fks) /*!< in: if TRUE, fail with error
2106
code DB_CANNOT_ADD_CONSTRAINT if
2107
any foreign keys are found. */
2111
ut_ad(mutex_own(&(dict_sys->mutex)));
2112
#ifdef UNIV_SYNC_DEBUG
2113
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
2114
#endif /* UNIV_SYNC_DEBUG */
2117
trx->op_info = "adding foreign keys";
2119
trx_start_if_not_started(trx);
2121
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
2123
err = dict_create_foreign_constraints(trx, sql_string, sql_length,
2125
if (err == DB_SUCCESS) {
2126
/* Check that also referencing constraints are ok */
2127
err = dict_load_foreigns(name, FALSE, TRUE);
2130
if (err != DB_SUCCESS) {
2131
/* We have special error handling here */
2133
trx->error_state = DB_SUCCESS;
2135
trx_general_rollback_for_mysql(trx, NULL);
2137
row_drop_table_for_mysql(name, trx, FALSE);
2139
trx_commit_for_mysql(trx);
2141
trx->error_state = DB_SUCCESS;
2147
/*********************************************************************//**
2148
Drops a table for MySQL as a background operation. MySQL relies on Unix
2149
in ALTER TABLE to the fact that the table handler does not remove the
2150
table before all handles to it has been removed. Furhermore, the MySQL's
2151
call to drop table must be non-blocking. Therefore we do the drop table
2152
as a background operation, which is taken care of by the master thread
2154
@return error code or DB_SUCCESS */
2157
row_drop_table_for_mysql_in_background(
2158
/*===================================*/
2159
const char* name) /*!< in: table name */
2164
trx = trx_allocate_for_background();
2166
/* If the original transaction was dropping a table referenced by
2167
foreign keys, we must set the following to be able to drop the
2170
trx->check_foreigns = FALSE;
2172
/* fputs("InnoDB: Error: Dropping table ", stderr);
2173
ut_print_name(stderr, trx, TRUE, name);
2174
fputs(" in background drop list\n", stderr); */
2176
/* Try to drop the table in InnoDB */
2178
error = row_drop_table_for_mysql(name, trx, FALSE);
2180
/* Flush the log to reduce probability that the .frm files and
2181
the InnoDB data dictionary get out-of-sync if the user runs
2182
with innodb_flush_log_at_trx_commit = 0 */
2184
log_buffer_flush_to_disk();
2186
trx_commit_for_mysql(trx);
2188
trx_free_for_background(trx);
2190
return((int) error);
2193
/*********************************************************************//**
2194
The master thread in srv0srv.c calls this regularly to drop tables which
2195
we must drop in background after queries to them have ended. Such lazy
2196
dropping of tables is needed in ALTER TABLE on Unix.
2197
@return how many tables dropped + remaining tables in list */
2200
row_drop_tables_for_mysql_in_background(void)
2201
/*=========================================*/
2203
row_mysql_drop_t* drop;
2204
dict_table_t* table;
2206
ulint n_tables_dropped = 0;
2208
mutex_enter(&kernel_mutex);
2210
if (!row_mysql_drop_list_inited) {
2212
UT_LIST_INIT(row_mysql_drop_list);
2213
row_mysql_drop_list_inited = TRUE;
2216
drop = UT_LIST_GET_FIRST(row_mysql_drop_list);
2218
n_tables = UT_LIST_GET_LEN(row_mysql_drop_list);
2220
mutex_exit(&kernel_mutex);
2223
/* All tables dropped */
2225
return(n_tables + n_tables_dropped);
2228
mutex_enter(&(dict_sys->mutex));
2229
table = dict_table_get_low(drop->table_name);
2230
mutex_exit(&(dict_sys->mutex));
2232
if (table == NULL) {
2233
/* If for some reason the table has already been dropped
2234
through some other mechanism, do not try to drop it */
2236
goto already_dropped;
2239
if (DB_SUCCESS != row_drop_table_for_mysql_in_background(
2240
drop->table_name)) {
2241
/* If the DROP fails for some table, we return, and let the
2242
main thread retry later */
2244
return(n_tables + n_tables_dropped);
2250
mutex_enter(&kernel_mutex);
2252
UT_LIST_REMOVE(row_mysql_drop_list, row_mysql_drop_list, drop);
2254
ut_print_timestamp(stderr);
2255
fputs(" InnoDB: Dropped table ", stderr);
2256
ut_print_name(stderr, NULL, TRUE, drop->table_name);
2257
fputs(" in background drop queue.\n", stderr);
2259
mem_free(drop->table_name);
2263
mutex_exit(&kernel_mutex);
2268
/*********************************************************************//**
2269
Get the background drop list length. NOTE: the caller must own the kernel
2271
@return how many tables in list */
2274
row_get_background_drop_list_len_low(void)
2275
/*======================================*/
2277
ut_ad(mutex_own(&kernel_mutex));
2279
if (!row_mysql_drop_list_inited) {
2281
UT_LIST_INIT(row_mysql_drop_list);
2282
row_mysql_drop_list_inited = TRUE;
2285
return(UT_LIST_GET_LEN(row_mysql_drop_list));
2288
/*********************************************************************//**
2289
If a table is not yet in the drop list, adds the table to the list of tables
2290
which the master thread drops in background. We need this on Unix because in
2291
ALTER TABLE MySQL may call drop table even if the table has running queries on
2292
it. Also, if there are running foreign key checks on the table, we drop the
2294
@return TRUE if the table was not yet in the drop list, and was added there */
2297
row_add_table_to_background_drop_list(
2298
/*==================================*/
2299
const char* name) /*!< in: table name */
2301
row_mysql_drop_t* drop;
2303
mutex_enter(&kernel_mutex);
2305
if (!row_mysql_drop_list_inited) {
2307
UT_LIST_INIT(row_mysql_drop_list);
2308
row_mysql_drop_list_inited = TRUE;
2311
/* Look if the table already is in the drop list */
2312
drop = UT_LIST_GET_FIRST(row_mysql_drop_list);
2314
while (drop != NULL) {
2315
if (strcmp(drop->table_name, name) == 0) {
2316
/* Already in the list */
2318
mutex_exit(&kernel_mutex);
2323
drop = UT_LIST_GET_NEXT(row_mysql_drop_list, drop);
2326
drop = mem_alloc(sizeof(row_mysql_drop_t));
2328
drop->table_name = mem_strdup(name);
2330
UT_LIST_ADD_LAST(row_mysql_drop_list, row_mysql_drop_list, drop);
2332
/* fputs("InnoDB: Adding table ", stderr);
2333
ut_print_name(stderr, trx, TRUE, drop->table_name);
2334
fputs(" to background drop list\n", stderr); */
2336
mutex_exit(&kernel_mutex);
2341
/*********************************************************************//**
2342
Discards the tablespace of a table which stored in an .ibd file. Discarding
2343
means that this function deletes the .ibd file and assigns a new table id for
2344
the table. Also the flag table->ibd_file_missing is set TRUE.
2345
@return error code or DB_SUCCESS */
2348
row_discard_tablespace_for_mysql(
2349
/*=============================*/
2350
const char* name, /*!< in: table name */
2351
trx_t* trx) /*!< in: transaction handle */
2353
dict_foreign_t* foreign;
2355
dict_table_t* table;
2358
pars_info_t* info = NULL;
2360
/* How do we prevent crashes caused by ongoing operations on
2361
the table? Old operations could try to access non-existent
2364
1) SQL queries, INSERT, SELECT, ...: we must get an exclusive
2365
MySQL table lock on the table before we can do DISCARD
2366
TABLESPACE. Then there are no running queries on the table.
2368
2) Purge and rollback: we assign a new table id for the
2369
table. Since purge and rollback look for the table based on
2370
the table id, they see the table as 'dropped' and discard
2373
3) Insert buffer: we remove all entries for the tablespace in
2374
the insert buffer tree; as long as the tablespace mem object
2375
does not exist, ongoing insert buffer page merges are
2376
discarded in buf0rea.c. If we recreate the tablespace mem
2377
object with IMPORT TABLESPACE later, then the tablespace will
2378
have the same id, but the tablespace_version field in the mem
2379
object is different, and ongoing old insert buffer page merges
2382
4) Linear readahead and random readahead: we use the same
2383
method as in 3) to discard ongoing operations.
2385
5) FOREIGN KEY operations: if
2386
table->n_foreign_key_checks_running > 0, we do not allow the
2387
discard. We also reserve the data dictionary latch. */
2389
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
2391
trx->op_info = "discarding tablespace";
2392
trx_start_if_not_started(trx);
2394
/* Serialize data dictionary operations with dictionary mutex:
2395
no deadlocks can occur then in these operations */
2397
row_mysql_lock_data_dictionary(trx);
2399
table = dict_table_get_low(name);
2402
err = DB_TABLE_NOT_FOUND;
2407
if (table->space == 0) {
2408
ut_print_timestamp(stderr);
2409
fputs(" InnoDB: Error: table ", stderr);
2410
ut_print_name(stderr, trx, TRUE, name);
2412
"InnoDB: is in the system tablespace 0"
2413
" which cannot be discarded\n", stderr);
2419
if (table->n_foreign_key_checks_running > 0) {
2421
ut_print_timestamp(stderr);
2422
fputs(" InnoDB: You are trying to DISCARD table ", stderr);
2423
ut_print_name(stderr, trx, TRUE, table->name);
2425
"InnoDB: though there is a foreign key check"
2427
"InnoDB: Cannot discard the table.\n",
2435
/* Check if the table is referenced by foreign key constraints from
2436
some other table (not the table itself) */
2438
foreign = UT_LIST_GET_FIRST(table->referenced_list);
2440
while (foreign && foreign->foreign_table == table) {
2441
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
2444
if (foreign && trx->check_foreigns) {
2446
FILE* ef = dict_foreign_err_file;
2448
/* We only allow discarding a referenced table if
2449
FOREIGN_KEY_CHECKS is set to 0 */
2451
err = DB_CANNOT_DROP_CONSTRAINT;
2453
mutex_enter(&dict_foreign_err_mutex);
2455
ut_print_timestamp(ef);
2457
fputs(" Cannot DISCARD table ", ef);
2458
ut_print_name(stderr, trx, TRUE, name);
2460
"because it is referenced by ", ef);
2461
ut_print_name(stderr, trx, TRUE, foreign->foreign_table_name);
2463
mutex_exit(&dict_foreign_err_mutex);
2468
dict_hdr_get_new_id(&new_id, NULL, NULL);
2470
/* Remove all locks except the table-level S and X locks. */
2471
lock_remove_all_on_table(table, FALSE);
2473
info = pars_info_create();
2475
pars_info_add_str_literal(info, "table_name", name);
2476
pars_info_add_ull_literal(info, "new_id", new_id);
2478
err = que_eval_sql(info,
2479
"PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
2482
"SELECT ID INTO old_id\n"
2484
"WHERE NAME = :table_name\n"
2485
"LOCK IN SHARE MODE;\n"
2486
"IF (SQL % NOTFOUND) THEN\n"
2490
"UPDATE SYS_TABLES SET ID = :new_id\n"
2491
" WHERE ID = old_id;\n"
2492
"UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n"
2493
" WHERE TABLE_ID = old_id;\n"
2494
"UPDATE SYS_INDEXES SET TABLE_ID = :new_id\n"
2495
" WHERE TABLE_ID = old_id;\n"
2500
if (err != DB_SUCCESS) {
2501
trx->error_state = DB_SUCCESS;
2502
trx_general_rollback_for_mysql(trx, NULL);
2503
trx->error_state = DB_SUCCESS;
2505
dict_table_change_id_in_cache(table, new_id);
2507
success = fil_discard_tablespace(table->space);
2510
trx->error_state = DB_SUCCESS;
2511
trx_general_rollback_for_mysql(trx, NULL);
2512
trx->error_state = DB_SUCCESS;
2516
/* Set the flag which tells that now it is legal to
2517
IMPORT a tablespace for this table */
2518
table->tablespace_discarded = TRUE;
2519
table->ibd_file_missing = TRUE;
2524
trx_commit_for_mysql(trx);
2526
row_mysql_unlock_data_dictionary(trx);
2533
/*****************************************************************//**
2534
Imports a tablespace. The space id in the .ibd file must match the space id
2535
of the table in the data dictionary.
2536
@return error code or DB_SUCCESS */
2539
row_import_tablespace_for_mysql(
2540
/*============================*/
2541
const char* name, /*!< in: table name */
2542
trx_t* trx) /*!< in: transaction handle */
2544
dict_table_t* table;
2546
ib_uint64_t current_lsn;
2547
ulint err = DB_SUCCESS;
2549
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
2551
trx_start_if_not_started(trx);
2553
trx->op_info = "importing tablespace";
2555
current_lsn = log_get_lsn();
2557
/* It is possible, though very improbable, that the lsn's in the
2558
tablespace to be imported have risen above the current system lsn, if
2559
a lengthy purge, ibuf merge, or rollback was performed on a backup
2560
taken with ibbackup. If that is the case, reset page lsn's in the
2561
file. We assume that mysqld was shut down after it performed these
2562
cleanup operations on the .ibd file, so that it stamped the latest lsn
2563
to the FIL_PAGE_FILE_FLUSH_LSN in the first page of the .ibd file.
2565
TODO: reset also the trx id's in clustered index records and write
2566
a new space id to each data page. That would allow us to import clean
2567
.ibd files from another MySQL installation. */
2569
success = fil_reset_too_high_lsns(name, current_lsn);
2572
ut_print_timestamp(stderr);
2573
fputs(" InnoDB: Error: cannot reset lsn's in table ", stderr);
2574
ut_print_name(stderr, trx, TRUE, name);
2576
"InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n",
2581
row_mysql_lock_data_dictionary(trx);
2586
/* Serialize data dictionary operations with dictionary mutex:
2587
no deadlocks can occur then in these operations */
2589
row_mysql_lock_data_dictionary(trx);
2591
table = dict_table_get_low(name);
2594
ut_print_timestamp(stderr);
2595
fputs(" InnoDB: table ", stderr);
2596
ut_print_name(stderr, trx, TRUE, name);
2598
"InnoDB: does not exist in the InnoDB data dictionary\n"
2599
"InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n",
2602
err = DB_TABLE_NOT_FOUND;
2607
if (table->space == 0) {
2608
ut_print_timestamp(stderr);
2609
fputs(" InnoDB: Error: table ", stderr);
2610
ut_print_name(stderr, trx, TRUE, name);
2612
"InnoDB: is in the system tablespace 0"
2613
" which cannot be imported\n", stderr);
2619
if (!table->tablespace_discarded) {
2620
ut_print_timestamp(stderr);
2621
fputs(" InnoDB: Error: you are trying to"
2622
" IMPORT a tablespace\n"
2623
"InnoDB: ", stderr);
2624
ut_print_name(stderr, trx, TRUE, name);
2625
fputs(", though you have not called DISCARD on it yet\n"
2626
"InnoDB: during the lifetime of the mysqld process!\n",
2634
/* Play safe and remove all insert buffer entries, though we should
2635
have removed them already when DISCARD TABLESPACE was called */
2637
ibuf_delete_for_discarded_space(table->space);
2639
success = fil_open_single_table_tablespace(
2641
table->flags == DICT_TF_COMPACT ? 0 : table->flags,
2644
table->ibd_file_missing = FALSE;
2645
table->tablespace_discarded = FALSE;
2647
if (table->ibd_file_missing) {
2648
ut_print_timestamp(stderr);
2649
fputs(" InnoDB: cannot find or open in the"
2650
" database directory the .ibd file of\n"
2651
"InnoDB: table ", stderr);
2652
ut_print_name(stderr, trx, TRUE, name);
2654
"InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n",
2662
trx_commit_for_mysql(trx);
2664
row_mysql_unlock_data_dictionary(trx);
2671
/*********************************************************************//**
2672
Truncates a table for MySQL.
2673
@return error code or DB_SUCCESS */
2676
row_truncate_table_for_mysql(
2677
/*=========================*/
2678
dict_table_t* table, /*!< in: table handle */
2679
trx_t* trx) /*!< in: transaction handle */
2681
dict_foreign_t* foreign;
2687
dict_index_t* sys_index;
2691
ulint recreate_space = 0;
2692
pars_info_t* info = NULL;
2694
/* How do we prevent crashes caused by ongoing operations on
2695
the table? Old operations could try to access non-existent
2698
1) SQL queries, INSERT, SELECT, ...: we must get an exclusive
2699
MySQL table lock on the table before we can do TRUNCATE
2700
TABLE. Then there are no running queries on the table. This is
2701
guaranteed, because in ha_innobase::store_lock(), we do not
2702
weaken the TL_WRITE lock requested by MySQL when executing
2705
2) Purge and rollback: we assign a new table id for the
2706
table. Since purge and rollback look for the table based on
2707
the table id, they see the table as 'dropped' and discard
2710
3) Insert buffer: TRUNCATE TABLE is analogous to DROP TABLE,
2711
so we do not have to remove insert buffer records, as the
2712
insert buffer works at a low level. If a freed page is later
2713
reallocated, the allocator will remove the ibuf entries for
2716
When we truncate *.ibd files by recreating them (analogous to
2717
DISCARD TABLESPACE), we remove all entries for the table in the
2718
insert buffer tree. This is not strictly necessary, because
2719
in 6) we will assign a new tablespace identifier, but we can
2720
free up some space in the system tablespace.
2722
4) Linear readahead and random readahead: we use the same
2723
method as in 3) to discard ongoing operations. (This is only
2724
relevant for TRUNCATE TABLE by DISCARD TABLESPACE.)
2726
5) FOREIGN KEY operations: if
2727
table->n_foreign_key_checks_running > 0, we do not allow the
2728
TRUNCATE. We also reserve the data dictionary latch.
2730
6) Crash recovery: To prevent the application of pre-truncation
2731
redo log records on the truncated tablespace, we will assign
2732
a new tablespace identifier to the truncated tablespace. */
2734
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
2737
if (srv_created_new_raw) {
2738
fputs("InnoDB: A new raw disk partition was initialized:\n"
2739
"InnoDB: we do not allow database modifications"
2741
"InnoDB: Shut down mysqld and edit my.cnf so that newraw"
2742
" is replaced with raw.\n", stderr);
2747
trx->op_info = "truncating table";
2749
trx_start_if_not_started(trx);
2751
/* Serialize data dictionary operations with dictionary mutex:
2752
no deadlocks can occur then in these operations */
2754
ut_a(trx->dict_operation_lock_mode == 0);
2755
/* Prevent foreign key checks etc. while we are truncating the
2758
row_mysql_lock_data_dictionary(trx);
2760
ut_ad(mutex_own(&(dict_sys->mutex)));
2761
#ifdef UNIV_SYNC_DEBUG
2762
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
2763
#endif /* UNIV_SYNC_DEBUG */
2765
/* Check if the table is referenced by foreign key constraints from
2766
some other table (not the table itself) */
2768
foreign = UT_LIST_GET_FIRST(table->referenced_list);
2770
while (foreign && foreign->foreign_table == table) {
2771
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
2774
if (foreign && trx->check_foreigns) {
2775
FILE* ef = dict_foreign_err_file;
2777
/* We only allow truncating a referenced table if
2778
FOREIGN_KEY_CHECKS is set to 0 */
2780
mutex_enter(&dict_foreign_err_mutex);
2782
ut_print_timestamp(ef);
2784
fputs(" Cannot truncate table ", ef);
2785
ut_print_name(ef, trx, TRUE, table->name);
2786
fputs(" by DROP+CREATE\n"
2787
"InnoDB: because it is referenced by ", ef);
2788
ut_print_name(ef, trx, TRUE, foreign->foreign_table_name);
2790
mutex_exit(&dict_foreign_err_mutex);
2796
/* TODO: could we replace the counter n_foreign_key_checks_running
2797
with lock checks on the table? Acquire here an exclusive lock on the
2798
table, and rewrite lock0lock.c and the lock wait in srv0srv.c so that
2799
they can cope with the table having been truncated here? Foreign key
2800
checks take an IS or IX lock on the table. */
2802
if (table->n_foreign_key_checks_running > 0) {
2803
ut_print_timestamp(stderr);
2804
fputs(" InnoDB: Cannot truncate table ", stderr);
2805
ut_print_name(stderr, trx, TRUE, table->name);
2806
fputs(" by DROP+CREATE\n"
2807
"InnoDB: because there is a foreign key check"
2808
" running on it.\n",
2815
/* Remove all locks except the table-level S and X locks. */
2816
lock_remove_all_on_table(table, FALSE);
2818
trx->table_id = table->id;
2820
/* Lock all index trees for this table, as we will
2821
truncate the table/index and possibly change their metadata.
2822
All DML/DDL are blocked by table level lock, with
2823
a few exceptions such as queries into information schema
2824
about the table, MySQL could try to access index stats
2825
for this kind of query, we need to use index locks to
2827
dict_table_x_lock_indexes(table);
2829
if (table->space && !table->dir_path_of_temp_table) {
2830
/* Discard and create the single-table tablespace. */
2831
ulint space = table->space;
2832
ulint flags = fil_space_get_flags(space);
2834
if (flags != ULINT_UNDEFINED
2835
&& fil_discard_tablespace(space)) {
2837
dict_index_t* index;
2839
dict_hdr_get_new_id(NULL, NULL, &space);
2841
if (space == ULINT_UNDEFINED
2842
|| fil_create_new_single_table_tablespace(
2843
space, table->name, FALSE, flags,
2844
FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
2845
dict_table_x_unlock_indexes(table);
2846
ut_print_timestamp(stderr);
2848
" InnoDB: TRUNCATE TABLE %s failed to"
2849
" create a new tablespace\n",
2851
table->ibd_file_missing = 1;
2856
recreate_space = space;
2858
/* Replace the space_id in the data dictionary cache.
2859
The persisent data dictionary (SYS_TABLES.SPACE
2860
and SYS_INDEXES.SPACE) are updated later in this
2862
table->space = space;
2863
index = dict_table_get_first_index(table);
2865
index->space = space;
2866
index = dict_table_get_next_index(index);
2870
fsp_header_init(space,
2871
FIL_IBD_FILE_INITIAL_SIZE, &mtr);
2876
/* scan SYS_INDEXES for all indexes of the table */
2877
heap = mem_heap_create(800);
2879
tuple = dtuple_create(heap, 1);
2880
dfield = dtuple_get_nth_field(tuple, 0);
2882
buf = mem_heap_alloc(heap, 8);
2883
mach_write_to_8(buf, table->id);
2885
dfield_set_data(dfield, buf, 8);
2886
sys_index = dict_table_get_first_index(dict_sys->sys_indexes);
2887
dict_index_copy_types(tuple, sys_index, 1);
2890
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
2891
BTR_MODIFY_LEAF, &pcur, &mtr);
2898
if (!btr_pcur_is_on_user_rec(&pcur)) {
2899
/* The end of SYS_INDEXES has been reached. */
2903
rec = btr_pcur_get_rec(&pcur);
2905
field = rec_get_nth_field_old(rec, 0, &len);
2908
if (memcmp(buf, field, len) != 0) {
2909
/* End of indexes for the table (TABLE_ID mismatch). */
2913
if (rec_get_deleted_flag(rec, FALSE)) {
2914
/* The index has been dropped. */
2918
/* This call may commit and restart mtr
2919
and reposition pcur. */
2920
root_page_no = dict_truncate_index_tree(table, recreate_space,
2923
rec = btr_pcur_get_rec(&pcur);
2925
if (root_page_no != FIL_NULL) {
2926
page_rec_write_index_page_no(
2927
rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
2928
root_page_no, &mtr);
2929
/* We will need to commit and restart the
2930
mini-transaction in order to avoid deadlocks.
2931
The dict_truncate_index_tree() call has allocated
2932
a page in this mini-transaction, and the rest of
2933
this loop could latch another index page. */
2936
btr_pcur_restore_position(BTR_MODIFY_LEAF,
2941
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
2944
btr_pcur_close(&pcur);
2947
mem_heap_free(heap);
2949
/* Done with index truncation, release index tree locks,
2950
subsequent work relates to table level metadata change */
2951
dict_table_x_unlock_indexes(table);
2953
dict_hdr_get_new_id(&new_id, NULL, NULL);
2955
info = pars_info_create();
2957
pars_info_add_int4_literal(info, "space", (lint) table->space);
2958
pars_info_add_ull_literal(info, "old_id", table->id);
2959
pars_info_add_ull_literal(info, "new_id", new_id);
2961
err = que_eval_sql(info,
2962
"PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
2965
" SET ID = :new_id, SPACE = :space\n"
2966
" WHERE ID = :old_id;\n"
2967
"UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n"
2968
" WHERE TABLE_ID = :old_id;\n"
2969
"UPDATE SYS_INDEXES"
2970
" SET TABLE_ID = :new_id, SPACE = :space\n"
2971
" WHERE TABLE_ID = :old_id;\n"
2976
if (err != DB_SUCCESS) {
2977
trx->error_state = DB_SUCCESS;
2978
trx_general_rollback_for_mysql(trx, NULL);
2979
trx->error_state = DB_SUCCESS;
2980
ut_print_timestamp(stderr);
2981
fputs(" InnoDB: Unable to assign a new identifier to table ",
2983
ut_print_name(stderr, trx, TRUE, table->name);
2985
"InnoDB: after truncating it. Background processes"
2986
" may corrupt the table!\n", stderr);
2989
dict_table_change_id_in_cache(table, new_id);
2993
MySQL calls ha_innobase::reset_auto_increment() which does
2996
dict_table_autoinc_lock(table);
2997
dict_table_autoinc_initialize(table, 1);
2998
dict_table_autoinc_unlock(table);
2999
dict_update_statistics(table);
3001
trx_commit_for_mysql(trx);
3005
row_mysql_unlock_data_dictionary(trx);
3009
srv_wake_master_thread();
3014
/*********************************************************************//**
3015
Drops a table for MySQL. If the name of the dropped table ends in
3016
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
3017
"innodb_table_monitor", then this will also stop the printing of monitor
3018
output by the master thread. If the data dictionary was not already locked
3019
by the transaction, the transaction will be committed. Otherwise, the
3020
data dictionary will remain locked.
3021
@return error code or DB_SUCCESS */
3024
row_drop_table_for_mysql(
3025
/*=====================*/
3026
const char* name, /*!< in: table name */
3027
trx_t* trx, /*!< in: transaction handle */
3028
ibool drop_db)/*!< in: TRUE=dropping whole database */
3030
dict_foreign_t* foreign;
3031
dict_table_t* table;
3034
const char* table_name;
3036
ibool locked_dictionary = FALSE;
3037
pars_info_t* info = NULL;
3041
if (srv_created_new_raw) {
3042
fputs("InnoDB: A new raw disk partition was initialized:\n"
3043
"InnoDB: we do not allow database modifications"
3045
"InnoDB: Shut down mysqld and edit my.cnf so that newraw"
3046
" is replaced with raw.\n", stderr);
3051
trx->op_info = "dropping table";
3053
trx_start_if_not_started(trx);
3055
/* The table name is prefixed with the database name and a '/'.
3056
Certain table names starting with 'innodb_' have their special
3057
meaning regardless of the database name. Thus, we need to
3058
ignore the database name prefix in the comparisons. */
3059
table_name = strchr(name, '/');
3062
namelen = strlen(table_name) + 1;
3064
if (namelen == sizeof S_innodb_monitor
3065
&& !memcmp(table_name, S_innodb_monitor,
3066
sizeof S_innodb_monitor)) {
3068
/* Table name equals "innodb_monitor":
3069
stop monitor prints */
3071
srv_print_innodb_monitor = FALSE;
3072
srv_print_innodb_lock_monitor = FALSE;
3073
} else if (namelen == sizeof S_innodb_lock_monitor
3074
&& !memcmp(table_name, S_innodb_lock_monitor,
3075
sizeof S_innodb_lock_monitor)) {
3076
srv_print_innodb_monitor = FALSE;
3077
srv_print_innodb_lock_monitor = FALSE;
3078
} else if (namelen == sizeof S_innodb_tablespace_monitor
3079
&& !memcmp(table_name, S_innodb_tablespace_monitor,
3080
sizeof S_innodb_tablespace_monitor)) {
3082
srv_print_innodb_tablespace_monitor = FALSE;
3083
} else if (namelen == sizeof S_innodb_table_monitor
3084
&& !memcmp(table_name, S_innodb_table_monitor,
3085
sizeof S_innodb_table_monitor)) {
3087
srv_print_innodb_table_monitor = FALSE;
3090
/* Serialize data dictionary operations with dictionary mutex:
3091
no deadlocks can occur then in these operations */
3093
if (trx->dict_operation_lock_mode != RW_X_LATCH) {
3094
/* Prevent foreign key checks etc. while we are dropping the
3097
row_mysql_lock_data_dictionary(trx);
3099
locked_dictionary = TRUE;
3102
ut_ad(mutex_own(&(dict_sys->mutex)));
3103
#ifdef UNIV_SYNC_DEBUG
3104
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
3105
#endif /* UNIV_SYNC_DEBUG */
3107
table = dict_table_get_low(name);
3110
#if defined(BUILD_DRIZZLE)
3113
err = DB_TABLE_NOT_FOUND;
3114
ut_print_timestamp(stderr);
3116
fputs(" InnoDB: Error: table ", stderr);
3117
ut_print_name(stderr, trx, TRUE, name);
3118
fputs(" does not exist in the InnoDB internal\n"
3119
"InnoDB: data dictionary though MySQL is"
3120
" trying to drop it.\n"
3121
"InnoDB: Have you copied the .frm file"
3122
" of the table to the\n"
3123
"InnoDB: MySQL database directory"
3124
" from another database?\n"
3125
"InnoDB: You can look for further help from\n"
3126
"InnoDB: " REFMAN "innodb-troubleshooting.html\n",
3128
#endif /* BUILD_DRIZZLE */
3132
/* Check if the table is referenced by foreign key constraints from
3133
some other table (not the table itself) */
3135
foreign = UT_LIST_GET_FIRST(table->referenced_list);
3137
while (foreign && foreign->foreign_table == table) {
3139
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
3142
if (foreign && trx->check_foreigns
3143
&& !(drop_db && dict_tables_have_same_db(
3144
name, foreign->foreign_table_name))) {
3145
FILE* ef = dict_foreign_err_file;
3147
/* We only allow dropping a referenced table if
3148
FOREIGN_KEY_CHECKS is set to 0 */
3150
err = DB_CANNOT_DROP_CONSTRAINT;
3152
mutex_enter(&dict_foreign_err_mutex);
3154
ut_print_timestamp(ef);
3156
fputs(" Cannot drop table ", ef);
3157
ut_print_name(ef, trx, TRUE, name);
3159
"because it is referenced by ", ef);
3160
ut_print_name(ef, trx, TRUE, foreign->foreign_table_name);
3162
mutex_exit(&dict_foreign_err_mutex);
3167
if (foreign && trx->check_foreigns) {
3168
goto check_next_foreign;
3171
if (table->n_mysql_handles_opened > 0) {
3174
added = row_add_table_to_background_drop_list(table->name);
3177
ut_print_timestamp(stderr);
3178
fputs(" InnoDB: Warning: MySQL is"
3179
" trying to drop table ", stderr);
3180
ut_print_name(stderr, trx, TRUE, table->name);
3182
"InnoDB: though there are still"
3183
" open handles to it.\n"
3184
"InnoDB: Adding the table to the"
3185
" background drop queue.\n",
3188
/* We return DB_SUCCESS to MySQL though the drop will
3189
happen lazily later */
3192
/* The table is already in the background drop list */
3199
/* TODO: could we replace the counter n_foreign_key_checks_running
3200
with lock checks on the table? Acquire here an exclusive lock on the
3201
table, and rewrite lock0lock.c and the lock wait in srv0srv.c so that
3202
they can cope with the table having been dropped here? Foreign key
3203
checks take an IS or IX lock on the table. */
3205
if (table->n_foreign_key_checks_running > 0) {
3207
const char* table_name = table->name;
3210
added = row_add_table_to_background_drop_list(table_name);
3213
ut_print_timestamp(stderr);
3214
fputs(" InnoDB: You are trying to drop table ",
3216
ut_print_name(stderr, trx, TRUE, table_name);
3218
"InnoDB: though there is a"
3219
" foreign key check running on it.\n"
3220
"InnoDB: Adding the table to"
3221
" the background drop queue.\n",
3224
/* We return DB_SUCCESS to MySQL though the drop will
3225
happen lazily later */
3229
/* The table is already in the background drop list */
3236
/* Remove all locks there are on the table or its records */
3237
lock_remove_all_on_table(table, TRUE);
3239
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
3240
trx->table_id = table->id;
3242
/* We use the private SQL parser of Innobase to generate the
3243
query graphs needed in deleting the dictionary data from system
3244
tables in Innobase. Deleting a row from SYS_INDEXES table also
3245
frees the file segments of the B-tree associated with the index. */
3247
info = pars_info_create();
3249
pars_info_add_str_literal(info, "table_name", name);
3251
err = que_eval_sql(info,
3252
"PROCEDURE DROP_TABLE_PROC () IS\n"
3253
"sys_foreign_id CHAR;\n"
3256
"foreign_id CHAR;\n"
3259
"SELECT ID INTO table_id\n"
3261
"WHERE NAME = :table_name\n"
3262
"LOCK IN SHARE MODE;\n"
3263
"IF (SQL % NOTFOUND) THEN\n"
3267
"SELECT ID INTO sys_foreign_id\n"
3269
"WHERE NAME = 'SYS_FOREIGN'\n"
3270
"LOCK IN SHARE MODE;\n"
3271
"IF (SQL % NOTFOUND) THEN\n"
3274
"IF (:table_name = 'SYS_FOREIGN') THEN\n"
3277
"IF (:table_name = 'SYS_FOREIGN_COLS') THEN\n"
3280
"WHILE found = 1 LOOP\n"
3281
" SELECT ID INTO foreign_id\n"
3282
" FROM SYS_FOREIGN\n"
3283
" WHERE FOR_NAME = :table_name\n"
3284
" AND TO_BINARY(FOR_NAME)\n"
3285
" = TO_BINARY(:table_name)\n"
3286
" LOCK IN SHARE MODE;\n"
3287
" IF (SQL % NOTFOUND) THEN\n"
3290
" DELETE FROM SYS_FOREIGN_COLS\n"
3291
" WHERE ID = foreign_id;\n"
3292
" DELETE FROM SYS_FOREIGN\n"
3293
" WHERE ID = foreign_id;\n"
3297
"WHILE found = 1 LOOP\n"
3298
" SELECT ID INTO index_id\n"
3299
" FROM SYS_INDEXES\n"
3300
" WHERE TABLE_ID = table_id\n"
3301
" LOCK IN SHARE MODE;\n"
3302
" IF (SQL % NOTFOUND) THEN\n"
3305
" DELETE FROM SYS_FIELDS\n"
3306
" WHERE INDEX_ID = index_id;\n"
3307
" DELETE FROM SYS_INDEXES\n"
3308
" WHERE ID = index_id\n"
3309
" AND TABLE_ID = table_id;\n"
3312
"DELETE FROM SYS_COLUMNS\n"
3313
"WHERE TABLE_ID = table_id;\n"
3314
"DELETE FROM SYS_TABLES\n"
3315
"WHERE ID = table_id;\n"
3321
const char* name_or_path;
3326
heap = mem_heap_create(200);
3328
/* Clone the name, in case it has been allocated
3329
from table->heap, which will be freed by
3330
dict_table_remove_from_cache(table) below. */
3331
name = mem_heap_strdup(heap, name);
3332
space_id = table->space;
3334
if (table->dir_path_of_temp_table != NULL) {
3335
name_or_path = mem_heap_strdup(
3336
heap, table->dir_path_of_temp_table);
3339
name_or_path = name;
3340
is_temp = (table->flags >> DICT_TF2_SHIFT)
3341
& DICT_TF2_TEMPORARY;
3344
dict_table_remove_from_cache(table);
3346
if (dict_load_table(name, TRUE) != NULL) {
3347
ut_print_timestamp(stderr);
3348
fputs(" InnoDB: Error: not able to remove table ",
3350
ut_print_name(stderr, trx, TRUE, name);
3351
fputs(" from the dictionary cache!\n", stderr);
3355
/* Do not drop possible .ibd tablespace if something went
3356
wrong: we do not want to delete valuable data of the user */
3358
if (err == DB_SUCCESS && space_id > 0) {
3359
if (!fil_space_for_table_exists_in_mem(space_id,
3366
"InnoDB: We removed now the InnoDB"
3367
" internal data dictionary entry\n"
3368
"InnoDB: of table ");
3369
ut_print_name(stderr, trx, TRUE, name);
3370
fprintf(stderr, ".\n");
3371
} else if (!fil_delete_tablespace(space_id)) {
3373
"InnoDB: We removed now the InnoDB"
3374
" internal data dictionary entry\n"
3375
"InnoDB: of table ");
3376
ut_print_name(stderr, trx, TRUE, name);
3377
fprintf(stderr, ".\n");
3379
ut_print_timestamp(stderr);
3381
" InnoDB: Error: not able to"
3382
" delete tablespace %lu of table ",
3384
ut_print_name(stderr, trx, TRUE, name);
3385
fputs("!\n", stderr);
3390
mem_heap_free(heap);
3393
case DB_TOO_MANY_CONCURRENT_TRXS:
3394
/* Cannot even find a free slot for the
3395
the undo log. We can directly exit here
3396
and return the DB_TOO_MANY_CONCURRENT_TRXS
3400
case DB_OUT_OF_FILE_SPACE:
3401
err = DB_MUST_GET_MORE_FILE_SPACE;
3403
row_mysql_handle_errors(&err, trx, NULL, NULL);
3405
/* Fall through to raise error */
3408
/* No other possible error returns */
3414
if (locked_dictionary) {
3415
trx_commit_for_mysql(trx);
3417
row_mysql_unlock_data_dictionary(trx);
3422
srv_wake_master_thread();
3427
/*********************************************************************//**
3428
Drop all temporary tables during crash recovery. */
3431
row_mysql_drop_temp_tables(void)
3432
/*============================*/
3439
trx = trx_allocate_for_background();
3440
trx->op_info = "dropping temporary tables";
3441
row_mysql_lock_data_dictionary(trx);
3443
heap = mem_heap_create(200);
3447
btr_pcur_open_at_index_side(
3449
dict_table_get_first_index(dict_sys->sys_tables),
3450
BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
3456
const char* table_name;
3457
dict_table_t* table;
3459
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
3461
if (!btr_pcur_is_on_user_rec(&pcur)) {
3465
rec = btr_pcur_get_rec(&pcur);
3466
field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len);
3467
if (len != 4 || !(mach_read_from_4(field) & 0x80000000UL)) {
3471
/* Because this is not a ROW_FORMAT=REDUNDANT table,
3472
the is_temp flag is valid. Examine it. */
3474
field = rec_get_nth_field_old(rec, 7/*MIX_LEN*/, &len);
3476
|| !(mach_read_from_4(field) & DICT_TF2_TEMPORARY)) {
3480
/* This is a temporary table. */
3481
field = rec_get_nth_field_old(rec, 0/*NAME*/, &len);
3482
if (len == UNIV_SQL_NULL || len == 0) {
3483
/* Corrupted SYS_TABLES.NAME */
3487
table_name = mem_heap_strdupl(heap, (const char*) field, len);
3489
btr_pcur_store_position(&pcur, &mtr);
3490
btr_pcur_commit_specify_mtr(&pcur, &mtr);
3492
table = dict_load_table(table_name, TRUE);
3495
row_drop_table_for_mysql(table_name, trx, FALSE);
3496
trx_commit_for_mysql(trx);
3500
btr_pcur_restore_position(BTR_SEARCH_LEAF,
3504
btr_pcur_close(&pcur);
3506
mem_heap_free(heap);
3507
row_mysql_unlock_data_dictionary(trx);
3508
trx_free_for_background(trx);
3511
/*******************************************************************//**
3512
Drop all foreign keys in a database, see Bug#18942.
3513
Called at the end of row_drop_database_for_mysql().
3514
@return error code or DB_SUCCESS */
3517
drop_all_foreign_keys_in_db(
3518
/*========================*/
3519
const char* name, /*!< in: database name which ends to '/' */
3520
trx_t* trx) /*!< in: transaction handle */
3525
ut_a(name[strlen(name) - 1] == '/');
3527
pinfo = pars_info_create();
3529
pars_info_add_str_literal(pinfo, "dbname", name);
3531
/** true if for_name is not prefixed with dbname */
3532
#define TABLE_NOT_IN_THIS_DB \
3533
"SUBSTR(for_name, 0, LENGTH(:dbname)) <> :dbname"
3535
err = que_eval_sql(pinfo,
3536
"PROCEDURE DROP_ALL_FOREIGN_KEYS_PROC () IS\n"
3537
"foreign_id CHAR;\n"
3540
"DECLARE CURSOR cur IS\n"
3541
"SELECT ID, FOR_NAME FROM SYS_FOREIGN\n"
3542
"WHERE FOR_NAME >= :dbname\n"
3543
"LOCK IN SHARE MODE\n"
3544
"ORDER BY FOR_NAME;\n"
3548
"WHILE found = 1 LOOP\n"
3549
" FETCH cur INTO foreign_id, for_name;\n"
3550
" IF (SQL % NOTFOUND) THEN\n"
3552
" ELSIF (" TABLE_NOT_IN_THIS_DB ") THEN\n"
3554
" ELSIF (1=1) THEN\n"
3555
" DELETE FROM SYS_FOREIGN_COLS\n"
3556
" WHERE ID = foreign_id;\n"
3557
" DELETE FROM SYS_FOREIGN\n"
3558
" WHERE ID = foreign_id;\n"
3564
FALSE, /* do not reserve dict mutex,
3565
we are already holding it */
3571
/*********************************************************************//**
3572
Drops a database for MySQL.
3573
@return error code or DB_SUCCESS */
3576
row_drop_database_for_mysql(
3577
/*========================*/
3578
const char* name, /*!< in: database name which ends to '/' */
3579
trx_t* trx) /*!< in: transaction handle */
3581
dict_table_t* table;
3583
int err = DB_SUCCESS;
3584
ulint namelen = strlen(name);
3586
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
3588
ut_a(name[namelen - 1] == '/');
3590
trx->op_info = "dropping database";
3592
trx_start_if_not_started(trx);
3594
row_mysql_lock_data_dictionary(trx);
3596
while ((table_name = dict_get_first_table_name_in_db(name))) {
3597
ut_a(memcmp(table_name, name, namelen) == 0);
3599
// For the time being I would like to see how often we see
3600
// lost temporary tables. --Brian
3601
fprintf(stderr, "Dropping lost temporary table %s\n", table_name);
3603
table = dict_table_get_low(table_name);
3607
/* Wait until MySQL does not have any queries running on
3610
if (table->n_mysql_handles_opened > 0) {
3611
row_mysql_unlock_data_dictionary(trx);
3613
ut_print_timestamp(stderr);
3614
fputs(" InnoDB: Warning: MySQL is trying to"
3615
" drop database ", stderr);
3616
ut_print_name(stderr, trx, TRUE, name);
3618
"InnoDB: though there are still"
3619
" open handles to table ", stderr);
3620
ut_print_name(stderr, trx, TRUE, table_name);
3621
fputs(".\n", stderr);
3623
os_thread_sleep(1000000);
3625
mem_free(table_name);
3630
err = row_drop_table_for_mysql(table_name, trx, TRUE);
3631
trx_commit_for_mysql(trx);
3633
if (err != DB_SUCCESS) {
3634
fputs("InnoDB: DROP DATABASE ", stderr);
3635
ut_print_name(stderr, trx, TRUE, name);
3636
fprintf(stderr, " failed with error %lu for table ",
3638
ut_print_name(stderr, trx, TRUE, table_name);
3640
mem_free(table_name);
3644
mem_free(table_name);
3647
if (err == DB_SUCCESS) {
3648
/* after dropping all tables try to drop all leftover
3649
foreign keys in case orphaned ones exist */
3650
err = (int) drop_all_foreign_keys_in_db(name, trx);
3652
if (err != DB_SUCCESS) {
3653
fputs("InnoDB: DROP DATABASE ", stderr);
3654
ut_print_name(stderr, trx, TRUE, name);
3655
fprintf(stderr, " failed with error %d while "
3656
"dropping all foreign keys", err);
3660
trx_commit_for_mysql(trx);
3662
row_mysql_unlock_data_dictionary(trx);
3669
/*********************************************************************//**
3670
Checks if a table name contains the string "/#sql" which denotes temporary
3672
@return TRUE if temporary table */
3675
row_is_mysql_tmp_table_name(
3676
/*========================*/
3677
const char* name) /*!< in: table name in the form
3678
'database/tablename' */
3680
return(strstr(name, "/#sql") != NULL);
3681
/* return(strstr(name, "/@0023sql") != NULL); */
3684
/****************************************************************//**
3685
Delete a single constraint.
3686
@return error code or DB_SUCCESS */
3689
row_delete_constraint_low(
3690
/*======================*/
3691
const char* id, /*!< in: constraint id */
3692
trx_t* trx) /*!< in: transaction handle */
3694
pars_info_t* info = pars_info_create();
3696
pars_info_add_str_literal(info, "id", id);
3698
return((int) que_eval_sql(info,
3699
"PROCEDURE DELETE_CONSTRAINT () IS\n"
3701
"DELETE FROM SYS_FOREIGN_COLS WHERE ID = :id;\n"
3702
"DELETE FROM SYS_FOREIGN WHERE ID = :id;\n"
3707
/****************************************************************//**
3708
Delete a single constraint.
3709
@return error code or DB_SUCCESS */
3712
row_delete_constraint(
3713
/*==================*/
3714
const char* id, /*!< in: constraint id */
3715
const char* database_name, /*!< in: database name, with the
3717
mem_heap_t* heap, /*!< in: memory heap */
3718
trx_t* trx) /*!< in: transaction handle */
3722
/* New format constraints have ids <databasename>/<constraintname>. */
3723
err = row_delete_constraint_low(
3724
mem_heap_strcat(heap, database_name, id), trx);
3726
if ((err == DB_SUCCESS) && !strchr(id, '/')) {
3727
/* Old format < 4.0.18 constraints have constraint ids
3728
<number>_<number>. We only try deleting them if the
3729
constraint name does not contain a '/' character, otherwise
3730
deleting a new format constraint named 'foo/bar' from
3731
database 'baz' would remove constraint 'bar' from database
3732
'foo', if it existed. */
3734
err = row_delete_constraint_low(id, trx);
3740
/*********************************************************************//**
3741
Renames a table for MySQL.
3742
@return error code or DB_SUCCESS */
3745
row_rename_table_for_mysql(
3746
/*=======================*/
3747
const char* old_name, /*!< in: old table name */
3748
const char* new_name, /*!< in: new table name */
3749
trx_t* trx, /*!< in: transaction handle */
3750
ibool commit) /*!< in: if TRUE then commit trx */
3752
dict_table_t* table;
3753
ulint err = DB_ERROR;
3754
mem_heap_t* heap = NULL;
3755
const char** constraints_to_drop = NULL;
3756
ulint n_constraints_to_drop = 0;
3757
ibool old_is_tmp, new_is_tmp;
3758
pars_info_t* info = NULL;
3760
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
3761
ut_a(old_name != NULL);
3762
ut_a(new_name != NULL);
3764
if (srv_created_new_raw || srv_force_recovery) {
3765
fputs("InnoDB: A new raw disk partition was initialized or\n"
3766
"InnoDB: innodb_force_recovery is on: we do not allow\n"
3767
"InnoDB: database modifications by the user. Shut down\n"
3768
"InnoDB: mysqld and edit my.cnf so that newraw"
3770
"InnoDB: with raw, and innodb_force_... is removed.\n",
3776
trx->op_info = "renaming table";
3777
trx_start_if_not_started(trx);
3779
old_is_tmp = row_is_mysql_tmp_table_name(old_name);
3780
new_is_tmp = row_is_mysql_tmp_table_name(new_name);
3782
table = dict_table_get_low(old_name);
3785
#if defined(BUILD_DRIZZLE)
3788
err = DB_TABLE_NOT_FOUND;
3789
ut_print_timestamp(stderr);
3791
fputs(" InnoDB: Error: table ", stderr);
3792
ut_print_name(stderr, trx, TRUE, old_name);
3793
fputs(" does not exist in the InnoDB internal\n"
3794
"InnoDB: data dictionary though MySQL is"
3795
" trying to rename the table.\n"
3796
"InnoDB: Have you copied the .frm file"
3797
" of the table to the\n"
3798
"InnoDB: MySQL database directory"
3799
" from another database?\n"
3800
"InnoDB: You can look for further help from\n"
3801
"InnoDB: " REFMAN "innodb-troubleshooting.html\n",
3803
#endif /* BUILD_DRIZZLE */
3805
} else if (table->ibd_file_missing) {
3806
err = DB_TABLE_NOT_FOUND;
3807
ut_print_timestamp(stderr);
3809
fputs(" InnoDB: Error: table ", stderr);
3810
ut_print_name(stderr, trx, TRUE, old_name);
3811
fputs(" does not have an .ibd file"
3812
" in the database directory.\n"
3813
"InnoDB: You can look for further help from\n"
3814
"InnoDB: " REFMAN "innodb-troubleshooting.html\n",
3817
} else if (new_is_tmp) {
3818
/* MySQL is doing an ALTER TABLE command and it renames the
3819
original table to a temporary table name. We want to preserve
3820
the original foreign key constraint definitions despite the
3821
name change. An exception is those constraints for which
3822
the ALTER TABLE contained DROP FOREIGN KEY <foreign key id>.*/
3824
heap = mem_heap_create(100);
3826
err = dict_foreign_parse_drop_constraints(
3827
heap, trx, table, &n_constraints_to_drop,
3828
&constraints_to_drop);
3830
if (err != DB_SUCCESS) {
3836
/* We use the private SQL parser of Innobase to generate the query
3837
graphs needed in updating the dictionary data from system tables. */
3839
info = pars_info_create();
3841
pars_info_add_str_literal(info, "new_table_name", new_name);
3842
pars_info_add_str_literal(info, "old_table_name", old_name);
3844
err = que_eval_sql(info,
3845
"PROCEDURE RENAME_TABLE () IS\n"
3847
"UPDATE SYS_TABLES SET NAME = :new_table_name\n"
3848
" WHERE NAME = :old_table_name;\n"
3852
if (err != DB_SUCCESS) {
3855
} else if (!new_is_tmp) {
3856
/* Rename all constraints. */
3858
info = pars_info_create();
3860
pars_info_add_str_literal(info, "new_table_name", new_name);
3861
pars_info_add_str_literal(info, "old_table_name", old_name);
3865
"PROCEDURE RENAME_CONSTRAINT_IDS () IS\n"
3866
"gen_constr_prefix CHAR;\n"
3867
"new_db_name CHAR;\n"
3868
"foreign_id CHAR;\n"
3869
"new_foreign_id CHAR;\n"
3870
"old_db_name_len INT;\n"
3871
"old_t_name_len INT;\n"
3872
"new_db_name_len INT;\n"
3877
"old_db_name_len := INSTR(:old_table_name, '/')-1;\n"
3878
"new_db_name_len := INSTR(:new_table_name, '/')-1;\n"
3879
"new_db_name := SUBSTR(:new_table_name, 0,\n"
3880
" new_db_name_len);\n"
3881
"old_t_name_len := LENGTH(:old_table_name);\n"
3882
"gen_constr_prefix := CONCAT(:old_table_name,\n"
3884
"WHILE found = 1 LOOP\n"
3885
" SELECT ID INTO foreign_id\n"
3886
" FROM SYS_FOREIGN\n"
3887
" WHERE FOR_NAME = :old_table_name\n"
3888
" AND TO_BINARY(FOR_NAME)\n"
3889
" = TO_BINARY(:old_table_name)\n"
3890
" LOCK IN SHARE MODE;\n"
3891
" IF (SQL % NOTFOUND) THEN\n"
3894
" UPDATE SYS_FOREIGN\n"
3895
" SET FOR_NAME = :new_table_name\n"
3896
" WHERE ID = foreign_id;\n"
3897
" id_len := LENGTH(foreign_id);\n"
3898
" IF (INSTR(foreign_id, '/') > 0) THEN\n"
3899
" IF (INSTR(foreign_id,\n"
3900
" gen_constr_prefix) > 0)\n"
3902
" new_foreign_id :=\n"
3903
" CONCAT(:new_table_name,\n"
3904
" SUBSTR(foreign_id, old_t_name_len,\n"
3905
" id_len - old_t_name_len));\n"
3907
" new_foreign_id :=\n"
3908
" CONCAT(new_db_name,\n"
3909
" SUBSTR(foreign_id,\n"
3910
" old_db_name_len,\n"
3911
" id_len - old_db_name_len));\n"
3913
" UPDATE SYS_FOREIGN\n"
3914
" SET ID = new_foreign_id\n"
3915
" WHERE ID = foreign_id;\n"
3916
" UPDATE SYS_FOREIGN_COLS\n"
3917
" SET ID = new_foreign_id\n"
3918
" WHERE ID = foreign_id;\n"
3922
"UPDATE SYS_FOREIGN SET REF_NAME = :new_table_name\n"
3923
"WHERE REF_NAME = :old_table_name\n"
3924
" AND TO_BINARY(REF_NAME)\n"
3925
" = TO_BINARY(:old_table_name);\n"
3929
} else if (n_constraints_to_drop > 0) {
3930
/* Drop some constraints of tmp tables. */
3932
ulint db_name_len = dict_get_db_name_len(old_name) + 1;
3933
char* db_name = mem_heap_strdupl(heap, old_name,
3937
for (i = 0; i < n_constraints_to_drop; i++) {
3938
err = row_delete_constraint(constraints_to_drop[i],
3939
db_name, heap, trx);
3941
if (err != DB_SUCCESS) {
3948
if (err != DB_SUCCESS) {
3949
if (err == DB_DUPLICATE_KEY) {
3950
ut_print_timestamp(stderr);
3951
fputs(" InnoDB: Error; possible reasons:\n"
3952
"InnoDB: 1) Table rename would cause"
3953
" two FOREIGN KEY constraints\n"
3954
"InnoDB: to have the same internal name"
3955
" in case-insensitive comparison.\n"
3956
"InnoDB: 2) table ", stderr);
3957
ut_print_name(stderr, trx, TRUE, new_name);
3958
fputs(" exists in the InnoDB internal data\n"
3959
"InnoDB: dictionary though MySQL is"
3960
" trying to rename table ", stderr);
3961
ut_print_name(stderr, trx, TRUE, old_name);
3963
"InnoDB: Have you deleted the .frm file"
3964
" and not used DROP TABLE?\n"
3965
"InnoDB: You can look for further help from\n"
3966
"InnoDB: " REFMAN "innodb-troubleshooting.html\n"
3967
"InnoDB: If table ", stderr);
3968
ut_print_name(stderr, trx, TRUE, new_name);
3969
fputs(" is a temporary table #sql..., then"
3971
"InnoDB: there are still queries running"
3972
" on the table, and it will be\n"
3973
"InnoDB: dropped automatically when"
3974
" the queries end.\n"
3975
"InnoDB: You can drop the orphaned table"
3976
" inside InnoDB by\n"
3977
"InnoDB: creating an InnoDB table with"
3978
" the same name in another\n"
3979
"InnoDB: database and copying the .frm file"
3980
" to the current database.\n"
3981
"InnoDB: Then MySQL thinks the table exists,"
3982
" and DROP TABLE will\n"
3983
"InnoDB: succeed.\n", stderr);
3985
trx->error_state = DB_SUCCESS;
3986
trx_general_rollback_for_mysql(trx, NULL);
3987
trx->error_state = DB_SUCCESS;
3989
/* The following call will also rename the .ibd data file if
3990
the table is stored in a single-table tablespace */
3992
if (!dict_table_rename_in_cache(table, new_name,
3994
trx->error_state = DB_SUCCESS;
3995
trx_general_rollback_for_mysql(trx, NULL);
3996
trx->error_state = DB_SUCCESS;
4000
/* We only want to switch off some of the type checking in
4001
an ALTER, not in a RENAME. */
4003
err = dict_load_foreigns(
4004
new_name, FALSE, !old_is_tmp || trx->check_foreigns);
4006
if (err != DB_SUCCESS) {
4007
ut_print_timestamp(stderr);
4010
fputs(" InnoDB: Error: in ALTER TABLE ",
4012
ut_print_name(stderr, trx, TRUE, new_name);
4014
"InnoDB: has or is referenced"
4015
" in foreign key constraints\n"
4016
"InnoDB: which are not compatible"
4017
" with the new table definition.\n",
4020
fputs(" InnoDB: Error: in RENAME TABLE"
4023
ut_print_name(stderr, trx, TRUE, new_name);
4025
"InnoDB: is referenced in"
4026
" foreign key constraints\n"
4027
"InnoDB: which are not compatible"
4028
" with the new table definition.\n",
4032
ut_a(dict_table_rename_in_cache(table,
4034
trx->error_state = DB_SUCCESS;
4035
trx_general_rollback_for_mysql(trx, NULL);
4036
trx->error_state = DB_SUCCESS;
4043
trx_commit_for_mysql(trx);
4046
if (UNIV_LIKELY_NULL(heap)) {
4047
mem_heap_free(heap);
4055
/*********************************************************************//**
4056
Checks that the index contains entries in an ascending order, unique
4057
constraint is not broken, and calculates the number of index entries
4058
in the read view of the current transaction.
4059
@return TRUE if ok */
4062
row_check_index_for_mysql(
4063
/*======================*/
4064
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct
4066
const dict_index_t* index, /*!< in: index */
4067
ulint* n_rows) /*!< out: number of entries
4068
seen in the consistent read */
4070
dtuple_t* prev_entry = NULL;
4071
ulint matched_fields;
4072
ulint matched_bytes;
4078
ibool contains_null;
4081
mem_heap_t* heap = NULL;
4083
ulint offsets_[REC_OFFS_NORMAL_SIZE];
4085
rec_offs_init(offsets_);
4089
buf = mem_alloc(UNIV_PAGE_SIZE);
4090
heap = mem_heap_create(100);
4094
ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
4096
/* Check thd->killed every 1,000 scanned rows */
4098
if (trx_is_interrupted(prebuilt->trx)) {
4108
ut_print_timestamp(stderr);
4109
fputs(" InnoDB: Warning: CHECK TABLE on ", stderr);
4110
dict_index_name_print(stderr, prebuilt->trx, index);
4111
fprintf(stderr, " returned %lu\n", ret);
4112
/* fall through (this error is ignored by CHECK TABLE) */
4113
case DB_END_OF_INDEX:
4116
mem_heap_free(heap);
4121
*n_rows = *n_rows + 1;
4123
/* row_search... returns the index record in buf, record origin offset
4124
within buf stored in the first 4 bytes, because we have built a dummy
4127
rec = buf + mach_read_from_4(buf);
4129
offsets = rec_get_offsets(rec, index, offsets_,
4130
ULINT_UNDEFINED, &heap);
4132
if (prev_entry != NULL) {
4136
cmp = cmp_dtuple_rec_with_match(prev_entry, rec, offsets,
4139
contains_null = FALSE;
4141
/* In a unique secondary index we allow equal key values if
4142
they contain SQL NULLs */
4145
i < dict_index_get_n_ordering_defined_by_user(index);
4147
if (UNIV_SQL_NULL == dfield_get_len(
4148
dtuple_get_nth_field(prev_entry, i))) {
4150
contains_null = TRUE;
4155
fputs("InnoDB: index records in a wrong order in ",
4158
dict_index_name_print(stderr,
4159
prebuilt->trx, index);
4161
"InnoDB: prev record ", stderr);
4162
dtuple_print(stderr, prev_entry);
4164
"InnoDB: record ", stderr);
4165
rec_print_new(stderr, rec, offsets);
4168
} else if (dict_index_is_unique(index)
4171
>= dict_index_get_n_ordering_defined_by_user(
4174
fputs("InnoDB: duplicate key in ", stderr);
4180
mem_heap_t* tmp_heap = NULL;
4182
/* Empty the heap on each round. But preserve offsets[]
4183
for the row_rec_to_index_entry() call, by copying them
4184
into a separate memory heap when needed. */
4185
if (UNIV_UNLIKELY(offsets != offsets_)) {
4186
ulint size = rec_offs_get_n_alloc(offsets)
4189
tmp_heap = mem_heap_create(size);
4190
offsets = mem_heap_dup(tmp_heap, offsets, size);
4193
mem_heap_empty(heap);
4195
prev_entry = row_rec_to_index_entry(ROW_COPY_DATA, rec,
4199
if (UNIV_LIKELY_NULL(tmp_heap)) {
4200
mem_heap_free(tmp_heap);
4204
ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, ROW_SEL_NEXT);
4209
/*********************************************************************//**
4210
Determines if a table is a magic monitor table.
4211
@return TRUE if monitor table */
4214
row_is_magic_monitor_table(
4215
/*=======================*/
4216
const char* table_name) /*!< in: name of the table, in the
4217
form database/table_name */
4219
const char* name; /* table_name without database/ */
4222
name = strchr(table_name, '/');
4225
len = strlen(name) + 1;
4227
if (STR_EQ(name, len, S_innodb_monitor)
4228
|| STR_EQ(name, len, S_innodb_lock_monitor)
4229
|| STR_EQ(name, len, S_innodb_tablespace_monitor)
4230
|| STR_EQ(name, len, S_innodb_table_monitor)
4231
|| STR_EQ(name, len, S_innodb_mem_validate)) {