1
/******************************************************
2
Interface between Innobase row operations and MySQL.
3
Contains also create table and other data dictionary operations.
7
Created 9/17/2000 Heikki Tuuri
8
*******************************************************/
10
#include "row0mysql.h"
13
#include "row0mysql.ic"
21
#include "pars0pars.h"
22
#include "dict0dict.h"
23
#include "dict0crea.h"
24
#include "dict0load.h"
25
#include "dict0boot.h"
27
#include "trx0purge.h"
30
#include "lock0lock.h"
35
#include "ibuf0ibuf.h"
37
/* Provide optional 4.x backwards compatibility for 5.0 and above */
38
UNIV_INTERN ibool row_rollback_on_timeout = FALSE;
40
/* List of tables we should drop in background. ALTER TABLE in MySQL requires
41
that the table handler can drop the table in background when there are no
42
queries to it any more. Protected by the kernel mutex. */
43
typedef struct row_mysql_drop_struct row_mysql_drop_t;
44
struct row_mysql_drop_struct{
46
UT_LIST_NODE_T(row_mysql_drop_t) row_mysql_drop_list;
49
static UT_LIST_BASE_NODE_T(row_mysql_drop_t) row_mysql_drop_list;
50
static ibool row_mysql_drop_list_inited = FALSE;
52
/* Magic table names for invoking various monitor threads */
53
static const char S_innodb_monitor[] = "innodb_monitor";
54
static const char S_innodb_lock_monitor[] = "innodb_lock_monitor";
55
static const char S_innodb_tablespace_monitor[] = "innodb_tablespace_monitor";
56
static const char S_innodb_table_monitor[] = "innodb_table_monitor";
57
static const char S_innodb_mem_validate[] = "innodb_mem_validate";
59
/* Evaluates to true if str1 equals str2_onstack, used for comparing
61
#define STR_EQ(str1, str1_len, str2_onstack) \
62
((str1_len) == sizeof(str2_onstack) \
63
&& memcmp(str1, str2_onstack, sizeof(str2_onstack)) == 0)
65
#ifndef UNIV_HOTBACKUP
66
/***********************************************************************
67
Determine if the given name is a name reserved for MySQL system tables. */
70
row_mysql_is_system_table(
71
/*======================*/
72
/* out: TRUE if name is a MySQL
76
if (strncmp(name, "mysql/", 6) != 0) {
81
return(0 == strcmp(name + 6, "host")
82
|| 0 == strcmp(name + 6, "user")
83
|| 0 == strcmp(name + 6, "db"));
85
#endif /* !UNIV_HOTBACKUP */
87
/*************************************************************************
88
If a table is not yet in the drop list, adds the table to the list of tables
89
which the master thread drops in background. We need this on Unix because in
90
ALTER TABLE MySQL may call drop table even if the table has running queries on
91
it. Also, if there are running foreign key checks on the table, we drop the
95
row_add_table_to_background_drop_list(
96
/*==================================*/
97
/* out: TRUE if the table was not yet in the
98
drop list, and was added there */
99
const char* name); /* in: table name */
101
/***********************************************************************
102
Delays an INSERT, DELETE or UPDATE operation if the purge is lagging. */
105
row_mysql_delay_if_needed(void)
106
/*===========================*/
108
if (srv_dml_needed_delay) {
109
os_thread_sleep(srv_dml_needed_delay);
113
/***********************************************************************
114
Frees the blob heap in prebuilt when no longer needed. */
117
row_mysql_prebuilt_free_blob_heap(
118
/*==============================*/
119
row_prebuilt_t* prebuilt) /* in: prebuilt struct of a
120
ha_innobase:: table handle */
122
mem_heap_free(prebuilt->blob_heap);
123
prebuilt->blob_heap = NULL;
126
/***********************************************************************
127
Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL row
131
row_mysql_store_true_var_len(
132
/*=========================*/
133
/* out: pointer to the data, we skip the 1 or 2 bytes
134
at the start that are used to store the len */
135
byte* dest, /* in: where to store */
136
ulint len, /* in: length, must fit in two bytes */
137
ulint lenlen) /* in: storage length of len: either 1 or 2 bytes */
140
ut_a(len < 256 * 256);
142
mach_write_to_2_little_endian(dest, len);
150
mach_write_to_1(dest, len);
155
/***********************************************************************
156
Reads a >= 5.0.3 format true VARCHAR length, in the MySQL row format, and
157
returns a pointer to the data. */
160
row_mysql_read_true_varchar(
161
/*========================*/
162
/* out: pointer to the data, we skip
163
the 1 or 2 bytes at the start that are
164
used to store the len */
165
ulint* len, /* out: variable-length field length */
166
const byte* field, /* in: field in the MySQL format */
167
ulint lenlen) /* in: storage length of len: either 1
171
*len = mach_read_from_2_little_endian(field);
178
*len = mach_read_from_1(field);
183
/***********************************************************************
184
Stores a reference to a BLOB in the MySQL format. */
187
row_mysql_store_blob_ref(
188
/*=====================*/
189
byte* dest, /* in: where to store */
190
ulint col_len,/* in: dest buffer size: determines into
191
how many bytes the BLOB length is stored,
192
the space for the length may vary from 1
194
const void* data, /* in: BLOB data; if the value to store
195
is SQL NULL this should be NULL pointer */
196
ulint len) /* in: BLOB length; if the value to store
197
is SQL NULL this should be 0; remember
198
also to set the NULL bit in the MySQL record
201
/* MySQL might assume the field is set to zero except the length and
202
the pointer fields */
204
memset(dest, '\0', col_len);
206
/* In dest there are 1 - 4 bytes reserved for the BLOB length,
207
and after that 8 bytes reserved for the pointer to the data.
208
In 32-bit architectures we only use the first 4 bytes of the pointer
211
ut_a(col_len - 8 > 1 || len < 256);
212
ut_a(col_len - 8 > 2 || len < 256 * 256);
213
ut_a(col_len - 8 > 3 || len < 256 * 256 * 256);
215
mach_write_to_n_little_endian(dest, col_len - 8, len);
217
memcpy(dest + col_len - 8, &data, sizeof data);
220
/***********************************************************************
221
Reads a reference to a BLOB in the MySQL format. */
224
row_mysql_read_blob_ref(
225
/*====================*/
226
/* out: pointer to BLOB data */
227
ulint* len, /* out: BLOB length */
228
const byte* ref, /* in: BLOB reference in the
230
ulint col_len) /* in: BLOB reference length
235
*len = mach_read_from_n_little_endian(ref, col_len - 8);
237
memcpy(&data, ref + col_len - 8, sizeof data);
242
/******************************************************************
243
Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
244
The counterpart of this function is row_sel_field_store_in_mysql_format() in
248
row_mysql_store_col_in_innobase_format(
249
/*===================================*/
250
/* out: up to which byte we used
251
buf in the conversion */
252
dfield_t* dfield, /* in/out: dfield where dtype
253
information must be already set when
254
this function is called! */
255
byte* buf, /* in/out: buffer for a converted
256
integer value; this must be at least
257
col_len long then! */
258
ibool row_format_col, /* TRUE if the mysql_data is from
259
a MySQL row, FALSE if from a MySQL
261
in MySQL, a true VARCHAR storage
262
format differs in a row and in a
263
key value: in a key value the length
264
is always stored in 2 bytes! */
265
const byte* mysql_data, /* in: MySQL column value, not
266
SQL NULL; NOTE that dfield may also
267
get a pointer to mysql_data,
268
therefore do not discard this as long
269
as dfield is used! */
270
ulint col_len, /* in: MySQL column length; NOTE that
271
this is the storage length of the
272
column in the MySQL format row, not
273
necessarily the length of the actual
274
payload data; if the column is a true
275
VARCHAR then this is irrelevant */
276
ulint comp) /* in: nonzero=compact format */
278
const byte* ptr = mysql_data;
279
const dtype_t* dtype;
283
dtype = dfield_get_type(dfield);
287
if (type == DATA_INT) {
288
/* Store integer data in Innobase in a big-endian format,
289
sign bit negated if the data is a signed integer. In MySQL,
290
integers are stored in a little-endian format. */
292
byte* p = buf + col_len;
303
if (!(dtype->prtype & DATA_UNSIGNED)) {
310
} else if ((type == DATA_VARCHAR
311
|| type == DATA_VARMYSQL
312
|| type == DATA_BINARY)) {
314
if (dtype_get_mysql_type(dtype) == DATA_MYSQL_TRUE_VARCHAR) {
315
/* The length of the actual data is stored to 1 or 2
316
bytes at the start of the field */
318
if (row_format_col) {
319
if (dtype->prtype & DATA_LONG_TRUE_VARCHAR) {
325
/* In a MySQL key value, lenlen is always 2 */
329
ptr = row_mysql_read_true_varchar(&col_len, mysql_data,
332
/* Remove trailing spaces from old style VARCHAR
335
/* Handle UCS2 strings differently. */
336
ulint mbminlen = dtype_get_mbminlen(dtype);
342
/* Trim "half-chars", just in case. */
345
while (col_len >= 2 && ptr[col_len - 2] == 0x00
346
&& ptr[col_len - 1] == 0x20) {
353
&& ptr[col_len - 1] == 0x20) {
358
} else if (comp && type == DATA_MYSQL
359
&& dtype_get_mbminlen(dtype) == 1
360
&& dtype_get_mbmaxlen(dtype) > 1) {
361
/* In some cases we strip trailing spaces from UTF-8 and other
362
multibyte charsets, from FIXED-length CHAR columns, to save
363
space. UTF-8 would otherwise normally use 3 * the string length
364
bytes to store a latin1 string! */
366
/* We assume that this CHAR field is encoded in a
367
variable-length character set where spaces have
368
1:1 correspondence to 0x20 bytes, such as UTF-8.
370
Consider a CHAR(n) field, a field of n characters.
371
It will contain between n * mbminlen and n * mbmaxlen bytes.
372
We will try to truncate it to n bytes by stripping
373
space padding. If the field contains single-byte
374
characters only, it will be truncated to n characters.
375
Consider a CHAR(5) field containing the string ".a "
376
where "." denotes a 3-byte character represented by
377
the bytes "$%&". After our stripping, the string will
378
be stored as "$%&a " (5 bytes). The string ".abc "
379
will be stored as "$%&abc" (6 bytes).
381
The space padding will be restored in row0sel.c, function
382
row_sel_field_store_in_mysql_format(). */
386
ut_a(!(dtype_get_len(dtype) % dtype_get_mbmaxlen(dtype)));
388
n_chars = dtype_get_len(dtype) / dtype_get_mbmaxlen(dtype);
390
/* Strip space padding. */
391
while (col_len > n_chars && ptr[col_len - 1] == 0x20) {
394
} else if (type == DATA_BLOB && row_format_col) {
396
ptr = row_mysql_read_blob_ref(&col_len, mysql_data, col_len);
399
dfield_set_data(dfield, ptr, col_len);
404
/******************************************************************
405
Convert a row in the MySQL format to a row in the Innobase format. Note that
406
the function to convert a MySQL format key value to an InnoDB dtuple is
407
row_sel_convert_mysql_key_to_innobase() in row0sel.c. */
410
row_mysql_convert_row_to_innobase(
411
/*==============================*/
412
dtuple_t* row, /* in/out: Innobase row where the
413
field type information is already
415
row_prebuilt_t* prebuilt, /* in: prebuilt struct where template
416
must be of type ROW_MYSQL_WHOLE_ROW */
417
byte* mysql_rec) /* in: row in the MySQL format;
418
NOTE: do not discard as long as
419
row is used, as row may contain
420
pointers to this record! */
422
mysql_row_templ_t* templ;
426
ut_ad(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
427
ut_ad(prebuilt->mysql_template);
429
for (i = 0; i < prebuilt->n_template; i++) {
431
templ = prebuilt->mysql_template + i;
432
dfield = dtuple_get_nth_field(row, i);
434
if (templ->mysql_null_bit_mask != 0) {
435
/* Column may be SQL NULL */
437
if (mysql_rec[templ->mysql_null_byte_offset]
438
& (byte) (templ->mysql_null_bit_mask)) {
442
dfield_set_null(dfield);
448
row_mysql_store_col_in_innobase_format(
450
prebuilt->ins_upd_rec_buff + templ->mysql_col_offset,
451
TRUE, /* MySQL row format data */
452
mysql_rec + templ->mysql_col_offset,
453
templ->mysql_col_len,
454
dict_table_is_comp(prebuilt->table));
460
/********************************************************************
461
Handles user errors and lock waits detected by the database engine. */
464
row_mysql_handle_errors(
465
/*====================*/
466
/* out: TRUE if it was a lock wait and
467
we should continue running the query thread */
468
ulint* new_err,/* out: possible new error encountered in
469
lock wait, or if no new error, the value
470
of trx->error_state at the entry of this
472
trx_t* trx, /* in: transaction */
473
que_thr_t* thr, /* in: query thread */
474
trx_savept_t* savept) /* in: savepoint or NULL */
476
#ifndef UNIV_HOTBACKUP
480
err = trx->error_state;
482
ut_a(err != DB_SUCCESS);
484
trx->error_state = DB_SUCCESS;
487
case DB_LOCK_WAIT_TIMEOUT:
488
if (row_rollback_on_timeout) {
489
trx_general_rollback_for_mysql(trx, FALSE, NULL);
493
case DB_DUPLICATE_KEY:
494
case DB_FOREIGN_DUPLICATE_KEY:
495
case DB_TOO_BIG_RECORD:
496
case DB_ROW_IS_REFERENCED:
497
case DB_NO_REFERENCED_ROW:
498
case DB_CANNOT_ADD_CONSTRAINT:
499
case DB_TOO_MANY_CONCURRENT_TRXS:
500
case DB_OUT_OF_FILE_SPACE:
502
/* Roll back the latest, possibly incomplete
503
insertion or update */
505
trx_general_rollback_for_mysql(trx, TRUE, savept);
507
/* MySQL will roll back the latest SQL statement */
510
srv_suspend_mysql_thread(thr);
512
if (trx->error_state != DB_SUCCESS) {
513
que_thr_stop_for_mysql(thr);
515
goto handle_new_error;
523
case DB_LOCK_TABLE_FULL:
524
/* Roll back the whole transaction; this resolution was added
525
to version 3.23.43 */
527
trx_general_rollback_for_mysql(trx, FALSE, NULL);
530
case DB_MUST_GET_MORE_FILE_SPACE:
531
fputs("InnoDB: The database cannot continue"
532
" operation because of\n"
533
"InnoDB: lack of space. You must add"
534
" a new data file to\n"
535
"InnoDB: my.cnf and restart the database.\n", stderr);
540
fputs("InnoDB: We detected index corruption"
541
" in an InnoDB type table.\n"
542
"InnoDB: You have to dump + drop + reimport"
543
" the table or, in\n"
544
"InnoDB: a case of widespread corruption,"
546
"InnoDB: tables and recreate the"
547
" whole InnoDB tablespace.\n"
548
"InnoDB: If the mysqld server crashes"
549
" after the startup or when\n"
550
"InnoDB: you dump the tables, look at\n"
551
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
552
"forcing-recovery.html"
553
" for help.\n", stderr);
556
fprintf(stderr, "InnoDB: unknown error code %lu\n",
561
if (trx->error_state != DB_SUCCESS) {
562
*new_err = trx->error_state;
567
trx->error_state = DB_SUCCESS;
570
#else /* UNIV_HOTBACKUP */
571
/* This function depends on MySQL code that is not included in
572
InnoDB Hot Backup builds. Besides, this function should never
573
be called in InnoDB Hot Backup. */
576
#endif /* UNIV_HOTBACKUP */
579
/************************************************************************
580
Create a prebuilt struct for a MySQL table handle. */
585
/* out, own: a prebuilt struct */
586
dict_table_t* table) /* in: Innobase table handle */
588
row_prebuilt_t* prebuilt;
590
dict_index_t* clust_index;
594
heap = mem_heap_create(sizeof *prebuilt + 128);
596
prebuilt = mem_heap_zalloc(heap, sizeof *prebuilt);
598
prebuilt->magic_n = ROW_PREBUILT_ALLOCATED;
599
prebuilt->magic_n2 = ROW_PREBUILT_ALLOCATED;
601
prebuilt->table = table;
603
prebuilt->sql_stat_start = TRUE;
604
prebuilt->heap = heap;
606
prebuilt->pcur = btr_pcur_create_for_mysql();
607
prebuilt->clust_pcur = btr_pcur_create_for_mysql();
609
prebuilt->select_lock_type = LOCK_NONE;
610
prebuilt->stored_select_lock_type = 99999999;
612
prebuilt->search_tuple = dtuple_create(
613
heap, 2 * dict_table_get_n_cols(table));
615
clust_index = dict_table_get_first_index(table);
617
/* Make sure that search_tuple is long enough for clustered index */
618
ut_a(2 * dict_table_get_n_cols(table) >= clust_index->n_fields);
620
ref_len = dict_index_get_n_unique(clust_index);
622
ref = dtuple_create(heap, ref_len);
624
dict_index_copy_types(ref, clust_index, ref_len);
626
prebuilt->clust_ref = ref;
631
/************************************************************************
632
Free a prebuilt struct for a MySQL table handle. */
637
row_prebuilt_t* prebuilt, /* in, own: prebuilt struct */
638
ibool dict_locked) /* in: TRUE=data dictionary locked */
643
(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED
644
|| prebuilt->magic_n2 != ROW_PREBUILT_ALLOCATED)) {
647
"InnoDB: Error: trying to free a corrupt\n"
648
"InnoDB: table handle. Magic n %lu,"
649
" magic n2 %lu, table name ",
650
(ulong) prebuilt->magic_n,
651
(ulong) prebuilt->magic_n2);
652
ut_print_name(stderr, NULL, TRUE, prebuilt->table->name);
655
mem_analyze_corruption(prebuilt);
660
prebuilt->magic_n = ROW_PREBUILT_FREED;
661
prebuilt->magic_n2 = ROW_PREBUILT_FREED;
663
btr_pcur_free_for_mysql(prebuilt->pcur);
664
btr_pcur_free_for_mysql(prebuilt->clust_pcur);
666
if (prebuilt->mysql_template) {
667
mem_free(prebuilt->mysql_template);
670
if (prebuilt->ins_graph) {
671
que_graph_free_recursive(prebuilt->ins_graph);
674
if (prebuilt->sel_graph) {
675
que_graph_free_recursive(prebuilt->sel_graph);
678
if (prebuilt->upd_graph) {
679
que_graph_free_recursive(prebuilt->upd_graph);
682
if (prebuilt->blob_heap) {
683
mem_heap_free(prebuilt->blob_heap);
686
if (prebuilt->old_vers_heap) {
687
mem_heap_free(prebuilt->old_vers_heap);
690
for (i = 0; i < MYSQL_FETCH_CACHE_SIZE; i++) {
691
if (prebuilt->fetch_cache[i] != NULL) {
693
if ((ROW_PREBUILT_FETCH_MAGIC_N != mach_read_from_4(
694
(prebuilt->fetch_cache[i]) - 4))
695
|| (ROW_PREBUILT_FETCH_MAGIC_N != mach_read_from_4(
696
(prebuilt->fetch_cache[i])
697
+ prebuilt->mysql_row_len))) {
698
fputs("InnoDB: Error: trying to free"
699
" a corrupt fetch buffer.\n", stderr);
701
mem_analyze_corruption(
702
prebuilt->fetch_cache[i]);
707
mem_free((prebuilt->fetch_cache[i]) - 4);
711
dict_table_decrement_handle_count(prebuilt->table, dict_locked);
713
mem_heap_free(prebuilt->heap);
716
/*************************************************************************
717
Updates the transaction pointers in query graphs stored in the prebuilt
721
row_update_prebuilt_trx(
722
/*====================*/
723
/* out: prebuilt dtuple */
724
row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL
726
trx_t* trx) /* in: transaction handle */
728
if (trx->magic_n != TRX_MAGIC_N) {
730
"InnoDB: Error: trying to use a corrupt\n"
731
"InnoDB: trx handle. Magic n %lu\n",
732
(ulong) trx->magic_n);
734
mem_analyze_corruption(trx);
739
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
741
"InnoDB: Error: trying to use a corrupt\n"
742
"InnoDB: table handle. Magic n %lu, table name ",
743
(ulong) prebuilt->magic_n);
744
ut_print_name(stderr, trx, TRUE, prebuilt->table->name);
747
mem_analyze_corruption(prebuilt);
754
if (prebuilt->ins_graph) {
755
prebuilt->ins_graph->trx = trx;
758
if (prebuilt->upd_graph) {
759
prebuilt->upd_graph->trx = trx;
762
if (prebuilt->sel_graph) {
763
prebuilt->sel_graph->trx = trx;
767
/*************************************************************************
768
Gets pointer to a prebuilt dtuple used in insertions. If the insert graph
769
has not yet been built in the prebuilt struct, then this function first
773
row_get_prebuilt_insert_row(
774
/*========================*/
775
/* out: prebuilt dtuple; the column
776
type information is also set in it */
777
row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
782
dict_table_t* table = prebuilt->table;
784
ut_ad(prebuilt && table && prebuilt->trx);
786
if (prebuilt->ins_node == NULL) {
788
/* Not called before for this handle: create an insert node
789
and query graph to the prebuilt struct */
791
node = ins_node_create(INS_DIRECT, table, prebuilt->heap);
793
prebuilt->ins_node = node;
795
if (prebuilt->ins_upd_rec_buff == NULL) {
796
prebuilt->ins_upd_rec_buff = mem_heap_alloc(
797
prebuilt->heap, prebuilt->mysql_row_len);
800
row = dtuple_create(prebuilt->heap,
801
dict_table_get_n_cols(table));
803
dict_table_copy_types(row, table);
805
ins_node_set_new_row(node, row);
807
prebuilt->ins_graph = que_node_get_parent(
808
pars_complete_graph_for_exec(node,
811
prebuilt->ins_graph->state = QUE_FORK_ACTIVE;
814
return(prebuilt->ins_node->row);
817
/*************************************************************************
818
Updates the table modification counter and calculates new estimates
819
for table and index statistics if necessary. */
822
row_update_statistics_if_needed(
823
/*============================*/
824
dict_table_t* table) /* in: table */
828
counter = table->stat_modified_counter;
830
table->stat_modified_counter = counter + 1;
832
/* Calculate new statistics if 1 / 16 of table has been modified
833
since the last time a statistics batch was run, or if
834
stat_modified_counter > 2 000 000 000 (to avoid wrap-around).
835
We calculate statistics at most every 16th round, since we may have
836
a counter table which is very small and updated very often. */
838
if (counter > 2000000000
839
|| ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) {
841
dict_update_statistics(table);
845
/*************************************************************************
846
Unlocks an AUTO_INC type lock possibly reserved by trx. */
849
row_unlock_table_autoinc_for_mysql(
850
/*===============================*/
851
trx_t* trx) /* in: transaction */
853
if (!trx->auto_inc_lock) {
858
lock_table_unlock_auto_inc(trx);
861
/*************************************************************************
862
Sets an AUTO_INC type lock on the table mentioned in prebuilt. The
863
AUTO_INC lock gives exclusive access to the auto-inc counter of the
864
table. The lock is reserved only for the duration of an SQL statement.
865
It is not compatible with another AUTO_INC or exclusive lock on the
869
row_lock_table_autoinc_for_mysql(
870
/*=============================*/
871
/* out: error code or DB_SUCCESS */
872
row_prebuilt_t* prebuilt) /* in: prebuilt struct in the MySQL
875
trx_t* trx = prebuilt->trx;
876
ins_node_t* node = prebuilt->ins_node;
882
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
884
if (trx->auto_inc_lock) {
889
trx->op_info = "setting auto-inc lock";
892
row_get_prebuilt_insert_row(prebuilt);
893
node = prebuilt->ins_node;
896
/* We use the insert query graph as the dummy graph needed
897
in the lock module call */
899
thr = que_fork_get_first_thr(prebuilt->ins_graph);
901
que_thr_move_to_run_state_for_mysql(thr, trx);
904
thr->run_node = node;
905
thr->prev_node = node;
907
/* It may be that the current session has not yet started
908
its transaction, or it has been committed: */
910
trx_start_if_not_started(trx);
912
err = lock_table(0, prebuilt->table, LOCK_AUTO_INC, thr);
914
trx->error_state = err;
916
if (err != DB_SUCCESS) {
917
que_thr_stop_for_mysql(thr);
919
was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL);
930
que_thr_stop_for_mysql_no_error(thr, trx);
937
/*************************************************************************
938
Sets a table lock on the table mentioned in prebuilt. */
941
row_lock_table_for_mysql(
942
/*=====================*/
943
/* out: error code or DB_SUCCESS */
944
row_prebuilt_t* prebuilt, /* in: prebuilt struct in the MySQL
946
dict_table_t* table, /* in: table to lock, or NULL
947
if prebuilt->table should be
949
prebuilt->select_lock_type */
950
ulint mode) /* in: lock mode of table
951
(ignored if table==NULL) */
953
trx_t* trx = prebuilt->trx;
959
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
961
trx->op_info = "setting table lock";
963
if (prebuilt->sel_graph == NULL) {
964
/* Build a dummy select query graph */
965
row_prebuild_sel_graph(prebuilt);
968
/* We use the select query graph as the dummy graph needed
969
in the lock module call */
971
thr = que_fork_get_first_thr(prebuilt->sel_graph);
973
que_thr_move_to_run_state_for_mysql(thr, trx);
977
thr->prev_node = thr->common.parent;
979
/* It may be that the current session has not yet started
980
its transaction, or it has been committed: */
982
trx_start_if_not_started(trx);
985
err = lock_table(0, table, mode, thr);
987
err = lock_table(0, prebuilt->table,
988
prebuilt->select_lock_type, thr);
991
trx->error_state = err;
993
if (err != DB_SUCCESS) {
994
que_thr_stop_for_mysql(thr);
996
was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL);
1007
que_thr_stop_for_mysql_no_error(thr, trx);
1014
/*************************************************************************
1015
Does an insert for MySQL. */
1018
row_insert_for_mysql(
1019
/*=================*/
1020
/* out: error code or DB_SUCCESS */
1021
byte* mysql_rec, /* in: row in the MySQL format */
1022
row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
1025
trx_savept_t savept;
1028
ibool was_lock_wait;
1029
trx_t* trx = prebuilt->trx;
1030
ins_node_t* node = prebuilt->ins_node;
1033
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1035
if (prebuilt->table->ibd_file_missing) {
1036
ut_print_timestamp(stderr);
1037
fprintf(stderr, " InnoDB: Error:\n"
1038
"InnoDB: MySQL is trying to use a table handle"
1039
" but the .ibd file for\n"
1040
"InnoDB: table %s does not exist.\n"
1041
"InnoDB: Have you deleted the .ibd file"
1042
" from the database directory under\n"
1043
"InnoDB: the MySQL datadir, or have you"
1044
" used DISCARD TABLESPACE?\n"
1045
"InnoDB: Look from\n"
1046
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
1047
"innodb-troubleshooting.html\n"
1048
"InnoDB: how you can resolve the problem.\n",
1049
prebuilt->table->name);
1053
if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
1055
"InnoDB: Error: trying to free a corrupt\n"
1056
"InnoDB: table handle. Magic n %lu, table name ",
1057
(ulong) prebuilt->magic_n);
1058
ut_print_name(stderr, trx, TRUE, prebuilt->table->name);
1061
mem_analyze_corruption(prebuilt);
1066
if (UNIV_UNLIKELY(srv_created_new_raw || srv_force_recovery)) {
1067
fputs("InnoDB: A new raw disk partition was initialized or\n"
1068
"InnoDB: innodb_force_recovery is on: we do not allow\n"
1069
"InnoDB: database modifications by the user. Shut down\n"
1070
"InnoDB: mysqld and edit my.cnf so that"
1071
" newraw is replaced\n"
1072
"InnoDB: with raw, and innodb_force_... is removed.\n",
1078
trx->op_info = "inserting";
1080
row_mysql_delay_if_needed();
1082
trx_start_if_not_started(trx);
1085
row_get_prebuilt_insert_row(prebuilt);
1086
node = prebuilt->ins_node;
1089
row_mysql_convert_row_to_innobase(node->row, prebuilt, mysql_rec);
1091
savept = trx_savept_take(trx);
1093
thr = que_fork_get_first_thr(prebuilt->ins_graph);
1095
if (prebuilt->sql_stat_start) {
1096
node->state = INS_NODE_SET_IX_LOCK;
1097
prebuilt->sql_stat_start = FALSE;
1099
node->state = INS_NODE_ALLOC_ROW_ID;
1102
que_thr_move_to_run_state_for_mysql(thr, trx);
1105
thr->run_node = node;
1106
thr->prev_node = node;
1110
err = trx->error_state;
1112
if (err != DB_SUCCESS) {
1113
que_thr_stop_for_mysql(thr);
1115
/* TODO: what is this? */ thr->lock_state= QUE_THR_LOCK_ROW;
1117
was_lock_wait = row_mysql_handle_errors(&err, trx, thr,
1119
thr->lock_state= QUE_THR_LOCK_NOLOCK;
1121
if (was_lock_wait) {
1130
que_thr_stop_for_mysql_no_error(thr, trx);
1132
prebuilt->table->stat_n_rows++;
1134
srv_n_rows_inserted++;
1136
if (prebuilt->table->stat_n_rows == 0) {
1137
/* Avoid wrap-over */
1138
prebuilt->table->stat_n_rows--;
1141
row_update_statistics_if_needed(prebuilt->table);
1147
/*************************************************************************
1148
Builds a dummy query graph used in selects. */
1151
row_prebuild_sel_graph(
1152
/*===================*/
1153
row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
1158
ut_ad(prebuilt && prebuilt->trx);
1160
if (prebuilt->sel_graph == NULL) {
1162
node = sel_node_create(prebuilt->heap);
1164
prebuilt->sel_graph = que_node_get_parent(
1165
pars_complete_graph_for_exec(node,
1169
prebuilt->sel_graph->state = QUE_FORK_ACTIVE;
1173
/*************************************************************************
1174
Creates an query graph node of 'update' type to be used in the MySQL
1178
row_create_update_node_for_mysql(
1179
/*=============================*/
1180
/* out, own: update node */
1181
dict_table_t* table, /* in: table to update */
1182
mem_heap_t* heap) /* in: mem heap from which allocated */
1186
node = upd_node_create(heap);
1188
node->in_mysql_interface = TRUE;
1189
node->is_delete = FALSE;
1190
node->searched_update = FALSE;
1191
node->select_will_do_update = FALSE;
1192
node->select = NULL;
1193
node->pcur = btr_pcur_create_for_mysql();
1194
node->table = table;
1196
node->update = upd_create(dict_table_get_n_cols(table), heap);
1198
node->update_n_fields = dict_table_get_n_cols(table);
1200
UT_LIST_INIT(node->columns);
1201
node->has_clust_rec_x_lock = TRUE;
1202
node->cmpl_info = 0;
1204
node->table_sym = NULL;
1205
node->col_assign_list = NULL;
1210
/*************************************************************************
1211
Gets pointer to a prebuilt update vector used in updates. If the update
1212
graph has not yet been built in the prebuilt struct, then this function
1216
row_get_prebuilt_update_vector(
1217
/*===========================*/
1218
/* out: prebuilt update vector */
1219
row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
1222
dict_table_t* table = prebuilt->table;
1225
ut_ad(prebuilt && table && prebuilt->trx);
1227
if (prebuilt->upd_node == NULL) {
1229
/* Not called before for this handle: create an update node
1230
and query graph to the prebuilt struct */
1232
node = row_create_update_node_for_mysql(table, prebuilt->heap);
1234
prebuilt->upd_node = node;
1236
prebuilt->upd_graph = que_node_get_parent(
1237
pars_complete_graph_for_exec(node,
1240
prebuilt->upd_graph->state = QUE_FORK_ACTIVE;
1243
return(prebuilt->upd_node->update);
1246
/*************************************************************************
1247
Does an update or delete of a row for MySQL. */
1250
row_update_for_mysql(
1251
/*=================*/
1252
/* out: error code or DB_SUCCESS */
1253
byte* mysql_rec, /* in: the row to be updated, in
1255
row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
1258
trx_savept_t savept;
1261
ibool was_lock_wait;
1262
dict_index_t* clust_index;
1263
/* ulint ref_len; */
1265
dict_table_t* table = prebuilt->table;
1266
trx_t* trx = prebuilt->trx;
1268
ut_ad(prebuilt && trx);
1269
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1270
UT_NOT_USED(mysql_rec);
1272
if (prebuilt->table->ibd_file_missing) {
1273
ut_print_timestamp(stderr);
1274
fprintf(stderr, " InnoDB: Error:\n"
1275
"InnoDB: MySQL is trying to use a table handle"
1276
" but the .ibd file for\n"
1277
"InnoDB: table %s does not exist.\n"
1278
"InnoDB: Have you deleted the .ibd file"
1279
" from the database directory under\n"
1280
"InnoDB: the MySQL datadir, or have you"
1281
" used DISCARD TABLESPACE?\n"
1282
"InnoDB: Look from\n"
1283
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
1284
"innodb-troubleshooting.html\n"
1285
"InnoDB: how you can resolve the problem.\n",
1286
prebuilt->table->name);
1290
if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
1292
"InnoDB: Error: trying to free a corrupt\n"
1293
"InnoDB: table handle. Magic n %lu, table name ",
1294
(ulong) prebuilt->magic_n);
1295
ut_print_name(stderr, trx, TRUE, prebuilt->table->name);
1298
mem_analyze_corruption(prebuilt);
1303
if (UNIV_UNLIKELY(srv_created_new_raw || srv_force_recovery)) {
1304
fputs("InnoDB: A new raw disk partition was initialized or\n"
1305
"InnoDB: innodb_force_recovery is on: we do not allow\n"
1306
"InnoDB: database modifications by the user. Shut down\n"
1307
"InnoDB: mysqld and edit my.cnf so that newraw"
1309
"InnoDB: with raw, and innodb_force_... is removed.\n",
1315
trx->op_info = "updating or deleting";
1317
row_mysql_delay_if_needed();
1319
trx_start_if_not_started(trx);
1321
node = prebuilt->upd_node;
1323
clust_index = dict_table_get_first_index(table);
1325
if (prebuilt->pcur->btr_cur.index == clust_index) {
1326
btr_pcur_copy_stored_position(node->pcur, prebuilt->pcur);
1328
btr_pcur_copy_stored_position(node->pcur,
1329
prebuilt->clust_pcur);
1332
ut_a(node->pcur->rel_pos == BTR_PCUR_ON);
1334
/* MySQL seems to call rnd_pos before updating each row it
1335
has cached: we can get the correct cursor position from
1336
prebuilt->pcur; NOTE that we cannot build the row reference
1337
from mysql_rec if the clustered index was automatically
1338
generated for the table: MySQL does not know anything about
1339
the row id used as the clustered index key */
1341
savept = trx_savept_take(trx);
1343
thr = que_fork_get_first_thr(prebuilt->upd_graph);
1345
node->state = UPD_NODE_UPDATE_CLUSTERED;
1347
ut_ad(!prebuilt->sql_stat_start);
1349
que_thr_move_to_run_state_for_mysql(thr, trx);
1352
thr->run_node = node;
1353
thr->prev_node = node;
1357
err = trx->error_state;
1359
if (err != DB_SUCCESS) {
1360
que_thr_stop_for_mysql(thr);
1362
if (err == DB_RECORD_NOT_FOUND) {
1363
trx->error_state = DB_SUCCESS;
1369
thr->lock_state= QUE_THR_LOCK_ROW;
1370
was_lock_wait = row_mysql_handle_errors(&err, trx, thr,
1372
thr->lock_state= QUE_THR_LOCK_NOLOCK;
1374
if (was_lock_wait) {
1383
que_thr_stop_for_mysql_no_error(thr, trx);
1385
if (node->is_delete) {
1386
if (prebuilt->table->stat_n_rows > 0) {
1387
prebuilt->table->stat_n_rows--;
1390
srv_n_rows_deleted++;
1392
srv_n_rows_updated++;
1395
row_update_statistics_if_needed(prebuilt->table);
1402
/*************************************************************************
1403
This can only be used when srv_locks_unsafe_for_binlog is TRUE or
1404
this session is using a READ COMMITTED isolation level. Before
1405
calling this function we must use trx_reset_new_rec_lock_info() and
1406
trx_register_new_rec_lock() to store the information which new record locks
1407
really were set. This function removes a newly set lock under prebuilt->pcur,
1408
and also under prebuilt->clust_pcur. Currently, this is only used and tested
1409
in the case of an UPDATE or a DELETE statement, where the row lock is of the
1411
Thus, this implements a 'mini-rollback' that releases the latest record
1415
row_unlock_for_mysql(
1416
/*=================*/
1417
/* out: error code or DB_SUCCESS */
1418
row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL
1420
ibool has_latches_on_recs)/* TRUE if called so that we have
1421
the latches on the records under pcur
1422
and clust_pcur, and we do not need to
1423
reposition the cursors. */
1425
dict_index_t* index;
1426
btr_pcur_t* pcur = prebuilt->pcur;
1427
btr_pcur_t* clust_pcur = prebuilt->clust_pcur;
1428
trx_t* trx = prebuilt->trx;
1432
ut_ad(prebuilt && trx);
1433
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1435
if (!(srv_locks_unsafe_for_binlog
1436
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
1439
"InnoDB: Error: calling row_unlock_for_mysql though\n"
1440
"InnoDB: srv_locks_unsafe_for_binlog is FALSE and\n"
1441
"InnoDB: this session is not using"
1442
" READ COMMITTED isolation level.\n");
1447
trx->op_info = "unlock_row";
1449
index = btr_pcur_get_btr_cur(pcur)->index;
1451
if (index != NULL && trx_new_rec_locks_contain(trx, index)) {
1455
/* Restore the cursor position and find the record */
1457
if (!has_latches_on_recs) {
1458
btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, &mtr);
1461
rec = btr_pcur_get_rec(pcur);
1463
lock_rec_unlock(trx, btr_pcur_get_block(pcur),
1464
rec, prebuilt->select_lock_type);
1468
/* If the search was done through the clustered index, then
1469
we have not used clust_pcur at all, and we must NOT try to
1470
reset locks on clust_pcur. The values in clust_pcur may be
1473
if (dict_index_is_clust(index)) {
1479
index = btr_pcur_get_btr_cur(clust_pcur)->index;
1481
if (index != NULL && trx_new_rec_locks_contain(trx, index)) {
1485
/* Restore the cursor position and find the record */
1487
if (!has_latches_on_recs) {
1488
btr_pcur_restore_position(BTR_SEARCH_LEAF, clust_pcur,
1492
rec = btr_pcur_get_rec(clust_pcur);
1494
lock_rec_unlock(trx, btr_pcur_get_block(clust_pcur),
1495
rec, prebuilt->select_lock_type);
1506
/**************************************************************************
1507
Does a cascaded delete or set null in a foreign key operation. */
1510
row_update_cascade_for_mysql(
1511
/*=========================*/
1512
/* out: error code or DB_SUCCESS */
1513
que_thr_t* thr, /* in: query thread */
1514
upd_node_t* node, /* in: update node used in the cascade
1515
or set null operation */
1516
dict_table_t* table) /* in: table where we do the operation */
1521
trx = thr_get_trx(thr);
1523
thr->run_node = node;
1524
thr->prev_node = node;
1528
err = trx->error_state;
1530
/* Note that the cascade node is a subnode of another InnoDB
1531
query graph node. We do a normal lock wait in this node, but
1532
all errors are handled by the parent node. */
1534
if (err == DB_LOCK_WAIT) {
1535
/* Handle lock wait here */
1537
que_thr_stop_for_mysql(thr);
1539
srv_suspend_mysql_thread(thr);
1541
/* Note that a lock wait may also end in a lock wait timeout,
1542
or this transaction is picked as a victim in selective
1543
deadlock resolution */
1545
if (trx->error_state != DB_SUCCESS) {
1547
return(trx->error_state);
1550
/* Retry operation after a normal lock wait */
1555
if (err != DB_SUCCESS) {
1560
if (node->is_delete) {
1561
if (table->stat_n_rows > 0) {
1562
table->stat_n_rows--;
1565
srv_n_rows_deleted++;
1567
srv_n_rows_updated++;
1570
row_update_statistics_if_needed(table);
1575
/*************************************************************************
1576
Checks if a table is such that we automatically created a clustered
1577
index on it (on row id). */
1580
row_table_got_default_clust_index(
1581
/*==============================*/
1582
const dict_table_t* table)
1584
const dict_index_t* clust_index;
1586
clust_index = dict_table_get_first_index(table);
1588
return(dict_index_get_nth_col(clust_index, 0)->mtype == DATA_SYS);
1591
/*************************************************************************
1592
Calculates the key number used inside MySQL for an Innobase index. We have
1593
to take into account if we generated a default clustered index for the table */
1596
row_get_mysql_key_number_for_index(
1597
/*===============================*/
1598
const dict_index_t* index)
1600
const dict_index_t* ind;
1606
ind = dict_table_get_first_index(index->table);
1608
while (index != ind) {
1609
ind = dict_table_get_next_index(ind);
1613
if (row_table_got_default_clust_index(index->table)) {
1621
/*************************************************************************
1622
Locks the data dictionary in shared mode from modifications, for performing
1623
foreign key check, rollback, or other operation invisible to MySQL. */
1626
row_mysql_freeze_data_dictionary(
1627
/*=============================*/
1628
trx_t* trx) /* in: transaction */
1630
ut_a(trx->dict_operation_lock_mode == 0);
1632
rw_lock_s_lock(&dict_operation_lock);
1634
trx->dict_operation_lock_mode = RW_S_LATCH;
1637
/*************************************************************************
1638
Unlocks the data dictionary shared lock. */
1641
row_mysql_unfreeze_data_dictionary(
1642
/*===============================*/
1643
trx_t* trx) /* in: transaction */
1645
ut_a(trx->dict_operation_lock_mode == RW_S_LATCH);
1647
rw_lock_s_unlock(&dict_operation_lock);
1649
trx->dict_operation_lock_mode = 0;
1652
/*************************************************************************
1653
Locks the data dictionary exclusively for performing a table create or other
1654
data dictionary modification operation. */
1657
row_mysql_lock_data_dictionary(
1658
/*===========================*/
1659
trx_t* trx) /* in: transaction */
1661
ut_a(trx->dict_operation_lock_mode == 0
1662
|| trx->dict_operation_lock_mode == RW_X_LATCH);
1664
/* Serialize data dictionary operations with dictionary mutex:
1665
no deadlocks or lock waits can occur then in these operations */
1667
rw_lock_x_lock(&dict_operation_lock);
1668
trx->dict_operation_lock_mode = RW_X_LATCH;
1670
mutex_enter(&(dict_sys->mutex));
1673
/*************************************************************************
1674
Unlocks the data dictionary exclusive lock. */
1677
row_mysql_unlock_data_dictionary(
1678
/*=============================*/
1679
trx_t* trx) /* in: transaction */
1681
ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
1683
/* Serialize data dictionary operations with dictionary mutex:
1684
no deadlocks can occur then in these operations */
1686
mutex_exit(&(dict_sys->mutex));
1687
rw_lock_x_unlock(&dict_operation_lock);
1689
trx->dict_operation_lock_mode = 0;
1692
#ifndef UNIV_HOTBACKUP
1693
/*************************************************************************
1694
Creates a table for MySQL. If the name of the table ends in
1695
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
1696
"innodb_table_monitor", then this will also start the printing of monitor
1697
output by the master thread. If the table name ends in "innodb_mem_validate",
1698
InnoDB will try to invoke mem_validate(). */
1701
row_create_table_for_mysql(
1702
/*=======================*/
1703
/* out: error code or DB_SUCCESS */
1704
dict_table_t* table, /* in: table definition */
1705
trx_t* trx) /* in: transaction handle */
1710
const char* table_name;
1711
ulint table_name_len;
1715
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1716
#ifdef UNIV_SYNC_DEBUG
1717
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
1718
#endif /* UNIV_SYNC_DEBUG */
1719
ut_ad(mutex_own(&(dict_sys->mutex)));
1720
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
1722
if (srv_created_new_raw) {
1723
fputs("InnoDB: A new raw disk partition was initialized:\n"
1724
"InnoDB: we do not allow database modifications"
1726
"InnoDB: Shut down mysqld and edit my.cnf so that newraw"
1727
" is replaced with raw.\n", stderr);
1729
dict_mem_table_free(table);
1730
trx_commit_for_mysql(trx);
1735
trx->op_info = "creating table";
1737
if (row_mysql_is_system_table(table->name)) {
1740
"InnoDB: Error: trying to create a MySQL system"
1741
" table %s of type InnoDB.\n"
1742
"InnoDB: MySQL system tables must be"
1743
" of the MyISAM type!\n",
1748
/* Check that no reserved column names are used. */
1749
for (i = 0; i < dict_table_get_n_user_cols(table); i++) {
1750
if (dict_col_name_is_reserved(
1751
dict_table_get_col_name(table, i))) {
1757
trx_start_if_not_started(trx);
1759
/* The table name is prefixed with the database name and a '/'.
1760
Certain table names starting with 'innodb_' have their special
1761
meaning regardless of the database name. Thus, we need to
1762
ignore the database name prefix in the comparisons. */
1763
table_name = strchr(table->name, '/');
1766
table_name_len = strlen(table_name) + 1;
1768
if (STR_EQ(table_name, table_name_len, S_innodb_monitor)) {
1770
/* Table equals "innodb_monitor":
1771
start monitor prints */
1773
srv_print_innodb_monitor = TRUE;
1775
/* The lock timeout monitor thread also takes care
1776
of InnoDB monitor prints */
1778
os_event_set(srv_lock_timeout_thread_event);
1779
} else if (STR_EQ(table_name, table_name_len,
1780
S_innodb_lock_monitor)) {
1782
srv_print_innodb_monitor = TRUE;
1783
srv_print_innodb_lock_monitor = TRUE;
1784
os_event_set(srv_lock_timeout_thread_event);
1785
} else if (STR_EQ(table_name, table_name_len,
1786
S_innodb_tablespace_monitor)) {
1788
srv_print_innodb_tablespace_monitor = TRUE;
1789
os_event_set(srv_lock_timeout_thread_event);
1790
} else if (STR_EQ(table_name, table_name_len,
1791
S_innodb_table_monitor)) {
1793
srv_print_innodb_table_monitor = TRUE;
1794
os_event_set(srv_lock_timeout_thread_event);
1795
} else if (STR_EQ(table_name, table_name_len,
1796
S_innodb_mem_validate)) {
1797
/* We define here a debugging feature intended for
1800
fputs("Validating InnoDB memory:\n"
1801
"to use this feature you must compile InnoDB with\n"
1802
"UNIV_MEM_DEBUG defined in univ.i and"
1803
" the server must be\n"
1804
"quiet because allocation from a mem heap"
1805
" is not protected\n"
1806
"by any semaphore.\n", stderr);
1807
#ifdef UNIV_MEM_DEBUG
1808
ut_a(mem_validate());
1809
fputs("Memory validated\n", stderr);
1810
#else /* UNIV_MEM_DEBUG */
1811
fputs("Memory NOT validated (recompile with UNIV_MEM_DEBUG)\n",
1813
#endif /* UNIV_MEM_DEBUG */
1816
heap = mem_heap_create(512);
1818
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
1820
node = tab_create_graph_create(table, heap);
1822
thr = pars_complete_graph_for_exec(node, trx, heap);
1824
ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
1825
que_run_threads(thr);
1827
err = trx->error_state;
1829
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
1830
trx->error_state = DB_SUCCESS;
1831
trx_general_rollback_for_mysql(trx, FALSE, NULL);
1835
case DB_OUT_OF_FILE_SPACE:
1836
ut_print_timestamp(stderr);
1837
fputs(" InnoDB: Warning: cannot create table ",
1839
ut_print_name(stderr, trx, TRUE, table->name);
1840
fputs(" because tablespace full\n", stderr);
1842
if (dict_table_get_low(table->name)) {
1844
row_drop_table_for_mysql(table->name, trx, FALSE);
1848
case DB_DUPLICATE_KEY:
1849
ut_print_timestamp(stderr);
1850
fputs(" InnoDB: Error: table ", stderr);
1851
ut_print_name(stderr, trx, TRUE, table->name);
1852
fputs(" already exists in InnoDB internal\n"
1853
"InnoDB: data dictionary. Have you deleted"
1855
"InnoDB: and not used DROP TABLE?"
1856
" Have you used DROP DATABASE\n"
1857
"InnoDB: for InnoDB tables in"
1858
" MySQL version <= 3.23.43?\n"
1859
"InnoDB: See the Restrictions section"
1860
" of the InnoDB manual.\n"
1861
"InnoDB: You can drop the orphaned table"
1862
" inside InnoDB by\n"
1863
"InnoDB: creating an InnoDB table with"
1864
" the same name in another\n"
1865
"InnoDB: database and copying the .frm file"
1866
" to the current database.\n"
1867
"InnoDB: Then MySQL thinks the table exists,"
1868
" and DROP TABLE will\n"
1869
"InnoDB: succeed.\n"
1870
"InnoDB: You can look for further help from\n"
1872
"http://dev.mysql.com/doc/refman/5.1/en/"
1873
"innodb-troubleshooting.html\n", stderr);
1875
/* We may also get err == DB_ERROR if the .ibd file for the
1876
table already exists */
1881
que_graph_free((que_t*) que_node_get_parent(thr));
1888
/*************************************************************************
1889
Does an index creation operation for MySQL. TODO: currently failure
1890
to create an index results in dropping the whole table! This is no problem
1891
currently as all indexes must be created at the same time as the table. */
1894
row_create_index_for_mysql(
1895
/*=======================*/
1896
/* out: error number or DB_SUCCESS */
1897
dict_index_t* index, /* in: index definition */
1898
trx_t* trx, /* in: transaction handle */
1899
const ulint* field_lengths) /* in: if not NULL, must contain
1900
dict_index_get_n_fields(index)
1901
actual field lengths for the
1902
index columns, which are
1903
then checked for not being too
1914
#ifdef UNIV_SYNC_DEBUG
1915
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
1916
#endif /* UNIV_SYNC_DEBUG */
1917
ut_ad(mutex_own(&(dict_sys->mutex)));
1918
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1920
trx->op_info = "creating index";
1922
/* Copy the table name because we may want to drop the
1923
table later, after the index object is freed (inside
1924
que_run_threads()) and thus index->table_name is not available. */
1925
table_name = mem_strdup(index->table_name);
1927
trx_start_if_not_started(trx);
1929
/* Check that the same column does not appear twice in the index.
1930
Starting from 4.0.14, InnoDB should be able to cope with that, but
1931
safer not to allow them. */
1933
for (i = 0; i < dict_index_get_n_fields(index); i++) {
1936
for (j = 0; j < i; j++) {
1938
dict_index_get_nth_field(index, j)->name,
1939
dict_index_get_nth_field(index, i)->name)) {
1940
ut_print_timestamp(stderr);
1942
fputs(" InnoDB: Error: column ", stderr);
1943
ut_print_name(stderr, trx, FALSE,
1944
dict_index_get_nth_field(
1946
fputs(" appears twice in ", stderr);
1947
dict_index_name_print(stderr, trx, index);
1949
"InnoDB: This is not allowed"
1950
" in InnoDB.\n", stderr);
1952
err = DB_COL_APPEARS_TWICE_IN_INDEX;
1954
goto error_handling;
1958
/* Check also that prefix_len and actual length
1959
< DICT_MAX_INDEX_COL_LEN */
1961
len = dict_index_get_nth_field(index, i)->prefix_len;
1963
if (field_lengths) {
1964
len = ut_max(len, field_lengths[i]);
1967
if (len >= DICT_MAX_INDEX_COL_LEN) {
1968
err = DB_TOO_BIG_RECORD;
1970
goto error_handling;
1974
heap = mem_heap_create(512);
1976
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
1978
/* Note that the space id where we store the index is inherited from
1979
the table in dict_build_index_def_step() in dict0crea.c. */
1981
node = ind_create_graph_create(index, heap);
1983
thr = pars_complete_graph_for_exec(node, trx, heap);
1985
ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
1986
que_run_threads(thr);
1988
err = trx->error_state;
1990
que_graph_free((que_t*) que_node_get_parent(thr));
1993
if (err != DB_SUCCESS) {
1994
/* We have special error handling here */
1996
trx->error_state = DB_SUCCESS;
1998
trx_general_rollback_for_mysql(trx, FALSE, NULL);
2000
row_drop_table_for_mysql(table_name, trx, FALSE);
2002
trx->error_state = DB_SUCCESS;
2007
mem_free(table_name);
2012
/*************************************************************************
2013
Scans a table create SQL string and adds to the data dictionary
2014
the foreign key constraints declared in the string. This function
2015
should be called after the indexes for a table have been created.
2016
Each foreign key constraint must be accompanied with indexes in
2017
bot participating tables. The indexes are allowed to contain more
2018
fields than mentioned in the constraint. Check also that foreign key
2019
constraints which reference this table are ok. */
2022
row_table_add_foreign_constraints(
2023
/*==============================*/
2024
/* out: error code or DB_SUCCESS */
2025
trx_t* trx, /* in: transaction */
2026
const char* sql_string, /* in: table create statement where
2027
foreign keys are declared like:
2028
FOREIGN KEY (a, b) REFERENCES table2(c, d),
2029
table2 can be written also with the
2030
database name before it: test.table2 */
2031
const char* name, /* in: table full name in the
2033
database_name/table_name */
2034
ibool reject_fks) /* in: if TRUE, fail with error
2035
code DB_CANNOT_ADD_CONSTRAINT if
2036
any foreign keys are found. */
2040
ut_ad(mutex_own(&(dict_sys->mutex)));
2041
#ifdef UNIV_SYNC_DEBUG
2042
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
2043
#endif /* UNIV_SYNC_DEBUG */
2046
trx->op_info = "adding foreign keys";
2048
trx_start_if_not_started(trx);
2050
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
2052
err = dict_create_foreign_constraints(trx, sql_string, name,
2054
#ifndef UNIV_HOTBACKUP
2055
if (err == DB_SUCCESS) {
2056
/* Check that also referencing constraints are ok */
2057
err = dict_load_foreigns(name, TRUE);
2059
#endif /* !UNIV_HOTBACKUP */
2060
if (err != DB_SUCCESS) {
2061
/* We have special error handling here */
2063
trx->error_state = DB_SUCCESS;
2065
trx_general_rollback_for_mysql(trx, FALSE, NULL);
2067
row_drop_table_for_mysql(name, trx, FALSE);
2069
trx->error_state = DB_SUCCESS;
2075
/*************************************************************************
2076
Drops a table for MySQL as a background operation. MySQL relies on Unix
2077
in ALTER TABLE to the fact that the table handler does not remove the
2078
table before all handles to it has been removed. Furhermore, the MySQL's
2079
call to drop table must be non-blocking. Therefore we do the drop table
2080
as a background operation, which is taken care of by the master thread
2084
row_drop_table_for_mysql_in_background(
2085
/*===================================*/
2086
/* out: error code or DB_SUCCESS */
2087
const char* name) /* in: table name */
2092
trx = trx_allocate_for_background();
2094
/* If the original transaction was dropping a table referenced by
2095
foreign keys, we must set the following to be able to drop the
2098
trx->check_foreigns = FALSE;
2100
/* fputs("InnoDB: Error: Dropping table ", stderr);
2101
ut_print_name(stderr, trx, TRUE, name);
2102
fputs(" in background drop list\n", stderr); */
2104
/* Try to drop the table in InnoDB */
2106
error = row_drop_table_for_mysql(name, trx, FALSE);
2108
/* Flush the log to reduce probability that the .frm files and
2109
the InnoDB data dictionary get out-of-sync if the user runs
2110
with innodb_flush_log_at_trx_commit = 0 */
2112
log_buffer_flush_to_disk();
2114
trx_commit_for_mysql(trx);
2116
trx_free_for_background(trx);
2118
return((int) error);
2121
/*************************************************************************
2122
The master thread in srv0srv.c calls this regularly to drop tables which
2123
we must drop in background after queries to them have ended. Such lazy
2124
dropping of tables is needed in ALTER TABLE on Unix. */
2127
row_drop_tables_for_mysql_in_background(void)
2128
/*=========================================*/
2129
/* out: how many tables dropped
2130
+ remaining tables in list */
2132
row_mysql_drop_t* drop;
2133
dict_table_t* table;
2135
ulint n_tables_dropped = 0;
2137
mutex_enter(&kernel_mutex);
2139
if (!row_mysql_drop_list_inited) {
2141
UT_LIST_INIT(row_mysql_drop_list);
2142
row_mysql_drop_list_inited = TRUE;
2145
drop = UT_LIST_GET_FIRST(row_mysql_drop_list);
2147
n_tables = UT_LIST_GET_LEN(row_mysql_drop_list);
2149
mutex_exit(&kernel_mutex);
2152
/* All tables dropped */
2154
return(n_tables + n_tables_dropped);
2157
mutex_enter(&(dict_sys->mutex));
2158
table = dict_table_get_low(drop->table_name);
2159
mutex_exit(&(dict_sys->mutex));
2161
if (table == NULL) {
2162
/* If for some reason the table has already been dropped
2163
through some other mechanism, do not try to drop it */
2165
goto already_dropped;
2168
if (DB_SUCCESS != row_drop_table_for_mysql_in_background(
2169
drop->table_name)) {
2170
/* If the DROP fails for some table, we return, and let the
2171
main thread retry later */
2173
return(n_tables + n_tables_dropped);
2179
mutex_enter(&kernel_mutex);
2181
UT_LIST_REMOVE(row_mysql_drop_list, row_mysql_drop_list, drop);
2183
ut_print_timestamp(stderr);
2184
fputs(" InnoDB: Dropped table ", stderr);
2185
ut_print_name(stderr, NULL, TRUE, drop->table_name);
2186
fputs(" in background drop queue.\n", stderr);
2188
mem_free(drop->table_name);
2192
mutex_exit(&kernel_mutex);
2197
/*************************************************************************
2198
Get the background drop list length. NOTE: the caller must own the kernel
2202
row_get_background_drop_list_len_low(void)
2203
/*======================================*/
2204
/* out: how many tables in list */
2206
ut_ad(mutex_own(&kernel_mutex));
2208
if (!row_mysql_drop_list_inited) {
2210
UT_LIST_INIT(row_mysql_drop_list);
2211
row_mysql_drop_list_inited = TRUE;
2214
return(UT_LIST_GET_LEN(row_mysql_drop_list));
2217
/*************************************************************************
2218
If a table is not yet in the drop list, adds the table to the list of tables
2219
which the master thread drops in background. We need this on Unix because in
2220
ALTER TABLE MySQL may call drop table even if the table has running queries on
2221
it. Also, if there are running foreign key checks on the table, we drop the
2225
row_add_table_to_background_drop_list(
2226
/*==================================*/
2227
/* out: TRUE if the table was not yet in the
2228
drop list, and was added there */
2229
const char* name) /* in: table name */
2231
row_mysql_drop_t* drop;
2233
mutex_enter(&kernel_mutex);
2235
if (!row_mysql_drop_list_inited) {
2237
UT_LIST_INIT(row_mysql_drop_list);
2238
row_mysql_drop_list_inited = TRUE;
2241
/* Look if the table already is in the drop list */
2242
drop = UT_LIST_GET_FIRST(row_mysql_drop_list);
2244
while (drop != NULL) {
2245
if (strcmp(drop->table_name, name) == 0) {
2246
/* Already in the list */
2248
mutex_exit(&kernel_mutex);
2253
drop = UT_LIST_GET_NEXT(row_mysql_drop_list, drop);
2256
drop = mem_alloc(sizeof(row_mysql_drop_t));
2258
drop->table_name = mem_strdup(name);
2260
UT_LIST_ADD_LAST(row_mysql_drop_list, row_mysql_drop_list, drop);
2262
/* fputs("InnoDB: Adding table ", stderr);
2263
ut_print_name(stderr, trx, TRUE, drop->table_name);
2264
fputs(" to background drop list\n", stderr); */
2266
mutex_exit(&kernel_mutex);
2271
/*************************************************************************
2272
Discards the tablespace of a table which stored in an .ibd file. Discarding
2273
means that this function deletes the .ibd file and assigns a new table id for
2274
the table. Also the flag table->ibd_file_missing is set TRUE. */
2277
row_discard_tablespace_for_mysql(
2278
/*=============================*/
2279
/* out: error code or DB_SUCCESS */
2280
const char* name, /* in: table name */
2281
trx_t* trx) /* in: transaction handle */
2283
dict_foreign_t* foreign;
2285
dict_table_t* table;
2288
pars_info_t* info = NULL;
2290
/* How do we prevent crashes caused by ongoing operations on
2291
the table? Old operations could try to access non-existent
2294
1) SQL queries, INSERT, SELECT, ...: we must get an exclusive
2295
MySQL table lock on the table before we can do DISCARD
2296
TABLESPACE. Then there are no running queries on the table.
2298
2) Purge and rollback: we assign a new table id for the
2299
table. Since purge and rollback look for the table based on
2300
the table id, they see the table as 'dropped' and discard
2303
3) Insert buffer: we remove all entries for the tablespace in
2304
the insert buffer tree; as long as the tablespace mem object
2305
does not exist, ongoing insert buffer page merges are
2306
discarded in buf0rea.c. If we recreate the tablespace mem
2307
object with IMPORT TABLESPACE later, then the tablespace will
2308
have the same id, but the tablespace_version field in the mem
2309
object is different, and ongoing old insert buffer page merges
2312
4) Linear readahead and random readahead: we use the same
2313
method as in 3) to discard ongoing operations.
2315
5) FOREIGN KEY operations: if
2316
table->n_foreign_key_checks_running > 0, we do not allow the
2317
discard. We also reserve the data dictionary latch. */
2319
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
2321
trx->op_info = "discarding tablespace";
2322
trx_start_if_not_started(trx);
2324
/* Serialize data dictionary operations with dictionary mutex:
2325
no deadlocks can occur then in these operations */
2327
row_mysql_lock_data_dictionary(trx);
2329
table = dict_table_get_low(name);
2332
err = DB_TABLE_NOT_FOUND;
2337
if (table->space == 0) {
2338
ut_print_timestamp(stderr);
2339
fputs(" InnoDB: Error: table ", stderr);
2340
ut_print_name(stderr, trx, TRUE, name);
2342
"InnoDB: is in the system tablespace 0"
2343
" which cannot be discarded\n", stderr);
2349
if (table->n_foreign_key_checks_running > 0) {
2351
ut_print_timestamp(stderr);
2352
fputs(" InnoDB: You are trying to DISCARD table ", stderr);
2353
ut_print_name(stderr, trx, TRUE, table->name);
2355
"InnoDB: though there is a foreign key check"
2357
"InnoDB: Cannot discard the table.\n",
2365
/* Check if the table is referenced by foreign key constraints from
2366
some other table (not the table itself) */
2368
foreign = UT_LIST_GET_FIRST(table->referenced_list);
2370
while (foreign && foreign->foreign_table == table) {
2371
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
2374
if (foreign && trx->check_foreigns) {
2376
FILE* ef = dict_foreign_err_file;
2378
/* We only allow discarding a referenced table if
2379
FOREIGN_KEY_CHECKS is set to 0 */
2381
err = DB_CANNOT_DROP_CONSTRAINT;
2383
mutex_enter(&dict_foreign_err_mutex);
2385
ut_print_timestamp(ef);
2387
fputs(" Cannot DISCARD table ", ef);
2388
ut_print_name(stderr, trx, TRUE, name);
2390
"because it is referenced by ", ef);
2391
ut_print_name(stderr, trx, TRUE, foreign->foreign_table_name);
2393
mutex_exit(&dict_foreign_err_mutex);
2398
new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
2400
/* Remove any locks there are on the table or its records */
2401
lock_reset_all_on_table(table);
2403
info = pars_info_create();
2405
pars_info_add_str_literal(info, "table_name", name);
2406
pars_info_add_dulint_literal(info, "new_id", new_id);
2408
err = que_eval_sql(info,
2409
"PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
2412
"SELECT ID INTO old_id\n"
2414
"WHERE NAME = :table_name\n"
2415
"LOCK IN SHARE MODE;\n"
2416
"IF (SQL % NOTFOUND) THEN\n"
2420
"UPDATE SYS_TABLES SET ID = :new_id\n"
2421
" WHERE ID = old_id;\n"
2422
"UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n"
2423
" WHERE TABLE_ID = old_id;\n"
2424
"UPDATE SYS_INDEXES SET TABLE_ID = :new_id\n"
2425
" WHERE TABLE_ID = old_id;\n"
2430
if (err != DB_SUCCESS) {
2431
trx->error_state = DB_SUCCESS;
2432
trx_general_rollback_for_mysql(trx, FALSE, NULL);
2433
trx->error_state = DB_SUCCESS;
2435
dict_table_change_id_in_cache(table, new_id);
2437
success = fil_discard_tablespace(table->space);
2440
trx->error_state = DB_SUCCESS;
2441
trx_general_rollback_for_mysql(trx, FALSE, NULL);
2442
trx->error_state = DB_SUCCESS;
2446
/* Set the flag which tells that now it is legal to
2447
IMPORT a tablespace for this table */
2448
table->tablespace_discarded = TRUE;
2449
table->ibd_file_missing = TRUE;
2454
trx_commit_for_mysql(trx);
2456
row_mysql_unlock_data_dictionary(trx);
2463
/*********************************************************************
2464
Imports a tablespace. The space id in the .ibd file must match the space id
2465
of the table in the data dictionary. */
2468
row_import_tablespace_for_mysql(
2469
/*============================*/
2470
/* out: error code or DB_SUCCESS */
2471
const char* name, /* in: table name */
2472
trx_t* trx) /* in: transaction handle */
2474
dict_table_t* table;
2476
ib_uint64_t current_lsn;
2477
ulint err = DB_SUCCESS;
2479
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
2481
trx_start_if_not_started(trx);
2483
trx->op_info = "importing tablespace";
2485
current_lsn = log_get_lsn();
2487
/* It is possible, though very improbable, that the lsn's in the
2488
tablespace to be imported have risen above the current system lsn, if
2489
a lengthy purge, ibuf merge, or rollback was performed on a backup
2490
taken with ibbackup. If that is the case, reset page lsn's in the
2491
file. We assume that mysqld was shut down after it performed these
2492
cleanup operations on the .ibd file, so that it stamped the latest lsn
2493
to the FIL_PAGE_FILE_FLUSH_LSN in the first page of the .ibd file.
2495
TODO: reset also the trx id's in clustered index records and write
2496
a new space id to each data page. That would allow us to import clean
2497
.ibd files from another MySQL installation. */
2499
success = fil_reset_too_high_lsns(name, current_lsn);
2502
ut_print_timestamp(stderr);
2503
fputs(" InnoDB: Error: cannot reset lsn's in table ", stderr);
2504
ut_print_name(stderr, trx, TRUE, name);
2506
"InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n",
2511
row_mysql_lock_data_dictionary(trx);
2516
/* Serialize data dictionary operations with dictionary mutex:
2517
no deadlocks can occur then in these operations */
2519
row_mysql_lock_data_dictionary(trx);
2521
table = dict_table_get_low(name);
2524
ut_print_timestamp(stderr);
2525
fputs(" InnoDB: table ", stderr);
2526
ut_print_name(stderr, trx, TRUE, name);
2528
"InnoDB: does not exist in the InnoDB data dictionary\n"
2529
"InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n",
2532
err = DB_TABLE_NOT_FOUND;
2537
if (table->space == 0) {
2538
ut_print_timestamp(stderr);
2539
fputs(" InnoDB: Error: table ", stderr);
2540
ut_print_name(stderr, trx, TRUE, name);
2542
"InnoDB: is in the system tablespace 0"
2543
" which cannot be imported\n", stderr);
2549
if (!table->tablespace_discarded) {
2550
ut_print_timestamp(stderr);
2551
fputs(" InnoDB: Error: you are trying to"
2552
" IMPORT a tablespace\n"
2553
"InnoDB: ", stderr);
2554
ut_print_name(stderr, trx, TRUE, name);
2555
fputs(", though you have not called DISCARD on it yet\n"
2556
"InnoDB: during the lifetime of the mysqld process!\n",
2564
/* Play safe and remove all insert buffer entries, though we should
2565
have removed them already when DISCARD TABLESPACE was called */
2567
ibuf_delete_for_discarded_space(table->space);
2569
success = fil_open_single_table_tablespace(
2571
table->flags == DICT_TF_COMPACT ? 0 : table->flags,
2574
table->ibd_file_missing = FALSE;
2575
table->tablespace_discarded = FALSE;
2577
if (table->ibd_file_missing) {
2578
ut_print_timestamp(stderr);
2579
fputs(" InnoDB: cannot find or open in the"
2580
" database directory the .ibd file of\n"
2581
"InnoDB: table ", stderr);
2582
ut_print_name(stderr, trx, TRUE, name);
2584
"InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n",
2592
trx_commit_for_mysql(trx);
2594
row_mysql_unlock_data_dictionary(trx);
2601
/*************************************************************************
2602
Truncates a table for MySQL. */
2605
row_truncate_table_for_mysql(
2606
/*=========================*/
2607
/* out: error code or DB_SUCCESS */
2608
dict_table_t* table, /* in: table handle */
2609
trx_t* trx) /* in: transaction handle */
2611
dict_foreign_t* foreign;
2617
dict_index_t* sys_index;
2621
ulint recreate_space = 0;
2622
pars_info_t* info = NULL;
2624
/* How do we prevent crashes caused by ongoing operations on
2625
the table? Old operations could try to access non-existent
2628
1) SQL queries, INSERT, SELECT, ...: we must get an exclusive
2629
MySQL table lock on the table before we can do TRUNCATE
2630
TABLE. Then there are no running queries on the table. This is
2631
guaranteed, because in ha_innobase::store_lock(), we do not
2632
weaken the TL_WRITE lock requested by MySQL when executing
2635
2) Purge and rollback: we assign a new table id for the
2636
table. Since purge and rollback look for the table based on
2637
the table id, they see the table as 'dropped' and discard
2640
3) Insert buffer: TRUNCATE TABLE is analogous to DROP TABLE,
2641
so we do not have to remove insert buffer records, as the
2642
insert buffer works at a low level. If a freed page is later
2643
reallocated, the allocator will remove the ibuf entries for
2646
When we truncate *.ibd files by recreating them (analogous to
2647
DISCARD TABLESPACE), we remove all entries for the table in the
2648
insert buffer tree. This is not strictly necessary, because
2649
in 6) we will assign a new tablespace identifier, but we can
2650
free up some space in the system tablespace.
2652
4) Linear readahead and random readahead: we use the same
2653
method as in 3) to discard ongoing operations. (This is only
2654
relevant for TRUNCATE TABLE by DISCARD TABLESPACE.)
2656
5) FOREIGN KEY operations: if
2657
table->n_foreign_key_checks_running > 0, we do not allow the
2658
TRUNCATE. We also reserve the data dictionary latch.
2660
6) Crash recovery: To prevent the application of pre-truncation
2661
redo log records on the truncated tablespace, we will assign
2662
a new tablespace identifier to the truncated tablespace. */
2664
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
2667
if (srv_created_new_raw) {
2668
fputs("InnoDB: A new raw disk partition was initialized:\n"
2669
"InnoDB: we do not allow database modifications"
2671
"InnoDB: Shut down mysqld and edit my.cnf so that newraw"
2672
" is replaced with raw.\n", stderr);
2677
trx->op_info = "truncating table";
2679
trx_start_if_not_started(trx);
2681
/* Serialize data dictionary operations with dictionary mutex:
2682
no deadlocks can occur then in these operations */
2684
ut_a(trx->dict_operation_lock_mode == 0);
2685
/* Prevent foreign key checks etc. while we are truncating the
2688
row_mysql_lock_data_dictionary(trx);
2690
ut_ad(mutex_own(&(dict_sys->mutex)));
2691
#ifdef UNIV_SYNC_DEBUG
2692
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
2693
#endif /* UNIV_SYNC_DEBUG */
2695
/* Check if the table is referenced by foreign key constraints from
2696
some other table (not the table itself) */
2698
foreign = UT_LIST_GET_FIRST(table->referenced_list);
2700
while (foreign && foreign->foreign_table == table) {
2701
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
2704
if (foreign && trx->check_foreigns) {
2705
FILE* ef = dict_foreign_err_file;
2707
/* We only allow truncating a referenced table if
2708
FOREIGN_KEY_CHECKS is set to 0 */
2710
mutex_enter(&dict_foreign_err_mutex);
2712
ut_print_timestamp(ef);
2714
fputs(" Cannot truncate table ", ef);
2715
ut_print_name(ef, trx, TRUE, table->name);
2716
fputs(" by DROP+CREATE\n"
2717
"InnoDB: because it is referenced by ", ef);
2718
ut_print_name(ef, trx, TRUE, foreign->foreign_table_name);
2720
mutex_exit(&dict_foreign_err_mutex);
2726
/* TODO: could we replace the counter n_foreign_key_checks_running
2727
with lock checks on the table? Acquire here an exclusive lock on the
2728
table, and rewrite lock0lock.c and the lock wait in srv0srv.c so that
2729
they can cope with the table having been truncated here? Foreign key
2730
checks take an IS or IX lock on the table. */
2732
if (table->n_foreign_key_checks_running > 0) {
2733
ut_print_timestamp(stderr);
2734
fputs(" InnoDB: Cannot truncate table ", stderr);
2735
ut_print_name(stderr, trx, TRUE, table->name);
2736
fputs(" by DROP+CREATE\n"
2737
"InnoDB: because there is a foreign key check"
2738
" running on it.\n",
2745
/* Remove any locks there are on the table or its records */
2747
lock_reset_all_on_table(table);
2749
trx->table_id = table->id;
2751
if (table->space && !table->dir_path_of_temp_table) {
2752
/* Discard and create the single-table tablespace. */
2753
ulint space = table->space;
2754
ulint flags = fil_space_get_flags(space);
2756
if (flags != ULINT_UNDEFINED
2757
&& fil_discard_tablespace(space)) {
2759
dict_index_t* index;
2763
if (fil_create_new_single_table_tablespace(
2764
&space, table->name, FALSE, flags,
2765
FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
2766
ut_print_timestamp(stderr);
2768
" InnoDB: TRUNCATE TABLE %s failed to"
2769
" create a new tablespace\n",
2771
table->ibd_file_missing = 1;
2776
recreate_space = space;
2778
/* Replace the space_id in the data dictionary cache.
2779
The persisent data dictionary (SYS_TABLES.SPACE
2780
and SYS_INDEXES.SPACE) are updated later in this
2782
table->space = space;
2783
index = dict_table_get_first_index(table);
2785
index->space = space;
2786
index = dict_table_get_next_index(index);
2790
fsp_header_init(space,
2791
FIL_IBD_FILE_INITIAL_SIZE, &mtr);
2796
/* scan SYS_INDEXES for all indexes of the table */
2797
heap = mem_heap_create(800);
2799
tuple = dtuple_create(heap, 1);
2800
dfield = dtuple_get_nth_field(tuple, 0);
2802
buf = mem_heap_alloc(heap, 8);
2803
mach_write_to_8(buf, table->id);
2805
dfield_set_data(dfield, buf, 8);
2806
sys_index = dict_table_get_first_index(dict_sys->sys_indexes);
2807
dict_index_copy_types(tuple, sys_index, 1);
2810
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
2811
BTR_MODIFY_LEAF, &pcur, &mtr);
2818
if (!btr_pcur_is_on_user_rec(&pcur)) {
2819
/* The end of SYS_INDEXES has been reached. */
2823
rec = btr_pcur_get_rec(&pcur);
2825
field = rec_get_nth_field_old(rec, 0, &len);
2828
if (memcmp(buf, field, len) != 0) {
2829
/* End of indexes for the table (TABLE_ID mismatch). */
2833
if (rec_get_deleted_flag(rec, FALSE)) {
2834
/* The index has been dropped. */
2838
/* This call may commit and restart mtr
2839
and reposition pcur. */
2840
root_page_no = dict_truncate_index_tree(table, recreate_space,
2843
rec = btr_pcur_get_rec(&pcur);
2845
if (root_page_no != FIL_NULL) {
2846
page_rec_write_index_page_no(
2847
rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
2848
root_page_no, &mtr);
2849
/* We will need to commit and restart the
2850
mini-transaction in order to avoid deadlocks.
2851
The dict_truncate_index_tree() call has allocated
2852
a page in this mini-transaction, and the rest of
2853
this loop could latch another index page. */
2856
btr_pcur_restore_position(BTR_MODIFY_LEAF,
2861
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
2864
btr_pcur_close(&pcur);
2867
mem_heap_free(heap);
2869
new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
2871
info = pars_info_create();
2873
pars_info_add_int4_literal(info, "space", (lint) table->space);
2874
pars_info_add_dulint_literal(info, "old_id", table->id);
2875
pars_info_add_dulint_literal(info, "new_id", new_id);
2877
err = que_eval_sql(info,
2878
"PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
2881
" SET ID = :new_id, SPACE = :space\n"
2882
" WHERE ID = :old_id;\n"
2883
"UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n"
2884
" WHERE TABLE_ID = :old_id;\n"
2885
"UPDATE SYS_INDEXES"
2886
" SET TABLE_ID = :new_id, SPACE = :space\n"
2887
" WHERE TABLE_ID = :old_id;\n"
2892
if (err != DB_SUCCESS) {
2893
trx->error_state = DB_SUCCESS;
2894
trx_general_rollback_for_mysql(trx, FALSE, NULL);
2895
trx->error_state = DB_SUCCESS;
2896
ut_print_timestamp(stderr);
2897
fputs(" InnoDB: Unable to assign a new identifier to table ",
2899
ut_print_name(stderr, trx, TRUE, table->name);
2901
"InnoDB: after truncating it. Background processes"
2902
" may corrupt the table!\n", stderr);
2905
dict_table_change_id_in_cache(table, new_id);
2908
/* MySQL calls ha_innobase::reset_auto_increment() which does
2910
dict_table_autoinc_lock(table);
2911
dict_table_autoinc_initialize(table, 0);
2912
dict_table_autoinc_unlock(table);
2913
dict_update_statistics(table);
2915
trx_commit_for_mysql(trx);
2919
row_mysql_unlock_data_dictionary(trx);
2923
srv_wake_master_thread();
2928
/*************************************************************************
2929
Drops a table for MySQL. If the name of the dropped table ends in
2930
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
2931
"innodb_table_monitor", then this will also stop the printing of monitor
2932
output by the master thread. */
2935
row_drop_table_for_mysql(
2936
/*=====================*/
2937
/* out: error code or DB_SUCCESS */
2938
const char* name, /* in: table name */
2939
trx_t* trx, /* in: transaction handle */
2940
ibool drop_db)/* in: TRUE=dropping whole database */
2944
err = row_drop_table_for_mysql_no_commit(name, trx, drop_db);
2945
trx_commit_for_mysql(trx);
2950
/*************************************************************************
2951
Drops a table for MySQL but does not commit the transaction. If the
2952
name of the dropped table ends in one of "innodb_monitor",
2953
"innodb_lock_monitor", "innodb_tablespace_monitor",
2954
"innodb_table_monitor", then this will also stop the printing of
2955
monitor output by the master thread. */
2958
row_drop_table_for_mysql_no_commit(
2959
/*===============================*/
2960
/* out: error code or DB_SUCCESS */
2961
const char* name, /* in: table name */
2962
trx_t* trx, /* in: transaction handle */
2963
ibool drop_db)/* in: TRUE=dropping whole database */
2965
dict_foreign_t* foreign;
2966
dict_table_t* table;
2969
const char* table_name;
2971
ibool locked_dictionary = FALSE;
2972
pars_info_t* info = NULL;
2976
if (srv_created_new_raw) {
2977
fputs("InnoDB: A new raw disk partition was initialized:\n"
2978
"InnoDB: we do not allow database modifications"
2980
"InnoDB: Shut down mysqld and edit my.cnf so that newraw"
2981
" is replaced with raw.\n", stderr);
2986
trx->op_info = "dropping table";
2988
trx_start_if_not_started(trx);
2990
/* The table name is prefixed with the database name and a '/'.
2991
Certain table names starting with 'innodb_' have their special
2992
meaning regardless of the database name. Thus, we need to
2993
ignore the database name prefix in the comparisons. */
2994
table_name = strchr(name, '/');
2997
namelen = strlen(table_name) + 1;
2999
if (namelen == sizeof S_innodb_monitor
3000
&& !memcmp(table_name, S_innodb_monitor,
3001
sizeof S_innodb_monitor)) {
3003
/* Table name equals "innodb_monitor":
3004
stop monitor prints */
3006
srv_print_innodb_monitor = FALSE;
3007
srv_print_innodb_lock_monitor = FALSE;
3008
} else if (namelen == sizeof S_innodb_lock_monitor
3009
&& !memcmp(table_name, S_innodb_lock_monitor,
3010
sizeof S_innodb_lock_monitor)) {
3011
srv_print_innodb_monitor = FALSE;
3012
srv_print_innodb_lock_monitor = FALSE;
3013
} else if (namelen == sizeof S_innodb_tablespace_monitor
3014
&& !memcmp(table_name, S_innodb_tablespace_monitor,
3015
sizeof S_innodb_tablespace_monitor)) {
3017
srv_print_innodb_tablespace_monitor = FALSE;
3018
} else if (namelen == sizeof S_innodb_table_monitor
3019
&& !memcmp(table_name, S_innodb_table_monitor,
3020
sizeof S_innodb_table_monitor)) {
3022
srv_print_innodb_table_monitor = FALSE;
3025
/* Serialize data dictionary operations with dictionary mutex:
3026
no deadlocks can occur then in these operations */
3028
if (trx->dict_operation_lock_mode != RW_X_LATCH) {
3029
/* Prevent foreign key checks etc. while we are dropping the
3032
row_mysql_lock_data_dictionary(trx);
3034
locked_dictionary = TRUE;
3037
ut_ad(mutex_own(&(dict_sys->mutex)));
3038
#ifdef UNIV_SYNC_DEBUG
3039
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
3040
#endif /* UNIV_SYNC_DEBUG */
3042
table = dict_table_get_low(name);
3045
err = DB_TABLE_NOT_FOUND;
3046
ut_print_timestamp(stderr);
3048
fputs(" InnoDB: Error: table ", stderr);
3049
ut_print_name(stderr, trx, TRUE, name);
3050
fputs(" does not exist in the InnoDB internal\n"
3051
"InnoDB: data dictionary though MySQL is"
3052
" trying to drop it.\n"
3053
"InnoDB: Have you copied the .frm file"
3054
" of the table to the\n"
3055
"InnoDB: MySQL database directory"
3056
" from another database?\n"
3057
"InnoDB: You can look for further help from\n"
3058
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
3059
"innodb-troubleshooting.html\n",
3064
/* Check if the table is referenced by foreign key constraints from
3065
some other table (not the table itself) */
3067
foreign = UT_LIST_GET_FIRST(table->referenced_list);
3069
while (foreign && foreign->foreign_table == table) {
3071
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
3074
if (foreign && trx->check_foreigns
3075
&& !(drop_db && dict_tables_have_same_db(
3076
name, foreign->foreign_table_name))) {
3077
FILE* ef = dict_foreign_err_file;
3079
/* We only allow dropping a referenced table if
3080
FOREIGN_KEY_CHECKS is set to 0 */
3082
err = DB_CANNOT_DROP_CONSTRAINT;
3084
mutex_enter(&dict_foreign_err_mutex);
3086
ut_print_timestamp(ef);
3088
fputs(" Cannot drop table ", ef);
3089
ut_print_name(ef, trx, TRUE, name);
3091
"because it is referenced by ", ef);
3092
ut_print_name(ef, trx, TRUE, foreign->foreign_table_name);
3094
mutex_exit(&dict_foreign_err_mutex);
3099
if (foreign && trx->check_foreigns) {
3100
goto check_next_foreign;
3103
if (table->n_mysql_handles_opened > 0) {
3106
added = row_add_table_to_background_drop_list(table->name);
3109
ut_print_timestamp(stderr);
3110
fputs(" InnoDB: Warning: MySQL is"
3111
" trying to drop table ", stderr);
3112
ut_print_name(stderr, trx, TRUE, table->name);
3114
"InnoDB: though there are still"
3115
" open handles to it.\n"
3116
"InnoDB: Adding the table to the"
3117
" background drop queue.\n",
3120
/* We return DB_SUCCESS to MySQL though the drop will
3121
happen lazily later */
3124
/* The table is already in the background drop list */
3131
/* TODO: could we replace the counter n_foreign_key_checks_running
3132
with lock checks on the table? Acquire here an exclusive lock on the
3133
table, and rewrite lock0lock.c and the lock wait in srv0srv.c so that
3134
they can cope with the table having been dropped here? Foreign key
3135
checks take an IS or IX lock on the table. */
3137
if (table->n_foreign_key_checks_running > 0) {
3139
const char* table_name = table->name;
3142
added = row_add_table_to_background_drop_list(table_name);
3145
ut_print_timestamp(stderr);
3146
fputs(" InnoDB: You are trying to drop table ",
3148
ut_print_name(stderr, trx, TRUE, table_name);
3150
"InnoDB: though there is a"
3151
" foreign key check running on it.\n"
3152
"InnoDB: Adding the table to"
3153
" the background drop queue.\n",
3156
/* We return DB_SUCCESS to MySQL though the drop will
3157
happen lazily later */
3161
/* The table is already in the background drop list */
3168
/* Remove any locks there are on the table or its records */
3170
lock_reset_all_on_table(table);
3172
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
3173
trx->table_id = table->id;
3175
/* We use the private SQL parser of Innobase to generate the
3176
query graphs needed in deleting the dictionary data from system
3177
tables in Innobase. Deleting a row from SYS_INDEXES table also
3178
frees the file segments of the B-tree associated with the index. */
3180
info = pars_info_create();
3182
pars_info_add_str_literal(info, "table_name", name);
3184
err = que_eval_sql(info,
3185
"PROCEDURE DROP_TABLE_PROC () IS\n"
3186
"sys_foreign_id CHAR;\n"
3189
"foreign_id CHAR;\n"
3192
"SELECT ID INTO table_id\n"
3194
"WHERE NAME = :table_name\n"
3195
"LOCK IN SHARE MODE;\n"
3196
"IF (SQL % NOTFOUND) THEN\n"
3200
"SELECT ID INTO sys_foreign_id\n"
3202
"WHERE NAME = 'SYS_FOREIGN'\n"
3203
"LOCK IN SHARE MODE;\n"
3204
"IF (SQL % NOTFOUND) THEN\n"
3207
"IF (:table_name = 'SYS_FOREIGN') THEN\n"
3210
"IF (:table_name = 'SYS_FOREIGN_COLS') THEN\n"
3213
"WHILE found = 1 LOOP\n"
3214
" SELECT ID INTO foreign_id\n"
3215
" FROM SYS_FOREIGN\n"
3216
" WHERE FOR_NAME = :table_name\n"
3217
" AND TO_BINARY(FOR_NAME)\n"
3218
" = TO_BINARY(:table_name)\n"
3219
" LOCK IN SHARE MODE;\n"
3220
" IF (SQL % NOTFOUND) THEN\n"
3223
" DELETE FROM SYS_FOREIGN_COLS\n"
3224
" WHERE ID = foreign_id;\n"
3225
" DELETE FROM SYS_FOREIGN\n"
3226
" WHERE ID = foreign_id;\n"
3230
"WHILE found = 1 LOOP\n"
3231
" SELECT ID INTO index_id\n"
3232
" FROM SYS_INDEXES\n"
3233
" WHERE TABLE_ID = table_id\n"
3234
" LOCK IN SHARE MODE;\n"
3235
" IF (SQL % NOTFOUND) THEN\n"
3238
" DELETE FROM SYS_FIELDS\n"
3239
" WHERE INDEX_ID = index_id;\n"
3240
" DELETE FROM SYS_INDEXES\n"
3241
" WHERE ID = index_id\n"
3242
" AND TABLE_ID = table_id;\n"
3245
"DELETE FROM SYS_COLUMNS\n"
3246
"WHERE TABLE_ID = table_id;\n"
3247
"DELETE FROM SYS_TABLES\n"
3248
"WHERE ID = table_id;\n"
3252
if (err != DB_SUCCESS) {
3253
ut_a(err == DB_OUT_OF_FILE_SPACE);
3255
err = DB_MUST_GET_MORE_FILE_SPACE;
3257
row_mysql_handle_errors(&err, trx, NULL, NULL);
3262
const char* name_or_path;
3265
heap = mem_heap_create(200);
3267
/* Clone the name, in case it has been allocated
3268
from table->heap, which will be freed by
3269
dict_table_remove_from_cache(table) below. */
3270
name = mem_heap_strdup(heap, name);
3271
space_id = table->space;
3273
if (table->dir_path_of_temp_table != NULL) {
3275
name_or_path = mem_heap_strdup(
3276
heap, table->dir_path_of_temp_table);
3279
name_or_path = name;
3282
dict_table_remove_from_cache(table);
3284
if (dict_load_table(name) != NULL) {
3285
ut_print_timestamp(stderr);
3286
fputs(" InnoDB: Error: not able to remove table ",
3288
ut_print_name(stderr, trx, TRUE, name);
3289
fputs(" from the dictionary cache!\n", stderr);
3293
/* Do not drop possible .ibd tablespace if something went
3294
wrong: we do not want to delete valuable data of the user */
3296
if (err == DB_SUCCESS && space_id > 0) {
3297
if (!fil_space_for_table_exists_in_mem(space_id,
3304
"InnoDB: We removed now the InnoDB"
3305
" internal data dictionary entry\n"
3306
"InnoDB: of table ");
3307
ut_print_name(stderr, trx, TRUE, name);
3308
fprintf(stderr, ".\n");
3309
} else if (!fil_delete_tablespace(space_id)) {
3311
"InnoDB: We removed now the InnoDB"
3312
" internal data dictionary entry\n"
3313
"InnoDB: of table ");
3314
ut_print_name(stderr, trx, TRUE, name);
3315
fprintf(stderr, ".\n");
3317
ut_print_timestamp(stderr);
3319
" InnoDB: Error: not able to"
3320
" delete tablespace %lu of table ",
3322
ut_print_name(stderr, trx, TRUE, name);
3323
fputs("!\n", stderr);
3328
mem_heap_free(heap);
3332
if (locked_dictionary) {
3333
row_mysql_unlock_data_dictionary(trx);
3338
#ifndef UNIV_HOTBACKUP
3339
srv_wake_master_thread();
3340
#endif /* !UNIV_HOTBACKUP */
3345
/***********************************************************************
3346
Drop all foreign keys in a database, see Bug#18942.
3347
Called at the end of row_drop_database_for_mysql(). */
3350
drop_all_foreign_keys_in_db(
3351
/*========================*/
3352
/* out: error code or DB_SUCCESS */
3353
const char* name, /* in: database name which ends to '/' */
3354
trx_t* trx) /* in: transaction handle */
3359
ut_a(name[strlen(name) - 1] == '/');
3361
pinfo = pars_info_create();
3363
pars_info_add_str_literal(pinfo, "dbname", name);
3365
/* true if for_name is not prefixed with dbname */
3366
#define TABLE_NOT_IN_THIS_DB \
3367
"SUBSTR(for_name, 0, LENGTH(:dbname)) <> :dbname"
3369
err = que_eval_sql(pinfo,
3370
"PROCEDURE DROP_ALL_FOREIGN_KEYS_PROC () IS\n"
3371
"foreign_id CHAR;\n"
3374
"DECLARE CURSOR cur IS\n"
3375
"SELECT ID, FOR_NAME FROM SYS_FOREIGN\n"
3376
"WHERE FOR_NAME >= :dbname\n"
3377
"LOCK IN SHARE MODE\n"
3378
"ORDER BY FOR_NAME;\n"
3382
"WHILE found = 1 LOOP\n"
3383
" FETCH cur INTO foreign_id, for_name;\n"
3384
" IF (SQL % NOTFOUND) THEN\n"
3386
" ELSIF (" TABLE_NOT_IN_THIS_DB ") THEN\n"
3388
" ELSIF (1=1) THEN\n"
3389
" DELETE FROM SYS_FOREIGN_COLS\n"
3390
" WHERE ID = foreign_id;\n"
3391
" DELETE FROM SYS_FOREIGN\n"
3392
" WHERE ID = foreign_id;\n"
3398
FALSE, /* do not reserve dict mutex,
3399
we are already holding it */
3405
/*************************************************************************
3406
Drops a database for MySQL. */
3409
row_drop_database_for_mysql(
3410
/*========================*/
3411
/* out: error code or DB_SUCCESS */
3412
const char* name, /* in: database name which ends to '/' */
3413
trx_t* trx) /* in: transaction handle */
3415
dict_table_t* table;
3417
int err = DB_SUCCESS;
3418
ulint namelen = strlen(name);
3420
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
3422
ut_a(name[namelen - 1] == '/');
3424
trx->op_info = "dropping database";
3426
trx_start_if_not_started(trx);
3428
row_mysql_lock_data_dictionary(trx);
3430
while ((table_name = dict_get_first_table_name_in_db(name))) {
3431
ut_a(memcmp(table_name, name, namelen) == 0);
3433
table = dict_table_get_low(table_name);
3437
/* Wait until MySQL does not have any queries running on
3440
if (table->n_mysql_handles_opened > 0) {
3441
row_mysql_unlock_data_dictionary(trx);
3443
ut_print_timestamp(stderr);
3444
fputs(" InnoDB: Warning: MySQL is trying to"
3445
" drop database ", stderr);
3446
ut_print_name(stderr, trx, TRUE, name);
3448
"InnoDB: though there are still"
3449
" open handles to table ", stderr);
3450
ut_print_name(stderr, trx, TRUE, table_name);
3451
fputs(".\n", stderr);
3453
os_thread_sleep(1000000);
3455
mem_free(table_name);
3460
err = row_drop_table_for_mysql(table_name, trx, TRUE);
3462
mem_free(table_name);
3464
if (err != DB_SUCCESS) {
3465
fputs("InnoDB: DROP DATABASE ", stderr);
3466
ut_print_name(stderr, trx, TRUE, name);
3467
fprintf(stderr, " failed with error %lu for table ",
3469
ut_print_name(stderr, trx, TRUE, table_name);
3475
if (err == DB_SUCCESS) {
3476
/* after dropping all tables try to drop all leftover
3477
foreign keys in case orphaned ones exist */
3478
err = (int) drop_all_foreign_keys_in_db(name, trx);
3480
if (err != DB_SUCCESS) {
3481
fputs("InnoDB: DROP DATABASE ", stderr);
3482
ut_print_name(stderr, trx, TRUE, name);
3483
fprintf(stderr, " failed with error %d while "
3484
"dropping all foreign keys", err);
3488
trx_commit_for_mysql(trx);
3490
row_mysql_unlock_data_dictionary(trx);
3497
/*************************************************************************
3498
Checks if a table name contains the string "/#sql" which denotes temporary
3502
row_is_mysql_tmp_table_name(
3503
/*========================*/
3504
/* out: TRUE if temporary table */
3505
const char* name) /* in: table name in the form
3506
'database/tablename' */
3508
return(strstr(name, "/#sql") != NULL);
3509
/* return(strstr(name, "/@0023sql") != NULL); */
3512
/********************************************************************
3513
Delete a single constraint. */
3516
row_delete_constraint_low(
3517
/*======================*/
3518
/* out: error code or DB_SUCCESS */
3519
const char* id, /* in: constraint id */
3520
trx_t* trx) /* in: transaction handle */
3522
pars_info_t* info = pars_info_create();
3524
pars_info_add_str_literal(info, "id", id);
3526
return((int) que_eval_sql(info,
3527
"PROCEDURE DELETE_CONSTRAINT () IS\n"
3529
"DELETE FROM SYS_FOREIGN_COLS WHERE ID = :id;\n"
3530
"DELETE FROM SYS_FOREIGN WHERE ID = :id;\n"
3535
/********************************************************************
3536
Delete a single constraint. */
3539
row_delete_constraint(
3540
/*==================*/
3541
/* out: error code or DB_SUCCESS */
3542
const char* id, /* in: constraint id */
3543
const char* database_name, /* in: database name, with the
3545
mem_heap_t* heap, /* in: memory heap */
3546
trx_t* trx) /* in: transaction handle */
3550
/* New format constraints have ids <databasename>/<constraintname>. */
3551
err = row_delete_constraint_low(
3552
mem_heap_strcat(heap, database_name, id), trx);
3554
if ((err == DB_SUCCESS) && !strchr(id, '/')) {
3555
/* Old format < 4.0.18 constraints have constraint ids
3556
<number>_<number>. We only try deleting them if the
3557
constraint name does not contain a '/' character, otherwise
3558
deleting a new format constraint named 'foo/bar' from
3559
database 'baz' would remove constraint 'bar' from database
3560
'foo', if it existed. */
3562
err = row_delete_constraint_low(id, trx);
3568
/*************************************************************************
3569
Renames a table for MySQL. */
3572
row_rename_table_for_mysql(
3573
/*=======================*/
3574
/* out: error code or DB_SUCCESS */
3575
const char* old_name, /* in: old table name */
3576
const char* new_name, /* in: new table name */
3577
trx_t* trx, /* in: transaction handle */
3578
ibool commit) /* in: if TRUE then commit trx */
3580
dict_table_t* table;
3581
ulint err = DB_ERROR;
3582
mem_heap_t* heap = NULL;
3583
const char** constraints_to_drop = NULL;
3584
ulint n_constraints_to_drop = 0;
3585
ibool old_is_tmp, new_is_tmp;
3586
pars_info_t* info = NULL;
3588
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
3589
ut_a(old_name != NULL);
3590
ut_a(new_name != NULL);
3592
if (srv_created_new_raw || srv_force_recovery) {
3593
fputs("InnoDB: A new raw disk partition was initialized or\n"
3594
"InnoDB: innodb_force_recovery is on: we do not allow\n"
3595
"InnoDB: database modifications by the user. Shut down\n"
3596
"InnoDB: mysqld and edit my.cnf so that newraw"
3598
"InnoDB: with raw, and innodb_force_... is removed.\n",
3602
} else if (row_mysql_is_system_table(new_name)) {
3605
"InnoDB: Error: trying to create a MySQL"
3606
" system table %s of type InnoDB.\n"
3607
"InnoDB: MySQL system tables must be"
3608
" of the MyISAM type!\n",
3614
trx->op_info = "renaming table";
3615
trx_start_if_not_started(trx);
3617
old_is_tmp = row_is_mysql_tmp_table_name(old_name);
3618
new_is_tmp = row_is_mysql_tmp_table_name(new_name);
3620
table = dict_table_get_low(old_name);
3623
err = DB_TABLE_NOT_FOUND;
3624
ut_print_timestamp(stderr);
3626
fputs(" InnoDB: Error: table ", stderr);
3627
ut_print_name(stderr, trx, TRUE, old_name);
3628
fputs(" does not exist in the InnoDB internal\n"
3629
"InnoDB: data dictionary though MySQL is"
3630
" trying to rename the table.\n"
3631
"InnoDB: Have you copied the .frm file"
3632
" of the table to the\n"
3633
"InnoDB: MySQL database directory"
3634
" from another database?\n"
3635
"InnoDB: You can look for further help from\n"
3636
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
3637
"innodb-troubleshooting.html\n",
3640
} else if (table->ibd_file_missing) {
3641
err = DB_TABLE_NOT_FOUND;
3642
ut_print_timestamp(stderr);
3644
fputs(" InnoDB: Error: table ", stderr);
3645
ut_print_name(stderr, trx, TRUE, old_name);
3646
fputs(" does not have an .ibd file"
3647
" in the database directory.\n"
3648
"InnoDB: You can look for further help from\n"
3649
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
3650
"innodb-troubleshooting.html\n",
3653
} else if (new_is_tmp) {
3654
/* MySQL is doing an ALTER TABLE command and it renames the
3655
original table to a temporary table name. We want to preserve
3656
the original foreign key constraint definitions despite the
3657
name change. An exception is those constraints for which
3658
the ALTER TABLE contained DROP FOREIGN KEY <foreign key id>.*/
3660
heap = mem_heap_create(100);
3662
err = dict_foreign_parse_drop_constraints(
3663
heap, trx, table, &n_constraints_to_drop,
3664
&constraints_to_drop);
3666
if (err != DB_SUCCESS) {
3672
/* We use the private SQL parser of Innobase to generate the query
3673
graphs needed in updating the dictionary data from system tables. */
3675
info = pars_info_create();
3677
pars_info_add_str_literal(info, "new_table_name", new_name);
3678
pars_info_add_str_literal(info, "old_table_name", old_name);
3680
err = que_eval_sql(info,
3681
"PROCEDURE RENAME_TABLE () IS\n"
3683
"UPDATE SYS_TABLES SET NAME = :new_table_name\n"
3684
" WHERE NAME = :old_table_name;\n"
3688
if (err != DB_SUCCESS) {
3691
} else if (!new_is_tmp) {
3692
/* Rename all constraints. */
3694
info = pars_info_create();
3696
pars_info_add_str_literal(info, "new_table_name", new_name);
3697
pars_info_add_str_literal(info, "old_table_name", old_name);
3701
"PROCEDURE RENAME_CONSTRAINT_IDS () IS\n"
3702
"gen_constr_prefix CHAR;\n"
3703
"new_db_name CHAR;\n"
3704
"foreign_id CHAR;\n"
3705
"new_foreign_id CHAR;\n"
3706
"old_db_name_len INT;\n"
3707
"old_t_name_len INT;\n"
3708
"new_db_name_len INT;\n"
3713
"old_db_name_len := INSTR(:old_table_name, '/')-1;\n"
3714
"new_db_name_len := INSTR(:new_table_name, '/')-1;\n"
3715
"new_db_name := SUBSTR(:new_table_name, 0,\n"
3716
" new_db_name_len);\n"
3717
"old_t_name_len := LENGTH(:old_table_name);\n"
3718
"gen_constr_prefix := CONCAT(:old_table_name,\n"
3720
"WHILE found = 1 LOOP\n"
3721
" SELECT ID INTO foreign_id\n"
3722
" FROM SYS_FOREIGN\n"
3723
" WHERE FOR_NAME = :old_table_name\n"
3724
" AND TO_BINARY(FOR_NAME)\n"
3725
" = TO_BINARY(:old_table_name)\n"
3726
" LOCK IN SHARE MODE;\n"
3727
" IF (SQL % NOTFOUND) THEN\n"
3730
" UPDATE SYS_FOREIGN\n"
3731
" SET FOR_NAME = :new_table_name\n"
3732
" WHERE ID = foreign_id;\n"
3733
" id_len := LENGTH(foreign_id);\n"
3734
" IF (INSTR(foreign_id, '/') > 0) THEN\n"
3735
" IF (INSTR(foreign_id,\n"
3736
" gen_constr_prefix) > 0)\n"
3738
" new_foreign_id :=\n"
3739
" CONCAT(:new_table_name,\n"
3740
" SUBSTR(foreign_id, old_t_name_len,\n"
3741
" id_len - old_t_name_len));\n"
3743
" new_foreign_id :=\n"
3744
" CONCAT(new_db_name,\n"
3745
" SUBSTR(foreign_id,\n"
3746
" old_db_name_len,\n"
3747
" id_len - old_db_name_len));\n"
3749
" UPDATE SYS_FOREIGN\n"
3750
" SET ID = new_foreign_id\n"
3751
" WHERE ID = foreign_id;\n"
3752
" UPDATE SYS_FOREIGN_COLS\n"
3753
" SET ID = new_foreign_id\n"
3754
" WHERE ID = foreign_id;\n"
3758
"UPDATE SYS_FOREIGN SET REF_NAME = :new_table_name\n"
3759
"WHERE REF_NAME = :old_table_name\n"
3760
" AND TO_BINARY(REF_NAME)\n"
3761
" = TO_BINARY(:old_table_name);\n"
3765
} else if (n_constraints_to_drop > 0) {
3766
/* Drop some constraints of tmp tables. */
3768
ulint db_name_len = dict_get_db_name_len(old_name) + 1;
3769
char* db_name = mem_heap_strdupl(heap, old_name,
3773
for (i = 0; i < n_constraints_to_drop; i++) {
3774
err = row_delete_constraint(constraints_to_drop[i],
3775
db_name, heap, trx);
3777
if (err != DB_SUCCESS) {
3784
if (err != DB_SUCCESS) {
3785
if (err == DB_DUPLICATE_KEY) {
3786
ut_print_timestamp(stderr);
3787
fputs(" InnoDB: Error; possible reasons:\n"
3788
"InnoDB: 1) Table rename would cause"
3789
" two FOREIGN KEY constraints\n"
3790
"InnoDB: to have the same internal name"
3791
" in case-insensitive comparison.\n"
3792
"InnoDB: 2) table ", stderr);
3793
ut_print_name(stderr, trx, TRUE, new_name);
3794
fputs(" exists in the InnoDB internal data\n"
3795
"InnoDB: dictionary though MySQL is"
3796
" trying to rename table ", stderr);
3797
ut_print_name(stderr, trx, TRUE, old_name);
3799
"InnoDB: Have you deleted the .frm file"
3800
" and not used DROP TABLE?\n"
3801
"InnoDB: You can look for further help from\n"
3802
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
3803
"innodb-troubleshooting.html\n"
3804
"InnoDB: If table ", stderr);
3805
ut_print_name(stderr, trx, TRUE, new_name);
3806
fputs(" is a temporary table #sql..., then"
3808
"InnoDB: there are still queries running"
3809
" on the table, and it will be\n"
3810
"InnoDB: dropped automatically when"
3811
" the queries end.\n"
3812
"InnoDB: You can drop the orphaned table"
3813
" inside InnoDB by\n"
3814
"InnoDB: creating an InnoDB table with"
3815
" the same name in another\n"
3816
"InnoDB: database and copying the .frm file"
3817
" to the current database.\n"
3818
"InnoDB: Then MySQL thinks the table exists,"
3819
" and DROP TABLE will\n"
3820
"InnoDB: succeed.\n", stderr);
3822
trx->error_state = DB_SUCCESS;
3823
trx_general_rollback_for_mysql(trx, FALSE, NULL);
3824
trx->error_state = DB_SUCCESS;
3826
/* The following call will also rename the .ibd data file if
3827
the table is stored in a single-table tablespace */
3829
if (!dict_table_rename_in_cache(table, new_name,
3831
trx->error_state = DB_SUCCESS;
3832
trx_general_rollback_for_mysql(trx, FALSE, NULL);
3833
trx->error_state = DB_SUCCESS;
3837
/* We only want to switch off some of the type checking in
3838
an ALTER, not in a RENAME. */
3840
err = dict_load_foreigns(
3841
new_name, !old_is_tmp || trx->check_foreigns);
3843
if (err != DB_SUCCESS) {
3844
ut_print_timestamp(stderr);
3847
fputs(" InnoDB: Error: in ALTER TABLE ",
3849
ut_print_name(stderr, trx, TRUE, new_name);
3851
"InnoDB: has or is referenced"
3852
" in foreign key constraints\n"
3853
"InnoDB: which are not compatible"
3854
" with the new table definition.\n",
3857
fputs(" InnoDB: Error: in RENAME TABLE"
3860
ut_print_name(stderr, trx, TRUE, new_name);
3862
"InnoDB: is referenced in"
3863
" foreign key constraints\n"
3864
"InnoDB: which are not compatible"
3865
" with the new table definition.\n",
3869
ut_a(dict_table_rename_in_cache(table,
3871
trx->error_state = DB_SUCCESS;
3872
trx_general_rollback_for_mysql(trx, FALSE, NULL);
3873
trx->error_state = DB_SUCCESS;
3880
trx_commit_for_mysql(trx);
3883
if (UNIV_LIKELY_NULL(heap)) {
3884
mem_heap_free(heap);
3892
/*************************************************************************
3893
Checks that the index contains entries in an ascending order, unique
3894
constraint is not broken, and calculates the number of index entries
3895
in the read view of the current transaction. */
3898
row_scan_and_check_index(
3899
/*=====================*/
3900
/* out: TRUE if ok */
3901
row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL */
3902
dict_index_t* index, /* in: index */
3903
ulint* n_rows) /* out: number of entries seen in the
3904
current consistent read */
3906
dtuple_t* prev_entry = NULL;
3907
ulint matched_fields;
3908
ulint matched_bytes;
3914
ibool contains_null;
3917
mem_heap_t* heap = NULL;
3919
ulint offsets_[REC_OFFS_NORMAL_SIZE];
3921
rec_offs_init(offsets_);
3925
buf = mem_alloc(UNIV_PAGE_SIZE);
3926
heap = mem_heap_create(100);
3928
/* Make a dummy template in prebuilt, which we will use
3929
in scanning the index entries */
3931
prebuilt->index = index;
3932
prebuilt->sql_stat_start = TRUE;
3933
prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
3934
prebuilt->n_template = 0;
3935
prebuilt->need_to_access_clustered = FALSE;
3937
dtuple_set_n_fields(prebuilt->search_tuple, 0);
3939
prebuilt->select_lock_type = LOCK_NONE;
3942
ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
3944
/* Check thd->killed every 1,000 scanned rows */
3946
if (trx_is_interrupted(prebuilt->trx)) {
3951
if (ret != DB_SUCCESS) {
3954
mem_heap_free(heap);
3959
*n_rows = *n_rows + 1;
3961
/* row_search... returns the index record in buf, record origin offset
3962
within buf stored in the first 4 bytes, because we have built a dummy
3965
rec = buf + mach_read_from_4(buf);
3967
offsets = rec_get_offsets(rec, index, offsets_,
3968
ULINT_UNDEFINED, &heap);
3970
if (prev_entry != NULL) {
3974
cmp = cmp_dtuple_rec_with_match(prev_entry, rec, offsets,
3977
contains_null = FALSE;
3979
/* In a unique secondary index we allow equal key values if
3980
they contain SQL NULLs */
3983
i < dict_index_get_n_ordering_defined_by_user(index);
3985
if (UNIV_SQL_NULL == dfield_get_len(
3986
dtuple_get_nth_field(prev_entry, i))) {
3988
contains_null = TRUE;
3993
fputs("InnoDB: index records in a wrong order in ",
3996
dict_index_name_print(stderr,
3997
prebuilt->trx, index);
3999
"InnoDB: prev record ", stderr);
4000
dtuple_print(stderr, prev_entry);
4002
"InnoDB: record ", stderr);
4003
rec_print_new(stderr, rec, offsets);
4006
} else if (dict_index_is_unique(index)
4009
>= dict_index_get_n_ordering_defined_by_user(
4012
fputs("InnoDB: duplicate key in ", stderr);
4018
mem_heap_t* tmp_heap = NULL;
4020
/* Empty the heap on each round. But preserve offsets[]
4021
for the row_rec_to_index_entry() call, by copying them
4022
into a separate memory heap when needed. */
4023
if (UNIV_UNLIKELY(offsets != offsets_)) {
4024
ulint size = rec_offs_get_n_alloc(offsets)
4027
tmp_heap = mem_heap_create(size);
4028
offsets = mem_heap_dup(tmp_heap, offsets, size);
4031
mem_heap_empty(heap);
4033
prev_entry = row_rec_to_index_entry(ROW_COPY_DATA, rec,
4037
if (UNIV_LIKELY_NULL(tmp_heap)) {
4038
mem_heap_free(tmp_heap);
4042
ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, ROW_SEL_NEXT);
4047
/*************************************************************************
4048
Checks a table for corruption. */
4051
row_check_table_for_mysql(
4052
/*======================*/
4053
/* out: DB_ERROR or DB_SUCCESS */
4054
row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
4057
dict_table_t* table = prebuilt->table;
4058
dict_index_t* index;
4060
ulint n_rows_in_table = ULINT_UNDEFINED;
4061
ulint ret = DB_SUCCESS;
4062
ulint old_isolation_level;
4064
if (table->ibd_file_missing) {
4065
ut_print_timestamp(stderr);
4066
fprintf(stderr, " InnoDB: Error:\n"
4067
"InnoDB: MySQL is trying to use a table handle"
4068
" but the .ibd file for\n"
4069
"InnoDB: table %s does not exist.\n"
4070
"InnoDB: Have you deleted the .ibd file"
4071
" from the database directory under\n"
4072
"InnoDB: the MySQL datadir, or have you"
4073
" used DISCARD TABLESPACE?\n"
4074
"InnoDB: Look from\n"
4075
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
4076
"innodb-troubleshooting.html\n"
4077
"InnoDB: how you can resolve the problem.\n",
4082
prebuilt->trx->op_info = "checking table";
4084
old_isolation_level = prebuilt->trx->isolation_level;
4086
/* We must run the index record counts at an isolation level
4087
>= READ COMMITTED, because a dirty read can see a wrong number
4088
of records in some index; to play safe, we use always
4089
REPEATABLE READ here */
4091
prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
4093
/* Enlarge the fatal lock wait timeout during CHECK TABLE. */
4094
mutex_enter(&kernel_mutex);
4095
srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
4096
mutex_exit(&kernel_mutex);
4098
index = dict_table_get_first_index(table);
4100
while (index != NULL) {
4101
/* fputs("Validating index ", stderr);
4102
ut_print_name(stderr, trx, FALSE, index->name);
4103
putc('\n', stderr); */
4105
if (!btr_validate_index(index, prebuilt->trx)) {
4108
if (!row_scan_and_check_index(prebuilt,index, &n_rows)){
4112
if (trx_is_interrupted(prebuilt->trx)) {
4116
/* fprintf(stderr, "%lu entries in index %s\n", n_rows,
4119
if (index == dict_table_get_first_index(table)) {
4120
n_rows_in_table = n_rows;
4121
} else if (n_rows != n_rows_in_table) {
4125
fputs("Error: ", stderr);
4126
dict_index_name_print(stderr,
4127
prebuilt->trx, index);
4129
" contains %lu entries,"
4132
(ulong) n_rows_in_table);
4136
index = dict_table_get_next_index(index);
4139
/* Restore the original isolation level */
4140
prebuilt->trx->isolation_level = old_isolation_level;
4142
/* We validate also the whole adaptive hash index for all tables
4143
at every CHECK TABLE */
4145
if (!btr_search_validate()) {
4150
/* Restore the fatal lock wait timeout after CHECK TABLE. */
4151
mutex_enter(&kernel_mutex);
4152
srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
4153
mutex_exit(&kernel_mutex);
4155
prebuilt->trx->op_info = "";
4159
#endif /* !UNIV_HOTBACKUP */
4161
/*************************************************************************
4162
Determines if a table is a magic monitor table. */
4165
row_is_magic_monitor_table(
4166
/*=======================*/
4167
/* out: TRUE if monitor table */
4168
const char* table_name) /* in: name of the table, in the
4169
form database/table_name */
4171
const char* name; /* table_name without database/ */
4174
name = strchr(table_name, '/');
4177
len = strlen(name) + 1;
4179
if (STR_EQ(name, len, S_innodb_monitor)
4180
|| STR_EQ(name, len, S_innodb_lock_monitor)
4181
|| STR_EQ(name, len, S_innodb_tablespace_monitor)
4182
|| STR_EQ(name, len, S_innodb_table_monitor)
4183
|| STR_EQ(name, len, S_innodb_mem_validate)) {