1
/* Copyright (C) 2000-2005 MySQL AB & Innobase Oy
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
/* This file defines the InnoDB handler: the interface between MySQL and InnoDB
17
NOTE: You can only use noninlined InnoDB functions in this file, because we
18
have disabled the InnoDB inlining in this file. */
20
/* TODO list for the InnoDB handler in 5.0:
21
- Remove the flag trx->active_trans and look at trx->conc_state
22
- fix savepoint functions to use savepoint storage area
23
- Find out what kind of problems the OS X case-insensitivity causes to
24
table and database names; should we 'normalize' the names like we do
28
#ifdef USE_PRAGMA_IMPLEMENTATION
29
#pragma implementation // gcc: Class implementation
32
#include <mysql_priv.h>
33
#include <mysqld_error.h>
37
#include <myisampack.h>
38
#include <mysys_err.h>
40
#include "ha_innodb.h"
41
#include <mysql/plugin.h>
44
/* This is needed because of Bug #3596. Let us hope that pthread_mutex_t
45
is defined the same in both builds: the MySQL server and the InnoDB plugin. */
46
extern pthread_mutex_t LOCK_thread_count;
47
#endif /* MYSQL_SERVER */
49
/** to protect innobase_open_files */
50
static pthread_mutex_t innobase_share_mutex;
51
/** to force correct commit order in binlog */
52
static pthread_mutex_t prepare_commit_mutex;
53
static ulong commit_threads = 0;
54
static pthread_mutex_t commit_threads_m;
55
static pthread_cond_t commit_cond;
56
static pthread_mutex_t commit_cond_m;
57
static bool innodb_inited = 0;
60
This needs to exist until the query cache callback is removed
61
or learns to pass hton.
63
static handlerton *innodb_hton_ptr;
66
static my_bool index_cond_func_innodb(void *arg);
71
#define INSIDE_HA_INNOBASE_CC
73
/* Include necessary InnoDB headers */
75
#include "../storage/innobase/include/univ.i"
76
#include "../storage/innobase/include/os0file.h"
77
#include "../storage/innobase/include/os0thread.h"
78
#include "../storage/innobase/include/srv0start.h"
79
#include "../storage/innobase/include/srv0srv.h"
80
#include "../storage/innobase/include/trx0roll.h"
81
#include "../storage/innobase/include/trx0trx.h"
82
#include "../storage/innobase/include/trx0sys.h"
83
#include "../storage/innobase/include/mtr0mtr.h"
84
#include "../storage/innobase/include/row0ins.h"
85
#include "../storage/innobase/include/row0mysql.h"
86
#include "../storage/innobase/include/row0sel.h"
87
#include "../storage/innobase/include/row0upd.h"
88
#include "../storage/innobase/include/log0log.h"
89
#include "../storage/innobase/include/lock0lock.h"
90
#include "../storage/innobase/include/dict0crea.h"
91
#include "../storage/innobase/include/btr0cur.h"
92
#include "../storage/innobase/include/btr0btr.h"
93
#include "../storage/innobase/include/fsp0fsp.h"
94
#include "../storage/innobase/include/sync0sync.h"
95
#include "../storage/innobase/include/fil0fil.h"
96
#include "../storage/innobase/include/trx0xa.h"
97
#include "../storage/innobase/include/thr0loc.h"
98
#include "../storage/innobase/include/ha_prototypes.h"
101
static const long AUTOINC_OLD_STYLE_LOCKING = 0;
102
static const long AUTOINC_NEW_STYLE_LOCKING = 1;
103
static const long AUTOINC_NO_LOCKING = 2;
105
static long innobase_mirrored_log_groups, innobase_log_files_in_group,
106
innobase_log_buffer_size, innobase_buffer_pool_awe_mem_mb,
107
innobase_additional_mem_pool_size, innobase_file_io_threads,
108
innobase_lock_wait_timeout, innobase_force_recovery,
109
innobase_open_files, innobase_autoinc_lock_mode;
111
static long long innobase_buffer_pool_size, innobase_log_file_size;
113
/* The default values for the following char* start-up parameters
114
are determined in innobase_init below: */
116
static char* innobase_data_home_dir = NULL;
117
static char* innobase_data_file_path = NULL;
118
static char* innobase_log_group_home_dir = NULL;
119
/* The following has a misleading name: starting from 4.0.5, this also
121
static char* innobase_unix_file_flush_method = NULL;
123
/* Below we have boolean-valued start-up parameters, and their default
126
static ulong innobase_fast_shutdown = 1;
127
#ifdef UNIV_LOG_ARCHIVE
128
static my_bool innobase_log_archive = FALSE;
129
static char* innobase_log_arch_dir = NULL;
130
#endif /* UNIV_LOG_ARCHIVE */
131
static my_bool innobase_use_doublewrite = TRUE;
132
static my_bool innobase_use_checksums = TRUE;
133
static my_bool innobase_file_per_table = FALSE;
134
static my_bool innobase_locks_unsafe_for_binlog = FALSE;
135
static my_bool innobase_rollback_on_timeout = FALSE;
136
static my_bool innobase_create_status_file = FALSE;
137
static my_bool innobase_stats_on_metadata = TRUE;
138
static my_bool innobase_use_adaptive_hash_indexes = TRUE;
140
static char* internal_innobase_data_file_path = NULL;
142
/* The following counter is used to convey information to InnoDB
143
about server activity: in selects it is not sensible to call
144
srv_active_wake_master_thread after each fetch or search, we only do
145
it every INNOBASE_WAKE_INTERVAL'th step. */
147
#define INNOBASE_WAKE_INTERVAL 32
148
static ulong innobase_active_counter = 0;
150
static HASH innobase_open_tables;
152
#ifdef __NETWARE__ /* some special cleanup for NetWare */
153
bool nw_panic = FALSE;
156
static uchar* innobase_get_key(INNOBASE_SHARE *share, size_t *length,
157
my_bool not_used __attribute__((unused)));
158
static INNOBASE_SHARE *get_share(const char *table_name);
159
static void free_share(INNOBASE_SHARE *share);
160
static int innobase_close_connection(handlerton *hton, THD* thd);
161
static int innobase_commit(handlerton *hton, THD* thd, bool all);
162
static int innobase_rollback(handlerton *hton, THD* thd, bool all);
163
static int innobase_rollback_to_savepoint(handlerton *hton, THD* thd,
165
static int innobase_savepoint(handlerton *hton, THD* thd, void *savepoint);
166
static int innobase_release_savepoint(handlerton *hton, THD* thd,
168
static handler *innobase_create_handler(handlerton *hton,
172
static const char innobase_hton_name[]= "InnoDB";
175
static MYSQL_THDVAR_BOOL(support_xa, PLUGIN_VAR_OPCMDARG,
176
"Enable InnoDB support for the XA two-phase commit",
177
/* check_func */ NULL, /* update_func */ NULL,
180
static MYSQL_THDVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG,
181
"Enable InnoDB locking in LOCK TABLES",
182
/* check_func */ NULL, /* update_func */ NULL,
185
static handler *innobase_create_handler(handlerton *hton,
189
return new (mem_root) ha_innobase(hton, table);
192
/***********************************************************************
193
This function is used to prepare X/Open XA distributed transaction */
198
/* out: 0 or error number */
200
THD* thd, /* in: handle to the MySQL thread of the user
201
whose XA transaction should be prepared */
202
bool all); /* in: TRUE - commit transaction
203
FALSE - the current SQL statement ended */
204
/***********************************************************************
205
This function is used to recover X/Open XA distributed transactions */
210
/* out: number of prepared transactions
211
stored in xid_list */
213
XID* xid_list, /* in/out: prepared transactions */
214
uint len); /* in: number of slots in xid_list */
215
/***********************************************************************
216
This function is used to commit one X/Open XA distributed transaction
217
which is in the prepared state */
220
innobase_commit_by_xid(
221
/*===================*/
222
/* out: 0 or error number */
224
XID* xid); /* in: X/Open XA transaction identification */
225
/***********************************************************************
226
This function is used to rollback one X/Open XA distributed transaction
227
which is in the prepared state */
230
innobase_rollback_by_xid(
231
/*=====================*/
232
/* out: 0 or error number */
234
XID *xid); /* in: X/Open XA transaction identification */
235
/***********************************************************************
236
Create a consistent view for a cursor based on current transaction
237
which is created if the corresponding MySQL thread still lacks one.
238
This consistent view is then used inside of MySQL when accessing records
242
innobase_create_cursor_view(
243
/*========================*/
244
/* out: pointer to cursor view or NULL */
245
handlerton* hton, /* in: innobase hton */
246
THD* thd); /* in: user thread handle */
247
/***********************************************************************
248
Set the given consistent cursor view to a transaction which is created
249
if the corresponding MySQL thread still lacks one. If the given
250
consistent cursor view is NULL global read view of a transaction is
251
restored to a transaction read view. */
254
innobase_set_cursor_view(
255
/*=====================*/
257
THD* thd, /* in: user thread handle */
258
void* curview);/* in: Consistent cursor view to be set */
259
/***********************************************************************
260
Close the given consistent cursor view of a transaction and restore
261
global read view to a transaction read view. Transaction is created if the
262
corresponding MySQL thread still lacks one. */
265
innobase_close_cursor_view(
266
/*=======================*/
268
THD* thd, /* in: user thread handle */
269
void* curview);/* in: Consistent read view to be closed */
270
/*********************************************************************
271
Removes all tables in the named database inside InnoDB. */
274
innobase_drop_database(
275
/*===================*/
276
/* out: error number */
277
handlerton* hton, /* in: handlerton of Innodb */
278
char* path); /* in: database path; inside InnoDB the name
279
of the last directory in the path is used as
280
the database name: for example, in 'mysql/data/test'
281
the database name is 'test' */
282
/***********************************************************************
283
Closes an InnoDB database. */
286
innobase_end(handlerton *hton, ha_panic_function type);
288
/*********************************************************************
289
Creates an InnoDB transaction struct for the thd if it does not yet have one.
290
Starts a new InnoDB transaction if a transaction is not yet started. And
291
assigns a new snapshot for a consistent read if the transaction does not yet
295
innobase_start_trx_and_assign_read_view(
296
/*====================================*/
298
handlerton* hton, /* in: Innodb handlerton */
299
THD* thd); /* in: MySQL thread handle of the user for whom
300
the transaction should be committed */
301
/********************************************************************
302
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
303
the logs, and the name of this function should be innobase_checkpoint. */
308
/* out: TRUE if error */
309
handlerton* hton); /* in: InnoDB handlerton */
311
/****************************************************************************
312
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
313
Monitor to the client. */
318
handlerton* hton, /* in: the innodb handlerton */
319
THD* thd, /* in: the MySQL query thread of the caller */
320
stat_print_fn *stat_print);
322
bool innobase_show_status(handlerton *hton, THD* thd,
323
stat_print_fn* stat_print,
324
enum ha_stat_type stat_type);
326
/*********************************************************************
327
Commits a transaction in an InnoDB database. */
332
trx_t* trx); /* in: transaction handle */
334
static SHOW_VAR innodb_status_variables[]= {
335
{"buffer_pool_pages_data",
336
(char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG},
337
{"buffer_pool_pages_dirty",
338
(char*) &export_vars.innodb_buffer_pool_pages_dirty, SHOW_LONG},
339
{"buffer_pool_pages_flushed",
340
(char*) &export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG},
341
{"buffer_pool_pages_free",
342
(char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG},
343
{"buffer_pool_pages_latched",
344
(char*) &export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG},
345
{"buffer_pool_pages_misc",
346
(char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG},
347
{"buffer_pool_pages_total",
348
(char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG},
349
{"buffer_pool_read_ahead_rnd",
350
(char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
351
{"buffer_pool_read_ahead_seq",
352
(char*) &export_vars.innodb_buffer_pool_read_ahead_seq, SHOW_LONG},
353
{"buffer_pool_read_requests",
354
(char*) &export_vars.innodb_buffer_pool_read_requests, SHOW_LONG},
355
{"buffer_pool_reads",
356
(char*) &export_vars.innodb_buffer_pool_reads, SHOW_LONG},
357
{"buffer_pool_wait_free",
358
(char*) &export_vars.innodb_buffer_pool_wait_free, SHOW_LONG},
359
{"buffer_pool_write_requests",
360
(char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG},
362
(char*) &export_vars.innodb_data_fsyncs, SHOW_LONG},
363
{"data_pending_fsyncs",
364
(char*) &export_vars.innodb_data_pending_fsyncs, SHOW_LONG},
365
{"data_pending_reads",
366
(char*) &export_vars.innodb_data_pending_reads, SHOW_LONG},
367
{"data_pending_writes",
368
(char*) &export_vars.innodb_data_pending_writes, SHOW_LONG},
370
(char*) &export_vars.innodb_data_read, SHOW_LONG},
372
(char*) &export_vars.innodb_data_reads, SHOW_LONG},
374
(char*) &export_vars.innodb_data_writes, SHOW_LONG},
376
(char*) &export_vars.innodb_data_written, SHOW_LONG},
377
{"dblwr_pages_written",
378
(char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG},
380
(char*) &export_vars.innodb_dblwr_writes, SHOW_LONG},
382
(char*) &export_vars.innodb_log_waits, SHOW_LONG},
383
{"log_write_requests",
384
(char*) &export_vars.innodb_log_write_requests, SHOW_LONG},
386
(char*) &export_vars.innodb_log_writes, SHOW_LONG},
388
(char*) &export_vars.innodb_os_log_fsyncs, SHOW_LONG},
389
{"os_log_pending_fsyncs",
390
(char*) &export_vars.innodb_os_log_pending_fsyncs, SHOW_LONG},
391
{"os_log_pending_writes",
392
(char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG},
394
(char*) &export_vars.innodb_os_log_written, SHOW_LONG},
396
(char*) &export_vars.innodb_page_size, SHOW_LONG},
398
(char*) &export_vars.innodb_pages_created, SHOW_LONG},
400
(char*) &export_vars.innodb_pages_read, SHOW_LONG},
402
(char*) &export_vars.innodb_pages_written, SHOW_LONG},
403
{"row_lock_current_waits",
404
(char*) &export_vars.innodb_row_lock_current_waits, SHOW_LONG},
406
(char*) &export_vars.innodb_row_lock_time, SHOW_LONGLONG},
407
{"row_lock_time_avg",
408
(char*) &export_vars.innodb_row_lock_time_avg, SHOW_LONG},
409
{"row_lock_time_max",
410
(char*) &export_vars.innodb_row_lock_time_max, SHOW_LONG},
412
(char*) &export_vars.innodb_row_lock_waits, SHOW_LONG},
414
(char*) &export_vars.innodb_rows_deleted, SHOW_LONG},
416
(char*) &export_vars.innodb_rows_inserted, SHOW_LONG},
418
(char*) &export_vars.innodb_rows_read, SHOW_LONG},
420
(char*) &export_vars.innodb_rows_updated, SHOW_LONG},
421
{NullS, NullS, SHOW_LONG}
424
/* General functions */
426
/**********************************************************************
427
Returns true if the thread is the replication thread on the slave
428
server. Used in srv_conc_enter_innodb() to determine if the thread
429
should be allowed to enter InnoDB - the replication thread is treated
430
differently than other threads. Also used in
431
srv_conc_force_exit_innodb(). */
434
thd_is_replication_slave_thread(
435
/*============================*/
436
/* out: true if thd is the replication thread */
437
void* thd) /* in: thread handle (THD*) */
439
return((ibool) thd_slave_thread((THD*) thd));
442
/**********************************************************************
443
Save some CPU by testing the value of srv_thread_concurrency in inline
447
innodb_srv_conc_enter_innodb(
448
/*=========================*/
449
trx_t* trx) /* in: transaction handle */
451
if (UNIV_LIKELY(!srv_thread_concurrency)) {
456
srv_conc_enter_innodb(trx);
459
/**********************************************************************
460
Save some CPU by testing the value of srv_thread_concurrency in inline
464
innodb_srv_conc_exit_innodb(
465
/*========================*/
466
trx_t* trx) /* in: transaction handle */
468
if (UNIV_LIKELY(!srv_thread_concurrency)) {
473
srv_conc_exit_innodb(trx);
476
/**********************************************************************
477
Releases possible search latch and InnoDB thread FIFO ticket. These should
478
be released at each SQL statement end, and also when mysqld passes the
479
control to the client. It does no harm to release these also in the middle
480
of an SQL statement. */
483
innobase_release_stat_resources(
484
/*============================*/
485
trx_t* trx) /* in: transaction object */
487
if (trx->has_search_latch) {
488
trx_search_latch_release_if_reserved(trx);
491
if (trx->declared_to_be_inside_innodb) {
492
/* Release our possible ticket in the FIFO */
494
srv_conc_force_exit_innodb(trx);
498
/**********************************************************************
499
Returns true if the transaction this thread is processing has edited
500
non-transactional tables. Used by the deadlock detector when deciding
501
which transaction to rollback in case of a deadlock - we try to avoid
502
rolling back transactions that have edited non-transactional tables. */
505
thd_has_edited_nontrans_tables(
506
/*===========================*/
507
/* out: true if non-transactional tables have
509
void* thd) /* in: thread handle (THD*) */
511
return((ibool) thd_non_transactional_update((THD*) thd));
514
/************************************************************************
515
Obtain the InnoDB transaction of a MySQL thread. */
520
/* out: reference to transaction pointer */
521
THD* thd) /* in: MySQL thread */
523
return(*(trx_t**) thd_ha_data(thd, innodb_hton_ptr));
526
/************************************************************************
527
Call this function when mysqld passes control to the client. That is to
528
avoid deadlocks on the adaptive hash S-latch possibly held by thd. For more
529
documentation, see handler.cc. */
532
innobase_release_temporary_latches(
533
/*===============================*/
535
handlerton* hton, /* in: handlerton */
536
THD* thd) /* in: MySQL thread */
540
DBUG_ASSERT(hton == innodb_hton_ptr);
542
if (!innodb_inited) {
547
trx = thd_to_trx(thd);
550
innobase_release_stat_resources(trx);
555
/************************************************************************
556
Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
557
time calls srv_active_wake_master_thread. This function should be used
558
when a single database operation may introduce a small need for
559
server utility activity, like checkpointing. */
562
innobase_active_small(void)
563
/*=======================*/
565
innobase_active_counter++;
567
if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
568
srv_active_wake_master_thread();
572
/************************************************************************
573
Converts an InnoDB error code to a MySQL error code and also tells to MySQL
574
about a possible transaction rollback inside InnoDB caused by a lock wait
575
timeout or a deadlock. */
578
convert_error_code_to_mysql(
579
/*========================*/
580
/* out: MySQL error code */
581
int error, /* in: InnoDB error code */
582
THD* thd) /* in: user thread handle or NULL */
584
if (error == DB_SUCCESS) {
588
} else if (error == (int) DB_DUPLICATE_KEY) {
590
return(HA_ERR_FOUND_DUPP_KEY);
592
} else if (error == (int) DB_FOREIGN_DUPLICATE_KEY) {
594
return(HA_ERR_FOREIGN_DUPLICATE_KEY);
596
} else if (error == (int) DB_RECORD_NOT_FOUND) {
598
return(HA_ERR_NO_ACTIVE_RECORD);
600
} else if (error == (int) DB_ERROR) {
602
return(-1); /* unspecified error */
604
} else if (error == (int) DB_DEADLOCK) {
605
/* Since we rolled back the whole transaction, we must
606
tell it also to MySQL so that MySQL knows to empty the
607
cached binlog for this transaction */
609
thd_mark_transaction_to_rollback(thd, TRUE);
611
return(HA_ERR_LOCK_DEADLOCK);
612
} else if (error == (int) DB_LOCK_WAIT_TIMEOUT) {
614
/* Starting from 5.0.13, we let MySQL just roll back the
615
latest SQL statement in a lock wait timeout. Previously, we
616
rolled back the whole transaction. */
618
thd_mark_transaction_to_rollback(thd,
619
(bool)row_rollback_on_timeout);
621
return(HA_ERR_LOCK_WAIT_TIMEOUT);
623
} else if (error == (int) DB_NO_REFERENCED_ROW) {
625
return(HA_ERR_NO_REFERENCED_ROW);
627
} else if (error == (int) DB_ROW_IS_REFERENCED) {
629
return(HA_ERR_ROW_IS_REFERENCED);
631
} else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) {
633
return(HA_ERR_CANNOT_ADD_FOREIGN);
635
} else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) {
637
return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
638
misleading, a new MySQL error
639
code should be introduced */
640
} else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) {
642
return(HA_ERR_CRASHED);
644
} else if (error == (int) DB_OUT_OF_FILE_SPACE) {
646
return(HA_ERR_RECORD_FILE_FULL);
648
} else if (error == (int) DB_TABLE_IS_BEING_USED) {
650
return(HA_ERR_WRONG_COMMAND);
652
} else if (error == (int) DB_TABLE_NOT_FOUND) {
654
return(HA_ERR_NO_SUCH_TABLE);
656
} else if (error == (int) DB_TOO_BIG_RECORD) {
658
return(HA_ERR_TO_BIG_ROW);
660
} else if (error == (int) DB_CORRUPTION) {
662
return(HA_ERR_CRASHED);
663
} else if (error == (int) DB_NO_SAVEPOINT) {
665
return(HA_ERR_NO_SAVEPOINT);
666
} else if (error == (int) DB_LOCK_TABLE_FULL) {
667
/* Since we rolled back the whole transaction, we must
668
tell it also to MySQL so that MySQL knows to empty the
669
cached binlog for this transaction */
671
thd_mark_transaction_to_rollback(thd, TRUE);
673
return(HA_ERR_LOCK_TABLE_FULL);
674
} else if (error == DB_TOO_MANY_CONCURRENT_TRXS) {
676
/* Once MySQL add the appropriate code to errmsg.txt then
677
we can get rid of this #ifdef. NOTE: The code checked by
678
the #ifdef is the suggested name for the error condition
679
and the actual error code name could very well be different.
680
This will require some monitoring, ie. the status
681
of this request on our part.*/
682
#ifdef ER_TOO_MANY_CONCURRENT_TRXS
683
return(ER_TOO_MANY_CONCURRENT_TRXS);
685
return(HA_ERR_RECORD_FILE_FULL);
688
} else if (error == DB_UNSUPPORTED) {
690
return(HA_ERR_UNSUPPORTED);
692
return(-1); // Unknown error
696
/*****************************************************************
697
If you want to print a thd that is not associated with the current thread,
698
you must call this function before reserving the InnoDB kernel_mutex, to
699
protect MySQL from setting thd->query NULL. If you print a thd of the current
700
thread, we know that MySQL cannot modify thd->query, and it is not necessary
701
to call this. Call innobase_mysql_end_print_arbitrary_thd() after you release
703
NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
707
innobase_mysql_prepare_print_arbitrary_thd(void)
708
/*============================================*/
710
VOID(pthread_mutex_lock(&LOCK_thread_count));
713
/*****************************************************************
714
Releases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
715
NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
719
innobase_mysql_end_print_arbitrary_thd(void)
720
/*========================================*/
722
VOID(pthread_mutex_unlock(&LOCK_thread_count));
725
/*****************************************************************
726
Prints info of a THD object (== user session thread) to the given file.
727
NOTE that /mysql/innobase/trx/trx0trx.c must contain the prototype for
731
innobase_mysql_print_thd(
732
/*=====================*/
733
FILE* f, /* in: output stream */
734
void* input_thd, /* in: pointer to a MySQL THD object */
735
uint max_query_len) /* in: max query length to print, or 0 to
736
use the default max length */
741
thd = (THD*) input_thd;
742
fputs(thd_security_context(thd, buffer, sizeof(buffer),
747
/**********************************************************************
748
Get the variable length bounds of the given character set.
750
NOTE that the exact prototype of this function has to be in
751
/innobase/include/data0type.ic! */
754
innobase_get_cset_width(
755
/*====================*/
756
ulint cset, /* in: MySQL charset-collation code */
757
ulint* mbminlen, /* out: minimum length of a char (in bytes) */
758
ulint* mbmaxlen) /* out: maximum length of a char (in bytes) */
765
cs = all_charsets[cset];
767
*mbminlen = cs->mbminlen;
768
*mbmaxlen = cs->mbmaxlen;
771
*mbminlen = *mbmaxlen = 0;
775
/**********************************************************************
776
Converts an identifier to a table name.
778
NOTE that the exact prototype of this function has to be in
779
/innobase/dict/dict0dict.c! */
782
innobase_convert_from_table_id(
783
/*===========================*/
784
char* to, /* out: converted identifier */
785
const char* from, /* in: identifier to convert */
786
ulint len) /* in: length of 'to', in bytes */
790
strconvert(thd_charset(current_thd), from,
791
&my_charset_filename, to, (uint) len, &errors);
794
/**********************************************************************
795
Converts an identifier to UTF-8.
797
NOTE that the exact prototype of this function has to be in
798
/innobase/dict/dict0dict.c! */
801
innobase_convert_from_id(
802
/*=====================*/
803
char* to, /* out: converted identifier */
804
const char* from, /* in: identifier to convert */
805
ulint len) /* in: length of 'to', in bytes */
809
strconvert(thd_charset(current_thd), from,
810
system_charset_info, to, (uint) len, &errors);
813
/**********************************************************************
814
Compares NUL-terminated UTF-8 strings case insensitively.
816
NOTE that the exact prototype of this function has to be in
817
/innobase/dict/dict0dict.c! */
822
/* out: 0 if a=b, <0 if a<b, >1 if a>b */
823
const char* a, /* in: first string to compare */
824
const char* b) /* in: second string to compare */
826
return(my_strcasecmp(system_charset_info, a, b));
829
/**********************************************************************
830
Makes all characters in a NUL-terminated UTF-8 string lower case.
832
NOTE that the exact prototype of this function has to be in
833
/innobase/dict/dict0dict.c! */
838
char* a) /* in/out: string to put in lower case */
840
my_casedn_str(system_charset_info, a);
843
/**************************************************************************
844
Determines the connection character set.
846
NOTE that the exact prototype of this function has to be in
847
/innobase/dict/dict0dict.c! */
849
struct charset_info_st*
850
innobase_get_charset(
851
/*=================*/
852
/* out: connection character set */
853
void* mysql_thd) /* in: MySQL thread handle */
855
return(thd_charset((THD*) mysql_thd));
858
/*************************************************************************
859
Creates a temporary file. */
862
innobase_mysql_tmpfile(void)
863
/*========================*/
864
/* out: temporary file descriptor, or < 0 on error */
867
File fd = mysql_tmpfile("ib");
869
/* Copy the file descriptor, so that the additional resources
870
allocated by create_temp_file() can be freed by invoking
873
Because the file descriptor returned by this function
874
will be passed to fdopen(), it will be closed by invoking
875
fclose(), which in turn will invoke close() instead of
879
DBUG_PRINT("error",("Got error %d on dup",fd2));
881
my_error(EE_OUT_OF_FILERESOURCES,
882
MYF(ME_BELL+ME_WAITTANG),
885
my_close(fd, MYF(MY_WME));
890
/*************************************************************************
891
Wrapper around MySQL's copy_and_convert function, see it for
895
innobase_convert_string(
896
/*====================*/
902
CHARSET_INFO* from_cs,
905
return(copy_and_convert((char*)to, (uint32) to_length, to_cs,
906
(const char*)from, (uint32) from_length, from_cs,
910
/*************************************************************************
911
Gets the InnoDB transaction handle for a MySQL handler object, creates
912
an InnoDB transaction struct if the corresponding MySQL thread struct still
918
/* out: InnoDB transaction handle */
919
THD* thd) /* in: user thread handle */
921
trx_t*& trx = thd_to_trx(thd);
923
ut_ad(thd == current_thd);
926
DBUG_ASSERT(thd != NULL);
927
trx = trx_allocate_for_mysql();
929
trx->mysql_thd = thd;
930
trx->mysql_query_str = thd_query(thd);
932
/* Update the info whether we should skip XA steps that eat
934
trx->support_xa = THDVAR(thd, support_xa);
936
if (trx->magic_n != TRX_MAGIC_N) {
937
mem_analyze_corruption(trx);
943
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
944
trx->check_foreigns = FALSE;
946
trx->check_foreigns = TRUE;
949
if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
950
trx->check_unique_secondary = FALSE;
952
trx->check_unique_secondary = TRUE;
959
/*************************************************************************
960
Construct ha_innobase handler. */
962
ha_innobase::ha_innobase(handlerton *hton, TABLE_SHARE *table_arg)
963
:handler(hton, table_arg),
964
int_table_flags(HA_REC_NOT_IN_SEQ |
968
HA_PRIMARY_KEY_REQUIRED_FOR_POSITION |
969
HA_PRIMARY_KEY_IN_READ_INDEX |
970
HA_BINLOG_ROW_CAPABLE |
971
HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ |
972
HA_TABLE_SCAN_ON_INDEX | HA_NEED_READ_RANGE_BUFFER |
974
primary_key(0), /* needs initialization because index_flags() may be called
975
before this is set to the real value. It's ok to have any
976
value here because it doesn't matter if we return the
977
HA_DO_INDEX_COND_PUSHDOWN bit from those "early" calls */
981
// ds_mrr.init(this, table, (DsMrr_impl::range_check_toggle_func_t)
982
// &ha_innobase::toggle_range_check);
985
/*************************************************************************
986
Updates the user_thd field in a handle and also allocates a new InnoDB
987
transaction handle if needed, and updates the transaction fields in the
991
ha_innobase::update_thd(
992
/*====================*/
993
/* out: 0 or error code */
994
THD* thd) /* in: thd to use the handle */
998
trx = check_trx_exists(thd);
1000
if (prebuilt->trx != trx) {
1002
row_update_prebuilt_trx(prebuilt, trx);
1010
/*************************************************************************
1011
Registers that InnoDB takes part in an SQL statement, so that MySQL knows to
1012
roll back the statement if the statement results in an error. This MUST be
1013
called for every SQL statement that may be rolled back by MySQL. Calling this
1014
several times to register the same statement is allowed, too. */
1017
innobase_register_stmt(
1018
/*===================*/
1019
handlerton* hton, /* in: Innobase hton */
1020
THD* thd) /* in: MySQL thd (connection) object */
1022
/* Register the statement */
1023
trans_register_ha(thd, FALSE, hton);
1026
/*************************************************************************
1027
Registers an InnoDB transaction in MySQL, so that the MySQL XA code knows
1028
to call the InnoDB prepare and commit, or rollback for the transaction. This
1029
MUST be called for every transaction for which the user may call commit or
1030
rollback. Calling this several times to register the same transaction is
1032
This function also registers the current SQL statement. */
1035
innobase_register_trx_and_stmt(
1036
/*===========================*/
1037
handlerton *hton, /* in: Innobase handlerton */
1038
THD* thd) /* in: MySQL thd (connection) object */
1040
/* NOTE that actually innobase_register_stmt() registers also
1041
the transaction in the AUTOCOMMIT=1 mode. */
1043
innobase_register_stmt(hton, thd);
1045
if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
1047
/* No autocommit mode, register for a transaction */
1048
trans_register_ha(thd, TRUE, hton);
1052
/* BACKGROUND INFO: HOW THE MYSQL QUERY CACHE WORKS WITH INNODB
1053
------------------------------------------------------------
1055
1) The use of the query cache for TBL is disabled when there is an
1056
uncommitted change to TBL.
1058
2) When a change to TBL commits, InnoDB stores the current value of
1059
its global trx id counter, let us denote it by INV_TRX_ID, to the table object
1060
in the InnoDB data dictionary, and does only allow such transactions whose
1061
id <= INV_TRX_ID to use the query cache.
1063
3) When InnoDB does an INSERT/DELETE/UPDATE to a table TBL, or an implicit
1064
modification because an ON DELETE CASCADE, we invalidate the MySQL query cache
1067
How this is implemented inside InnoDB:
1069
1) Since every modification always sets an IX type table lock on the InnoDB
1070
table, it is easy to check if there can be uncommitted modifications for a
1071
table: just check if there are locks in the lock list of the table.
1073
2) When a transaction inside InnoDB commits, it reads the global trx id
1074
counter and stores the value INV_TRX_ID to the tables on which it had a lock.
1076
3) If there is an implicit table change from ON DELETE CASCADE or SET NULL,
1077
InnoDB calls an invalidate method for the MySQL query cache for that table.
1079
How this is implemented inside sql_cache.cc:
1081
1) The query cache for an InnoDB table TBL is invalidated immediately at an
1082
INSERT/UPDATE/DELETE, just like in the case of MyISAM. No need to delay
1083
invalidation to the transaction commit.
1085
2) To store or retrieve a value from the query cache of an InnoDB table TBL,
1086
any query must first ask InnoDB's permission. We must pass the thd as a
1087
parameter because InnoDB will look at the trx id, if any, associated with
1090
3) Use of the query cache for InnoDB tables is now allowed also when
1091
AUTOCOMMIT==0 or we are inside BEGIN ... COMMIT. Thus transactions no longer
1092
put restrictions on the use of the query cache.
1095
/**********************************************************************
1096
The MySQL query cache uses this to check from InnoDB if the query cache at
1097
the moment is allowed to operate on an InnoDB table. The SQL query must
1098
be a non-locking SELECT.
1100
The query cache is allowed to operate on certain query only if this function
1101
returns TRUE for all tables in the query.
1103
If thd is not in the autocommit state, this function also starts a new
1104
transaction for thd if there is no active trx yet, and assigns a consistent
1105
read view to it if there is no read view yet.
1107
Why a deadlock of threads is not possible: the query cache calls this function
1108
at the start of a SELECT processing. Then the calling thread cannot be
1109
holding any InnoDB semaphores. The calling thread is holding the
1110
query cache mutex, and this function will reserver the InnoDB kernel mutex.
1111
Thus, the 'rank' in sync0sync.h of the MySQL query cache mutex is above
1112
the InnoDB kernel mutex. */
1115
innobase_query_caching_of_table_permitted(
1116
/*======================================*/
1117
/* out: TRUE if permitted, FALSE if not;
1118
note that the value FALSE does not mean
1119
we should invalidate the query cache:
1120
invalidation is called explicitly */
1121
THD* thd, /* in: thd of the user who is trying to
1122
store a result to the query cache or
1124
char* full_name, /* in: concatenation of database name,
1125
the null character '\0', and the table
1127
uint full_name_len, /* in: length of the full name, i.e.
1128
len(dbname) + len(tablename) + 1 */
1129
ulonglong *unused) /* unused for this engine */
1131
ibool is_autocommit;
1133
char norm_name[1000];
1135
ut_a(full_name_len < 999);
1137
trx = check_trx_exists(thd);
1139
if (trx->isolation_level == TRX_ISO_SERIALIZABLE) {
1140
/* In the SERIALIZABLE mode we add LOCK IN SHARE MODE to every
1141
plain SELECT if AUTOCOMMIT is not on. */
1143
return((my_bool)FALSE);
1146
if (trx->has_search_latch) {
1147
sql_print_error("The calling thread is holding the adaptive "
1148
"search, latch though calling "
1149
"innobase_query_caching_of_table_permitted.");
1151
mutex_enter_noninline(&kernel_mutex);
1152
trx_print(stderr, trx, 1024);
1153
mutex_exit_noninline(&kernel_mutex);
1156
innobase_release_stat_resources(trx);
1158
if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
1160
is_autocommit = TRUE;
1162
is_autocommit = FALSE;
1166
if (is_autocommit && trx->n_mysql_tables_in_use == 0) {
1167
/* We are going to retrieve the query result from the query
1168
cache. This cannot be a store operation to the query cache
1169
because then MySQL would have locks on tables already.
1171
TODO: if the user has used LOCK TABLES to lock the table,
1172
then we open a transaction in the call of row_.. below.
1173
That trx can stay open until UNLOCK TABLES. The same problem
1174
exists even if we do not use the query cache. MySQL should be
1175
modified so that it ALWAYS calls some cleanup function when
1176
the processing of a query ends!
1178
We can imagine we instantaneously serialize this consistent
1179
read trx to the current trx id counter. If trx2 would have
1180
changed the tables of a query result stored in the cache, and
1181
trx2 would have already committed, making the result obsolete,
1182
then trx2 would have already invalidated the cache. Thus we
1183
can trust the result in the cache is ok for this query. */
1185
return((my_bool)TRUE);
1188
/* Normalize the table name to InnoDB format */
1190
memcpy(norm_name, full_name, full_name_len);
1192
norm_name[strlen(norm_name)] = '/'; /* InnoDB uses '/' as the
1193
separator between db and table */
1194
norm_name[full_name_len] = '\0';
1196
innobase_casedn_str(norm_name);
1198
/* The call of row_search_.. will start a new transaction if it is
1201
if (trx->active_trans == 0) {
1203
innobase_register_trx_and_stmt(innodb_hton_ptr, thd);
1204
trx->active_trans = 1;
1207
if (row_search_check_if_query_cache_permitted(trx, norm_name)) {
1209
/* printf("Query cache for %s permitted\n", norm_name); */
1211
return((my_bool)TRUE);
1214
/* printf("Query cache for %s NOT permitted\n", norm_name); */
1216
return((my_bool)FALSE);
1219
/*********************************************************************
1220
Invalidates the MySQL query cache for the table.
1221
NOTE that the exact prototype of this function has to be in
1222
/innobase/row/row0ins.c! */
1225
innobase_invalidate_query_cache(
1226
/*============================*/
1227
trx_t* trx, /* in: transaction which modifies the table */
1228
char* full_name, /* in: concatenation of database name, null
1229
char '\0', table name, null char'\0';
1230
NOTE that in Windows this is always
1232
ulint full_name_len) /* in: full name length where also the null
1235
/* Note that the sync0sync.h rank of the query cache mutex is just
1236
above the InnoDB kernel mutex. The caller of this function must not
1237
have latches of a lower rank. */
1239
/* Argument TRUE below means we are using transactions */
1240
#ifdef HAVE_QUERY_CACHE
1241
mysql_query_cache_invalidate4((THD*) trx->mysql_thd,
1242
(const char*) full_name,
1243
(uint32) full_name_len,
1248
/*********************************************************************
1249
Display an SQL identifier. */
1252
innobase_print_identifier(
1253
/*======================*/
1254
FILE* f, /* in: output stream */
1255
trx_t* trx, /* in: transaction */
1256
ibool table_id,/* in: TRUE=print a table name,
1257
FALSE=print other identifier */
1258
const char* name, /* in: name to print */
1259
ulint namelen)/* in: length of name */
1261
const char* s = name;
1266
/* Decode the table name. The filename_to_tablename()
1267
function expects a NUL-terminated string. The input and
1268
output strings buffers must not be shared. The function
1269
only produces more output when the name contains other
1270
characters than [0-9A-Z_a-z]. */
1271
char* temp_name = (char*) my_malloc((uint) namelen + 1, MYF(MY_WME));
1272
uint qnamelen = (uint) (namelen
1273
+ (1 + sizeof srv_mysql50_table_name_prefix));
1276
qname = (char*) my_malloc(qnamelen, MYF(MY_WME));
1278
memcpy(temp_name, name, namelen);
1279
temp_name[namelen] = 0;
1281
namelen = filename_to_tablename(temp_name,
1284
my_free(temp_name, MYF(0));
1288
if (!trx || !trx->mysql_thd) {
1292
q = get_quote_char_for_identifier((THD*) trx->mysql_thd,
1297
fwrite(s, 1, namelen, f);
1299
const char* e = s + namelen;
1311
my_free(qname, MYF(MY_ALLOW_ZERO_PTR));
1314
/**************************************************************************
1315
Determines if the currently running transaction has been interrupted. */
1320
/* out: TRUE if interrupted */
1321
trx_t* trx) /* in: transaction */
1323
return(trx && trx->mysql_thd && thd_killed((THD*) trx->mysql_thd));
1326
/******************************************************************
1327
Resets some fields of a prebuilt struct. The template is used in fast
1328
retrieval of just those column values MySQL needs in its processing. */
1333
row_prebuilt_t* prebuilt) /* in/out: prebuilt struct */
1335
prebuilt->keep_other_fields_on_keyread = 0;
1336
prebuilt->read_just_key = 0;
1339
/*********************************************************************
1340
Call this when you have opened a new table handle in HANDLER, before you
1341
call index_read_idx() etc. Actually, we can let the cursor stay open even
1342
over a transaction commit! Then you should call this before every operation,
1343
fetch next etc. This function inits the necessary things even after a
1344
transaction commit. */
1347
ha_innobase::init_table_handle_for_HANDLER(void)
1348
/*============================================*/
1350
/* If current thd does not yet have a trx struct, create one.
1351
If the current handle does not yet have a prebuilt struct, create
1352
one. Update the trx pointers in the prebuilt struct. Normally
1353
this operation is done in external_lock. */
1355
update_thd(ha_thd());
1357
/* Initialize the prebuilt struct much like it would be inited in
1360
innobase_release_stat_resources(prebuilt->trx);
1362
/* If the transaction is not started yet, start it */
1364
trx_start_if_not_started_noninline(prebuilt->trx);
1366
/* Assign a read view if the transaction does not have it yet */
1368
trx_assign_read_view(prebuilt->trx);
1370
/* Set the MySQL flag to mark that there is an active transaction */
1372
if (prebuilt->trx->active_trans == 0) {
1374
innobase_register_trx_and_stmt(ht, user_thd);
1376
prebuilt->trx->active_trans = 1;
1379
/* We did the necessary inits in this function, no need to repeat them
1380
in row_search_for_mysql */
1382
prebuilt->sql_stat_start = FALSE;
1384
/* We let HANDLER always to do the reads as consistent reads, even
1385
if the trx isolation level would have been specified as SERIALIZABLE */
1387
prebuilt->select_lock_type = LOCK_NONE;
1388
prebuilt->stored_select_lock_type = LOCK_NONE;
1390
/* Always fetch all columns in the index record */
1392
prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
1394
/* We want always to fetch all columns in the whole row? Or do
1397
prebuilt->used_in_HANDLER = TRUE;
1398
reset_template(prebuilt);
1401
/*************************************************************************
1402
Opens an InnoDB database. */
1407
/* out: 0 on success, error code on failure */
1408
void *p) /* in: InnoDB handlerton */
1410
static char current_dir[3]; /* Set if using current lib */
1415
DBUG_ENTER("innobase_init");
1416
handlerton *innobase_hton= (handlerton *)p;
1417
innodb_hton_ptr = innobase_hton;
1419
innobase_hton->state = SHOW_OPTION_YES;
1420
innobase_hton->db_type= DB_TYPE_INNODB;
1421
innobase_hton->savepoint_offset=sizeof(trx_named_savept_t);
1422
innobase_hton->close_connection=innobase_close_connection;
1423
innobase_hton->savepoint_set=innobase_savepoint;
1424
innobase_hton->savepoint_rollback=innobase_rollback_to_savepoint;
1425
innobase_hton->savepoint_release=innobase_release_savepoint;
1426
innobase_hton->commit=innobase_commit;
1427
innobase_hton->rollback=innobase_rollback;
1428
innobase_hton->prepare=innobase_xa_prepare;
1429
innobase_hton->recover=innobase_xa_recover;
1430
innobase_hton->commit_by_xid=innobase_commit_by_xid;
1431
innobase_hton->rollback_by_xid=innobase_rollback_by_xid;
1432
innobase_hton->create_cursor_read_view=innobase_create_cursor_view;
1433
innobase_hton->set_cursor_read_view=innobase_set_cursor_view;
1434
innobase_hton->close_cursor_read_view=innobase_close_cursor_view;
1435
innobase_hton->create=innobase_create_handler;
1436
innobase_hton->drop_database=innobase_drop_database;
1437
innobase_hton->panic=innobase_end;
1438
innobase_hton->start_consistent_snapshot=innobase_start_trx_and_assign_read_view;
1439
innobase_hton->flush_logs=innobase_flush_logs;
1440
innobase_hton->show_status=innobase_show_status;
1441
innobase_hton->flags=HTON_NO_FLAGS;
1442
innobase_hton->release_temporary_latches=innobase_release_temporary_latches;
1444
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
1447
static const char test_filename[] = "-@";
1448
char test_tablename[sizeof test_filename
1449
+ sizeof srv_mysql50_table_name_prefix];
1450
if ((sizeof test_tablename) - 1
1451
!= filename_to_tablename(test_filename, test_tablename,
1452
sizeof test_tablename)
1453
|| strncmp(test_tablename,
1454
srv_mysql50_table_name_prefix,
1455
sizeof srv_mysql50_table_name_prefix)
1456
|| strcmp(test_tablename
1457
+ sizeof srv_mysql50_table_name_prefix,
1459
sql_print_error("tablename encoding has been changed");
1462
#endif /* UNIV_DEBUG */
1464
/* Check that values don't overflow on 32-bit systems. */
1465
if (sizeof(ulint) == 4) {
1466
if (innobase_buffer_pool_size > UINT_MAX32) {
1468
"innobase_buffer_pool_size can't be over 4GB"
1469
" on 32-bit systems");
1474
if (innobase_log_file_size > UINT_MAX32) {
1476
"innobase_log_file_size can't be over 4GB"
1477
" on 32-bit systems");
1483
os_innodb_umask = (ulint)my_umask;
1485
/* First calculate the default path for innodb_data_home_dir etc.,
1486
in case the user has not given any value.
1488
Note that when using the embedded server, the datadirectory is not
1489
necessarily the current directory of this program. */
1491
if (mysqld_embedded) {
1492
default_path = mysql_real_data_home;
1493
fil_path_to_mysql_datadir = mysql_real_data_home;
1495
/* It's better to use current lib, to keep paths short */
1496
current_dir[0] = FN_CURLIB;
1497
current_dir[1] = FN_LIBCHAR;
1499
default_path = current_dir;
1504
if (specialflag & SPECIAL_NO_PRIOR) {
1505
srv_set_thread_priorities = FALSE;
1507
srv_set_thread_priorities = TRUE;
1508
srv_query_thread_priority = QUERY_PRIOR;
1511
/* Set InnoDB initialization parameters according to the values
1512
read from MySQL .cnf file */
1514
/*--------------- Data files -------------------------*/
1516
/* The default dir for data files is the datadir of MySQL */
1518
srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
1521
/* Set default InnoDB data file size to 10 MB and let it be
1522
auto-extending. Thus users can use InnoDB in >= 4.0 without having
1523
to specify any startup options. */
1525
if (!innobase_data_file_path) {
1526
innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
1529
/* Since InnoDB edits the argument in the next call, we make another
1532
internal_innobase_data_file_path = my_strdup(innobase_data_file_path,
1535
ret = (bool) srv_parse_data_file_paths_and_sizes(
1536
internal_innobase_data_file_path,
1537
&srv_data_file_names,
1538
&srv_data_file_sizes,
1539
&srv_data_file_is_raw_partition,
1541
&srv_auto_extend_last_data_file,
1542
&srv_last_file_size_max);
1545
"InnoDB: syntax error in innodb_data_file_path");
1546
my_free(internal_innobase_data_file_path,
1547
MYF(MY_ALLOW_ZERO_PTR));
1551
/* -------------- Log files ---------------------------*/
1553
/* The default dir for log files is the datadir of MySQL */
1555
if (!innobase_log_group_home_dir) {
1556
innobase_log_group_home_dir = default_path;
1559
#ifdef UNIV_LOG_ARCHIVE
1560
/* Since innodb_log_arch_dir has no relevance under MySQL,
1561
starting from 4.0.6 we always set it the same as
1562
innodb_log_group_home_dir: */
1564
innobase_log_arch_dir = innobase_log_group_home_dir;
1566
srv_arch_dir = innobase_log_arch_dir;
1567
#endif /* UNIG_LOG_ARCHIVE */
1570
srv_parse_log_group_home_dirs(innobase_log_group_home_dir,
1571
&srv_log_group_home_dirs);
1573
if (ret == FALSE || innobase_mirrored_log_groups != 1) {
1574
sql_print_error("syntax error in innodb_log_group_home_dir, or a "
1575
"wrong number of mirrored log groups");
1577
my_free(internal_innobase_data_file_path,
1578
MYF(MY_ALLOW_ZERO_PTR));
1582
/* --------------------------------------------------*/
1584
srv_file_flush_method_str = innobase_unix_file_flush_method;
1586
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
1587
srv_n_log_files = (ulint) innobase_log_files_in_group;
1588
srv_log_file_size = (ulint) innobase_log_file_size;
1590
#ifdef UNIV_LOG_ARCHIVE
1591
srv_log_archive_on = (ulint) innobase_log_archive;
1592
#endif /* UNIV_LOG_ARCHIVE */
1593
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
1595
/* We set srv_pool_size here in units of 1 kB. InnoDB internally
1596
changes the value so that it becomes the number of database pages. */
1598
if (innobase_buffer_pool_awe_mem_mb == 0) {
1599
srv_pool_size = (ulint)(innobase_buffer_pool_size / 1024);
1602
srv_pool_size = (ulint)
1603
(1024 * innobase_buffer_pool_awe_mem_mb);
1604
srv_awe_window_size = (ulint) innobase_buffer_pool_size;
1606
/* Note that what the user specified as
1607
innodb_buffer_pool_size is actually the AWE memory window
1608
size in this case, and the real buffer pool size is
1609
determined by .._awe_mem_mb. */
1612
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
1614
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
1616
srv_lock_wait_timeout = (ulint) innobase_lock_wait_timeout;
1617
srv_force_recovery = (ulint) innobase_force_recovery;
1619
srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
1620
srv_use_checksums = (ibool) innobase_use_checksums;
1622
#ifdef HAVE_LARGE_PAGES
1623
if ((os_use_large_pages = (ibool) my_use_large_pages))
1624
os_large_page_size = (ulint) opt_large_page_size;
1627
row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
1629
srv_file_per_table = (ibool) innobase_file_per_table;
1630
srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
1632
srv_max_n_open_files = (ulint) innobase_open_files;
1633
srv_innodb_status = (ibool) innobase_create_status_file;
1635
srv_stats_on_metadata = (ibool) innobase_stats_on_metadata;
1637
srv_use_adaptive_hash_indexes =
1638
(ibool) innobase_use_adaptive_hash_indexes;
1640
srv_print_verbose_log = mysqld_embedded ? 0 : 1;
1642
/* Store the default charset-collation number of this MySQL
1645
data_mysql_default_charset_coll = (ulint)default_charset_info->number;
1647
ut_a(DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL ==
1648
my_charset_latin1.number);
1649
ut_a(DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number);
1651
/* Store the latin1_swedish_ci character ordering table to InnoDB. For
1652
non-latin1_swedish_ci charsets we use the MySQL comparison functions,
1653
and consequently we do not need to know the ordering internally in
1656
ut_a(0 == strcmp((char*)my_charset_latin1.name,
1657
(char*)"latin1_swedish_ci"));
1658
memcpy(srv_latin1_ordering, my_charset_latin1.sort_order, 256);
1660
/* Since we in this module access directly the fields of a trx
1661
struct, and due to different headers and flags it might happen that
1662
mutex_t has a different size in this module and in InnoDB
1663
modules, we check at run time that the size is the same in
1664
these compilation modules. */
1666
srv_sizeof_trx_t_in_ha_innodb_cc = sizeof(trx_t);
1668
err = innobase_start_or_create_for_mysql();
1670
if (err != DB_SUCCESS) {
1671
my_free(internal_innobase_data_file_path,
1672
MYF(MY_ALLOW_ZERO_PTR));
1676
(void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0,
1677
(hash_get_key) innobase_get_key, 0, 0);
1678
pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
1679
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
1680
pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
1681
pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
1682
pthread_cond_init(&commit_cond, NULL);
1690
/***********************************************************************
1691
Closes an InnoDB database. */
1694
innobase_end(handlerton *hton, ha_panic_function type)
1696
/* out: TRUE if error */
1700
DBUG_ENTER("innobase_end");
1702
#ifdef __NETWARE__ /* some special cleanup for NetWare */
1704
set_panic_flag_for_netware();
1707
if (innodb_inited) {
1709
srv_fast_shutdown = (ulint) innobase_fast_shutdown;
1711
if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
1714
hash_free(&innobase_open_tables);
1715
my_free(internal_innobase_data_file_path,
1716
MYF(MY_ALLOW_ZERO_PTR));
1717
pthread_mutex_destroy(&innobase_share_mutex);
1718
pthread_mutex_destroy(&prepare_commit_mutex);
1719
pthread_mutex_destroy(&commit_threads_m);
1720
pthread_mutex_destroy(&commit_cond_m);
1721
pthread_cond_destroy(&commit_cond);
1727
/********************************************************************
1728
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
1729
the logs, and the name of this function should be innobase_checkpoint. */
1732
innobase_flush_logs(handlerton *hton)
1733
/*=====================*/
1734
/* out: TRUE if error */
1738
DBUG_ENTER("innobase_flush_logs");
1740
log_buffer_flush_to_disk();
1742
DBUG_RETURN(result);
1745
/*********************************************************************
1746
Commits a transaction in an InnoDB database. */
1749
innobase_commit_low(
1750
/*================*/
1751
trx_t* trx) /* in: transaction handle */
1753
if (trx->conc_state == TRX_NOT_STARTED) {
1758
trx_commit_for_mysql(trx);
1761
/*********************************************************************
1762
Creates an InnoDB transaction struct for the thd if it does not yet have one.
1763
Starts a new InnoDB transaction if a transaction is not yet started. And
1764
assigns a new snapshot for a consistent read if the transaction does not yet
1768
innobase_start_trx_and_assign_read_view(
1769
/*====================================*/
1771
handlerton *hton, /* in: Innodb handlerton */
1772
THD* thd) /* in: MySQL thread handle of the user for whom
1773
the transaction should be committed */
1777
DBUG_ENTER("innobase_start_trx_and_assign_read_view");
1779
/* Create a new trx struct for thd, if it does not yet have one */
1781
trx = check_trx_exists(thd);
1783
/* This is just to play safe: release a possible FIFO ticket and
1784
search latch. Since we will reserve the kernel mutex, we have to
1785
release the search system latch first to obey the latching order. */
1787
innobase_release_stat_resources(trx);
1789
/* If the transaction is not started yet, start it */
1791
trx_start_if_not_started_noninline(trx);
1793
/* Assign a read view if the transaction does not have it yet */
1795
trx_assign_read_view(trx);
1797
/* Set the MySQL flag to mark that there is an active transaction */
1799
if (trx->active_trans == 0) {
1800
innobase_register_trx_and_stmt(hton, current_thd);
1801
trx->active_trans = 1;
1807
/*********************************************************************
1808
Commits a transaction in an InnoDB database or marks an SQL statement
1815
handlerton *hton, /* in: Innodb handlerton */
1816
THD* thd, /* in: MySQL thread handle of the user for whom
1817
the transaction should be committed */
1818
bool all) /* in: TRUE - commit transaction
1819
FALSE - the current SQL statement ended */
1823
DBUG_ENTER("innobase_commit");
1824
DBUG_PRINT("trans", ("ending transaction"));
1826
trx = check_trx_exists(thd);
1828
/* Update the info whether we should skip XA steps that eat CPU time */
1829
trx->support_xa = THDVAR(thd, support_xa);
1831
/* Since we will reserve the kernel mutex, we have to release
1832
the search system latch first to obey the latching order. */
1834
if (trx->has_search_latch) {
1835
trx_search_latch_release_if_reserved(trx);
1838
/* The flag trx->active_trans is set to 1 in
1840
1. ::external_lock(),
1842
3. innobase_query_caching_of_table_permitted(),
1843
4. innobase_savepoint(),
1844
5. ::init_table_handle_for_HANDLER(),
1845
6. innobase_start_trx_and_assign_read_view(),
1846
7. ::transactional_table_lock()
1848
and it is only set to 0 in a commit or a rollback. If it is 0 we know
1849
there cannot be resources to be freed and we could return immediately.
1850
For the time being, we play safe and do the cleanup though there should
1851
be nothing to clean up. */
1853
if (trx->active_trans == 0
1854
&& trx->conc_state != TRX_NOT_STARTED) {
1856
sql_print_error("trx->active_trans == 0, but"
1857
" trx->conc_state != TRX_NOT_STARTED");
1860
|| (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
1862
/* We were instructed to commit the whole transaction, or
1863
this is an SQL statement end and autocommit is on */
1865
/* We need current binlog position for ibbackup to work.
1866
Note, the position is current because of
1867
prepare_commit_mutex */
1869
if (srv_commit_concurrency > 0) {
1870
pthread_mutex_lock(&commit_cond_m);
1873
if (commit_threads > srv_commit_concurrency) {
1875
pthread_cond_wait(&commit_cond,
1877
pthread_mutex_unlock(&commit_cond_m);
1881
pthread_mutex_unlock(&commit_cond_m);
1885
trx->mysql_log_file_name = mysql_bin_log_file_name();
1886
trx->mysql_log_offset = (ib_longlong) mysql_bin_log_file_pos();
1888
innobase_commit_low(trx);
1890
if (srv_commit_concurrency > 0) {
1891
pthread_mutex_lock(&commit_cond_m);
1893
pthread_cond_signal(&commit_cond);
1894
pthread_mutex_unlock(&commit_cond_m);
1897
if (trx->active_trans == 2) {
1899
pthread_mutex_unlock(&prepare_commit_mutex);
1902
trx->active_trans = 0;
1905
/* We just mark the SQL statement ended and do not do a
1906
transaction commit */
1908
/* If we had reserved the auto-inc lock for some
1909
table in this SQL statement we release it now */
1911
row_unlock_table_autoinc_for_mysql(trx);
1913
/* Store the current undo_no of the transaction so that we
1914
know where to roll back if we have to roll back the next
1917
trx_mark_sql_stat_end(trx);
1920
trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
1922
if (trx->declared_to_be_inside_innodb) {
1923
/* Release our possible ticket in the FIFO */
1925
srv_conc_force_exit_innodb(trx);
1928
/* Tell the InnoDB server that there might be work for utility
1930
srv_active_wake_master_thread();
1935
/*********************************************************************
1936
Rolls back a transaction or the latest SQL statement. */
1941
/* out: 0 or error number */
1942
handlerton *hton, /* in: Innodb handlerton */
1943
THD* thd, /* in: handle to the MySQL thread of the user
1944
whose transaction should be rolled back */
1945
bool all) /* in: TRUE - commit transaction
1946
FALSE - the current SQL statement ended */
1951
DBUG_ENTER("innobase_rollback");
1952
DBUG_PRINT("trans", ("aborting transaction"));
1954
trx = check_trx_exists(thd);
1956
/* Update the info whether we should skip XA steps that eat CPU time */
1957
trx->support_xa = THDVAR(thd, support_xa);
1959
/* Release a possible FIFO ticket and search latch. Since we will
1960
reserve the kernel mutex, we have to release the search system latch
1961
first to obey the latching order. */
1963
innobase_release_stat_resources(trx);
1965
/* If we had reserved the auto-inc lock for some table (if
1966
we come here to roll back the latest SQL statement) we
1967
release it now before a possibly lengthy rollback */
1969
row_unlock_table_autoinc_for_mysql(trx);
1972
|| !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
1974
error = trx_rollback_for_mysql(trx);
1975
trx->active_trans = 0;
1977
error = trx_rollback_last_sql_stat_for_mysql(trx);
1980
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
1983
/*********************************************************************
1984
Rolls back a transaction */
1987
innobase_rollback_trx(
1988
/*==================*/
1989
/* out: 0 or error number */
1990
trx_t* trx) /* in: transaction */
1994
DBUG_ENTER("innobase_rollback_trx");
1995
DBUG_PRINT("trans", ("aborting transaction"));
1997
/* Release a possible FIFO ticket and search latch. Since we will
1998
reserve the kernel mutex, we have to release the search system latch
1999
first to obey the latching order. */
2001
innobase_release_stat_resources(trx);
2003
/* If we had reserved the auto-inc lock for some table (if
2004
we come here to roll back the latest SQL statement) we
2005
release it now before a possibly lengthy rollback */
2007
row_unlock_table_autoinc_for_mysql(trx);
2009
error = trx_rollback_for_mysql(trx);
2011
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
2014
/*********************************************************************
2015
Rolls back a transaction to a savepoint. */
2018
innobase_rollback_to_savepoint(
2019
/*===========================*/
2020
/* out: 0 if success, HA_ERR_NO_SAVEPOINT if
2021
no savepoint with the given name */
2022
handlerton *hton, /* in: Innodb handlerton */
2023
THD* thd, /* in: handle to the MySQL thread of the user
2024
whose transaction should be rolled back */
2025
void* savepoint) /* in: savepoint data */
2027
ib_longlong mysql_binlog_cache_pos;
2032
DBUG_ENTER("innobase_rollback_to_savepoint");
2034
trx = check_trx_exists(thd);
2036
/* Release a possible FIFO ticket and search latch. Since we will
2037
reserve the kernel mutex, we have to release the search system latch
2038
first to obey the latching order. */
2040
innobase_release_stat_resources(trx);
2042
/* TODO: use provided savepoint data area to store savepoint data */
2044
longlong2str((ulint)savepoint, name, 36);
2046
error = (int) trx_rollback_to_savepoint_for_mysql(trx, name,
2047
&mysql_binlog_cache_pos);
2048
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
2051
/*********************************************************************
2052
Release transaction savepoint name. */
2055
innobase_release_savepoint(
2056
/*=======================*/
2057
/* out: 0 if success, HA_ERR_NO_SAVEPOINT if
2058
no savepoint with the given name */
2059
handlerton* hton, /* in: handlerton for Innodb */
2060
THD* thd, /* in: handle to the MySQL thread of the user
2061
whose transaction should be rolled back */
2062
void* savepoint) /* in: savepoint data */
2068
DBUG_ENTER("innobase_release_savepoint");
2070
trx = check_trx_exists(thd);
2072
/* TODO: use provided savepoint data area to store savepoint data */
2074
longlong2str((ulint)savepoint, name, 36);
2076
error = (int) trx_release_savepoint_for_mysql(trx, name);
2078
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
2081
/*********************************************************************
2082
Sets a transaction savepoint. */
2087
/* out: always 0, that is, always succeeds */
2088
handlerton* hton, /* in: handle to the Innodb handlerton */
2089
THD* thd, /* in: handle to the MySQL thread */
2090
void* savepoint) /* in: savepoint data */
2095
DBUG_ENTER("innobase_savepoint");
2098
In the autocommit mode there is no sense to set a savepoint
2099
(unless we are in sub-statement), so SQL layer ensures that
2100
this method is never called in such situation.
2102
#ifdef MYSQL_SERVER /* plugins cannot access thd->in_sub_stmt */
2103
DBUG_ASSERT(thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ||
2105
#endif /* MYSQL_SERVER */
2107
trx = check_trx_exists(thd);
2109
/* Release a possible FIFO ticket and search latch. Since we will
2110
reserve the kernel mutex, we have to release the search system latch
2111
first to obey the latching order. */
2113
innobase_release_stat_resources(trx);
2115
/* cannot happen outside of transaction */
2116
DBUG_ASSERT(trx->active_trans);
2118
/* TODO: use provided savepoint data area to store savepoint data */
2120
longlong2str((ulint)savepoint,name,36);
2122
error = (int) trx_savepoint_for_mysql(trx, name, (ib_longlong)0);
2124
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
2127
/*********************************************************************
2128
Frees a possible InnoDB trx object associated with the current THD. */
2131
innobase_close_connection(
2132
/*======================*/
2133
/* out: 0 or error number */
2134
handlerton* hton, /* in: innobase handlerton */
2135
THD* thd) /* in: handle to the MySQL thread of the user
2136
whose resources should be free'd */
2140
DBUG_ENTER("innobase_close_connection");
2141
DBUG_ASSERT(hton == innodb_hton_ptr);
2142
trx = thd_to_trx(thd);
2146
if (trx->active_trans == 0
2147
&& trx->conc_state != TRX_NOT_STARTED) {
2149
sql_print_error("trx->active_trans == 0, but"
2150
" trx->conc_state != TRX_NOT_STARTED");
2154
if (trx->conc_state != TRX_NOT_STARTED &&
2155
global_system_variables.log_warnings) {
2157
"MySQL is closing a connection that has an active "
2158
"InnoDB transaction. %lu row modifications will "
2160
(ulong) trx->undo_no.low);
2163
innobase_rollback_trx(trx);
2165
thr_local_free(trx->mysql_thread_id);
2166
trx_free_for_mysql(trx);
2172
/*****************************************************************************
2173
** InnoDB database tables
2174
*****************************************************************************/
2176
/********************************************************************
2177
Get the record format from the data dictionary. */
2179
ha_innobase::get_row_type() const
2180
/*=============================*/
2181
/* out: ROW_TYPE_REDUNDANT or ROW_TYPE_COMPACT */
2183
if (prebuilt && prebuilt->table) {
2184
if (dict_table_is_comp_noninline(prebuilt->table)) {
2185
return(ROW_TYPE_COMPACT);
2187
return(ROW_TYPE_REDUNDANT);
2191
return(ROW_TYPE_NOT_USED);
2196
/********************************************************************
2197
Get the table flags to use for the statement. */
2198
handler::Table_flags
2199
ha_innobase::table_flags() const
2201
/* Need to use tx_isolation here since table flags is (also)
2202
called before prebuilt is inited. */
2203
ulong const tx_isolation = thd_tx_isolation(current_thd);
2204
if (tx_isolation <= ISO_READ_COMMITTED)
2205
return int_table_flags;
2206
return int_table_flags | HA_BINLOG_STMT_CAPABLE;
2209
/********************************************************************
2210
Gives the file extension of an InnoDB single-table tablespace. */
2211
static const char* ha_innobase_exts[] = {
2217
ha_innobase::bas_ext() const
2218
/*========================*/
2219
/* out: file extension string */
2221
return ha_innobase_exts;
2225
/*********************************************************************
2226
Normalizes a table name string. A normalized name consists of the
2227
database name catenated to '/' and table name. An example:
2228
test/mytable. On Windows normalization puts both the database name and the
2229
table name always to lower case. */
2232
normalize_table_name(
2233
/*=================*/
2234
char* norm_name, /* out: normalized name as a
2235
null-terminated string */
2236
const char* name) /* in: table name string */
2242
/* Scan name from the end */
2244
ptr = strend(name)-1;
2246
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2252
DBUG_ASSERT(ptr > name);
2256
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2262
memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
2264
norm_name[name_ptr - db_ptr - 1] = '/';
2267
innobase_casedn_str(norm_name);
2271
/*********************************************************************
2272
Creates and opens a handle to a table which already exists in an InnoDB
2278
/* out: 1 if error, 0 if success */
2279
const char* name, /* in: table name */
2280
int mode, /* in: not used */
2281
uint test_if_locked) /* in: not used */
2283
dict_table_t* ib_table;
2284
char norm_name[1000];
2287
DBUG_ENTER("ha_innobase::open");
2290
UT_NOT_USED(test_if_locked);
2293
normalize_table_name(norm_name, name);
2297
if (!(share=get_share(name))) {
2302
/* Create buffers for packing the fields of a record. Why
2303
table->reclength did not work here? Obviously, because char
2304
fields when packed actually became 1 byte longer, when we also
2305
stored the string length as the first byte. */
2307
upd_and_key_val_buff_len =
2308
table->s->reclength + table->s->max_key_length
2309
+ MAX_REF_PARTS * 3;
2310
if (!(uchar*) my_multi_malloc(MYF(MY_WME),
2311
&upd_buff, upd_and_key_val_buff_len,
2312
&key_val_buff, upd_and_key_val_buff_len,
2319
/* Get pointer to a table object in InnoDB dictionary cache */
2321
ib_table = dict_table_get(norm_name, TRUE);
2323
if (NULL == ib_table) {
2324
sql_print_error("Cannot find or open table %s from\n"
2325
"the internal data dictionary of InnoDB "
2326
"though the .frm file for the\n"
2327
"table exists. Maybe you have deleted and "
2328
"recreated InnoDB data\n"
2329
"files but have forgotten to delete the "
2330
"corresponding .frm files\n"
2331
"of InnoDB tables, or you have moved .frm "
2332
"files to another database?\n"
2333
"or, the table contains indexes that this "
2334
"version of the engine\n"
2335
"doesn't support.\n"
2336
"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
2337
"how you can resolve the problem.\n",
2340
my_free(upd_buff, MYF(0));
2343
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
2346
if (ib_table->ibd_file_missing && !thd_tablespace_op(thd)) {
2347
sql_print_error("MySQL is trying to open a table handle but "
2348
"the .ibd file for\ntable %s does not exist.\n"
2349
"Have you deleted the .ibd file from the "
2350
"database directory under\nthe MySQL datadir, "
2351
"or have you used DISCARD TABLESPACE?\n"
2352
"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
2353
"how you can resolve the problem.\n",
2356
my_free(upd_buff, MYF(0));
2359
dict_table_decrement_handle_count(ib_table);
2360
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
2363
prebuilt = row_create_prebuilt(ib_table);
2365
prebuilt->mysql_row_len = table->s->reclength;
2366
prebuilt->idx_cond_func= NULL;
2368
/* Looks like MySQL-3.23 sometimes has primary key number != 0 */
2370
primary_key = table->s->primary_key;
2371
key_used_on_scan = primary_key;
2373
/* Allocate a buffer for a 'row reference'. A row reference is
2374
a string of bytes of length ref_length which uniquely specifies
2375
a row in our table. Note that MySQL may also compare two row
2376
references for equality by doing a simple memcmp on the strings
2377
of length ref_length! */
2379
if (!row_table_got_default_clust_index(ib_table)) {
2380
if (primary_key >= MAX_KEY) {
2381
sql_print_error("Table %s has a primary key in InnoDB data "
2382
"dictionary, but not in MySQL!", name);
2385
prebuilt->clust_index_was_generated = FALSE;
2387
/* MySQL allocates the buffer for ref. key_info->key_length
2388
includes space for all key columns + one byte for each column
2389
that may be NULL. ref_length must be as exact as possible to
2390
save space, because all row reference buffers are allocated
2391
based on ref_length. */
2393
ref_length = table->key_info[primary_key].key_length;
2395
if (primary_key != MAX_KEY) {
2396
sql_print_error("Table %s has no primary key in InnoDB data "
2397
"dictionary, but has one in MySQL! If you "
2398
"created the table with a MySQL version < "
2399
"3.23.54 and did not define a primary key, "
2400
"but defined a unique key with all non-NULL "
2401
"columns, then MySQL internally treats that "
2402
"key as the primary key. You can fix this "
2403
"error by dump + DROP + CREATE + reimport "
2404
"of the table.", name);
2407
prebuilt->clust_index_was_generated = TRUE;
2409
ref_length = DATA_ROW_ID_LEN;
2411
/* If we automatically created the clustered index, then
2412
MySQL does not know about it, and MySQL must NOT be aware
2413
of the index used on scan, to make it avoid checking if we
2414
update the column of the index. That is why we assert below
2415
that key_used_on_scan is the undefined value MAX_KEY.
2416
The column is the row id in the automatical generation case,
2417
and it will never be updated anyway. */
2419
if (key_used_on_scan != MAX_KEY) {
2421
"Table %s key_used_on_scan is %lu even "
2422
"though there is no primary key inside "
2423
"InnoDB.", name, (ulong) key_used_on_scan);
2427
stats.block_size = 16 * 1024; /* Index block size in InnoDB: used by MySQL
2428
in query optimization */
2430
/* Init table lock structure */
2431
thr_lock_data_init(&share->lock,&lock,(void*) 0);
2433
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
2439
ha_innobase::max_supported_key_part_length() const
2441
return(DICT_MAX_INDEX_COL_LEN - 1);
2444
/**********************************************************************
2445
Closes a handle to an InnoDB table. */
2448
ha_innobase::close(void)
2449
/*====================*/
2454
DBUG_ENTER("ha_innobase::close");
2456
thd = current_thd; // avoid calling current_thd twice, it may be slow
2458
innobase_release_temporary_latches(ht, thd);
2461
row_prebuilt_free(prebuilt);
2463
my_free(upd_buff, MYF(0));
2466
/* Tell InnoDB server that there might be work for
2469
srv_active_wake_master_thread();
2474
/* The following accessor functions should really be inside MySQL code! */
2476
/******************************************************************
2477
Gets field offset for a field in a table. */
2483
TABLE* table, /* in: MySQL table object */
2484
Field* field) /* in: MySQL field object */
2486
return((uint) (field->ptr - table->record[0]));
2489
/******************************************************************
2490
Checks if a field in a record is SQL NULL. Uses the record format
2491
information in table to track the null bit in record. */
2494
field_in_record_is_null(
2495
/*====================*/
2496
/* out: 1 if NULL, 0 otherwise */
2497
TABLE* table, /* in: MySQL table object */
2498
Field* field, /* in: MySQL field object */
2499
char* record) /* in: a row in MySQL format */
2503
if (!field->null_ptr) {
2508
null_offset = (uint) ((char*) field->null_ptr
2509
- (char*) table->record[0]);
2511
if (record[null_offset] & field->null_bit) {
2519
/******************************************************************
2520
Sets a field in a record to SQL NULL. Uses the record format
2521
information in table to track the null bit in record. */
2524
set_field_in_record_to_null(
2525
/*========================*/
2526
TABLE* table, /* in: MySQL table object */
2527
Field* field, /* in: MySQL field object */
2528
char* record) /* in: a row in MySQL format */
2532
null_offset = (uint) ((char*) field->null_ptr
2533
- (char*) table->record[0]);
2535
record[null_offset] = record[null_offset] | field->null_bit;
2539
/*****************************************************************
2540
InnoDB uses this function to compare two data fields for which the data type
2541
is such that we must use MySQL code to compare them. NOTE that the prototype
2542
of this function is in rem0cmp.c in InnoDB source code! If you change this
2543
function, remember to update the prototype there! */
2548
/* out: 1, 0, -1, if a is greater,
2549
equal, less than b, respectively */
2550
int mysql_type, /* in: MySQL type */
2551
uint charset_number, /* in: number of the charset */
2552
unsigned char* a, /* in: data field */
2553
unsigned int a_length, /* in: data field length,
2554
not UNIV_SQL_NULL */
2555
unsigned char* b, /* in: data field */
2556
unsigned int b_length) /* in: data field length,
2557
not UNIV_SQL_NULL */
2559
CHARSET_INFO* charset;
2560
enum_field_types mysql_tp;
2563
DBUG_ASSERT(a_length != UNIV_SQL_NULL);
2564
DBUG_ASSERT(b_length != UNIV_SQL_NULL);
2566
mysql_tp = (enum_field_types) mysql_type;
2570
case MYSQL_TYPE_BIT:
2571
case MYSQL_TYPE_STRING:
2572
case MYSQL_TYPE_VAR_STRING:
2573
case MYSQL_TYPE_TINY_BLOB:
2574
case MYSQL_TYPE_MEDIUM_BLOB:
2575
case MYSQL_TYPE_BLOB:
2576
case MYSQL_TYPE_LONG_BLOB:
2577
case MYSQL_TYPE_VARCHAR:
2578
/* Use the charset number to pick the right charset struct for
2579
the comparison. Since the MySQL function get_charset may be
2580
slow before Bar removes the mutex operation there, we first
2581
look at 2 common charsets directly. */
2583
if (charset_number == default_charset_info->number) {
2584
charset = default_charset_info;
2585
} else if (charset_number == my_charset_latin1.number) {
2586
charset = &my_charset_latin1;
2588
charset = get_charset(charset_number, MYF(MY_WME));
2590
if (charset == NULL) {
2591
sql_print_error("InnoDB needs charset %lu for doing "
2592
"a comparison, but MySQL cannot "
2593
"find that charset.",
2594
(ulong) charset_number);
2599
/* Starting from 4.1.3, we use strnncollsp() in comparisons of
2600
non-latin1_swedish_ci strings. NOTE that the collation order
2601
changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users
2602
having indexes on such data need to rebuild their tables! */
2604
ret = charset->coll->strnncollsp(charset,
2609
} else if (ret > 0) {
2622
/******************************************************************
2623
Converts a MySQL type to an InnoDB type. Note that this function returns
2624
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
2625
VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'. */
2628
get_innobase_type_from_mysql_type(
2629
/*==============================*/
2630
/* out: DATA_BINARY, DATA_VARCHAR, ... */
2631
ulint* unsigned_flag, /* out: DATA_UNSIGNED if an 'unsigned type';
2632
at least ENUM and SET, and unsigned integer
2633
types are 'unsigned types' */
2634
Field* field) /* in: MySQL field */
2636
/* The following asserts try to check that the MySQL type code fits in
2637
8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
2640
DBUG_ASSERT((ulint)MYSQL_TYPE_STRING < 256);
2641
DBUG_ASSERT((ulint)MYSQL_TYPE_VAR_STRING < 256);
2642
DBUG_ASSERT((ulint)MYSQL_TYPE_DOUBLE < 256);
2643
DBUG_ASSERT((ulint)MYSQL_TYPE_FLOAT < 256);
2644
DBUG_ASSERT((ulint)MYSQL_TYPE_DECIMAL < 256);
2646
if (field->flags & UNSIGNED_FLAG) {
2648
*unsigned_flag = DATA_UNSIGNED;
2653
if (field->real_type() == MYSQL_TYPE_ENUM
2654
|| field->real_type() == MYSQL_TYPE_SET) {
2656
/* MySQL has field->type() a string type for these, but the
2657
data is actually internally stored as an unsigned integer
2660
*unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
2661
flag set to zero, even though
2662
internally this is an unsigned
2667
switch (field->type()) {
2668
/* NOTE that we only allow string types in DATA_MYSQL and
2670
case MYSQL_TYPE_VAR_STRING: /* old <= 4.1 VARCHAR */
2671
case MYSQL_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */
2672
if (field->binary()) {
2673
return(DATA_BINARY);
2675
field->charset()->name,
2676
"latin1_swedish_ci") == 0) {
2677
return(DATA_VARCHAR);
2679
return(DATA_VARMYSQL);
2681
case MYSQL_TYPE_BIT:
2682
case MYSQL_TYPE_STRING: if (field->binary()) {
2684
return(DATA_FIXBINARY);
2686
field->charset()->name,
2687
"latin1_swedish_ci") == 0) {
2692
case MYSQL_TYPE_NEWDECIMAL:
2693
return(DATA_FIXBINARY);
2694
case MYSQL_TYPE_LONG:
2695
case MYSQL_TYPE_LONGLONG:
2696
case MYSQL_TYPE_TINY:
2697
case MYSQL_TYPE_SHORT:
2698
case MYSQL_TYPE_INT24:
2699
case MYSQL_TYPE_DATE:
2700
case MYSQL_TYPE_DATETIME:
2701
case MYSQL_TYPE_YEAR:
2702
case MYSQL_TYPE_NEWDATE:
2703
case MYSQL_TYPE_TIME:
2704
case MYSQL_TYPE_TIMESTAMP:
2706
case MYSQL_TYPE_FLOAT:
2708
case MYSQL_TYPE_DOUBLE:
2709
return(DATA_DOUBLE);
2710
case MYSQL_TYPE_DECIMAL:
2711
return(DATA_DECIMAL);
2712
case MYSQL_TYPE_GEOMETRY:
2713
case MYSQL_TYPE_TINY_BLOB:
2714
case MYSQL_TYPE_MEDIUM_BLOB:
2715
case MYSQL_TYPE_BLOB:
2716
case MYSQL_TYPE_LONG_BLOB:
2725
/***********************************************************************
2726
Writes an unsigned integer value < 64k to 2 bytes, in the little-endian
2730
innobase_write_to_2_little_endian(
2731
/*==============================*/
2732
byte* buf, /* in: where to store */
2733
ulint val) /* in: value to write, must be < 64k */
2735
ut_a(val < 256 * 256);
2737
buf[0] = (byte)(val & 0xFF);
2738
buf[1] = (byte)(val / 256);
2741
/***********************************************************************
2742
Reads an unsigned integer value < 64k from 2 bytes, in the little-endian
2746
innobase_read_from_2_little_endian(
2747
/*===============================*/
2749
const uchar* buf) /* in: from where to read */
2751
return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
2754
/***********************************************************************
2755
Stores a key value for a row to a buffer. */
2758
ha_innobase::store_key_val_for_row(
2759
/*===============================*/
2760
/* out: key value length as stored in buff */
2761
uint keynr, /* in: key number */
2762
char* buff, /* in/out: buffer for the key value (in MySQL
2764
uint buff_len,/* in: buffer length */
2765
const uchar* record)/* in: row in MySQL format */
2767
KEY* key_info = table->key_info + keynr;
2768
KEY_PART_INFO* key_part = key_info->key_part;
2769
KEY_PART_INFO* end = key_part + key_info->key_parts;
2770
char* buff_start = buff;
2771
enum_field_types mysql_type;
2775
DBUG_ENTER("store_key_val_for_row");
2777
/* The format for storing a key field in MySQL is the following:
2779
1. If the column can be NULL, then in the first byte we put 1 if the
2780
field value is NULL, 0 otherwise.
2782
2. If the column is of a BLOB type (it must be a column prefix field
2783
in this case), then we put the length of the data in the field to the
2784
next 2 bytes, in the little-endian format. If the field is SQL NULL,
2785
then these 2 bytes are set to 0. Note that the length of data in the
2786
field is <= column prefix length.
2788
3. In a column prefix field, prefix_len next bytes are reserved for
2789
data. In a normal field the max field length next bytes are reserved
2790
for data. For a VARCHAR(n) the max field length is n. If the stored
2791
value is the SQL NULL then these data bytes are set to 0.
2793
4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
2794
in the MySQL row format, the length is stored in 1 or 2 bytes,
2795
depending on the maximum allowed length. But in the MySQL key value
2796
format, the length always takes 2 bytes.
2798
We have to zero-fill the buffer so that MySQL is able to use a
2799
simple memcmp to compare two key values to determine if they are
2800
equal. MySQL does this to compare contents of two 'ref' values. */
2802
bzero(buff, buff_len);
2804
for (; key_part != end; key_part++) {
2807
if (key_part->null_bit) {
2808
if (record[key_part->null_offset]
2809
& key_part->null_bit) {
2818
field = key_part->field;
2819
mysql_type = field->type();
2821
if (mysql_type == MYSQL_TYPE_VARCHAR) {
2822
/* >= 5.0.3 true VARCHAR */
2831
key_len = key_part->length;
2834
buff += key_len + 2;
2838
cs = field->charset();
2841
(((Field_varstring*)field)->length_bytes);
2843
data = row_mysql_read_true_varchar(&len,
2845
+ (ulint)get_field_offset(table, field)),
2850
/* For multi byte character sets we need to calculate
2851
the true length of the key */
2853
if (len > 0 && cs->mbmaxlen > 1) {
2854
true_len = (ulint) cs->cset->well_formed_len(cs,
2855
(const char *) data,
2856
(const char *) data + len,
2862
/* In a column prefix index, we may need to truncate
2863
the stored value: */
2865
if (true_len > key_len) {
2869
/* The length in a key value is always stored in 2
2872
row_mysql_store_true_var_len((byte*)buff, true_len, 2);
2875
memcpy(buff, data, true_len);
2877
/* Note that we always reserve the maximum possible
2878
length of the true VARCHAR in the key value, though
2879
only len first bytes after the 2 length bytes contain
2880
actual data. The rest of the space was reset to zero
2881
in the bzero() call above. */
2885
} else if (mysql_type == MYSQL_TYPE_TINY_BLOB
2886
|| mysql_type == MYSQL_TYPE_MEDIUM_BLOB
2887
|| mysql_type == MYSQL_TYPE_BLOB
2888
|| mysql_type == MYSQL_TYPE_LONG_BLOB) {
2897
ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
2899
key_len = key_part->length;
2902
buff += key_len + 2;
2907
cs = field->charset();
2909
blob_data = row_mysql_read_blob_ref(&blob_len,
2911
+ (ulint)get_field_offset(table, field)),
2912
(ulint) field->pack_length());
2914
true_len = blob_len;
2916
ut_a(get_field_offset(table, field)
2917
== key_part->offset);
2919
/* For multi byte character sets we need to calculate
2920
the true length of the key */
2922
if (blob_len > 0 && cs->mbmaxlen > 1) {
2923
true_len = (ulint) cs->cset->well_formed_len(cs,
2924
(const char *) blob_data,
2925
(const char *) blob_data
2932
/* All indexes on BLOB and TEXT are column prefix
2933
indexes, and we may need to truncate the data to be
2934
stored in the key value: */
2936
if (true_len > key_len) {
2940
/* MySQL reserves 2 bytes for the length and the
2941
storage of the number is little-endian */
2943
innobase_write_to_2_little_endian(
2944
(byte*)buff, true_len);
2947
memcpy(buff, blob_data, true_len);
2949
/* Note that we always reserve the maximum possible
2950
length of the BLOB prefix in the key value. */
2954
/* Here we handle all other data types except the
2955
true VARCHAR, BLOB and TEXT. Note that the column
2956
value we store may be also in a column prefix
2962
const uchar* src_start;
2964
enum_field_types real_type;
2966
key_len = key_part->length;
2974
src_start = record + key_part->offset;
2975
real_type = field->real_type();
2978
/* Character set for the field is defined only
2979
to fields whose type is string and real field
2980
type is not enum or set. For these fields check
2981
if character set is multi byte. */
2983
if (real_type != MYSQL_TYPE_ENUM
2984
&& real_type != MYSQL_TYPE_SET
2985
&& ( mysql_type == MYSQL_TYPE_VAR_STRING
2986
|| mysql_type == MYSQL_TYPE_STRING)) {
2988
cs = field->charset();
2990
/* For multi byte character sets we need to
2991
calculate the true length of the key */
2993
if (key_len > 0 && cs->mbmaxlen > 1) {
2996
cs->cset->well_formed_len(cs,
2997
(const char *)src_start,
2998
(const char *)src_start
3006
memcpy(buff, src_start, true_len);
3009
/* Pad the unused space with spaces. Note that no
3010
padding is ever needed for UCS-2 because in MySQL,
3011
all UCS2 characters are 2 bytes, as MySQL does not
3012
support surrogate pairs, which are needed to represent
3013
characters in the range U+10000 to U+10FFFF. */
3015
if (true_len < key_len) {
3016
ulint pad_len = key_len - true_len;
3017
memset(buff, ' ', pad_len);
3023
ut_a(buff <= buff_start + buff_len);
3025
DBUG_RETURN((uint)(buff - buff_start));
3028
/******************************************************************
3029
Builds a 'template' to the prebuilt struct. The template is used in fast
3030
retrieval of just those column values MySQL needs in its processing. */
3035
row_prebuilt_t* prebuilt, /* in/out: prebuilt struct */
3036
THD* thd, /* in: current user thread, used
3037
only if templ_type is
3038
ROW_MYSQL_REC_FIELDS */
3039
TABLE* table, /* in: MySQL table */
3040
ha_innobase* file, /* in: ha_innobase handler */
3041
uint templ_type) /* in: ROW_MYSQL_WHOLE_ROW or
3042
ROW_MYSQL_REC_FIELDS */
3044
dict_index_t* index;
3045
dict_index_t* clust_index;
3046
mysql_row_templ_t* templ;
3049
ulint n_requested_fields = 0;
3050
ibool fetch_all_in_key = FALSE;
3051
ibool fetch_primary_key_cols = FALSE;
3053
/* byte offset of the end of last requested column */
3054
ulint mysql_prefix_len = 0;
3055
ibool do_idx_cond_push= FALSE;
3056
ibool need_second_pass= FALSE;
3058
if (prebuilt->select_lock_type == LOCK_X) {
3059
/* We always retrieve the whole clustered index record if we
3060
use exclusive row level locks, for example, if the read is
3061
done in an UPDATE statement. */
3063
templ_type = ROW_MYSQL_WHOLE_ROW;
3066
if (templ_type == ROW_MYSQL_REC_FIELDS) {
3067
if (prebuilt->hint_need_to_fetch_extra_cols
3068
== ROW_RETRIEVE_ALL_COLS) {
3070
/* We know we must at least fetch all columns in the
3071
key, or all columns in the table */
3073
if (prebuilt->read_just_key) {
3074
/* MySQL has instructed us that it is enough
3075
to fetch the columns in the key; looks like
3076
MySQL can set this flag also when there is
3077
only a prefix of the column in the key: in
3078
that case we retrieve the whole column from
3079
the clustered index */
3081
fetch_all_in_key = TRUE;
3083
templ_type = ROW_MYSQL_WHOLE_ROW;
3085
} else if (prebuilt->hint_need_to_fetch_extra_cols
3086
== ROW_RETRIEVE_PRIMARY_KEY) {
3087
/* We must at least fetch all primary key cols. Note
3088
that if the clustered index was internally generated
3089
by InnoDB on the row id (no primary key was
3090
defined), then row_search_for_mysql() will always
3091
retrieve the row id to a special buffer in the
3094
fetch_primary_key_cols = TRUE;
3098
clust_index = dict_table_get_first_index_noninline(prebuilt->table);
3100
if (templ_type == ROW_MYSQL_REC_FIELDS) {
3101
index = prebuilt->index;
3103
index = clust_index;
3106
if (index == clust_index) {
3107
prebuilt->need_to_access_clustered = TRUE;
3109
prebuilt->need_to_access_clustered = FALSE;
3110
/* Below we check column by column if we need to access
3111
the clustered index */
3114
n_fields = (ulint)table->s->fields; /* number of columns */
3116
if (!prebuilt->mysql_template) {
3117
prebuilt->mysql_template = (mysql_row_templ_t*)
3118
mem_alloc_noninline(
3119
n_fields * sizeof(mysql_row_templ_t));
3122
prebuilt->template_type = templ_type;
3123
prebuilt->null_bitmap_len = table->s->null_bytes;
3125
prebuilt->templ_contains_blob = FALSE;
3129
Setup index condition pushdown (note: we don't need to check if
3130
this is a scan on primary key as that is checked in idx_cond_push)
3132
if (file->active_index == file->pushed_idx_cond_keyno &&
3133
file->active_index != MAX_KEY)
3134
do_idx_cond_push= need_second_pass= TRUE;
3137
Ok, now build an array of mysql_row_templ_struct structures.
3138
If index condition pushdown is used, the array is split into two
3139
parts: first go index fields, then go table fields.
3141
Note that in InnoDB, i is the column number. MySQL calls columns
3144
for (i = 0; i < n_fields; i++) {
3145
templ = prebuilt->mysql_template + n_requested_fields;
3146
field = table->field[i];
3148
if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
3149
/* Decide which columns we should fetch
3150
and which we can skip. */
3151
register const ibool index_contains_field =
3152
dict_index_contains_col_or_prefix(index, i);
3153
register const ibool index_covers_field =
3154
field->part_of_key.is_set(file->active_index);
3156
if (!index_contains_field && prebuilt->read_just_key) {
3157
/* If this is a 'key read', we do not need
3158
columns that are not in the key */
3163
if (index_contains_field && fetch_all_in_key) {
3164
/* This field is needed in the query */
3169
if (bitmap_is_set(table->read_set, i) ||
3170
bitmap_is_set(table->write_set, i)) {
3171
/* This field is needed in the query */
3176
if (fetch_primary_key_cols
3177
&& dict_table_col_in_clustered_key(
3179
/* This field is needed in the query */
3184
/* This field is not needed in the query, skip it */
3188
if (do_idx_cond_push &&
3189
((need_second_pass && !index_covers_field) ||
3190
(!need_second_pass && index_covers_field)))
3193
n_requested_fields++;
3197
if (index == clust_index) {
3198
templ->rec_field_no = dict_col_get_clust_pos_noninline(
3199
&index->table->cols[i], index);
3201
templ->rec_field_no = dict_index_get_nth_col_pos(
3205
if (templ->rec_field_no == ULINT_UNDEFINED) {
3206
prebuilt->need_to_access_clustered = TRUE;
3209
if (field->null_ptr) {
3210
templ->mysql_null_byte_offset =
3211
(ulint) ((char*) field->null_ptr
3212
- (char*) table->record[0]);
3214
templ->mysql_null_bit_mask = (ulint) field->null_bit;
3216
templ->mysql_null_bit_mask = 0;
3219
templ->mysql_col_offset = (ulint)
3220
get_field_offset(table, field);
3222
templ->mysql_col_len = (ulint) field->pack_length();
3223
if (mysql_prefix_len < templ->mysql_col_offset
3224
+ templ->mysql_col_len) {
3225
mysql_prefix_len = templ->mysql_col_offset
3226
+ templ->mysql_col_len;
3228
templ->type = index->table->cols[i].mtype;
3229
templ->mysql_type = (ulint)field->type();
3231
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
3232
templ->mysql_length_bytes = (ulint)
3233
(((Field_varstring*)field)->length_bytes);
3236
templ->charset = dtype_get_charset_coll_noninline(
3237
index->table->cols[i].prtype);
3238
templ->mbminlen = index->table->cols[i].mbminlen;
3239
templ->mbmaxlen = index->table->cols[i].mbmaxlen;
3240
templ->is_unsigned = index->table->cols[i].prtype
3242
if (templ->type == DATA_BLOB) {
3243
prebuilt->templ_contains_blob = TRUE;
3246
if (need_second_pass && (i+1 == n_fields))
3248
prebuilt->n_index_fields= n_requested_fields;
3249
need_second_pass= FALSE;
3250
i= (~(ulint)0); /* to start from 0 */
3254
prebuilt->n_template = n_requested_fields;
3255
prebuilt->mysql_prefix_len = mysql_prefix_len;
3257
if (do_idx_cond_push)
3259
prebuilt->idx_cond_func= index_cond_func_innodb;
3260
prebuilt->idx_cond_func_arg= file;
3264
prebuilt->idx_cond_func= NULL;
3265
prebuilt->n_index_fields= n_requested_fields;
3267
// file->in_range_read= FALSE;
3269
if (index != clust_index && prebuilt->need_to_access_clustered) {
3270
/* Change rec_field_no's to correspond to the clustered index
3272
for (i = do_idx_cond_push? prebuilt->n_index_fields : 0;
3273
i < n_requested_fields; i++) {
3274
templ = prebuilt->mysql_template + i;
3275
templ->rec_field_no = dict_col_get_clust_pos_noninline(
3276
&index->table->cols[templ->col_no],
3282
/************************************************************************
3283
This special handling is really to overcome the limitations of MySQL's
3284
binlogging. We need to eliminate the non-determinism that will arise in
3285
INSERT ... SELECT type of statements, since MySQL binlog only stores the
3286
min value of the autoinc interval. Once that is fixed we can get rid of
3287
the special lock handling.*/
3290
ha_innobase::innobase_autoinc_lock(void)
3291
/*====================================*/
3292
/* out: DB_SUCCESS if all OK else
3295
ulint error = DB_SUCCESS;
3297
switch (innobase_autoinc_lock_mode) {
3298
case AUTOINC_NO_LOCKING:
3299
/* Acquire only the AUTOINC mutex. */
3300
dict_table_autoinc_lock(prebuilt->table);
3303
case AUTOINC_NEW_STYLE_LOCKING:
3304
/* For simple (single/multi) row INSERTs, we fallback to the
3305
old style only if another transaction has already acquired
3306
the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
3307
etc. type of statement. */
3308
if (thd_sql_command(user_thd) == SQLCOM_INSERT) {
3309
dict_table_t* table = prebuilt->table;
3311
/* Acquire the AUTOINC mutex. */
3312
dict_table_autoinc_lock(table);
3314
/* We need to check that another transaction isn't
3315
already holding the AUTOINC lock on the table. */
3316
if (table->n_waiting_or_granted_auto_inc_locks) {
3317
/* Release the mutex to avoid deadlocks. */
3318
dict_table_autoinc_unlock(table);
3323
/* Fall through to old style locking. */
3325
case AUTOINC_OLD_STYLE_LOCKING:
3326
error = row_lock_table_autoinc_for_mysql(prebuilt);
3328
if (error == DB_SUCCESS) {
3330
/* Acquire the AUTOINC mutex. */
3331
dict_table_autoinc_lock(prebuilt->table);
3339
return(ulong(error));
3342
/************************************************************************
3343
Reset the autoinc value in the table.*/
3346
ha_innobase::innobase_reset_autoinc(
3347
/*================================*/
3348
/* out: DB_SUCCESS if all went well
3350
ulonglong autoinc) /* in: value to store */
3354
error = innobase_autoinc_lock();
3356
if (error == DB_SUCCESS) {
3358
dict_table_autoinc_initialize(prebuilt->table, autoinc);
3360
dict_table_autoinc_unlock(prebuilt->table);
3363
return(ulong(error));
3366
/************************************************************************
3367
Store the autoinc value in the table. The autoinc value is only set if
3368
it's greater than the existing autoinc value in the table.*/
3371
ha_innobase::innobase_set_max_autoinc(
3372
/*==================================*/
3373
/* out: DB_SUCCES if all went well
3375
ulonglong auto_inc) /* in: value to store */
3379
error = innobase_autoinc_lock();
3381
if (error == DB_SUCCESS) {
3383
dict_table_autoinc_update(prebuilt->table, auto_inc);
3385
dict_table_autoinc_unlock(prebuilt->table);
3388
return(ulong(error));
3391
/************************************************************************
3392
Stores a row in an InnoDB database, to the table specified in this
3396
ha_innobase::write_row(
3397
/*===================*/
3398
/* out: error code */
3399
uchar* record) /* in: a row in MySQL format */
3402
ibool auto_inc_used= FALSE;
3404
trx_t* trx = thd_to_trx(user_thd);
3406
DBUG_ENTER("ha_innobase::write_row");
3408
if (prebuilt->trx != trx) {
3409
sql_print_error("The transaction object for the table handle is at "
3410
"%p, but for the current thread it is at %p",
3411
prebuilt->trx, trx);
3413
fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
3414
ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
3416
"InnoDB: Dump of 200 bytes around ha_data: ",
3418
ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
3423
ha_statistic_increment(&SSV::ha_write_count);
3425
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
3426
table->timestamp_field->set_time();
3428
sql_command = thd_sql_command(user_thd);
3430
if ((sql_command == SQLCOM_ALTER_TABLE
3431
|| sql_command == SQLCOM_OPTIMIZE
3432
|| sql_command == SQLCOM_CREATE_INDEX
3433
|| sql_command == SQLCOM_DROP_INDEX)
3434
&& num_write_row >= 10000) {
3435
/* ALTER TABLE is COMMITted at every 10000 copied rows.
3436
The IX table lock for the original table has to be re-issued.
3437
As this method will be called on a temporary table where the
3438
contents of the original table is being copied to, it is
3439
a bit tricky to determine the source table. The cursor
3440
position in the source table need not be adjusted after the
3441
intermediate COMMIT, since writes by other transactions are
3442
being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
3444
dict_table_t* src_table;
3449
/* Commit the transaction. This will release the table
3450
locks, so they have to be acquired again. */
3452
/* Altering an InnoDB table */
3453
/* Get the source table. */
3454
src_table = lock_get_src_table(
3455
prebuilt->trx, prebuilt->table, &mode);
3458
/* Unknown situation: do not commit */
3460
ut_print_timestamp(stderr);
3462
" InnoDB: ALTER TABLE is holding lock"
3463
" on %lu tables!\n",
3464
prebuilt->trx->mysql_n_tables_locked);
3467
} else if (src_table == prebuilt->table) {
3468
/* Source table is not in InnoDB format:
3469
no need to re-acquire locks on it. */
3471
/* Altering to InnoDB format */
3472
innobase_commit(ht, user_thd, 1);
3473
/* Note that this transaction is still active. */
3474
prebuilt->trx->active_trans = 1;
3475
/* We will need an IX lock on the destination table. */
3476
prebuilt->sql_stat_start = TRUE;
3478
/* Ensure that there are no other table locks than
3479
LOCK_IX and LOCK_AUTO_INC on the destination table. */
3481
if (!lock_is_table_exclusive(prebuilt->table,
3486
/* Commit the transaction. This will release the table
3487
locks, so they have to be acquired again. */
3488
innobase_commit(ht, user_thd, 1);
3489
/* Note that this transaction is still active. */
3490
prebuilt->trx->active_trans = 1;
3491
/* Re-acquire the table lock on the source table. */
3492
row_lock_table_for_mysql(prebuilt, src_table, mode);
3493
/* We will need an IX lock on the destination table. */
3494
prebuilt->sql_stat_start = TRUE;
3500
/* This is the case where the table has an auto-increment column */
3501
if (table->next_number_field && record == table->record[0]) {
3503
if ((error = update_auto_increment())) {
3508
auto_inc_used = TRUE;
3511
if (prebuilt->mysql_template == NULL
3512
|| prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
3514
/* Build the template used in converting quickly between
3515
the two database formats */
3517
build_template(prebuilt, NULL, table,
3518
this, ROW_MYSQL_WHOLE_ROW);
3521
innodb_srv_conc_enter_innodb(prebuilt->trx);
3523
error = row_insert_for_mysql((byte*) record, prebuilt);
3525
/* Handle duplicate key errors */
3526
if (auto_inc_used) {
3530
/* Note the number of rows processed for this statement, used
3531
by get_auto_increment() to determine the number of AUTO-INC
3532
values to reserve. This is only useful for a mult-value INSERT
3533
and is a statement level counter.*/
3534
if (trx->n_autoinc_rows > 0) {
3535
--trx->n_autoinc_rows;
3538
/* Get the value that MySQL attempted to store in the table.*/
3539
auto_inc = table->next_number_field->val_int();
3542
case DB_DUPLICATE_KEY:
3544
/* A REPLACE command and LOAD DATA INFILE REPLACE
3545
handle a duplicate key error themselves, but we
3546
must update the autoinc counter if we are performing
3547
those statements. */
3549
switch (sql_command) {
3551
if ((trx->duplicates
3552
& (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
3554
goto set_max_autoinc;
3558
case SQLCOM_REPLACE:
3559
case SQLCOM_INSERT_SELECT:
3560
case SQLCOM_REPLACE_SELECT:
3561
goto set_max_autoinc;
3571
/* If the actual value inserted is greater than
3572
the upper limit of the interval, then we try and
3573
update the table upper limit. Note: last_value
3574
will be 0 if get_auto_increment() was not called.*/
3576
if (auto_inc > prebuilt->last_value) {
3578
ut_a(prebuilt->table->autoinc_increment > 0);
3579
auto_inc += prebuilt->table->autoinc_increment;
3581
err = innobase_set_max_autoinc(auto_inc);
3583
if (err != DB_SUCCESS) {
3591
innodb_srv_conc_exit_innodb(prebuilt->trx);
3593
error = convert_error_code_to_mysql(error, user_thd);
3596
innobase_active_small();
3601
/**************************************************************************
3602
Checks which fields have changed in a row and stores information
3603
of them to an update vector. */
3606
calc_row_difference(
3607
/*================*/
3608
/* out: error number or 0 */
3609
upd_t* uvect, /* in/out: update vector */
3610
uchar* old_row, /* in: old row in MySQL format */
3611
uchar* new_row, /* in: new row in MySQL format */
3612
struct st_table* table, /* in: table in MySQL data
3614
uchar* upd_buff, /* in: buffer to use */
3615
ulint buff_len, /* in: buffer length */
3616
row_prebuilt_t* prebuilt, /* in: InnoDB prebuilt struct */
3617
THD* thd) /* in: user thread */
3619
uchar* original_upd_buff = upd_buff;
3621
enum_field_types field_mysql_type;
3626
byte* new_mysql_row_col;
3630
upd_field_t* ufield;
3632
ulint n_changed = 0;
3634
dict_index_t* clust_index;
3637
n_fields = table->s->fields;
3638
clust_index = dict_table_get_first_index_noninline(prebuilt->table);
3640
/* We use upd_buff to convert changed fields */
3641
buf = (byte*) upd_buff;
3643
for (i = 0; i < n_fields; i++) {
3644
field = table->field[i];
3646
o_ptr = (byte*) old_row + get_field_offset(table, field);
3647
n_ptr = (byte*) new_row + get_field_offset(table, field);
3649
/* Use new_mysql_row_col and col_pack_len save the values */
3651
new_mysql_row_col = n_ptr;
3652
col_pack_len = field->pack_length();
3654
o_len = col_pack_len;
3655
n_len = col_pack_len;
3657
/* We use o_ptr and n_ptr to dig up the actual data for
3660
field_mysql_type = field->type();
3662
col_type = prebuilt->table->cols[i].mtype;
3667
o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
3668
n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
3675
if (field_mysql_type == MYSQL_TYPE_VARCHAR) {
3676
/* This is a >= 5.0.3 type true VARCHAR where
3677
the real payload data length is stored in
3680
o_ptr = row_mysql_read_true_varchar(
3683
(((Field_varstring*)field)->length_bytes));
3685
n_ptr = row_mysql_read_true_varchar(
3688
(((Field_varstring*)field)->length_bytes));
3696
if (field->null_ptr) {
3697
if (field_in_record_is_null(table, field,
3699
o_len = UNIV_SQL_NULL;
3702
if (field_in_record_is_null(table, field,
3704
n_len = UNIV_SQL_NULL;
3708
if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
3709
0 != memcmp(o_ptr, n_ptr, o_len))) {
3710
/* The field has changed */
3712
ufield = uvect->fields + n_changed;
3714
/* Let us use a dummy dfield to make the conversion
3715
from the MySQL column format to the InnoDB format */
3717
dict_col_copy_type_noninline(prebuilt->table->cols + i,
3720
if (n_len != UNIV_SQL_NULL) {
3721
buf = row_mysql_store_col_in_innobase_format(
3727
dict_table_is_comp_noninline(
3729
ufield->new_val.data = dfield.data;
3730
ufield->new_val.len = dfield.len;
3732
ufield->new_val.data = NULL;
3733
ufield->new_val.len = UNIV_SQL_NULL;
3737
ufield->field_no = dict_col_get_clust_pos_noninline(
3738
&prebuilt->table->cols[i], clust_index);
3743
uvect->n_fields = n_changed;
3744
uvect->info_bits = 0;
3746
ut_a(buf <= (byte*)original_upd_buff + buff_len);
3751
/**************************************************************************
3752
Updates a row given as a parameter to a new value. Note that we are given
3753
whole rows, not just the fields which are updated: this incurs some
3754
overhead for CPU when we check which fields are actually updated.
3755
TODO: currently InnoDB does not prevent the 'Halloween problem':
3756
in a searched update a single row can get updated several times
3757
if its index columns are updated! */
3760
ha_innobase::update_row(
3761
/*====================*/
3762
/* out: error number or 0 */
3763
const uchar* old_row, /* in: old row in MySQL format */
3764
uchar* new_row) /* in: new row in MySQL format */
3768
trx_t* trx = thd_to_trx(user_thd);
3770
DBUG_ENTER("ha_innobase::update_row");
3772
ut_a(prebuilt->trx == trx);
3774
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
3775
table->timestamp_field->set_time();
3777
if (prebuilt->upd_node) {
3778
uvect = prebuilt->upd_node->update;
3780
uvect = row_get_prebuilt_update_vector(prebuilt);
3783
/* Build an update vector from the modified fields in the rows
3784
(uses upd_buff of the handle) */
3786
calc_row_difference(uvect, (uchar*) old_row, new_row, table,
3787
upd_buff, (ulint)upd_and_key_val_buff_len,
3788
prebuilt, user_thd);
3790
/* This is not a delete */
3791
prebuilt->upd_node->is_delete = FALSE;
3793
assert(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
3795
innodb_srv_conc_enter_innodb(trx);
3797
error = row_update_for_mysql((byte*) old_row, prebuilt);
3799
/* We need to do some special AUTOINC handling for the following case:
3801
INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
3803
We need to use the AUTOINC counter that was actually used by
3804
MySQL in the UPDATE statement, which can be different from the
3805
value used in the INSERT statement.*/
3807
if (error == DB_SUCCESS
3808
&& table->next_number_field
3809
&& new_row == table->record[0]
3810
&& thd_sql_command(user_thd) == SQLCOM_INSERT
3811
&& (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
3812
== TRX_DUP_IGNORE) {
3816
auto_inc = table->next_number_field->val_int();
3818
if (auto_inc != 0) {
3819
auto_inc += prebuilt->table->autoinc_increment;
3821
error = innobase_set_max_autoinc(auto_inc);
3825
innodb_srv_conc_exit_innodb(trx);
3827
error = convert_error_code_to_mysql(error, user_thd);
3829
/* Tell InnoDB server that there might be work for
3832
innobase_active_small();
3837
/**************************************************************************
3838
Deletes a row given as the parameter. */
3841
ha_innobase::delete_row(
3842
/*====================*/
3843
/* out: error number or 0 */
3844
const uchar* record) /* in: a row in MySQL format */
3847
trx_t* trx = thd_to_trx(user_thd);
3849
DBUG_ENTER("ha_innobase::delete_row");
3851
ut_a(prebuilt->trx == trx);
3853
/* Only if the table has an AUTOINC column */
3854
if (table->found_next_number_field && record == table->record[0]) {
3855
ulonglong dummy = 0;
3857
/* First check whether the AUTOINC sub-system has been
3858
initialized using the AUTOINC mutex. If not then we
3859
do it the "proper" way, by acquiring the heavier locks. */
3860
dict_table_autoinc_lock(prebuilt->table);
3862
if (!prebuilt->table->autoinc_inited) {
3863
dict_table_autoinc_unlock(prebuilt->table);
3865
error = innobase_get_auto_increment(&dummy);
3867
if (error == DB_SUCCESS) {
3868
dict_table_autoinc_unlock(prebuilt->table);
3873
dict_table_autoinc_unlock(prebuilt->table);
3877
if (!prebuilt->upd_node) {
3878
row_get_prebuilt_update_vector(prebuilt);
3881
/* This is a delete */
3883
prebuilt->upd_node->is_delete = TRUE;
3885
innodb_srv_conc_enter_innodb(trx);
3887
error = row_update_for_mysql((byte*) record, prebuilt);
3889
innodb_srv_conc_exit_innodb(trx);
3892
error = convert_error_code_to_mysql(error, user_thd);
3894
/* Tell the InnoDB server that there might be work for
3897
innobase_active_small();
3902
/**************************************************************************
3903
Removes a new lock set on a row, if it was not read optimistically. This can
3904
be called after a row has been read in the processing of an UPDATE or a DELETE
3905
query, if the option innodb_locks_unsafe_for_binlog is set. */
3908
ha_innobase::unlock_row(void)
3909
/*=========================*/
3911
DBUG_ENTER("ha_innobase::unlock_row");
3913
/* Consistent read does not take any locks, thus there is
3914
nothing to unlock. */
3916
if (prebuilt->select_lock_type == LOCK_NONE) {
3920
switch (prebuilt->row_read_type) {
3921
case ROW_READ_WITH_LOCKS:
3922
if (!srv_locks_unsafe_for_binlog
3923
|| prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED) {
3927
case ROW_READ_TRY_SEMI_CONSISTENT:
3928
row_unlock_for_mysql(prebuilt, FALSE);
3930
case ROW_READ_DID_SEMI_CONSISTENT:
3931
prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
3938
/* See handler.h and row0mysql.h for docs on this function. */
3940
ha_innobase::was_semi_consistent_read(void)
3941
/*=======================================*/
3943
return(prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT);
3946
/* See handler.h and row0mysql.h for docs on this function. */
3948
ha_innobase::try_semi_consistent_read(bool yes)
3949
/*===========================================*/
3951
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
3953
/* Row read type is set to semi consistent read if this was
3954
requested by the MySQL and either innodb_locks_unsafe_for_binlog
3955
option is used or this session is using READ COMMITTED isolation
3959
&& (srv_locks_unsafe_for_binlog
3960
|| prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
3961
prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
3963
prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
3967
/**********************************************************************
3968
Initializes a handle to use an index. */
3971
ha_innobase::index_init(
3972
/*====================*/
3973
/* out: 0 or error number */
3974
uint keynr, /* in: key (index) number */
3975
bool sorted) /* in: 1 if result MUST be sorted according to index */
3978
DBUG_ENTER("index_init");
3980
error = change_active_index(keynr);
3985
/**********************************************************************
3986
Currently does nothing. */
3989
ha_innobase::index_end(void)
3990
/*========================*/
3993
DBUG_ENTER("index_end");
3994
active_index=MAX_KEY;
3995
in_range_check_pushed_down= FALSE;
3996
ds_mrr.dsmrr_close();
4000
/*************************************************************************
4001
Converts a search mode flag understood by MySQL to a flag understood
4005
convert_search_mode_to_innobase(
4006
/*============================*/
4007
enum ha_rkey_function find_flag)
4009
switch (find_flag) {
4010
case HA_READ_KEY_EXACT:
4011
/* this does not require the index to be UNIQUE */
4012
return(PAGE_CUR_GE);
4013
case HA_READ_KEY_OR_NEXT:
4014
return(PAGE_CUR_GE);
4015
case HA_READ_KEY_OR_PREV:
4016
return(PAGE_CUR_LE);
4017
case HA_READ_AFTER_KEY:
4019
case HA_READ_BEFORE_KEY:
4021
case HA_READ_PREFIX:
4022
return(PAGE_CUR_GE);
4023
case HA_READ_PREFIX_LAST:
4024
return(PAGE_CUR_LE);
4025
case HA_READ_PREFIX_LAST_OR_PREV:
4026
return(PAGE_CUR_LE);
4027
/* In MySQL-4.0 HA_READ_PREFIX and HA_READ_PREFIX_LAST always
4028
pass a complete-field prefix of a key value as the search
4029
tuple. I.e., it is not allowed that the last field would
4030
just contain n first bytes of the full field value.
4031
MySQL uses a 'padding' trick to convert LIKE 'abc%'
4032
type queries so that it can use as a search tuple
4033
a complete-field-prefix of a key value. Thus, the InnoDB
4034
search mode PAGE_CUR_LE_OR_EXTENDS is never used.
4035
TODO: when/if MySQL starts to use also partial-field
4036
prefixes, we have to deal with stripping of spaces
4037
and comparison of non-latin1 char type fields in
4038
innobase_mysql_cmp() to get PAGE_CUR_LE_OR_EXTENDS to
4040
case HA_READ_MBR_CONTAIN:
4041
case HA_READ_MBR_INTERSECT:
4042
case HA_READ_MBR_WITHIN:
4043
case HA_READ_MBR_DISJOINT:
4044
case HA_READ_MBR_EQUAL:
4045
my_error(ER_TABLE_CANT_HANDLE_SPKEYS, MYF(0));
4046
return(PAGE_CUR_UNSUPP);
4047
/* do not use "default:" in order to produce a gcc warning:
4048
enumeration value '...' not handled in switch
4049
(if -Wswitch or -Wall is used) */
4052
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "this functionality");
4054
return(PAGE_CUR_UNSUPP);
4058
BACKGROUND INFO: HOW A SELECT SQL QUERY IS EXECUTED
4059
---------------------------------------------------
4060
The following does not cover all the details, but explains how we determine
4061
the start of a new SQL statement, and what is associated with it.
4063
For each table in the database the MySQL interpreter may have several
4064
table handle instances in use, also in a single SQL query. For each table
4065
handle instance there is an InnoDB 'prebuilt' struct which contains most
4066
of the InnoDB data associated with this table handle instance.
4068
A) if the user has not explicitly set any MySQL table level locks:
4070
1) MySQL calls ::external_lock to set an 'intention' table level lock on
4071
the table of the handle instance. There we set
4072
prebuilt->sql_stat_start = TRUE. The flag sql_stat_start should be set
4073
true if we are taking this table handle instance to use in a new SQL
4074
statement issued by the user. We also increment trx->n_mysql_tables_in_use.
4076
2) If prebuilt->sql_stat_start == TRUE we 'pre-compile' the MySQL search
4077
instructions to prebuilt->template of the table handle instance in
4078
::index_read. The template is used to save CPU time in large joins.
4080
3) In row_search_for_mysql, if prebuilt->sql_stat_start is true, we
4081
allocate a new consistent read view for the trx if it does not yet have one,
4082
or in the case of a locking read, set an InnoDB 'intention' table level
4085
4) We do the SELECT. MySQL may repeatedly call ::index_read for the
4086
same table handle instance, if it is a join.
4088
5) When the SELECT ends, MySQL removes its intention table level locks
4089
in ::external_lock. When trx->n_mysql_tables_in_use drops to zero,
4090
(a) we execute a COMMIT there if the autocommit is on,
4091
(b) we also release possible 'SQL statement level resources' InnoDB may
4092
have for this SQL statement. The MySQL interpreter does NOT execute
4093
autocommit for pure read transactions, though it should. That is why the
4094
table handler in that case has to execute the COMMIT in ::external_lock.
4096
B) If the user has explicitly set MySQL table level locks, then MySQL
4097
does NOT call ::external_lock at the start of the statement. To determine
4098
when we are at the start of a new SQL statement we at the start of
4099
::index_read also compare the query id to the latest query id where the
4100
table handle instance was used. If it has changed, we know we are at the
4101
start of a new SQL statement. Since the query id can theoretically
4102
overwrap, we use this test only as a secondary way of determining the
4103
start of a new SQL statement. */
4106
/**************************************************************************
4107
Positions an index cursor to the index specified in the handle. Fetches the
4111
ha_innobase::index_read(
4112
/*====================*/
4113
/* out: 0, HA_ERR_KEY_NOT_FOUND,
4115
uchar* buf, /* in/out: buffer for the returned
4117
const uchar* key_ptr, /* in: key value; if this is NULL
4118
we position the cursor at the
4119
start or end of index; this can
4120
also contain an InnoDB row id, in
4121
which case key_len is the InnoDB
4122
row id length; the key value can
4123
also be a prefix of a full key value,
4124
and the last column can be a prefix
4126
uint key_len,/* in: key value length */
4127
enum ha_rkey_function find_flag)/* in: search flags from my_base.h */
4130
dict_index_t* index;
4131
ulint match_mode = 0;
4135
DBUG_ENTER("index_read");
4137
ut_a(prebuilt->trx == thd_to_trx(user_thd));
4139
ha_statistic_increment(&SSV::ha_read_key_count);
4141
index = prebuilt->index;
4143
/* Note that if the index for which the search template is built is not
4144
necessarily prebuilt->index, but can also be the clustered index */
4146
if (prebuilt->sql_stat_start) {
4147
build_template(prebuilt, user_thd, table, this,
4148
ROW_MYSQL_REC_FIELDS);
4152
/* Convert the search key value to InnoDB format into
4153
prebuilt->search_tuple */
4155
row_sel_convert_mysql_key_to_innobase(prebuilt->search_tuple,
4156
(byte*) key_val_buff,
4157
(ulint)upd_and_key_val_buff_len,
4160
(ulint) key_len, prebuilt->trx);
4162
/* We position the cursor to the last or the first entry
4165
dtuple_set_n_fields(prebuilt->search_tuple, 0);
4168
mode = convert_search_mode_to_innobase(find_flag);
4172
if (find_flag == HA_READ_KEY_EXACT) {
4173
match_mode = ROW_SEL_EXACT;
4175
} else if (find_flag == HA_READ_PREFIX
4176
|| find_flag == HA_READ_PREFIX_LAST) {
4177
match_mode = ROW_SEL_EXACT_PREFIX;
4180
last_match_mode = (uint) match_mode;
4182
if (mode != PAGE_CUR_UNSUPP) {
4184
innodb_srv_conc_enter_innodb(prebuilt->trx);
4186
ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
4189
innodb_srv_conc_exit_innodb(prebuilt->trx);
4192
ret = DB_UNSUPPORTED;
4195
if (ret == DB_SUCCESS) {
4199
} else if (ret == DB_RECORD_NOT_FOUND) {
4200
error = HA_ERR_KEY_NOT_FOUND;
4201
table->status = STATUS_NOT_FOUND;
4203
} else if (ret == DB_END_OF_INDEX) {
4204
error = HA_ERR_KEY_NOT_FOUND;
4205
table->status = STATUS_NOT_FOUND;
4207
error = convert_error_code_to_mysql((int) ret, user_thd);
4208
table->status = STATUS_NOT_FOUND;
4214
/***********************************************************************
4215
The following functions works like index_read, but it find the last
4216
row with the current key value or prefix. */
4219
ha_innobase::index_read_last(
4220
/*=========================*/
4221
/* out: 0, HA_ERR_KEY_NOT_FOUND, or an
4223
uchar* buf, /* out: fetched row */
4224
const uchar* key_ptr,/* in: key value, or a prefix of a full
4226
uint key_len)/* in: length of the key val or prefix
4229
return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
4232
/************************************************************************
4233
Get the index for a handle. Does not change active index.*/
4236
ha_innobase::innobase_get_index(
4237
/*============================*/
4238
/* out: NULL or index instance. */
4239
uint keynr) /* in: use this index; MAX_KEY means always
4240
clustered index, even if it was internally
4241
generated by InnoDB */
4244
dict_index_t* index = 0;
4246
DBUG_ENTER("innobase_get_index");
4247
ha_statistic_increment(&SSV::ha_read_key_count);
4249
ut_ad(user_thd == ha_thd());
4250
ut_a(prebuilt->trx == thd_to_trx(user_thd));
4252
if (keynr != MAX_KEY && table->s->keys > 0) {
4253
key = table->key_info + keynr;
4255
index = dict_table_get_index_noninline(
4256
prebuilt->table, key->name);
4258
index = dict_table_get_first_index_noninline(prebuilt->table);
4263
"Innodb could not find key n:o %u with name %s "
4264
"from dict cache for table %s",
4265
keynr, key ? key->name : "NULL",
4266
prebuilt->table->name);
4272
/************************************************************************
4273
Changes the active index of a handle. */
4276
ha_innobase::change_active_index(
4277
/*=============================*/
4278
/* out: 0 or error code */
4279
uint keynr) /* in: use this index; MAX_KEY means always clustered
4280
index, even if it was internally generated by
4283
DBUG_ENTER("change_active_index");
4285
ut_ad(user_thd == ha_thd());
4286
ut_a(prebuilt->trx == thd_to_trx(user_thd));
4288
active_index = keynr;
4290
prebuilt->index = innobase_get_index(keynr);
4292
if (!prebuilt->index) {
4296
assert(prebuilt->search_tuple != 0);
4298
dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
4300
dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
4301
prebuilt->index->n_fields);
4303
/* MySQL changes the active index for a handle also during some
4304
queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
4305
and then calculates the sum. Previously we played safe and used
4306
the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
4307
copying. Starting from MySQL-4.1 we use a more efficient flag here. */
4309
build_template(prebuilt, user_thd, table, this, ROW_MYSQL_REC_FIELDS);
4314
/**************************************************************************
4315
Positions an index cursor to the index specified in keynr. Fetches the
4317
/* ??? This is only used to read whole keys ??? */
4320
ha_innobase::index_read_idx(
4321
/*========================*/
4322
/* out: error number or 0 */
4323
uchar* buf, /* in/out: buffer for the returned
4325
uint keynr, /* in: use this index */
4326
const uchar* key, /* in: key value; if this is NULL
4327
we position the cursor at the
4328
start or end of index */
4329
uint key_len, /* in: key value length */
4330
enum ha_rkey_function find_flag)/* in: search flags from my_base.h */
4332
if (change_active_index(keynr)) {
4337
return(index_read(buf, key, key_len, find_flag));
4340
/***************************************************************************
4341
Reads the next or previous row from a cursor, which must have previously been
4342
positioned using index_read. */
4345
ha_innobase::general_fetch(
4346
/*=======================*/
4347
/* out: 0, HA_ERR_END_OF_FILE, or error
4349
uchar* buf, /* in/out: buffer for next row in MySQL
4351
uint direction, /* in: ROW_SEL_NEXT or ROW_SEL_PREV */
4352
uint match_mode) /* in: 0, ROW_SEL_EXACT, or
4353
ROW_SEL_EXACT_PREFIX */
4358
DBUG_ENTER("general_fetch");
4360
ut_a(prebuilt->trx == thd_to_trx(user_thd));
4362
innodb_srv_conc_enter_innodb(prebuilt->trx);
4364
ret = row_search_for_mysql((byte*)buf, 0, prebuilt, match_mode,
4366
innodb_srv_conc_exit_innodb(prebuilt->trx);
4368
if (ret == DB_SUCCESS) {
4372
} else if (ret == DB_RECORD_NOT_FOUND) {
4373
error = HA_ERR_END_OF_FILE;
4374
table->status = STATUS_NOT_FOUND;
4376
} else if (ret == DB_END_OF_INDEX) {
4377
error = HA_ERR_END_OF_FILE;
4378
table->status = STATUS_NOT_FOUND;
4380
error = convert_error_code_to_mysql((int) ret, user_thd);
4381
table->status = STATUS_NOT_FOUND;
4387
/***************************************************************************
4388
Reads the next row from a cursor, which must have previously been
4389
positioned using index_read. */
4392
ha_innobase::index_next(
4393
/*====================*/
4394
/* out: 0, HA_ERR_END_OF_FILE, or error
4396
uchar* buf) /* in/out: buffer for next row in MySQL
4399
ha_statistic_increment(&SSV::ha_read_next_count);
4401
return(general_fetch(buf, ROW_SEL_NEXT, 0));
4404
/***********************************************************************
4405
Reads the next row matching to the key value given as the parameter. */
4408
ha_innobase::index_next_same(
4409
/*=========================*/
4410
/* out: 0, HA_ERR_END_OF_FILE, or error
4412
uchar* buf, /* in/out: buffer for the row */
4413
const uchar* key, /* in: key value */
4414
uint keylen) /* in: key value length */
4416
ha_statistic_increment(&SSV::ha_read_next_count);
4418
return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
4421
/***************************************************************************
4422
Reads the previous row from a cursor, which must have previously been
4423
positioned using index_read. */
4426
ha_innobase::index_prev(
4427
/*====================*/
4428
/* out: 0, HA_ERR_END_OF_FILE, or error number */
4429
uchar* buf) /* in/out: buffer for previous row in MySQL format */
4431
ha_statistic_increment(&SSV::ha_read_prev_count);
4433
return(general_fetch(buf, ROW_SEL_PREV, 0));
4436
/************************************************************************
4437
Positions a cursor on the first record in an index and reads the
4438
corresponding row to buf. */
4441
ha_innobase::index_first(
4442
/*=====================*/
4443
/* out: 0, HA_ERR_END_OF_FILE, or error code */
4444
uchar* buf) /* in/out: buffer for the row */
4448
DBUG_ENTER("index_first");
4449
ha_statistic_increment(&SSV::ha_read_first_count);
4451
error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
4453
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4455
if (error == HA_ERR_KEY_NOT_FOUND) {
4456
error = HA_ERR_END_OF_FILE;
4462
/************************************************************************
4463
Positions a cursor on the last record in an index and reads the
4464
corresponding row to buf. */
4467
ha_innobase::index_last(
4468
/*====================*/
4469
/* out: 0, HA_ERR_END_OF_FILE, or error code */
4470
uchar* buf) /* in/out: buffer for the row */
4474
DBUG_ENTER("index_last");
4475
ha_statistic_increment(&SSV::ha_read_last_count);
4477
error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
4479
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4481
if (error == HA_ERR_KEY_NOT_FOUND) {
4482
error = HA_ERR_END_OF_FILE;
4488
/********************************************************************
4489
Initialize a table scan. */
4492
ha_innobase::rnd_init(
4493
/*==================*/
4494
/* out: 0 or error number */
4495
bool scan) /* in: ???????? */
4499
/* Store the active index value so that we can restore the original
4500
value after a scan */
4502
if (prebuilt->clust_index_was_generated) {
4503
err = change_active_index(MAX_KEY);
4505
err = change_active_index(primary_key);
4508
/* Don't use semi-consistent read in random row reads (by position).
4509
This means we must disable semi_consistent_read if scan is false */
4512
try_semi_consistent_read(0);
4520
/*********************************************************************
4521
Ends a table scan. */
4524
ha_innobase::rnd_end(void)
4525
/*======================*/
4526
/* out: 0 or error number */
4528
return(index_end());
4531
/*********************************************************************
4532
Reads the next row in a table scan (also used to read the FIRST row
4533
in a table scan). */
4536
ha_innobase::rnd_next(
4537
/*==================*/
4538
/* out: 0, HA_ERR_END_OF_FILE, or error number */
4539
uchar* buf) /* in/out: returns the row in this buffer,
4544
DBUG_ENTER("rnd_next");
4545
ha_statistic_increment(&SSV::ha_read_rnd_next_count);
4547
if (start_of_scan) {
4548
error = index_first(buf);
4549
if (error == HA_ERR_KEY_NOT_FOUND) {
4550
error = HA_ERR_END_OF_FILE;
4554
error = general_fetch(buf, ROW_SEL_NEXT, 0);
4560
/**************************************************************************
4561
Fetches a row from the table based on a row reference. */
4564
ha_innobase::rnd_pos(
4565
/*=================*/
4566
/* out: 0, HA_ERR_KEY_NOT_FOUND, or error code */
4567
uchar* buf, /* in/out: buffer for the row */
4568
uchar* pos) /* in: primary key value of the row in the
4569
MySQL format, or the row id if the clustered
4570
index was internally generated by InnoDB; the
4571
length of data in pos has to be ref_length */
4574
DBUG_ENTER("rnd_pos");
4575
DBUG_DUMP("key", pos, ref_length);
4577
ha_statistic_increment(&SSV::ha_read_rnd_count);
4579
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
4581
/* Note that we assume the length of the row reference is fixed
4582
for the table, and it is == ref_length */
4584
error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
4587
DBUG_PRINT("error", ("Got error: %d", error));
4593
/*************************************************************************
4594
Stores a reference to the current row to 'ref' field of the handle. Note
4595
that in the case where we have generated the clustered index for the
4596
table, the function parameter is illogical: we MUST ASSUME that 'record'
4597
is the current 'position' of the handle, because if row ref is actually
4598
the row id internally generated in InnoDB, then 'record' does not contain
4599
it. We just guess that the row id must be for the record where the handle
4600
was positioned the last time. */
4603
ha_innobase::position(
4604
/*==================*/
4605
const uchar* record) /* in: row in MySQL format */
4609
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
4611
/*if (ds_mrr.call_position_for != this) {
4612
((ha_innobase*)ds_mrr.call_position_for)->position(record);
4615
if (prebuilt->clust_index_was_generated) {
4616
/* No primary key was defined for the table and we
4617
generated the clustered index from row id: the
4618
row reference will be the row id, not any key value
4619
that MySQL knows of */
4621
len = DATA_ROW_ID_LEN;
4623
memcpy(ref, prebuilt->row_id, len);
4625
len = store_key_val_for_row(primary_key, (char*)ref,
4626
ref_length, record);
4629
/* We assume that the 'ref' value len is always fixed for the same
4632
if (len != ref_length) {
4633
sql_print_error("Stored ref len is %lu, but table ref len is %lu",
4634
(ulong) len, (ulong) ref_length);
4638
/*********************************************************************
4639
If it's a DB_TOO_BIG_RECORD error then set a suitable message to
4640
return to the client.*/
4643
innodb_check_for_record_too_big_error(
4644
/*==================================*/
4645
ulint comp, /* in: ROW_FORMAT: nonzero=COMPACT, 0=REDUNDANT */
4646
int error) /* in: error code to check */
4648
if (error == (int)DB_TOO_BIG_RECORD) {
4650
= page_get_free_space_of_empty_noninline(comp) / 2;
4652
my_error(ER_TOO_BIG_ROWSIZE, MYF(0), max_row_size);
4656
/*********************************************************************
4657
Creates a table definition to an InnoDB database. */
4662
trx_t* trx, /* in: InnoDB transaction handle */
4663
TABLE* form, /* in: information on table
4664
columns and indexes */
4665
const char* table_name, /* in: table name */
4666
const char* path_of_temp_table,/* in: if this is a table explicitly
4667
created by the user with the
4668
TEMPORARY keyword, then this
4669
parameter is the dir path where the
4670
table should be placed if we create
4671
an .ibd file for it (no .ibd extension
4672
in the path, though); otherwise this
4674
ulint flags) /* in: table flags */
4677
dict_table_t* table;
4682
ulint nulls_allowed;
4683
ulint unsigned_type;
4685
ulint long_true_varchar;
4689
DBUG_ENTER("create_table_def");
4690
DBUG_PRINT("enter", ("table_name: %s", table_name));
4692
n_cols = form->s->fields;
4694
/* We pass 0 as the space id, and determine at a lower level the space
4695
id where to store the table */
4697
table = dict_mem_table_create(table_name, 0, n_cols, flags);
4699
if (path_of_temp_table) {
4700
table->dir_path_of_temp_table =
4701
mem_heap_strdup(table->heap, path_of_temp_table);
4704
for (i = 0; i < n_cols; i++) {
4705
field = form->field[i];
4707
col_type = get_innobase_type_from_mysql_type(&unsigned_type,
4709
if (field->null_ptr) {
4712
nulls_allowed = DATA_NOT_NULL;
4715
if (field->binary()) {
4716
binary_type = DATA_BINARY_TYPE;
4723
if (dtype_is_string_type(col_type)) {
4725
charset_no = (ulint)field->charset()->number;
4727
ut_a(charset_no < 256); /* in data0type.h we assume
4728
that the number fits in one
4732
ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
4733
that this fits in one byte */
4734
col_len = field->pack_length();
4736
/* The MySQL pack length contains 1 or 2 bytes length field
4737
for a true VARCHAR. Let us subtract that, so that the InnoDB
4738
column length in the InnoDB data dictionary is the real
4739
maximum byte length of the actual data. */
4741
long_true_varchar = 0;
4743
if (field->type() == MYSQL_TYPE_VARCHAR) {
4744
col_len -= ((Field_varstring*)field)->length_bytes;
4746
if (((Field_varstring*)field)->length_bytes == 2) {
4747
long_true_varchar = DATA_LONG_TRUE_VARCHAR;
4751
dict_mem_table_add_col(table, table->heap,
4752
(char*) field->field_name,
4755
(ulint)field->type()
4756
| nulls_allowed | unsigned_type
4757
| binary_type | long_true_varchar,
4762
error = row_create_table_for_mysql(table, trx);
4764
innodb_check_for_record_too_big_error(flags & DICT_TF_COMPACT, error);
4766
error = convert_error_code_to_mysql(error, NULL);
4771
/*********************************************************************
4772
Creates an index in an InnoDB database. */
4777
trx_t* trx, /* in: InnoDB transaction handle */
4778
TABLE* form, /* in: information on table
4779
columns and indexes */
4780
const char* table_name, /* in: table name */
4781
uint key_num) /* in: index number */
4784
dict_index_t* index;
4788
KEY_PART_INFO* key_part;
4795
ulint* field_lengths;
4797
DBUG_ENTER("create_index");
4799
key = form->key_info + key_num;
4801
n_fields = key->key_parts;
4805
if (key_num == form->s->primary_key) {
4806
ind_type = ind_type | DICT_CLUSTERED;
4809
if (key->flags & HA_NOSAME ) {
4810
ind_type = ind_type | DICT_UNIQUE;
4813
/* We pass 0 as the space id, and determine at a lower level the space
4814
id where to store the table */
4816
index = dict_mem_index_create((char*) table_name, key->name, 0,
4817
ind_type, n_fields);
4819
field_lengths = (ulint*) my_malloc(sizeof(ulint) * n_fields,
4822
for (i = 0; i < n_fields; i++) {
4823
key_part = key->key_part + i;
4825
/* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix
4826
field in an index: we only store a specified number of first
4827
bytes of the column to the index field.) The flag does not
4828
seem to be properly set by MySQL. Let us fall back on testing
4829
the length of the key part versus the column. */
4832
for (j = 0; j < form->s->fields; j++) {
4834
field = form->field[j];
4836
if (0 == innobase_strcasecmp(
4838
key_part->field->field_name)) {
4839
/* Found the corresponding column */
4845
ut_a(j < form->s->fields);
4847
col_type = get_innobase_type_from_mysql_type(
4848
&is_unsigned, key_part->field);
4850
if (DATA_BLOB == col_type
4851
|| (key_part->length < field->pack_length()
4852
&& field->type() != MYSQL_TYPE_VARCHAR)
4853
|| (field->type() == MYSQL_TYPE_VARCHAR
4854
&& key_part->length < field->pack_length()
4855
- ((Field_varstring*)field)->length_bytes)) {
4857
prefix_len = key_part->length;
4859
if (col_type == DATA_INT
4860
|| col_type == DATA_FLOAT
4861
|| col_type == DATA_DOUBLE
4862
|| col_type == DATA_DECIMAL) {
4864
"MySQL is trying to create a column "
4865
"prefix index field, on an "
4866
"inappropriate data type. Table "
4867
"name %s, column name %s.",
4869
key_part->field->field_name);
4877
field_lengths[i] = key_part->length;
4879
dict_mem_index_add_field(index,
4880
(char*) key_part->field->field_name, prefix_len);
4883
/* Even though we've defined max_supported_key_part_length, we
4884
still do our own checking using field_lengths to be absolutely
4885
sure we don't create too long indexes. */
4886
error = row_create_index_for_mysql(index, trx, field_lengths);
4888
innodb_check_for_record_too_big_error(form->s->row_type
4889
!= ROW_TYPE_REDUNDANT, error);
4891
error = convert_error_code_to_mysql(error, NULL);
4893
my_free(field_lengths, MYF(0));
4898
/*********************************************************************
4899
Creates an index to an InnoDB table when the user has defined no
4903
create_clustered_index_when_no_primary(
4904
/*===================================*/
4905
trx_t* trx, /* in: InnoDB transaction handle */
4906
ulint comp, /* in: ROW_FORMAT:
4907
nonzero=COMPACT, 0=REDUNDANT */
4908
const char* table_name) /* in: table name */
4910
dict_index_t* index;
4913
/* We pass 0 as the space id, and determine at a lower level the space
4914
id where to store the table */
4916
index = dict_mem_index_create(table_name, "GEN_CLUST_INDEX",
4917
0, DICT_CLUSTERED, 0);
4918
error = row_create_index_for_mysql(index, trx, NULL);
4920
innodb_check_for_record_too_big_error(comp, error);
4922
error = convert_error_code_to_mysql(error, NULL);
4927
/*********************************************************************
4928
Update create_info. Used in SHOW CREATE TABLE et al. */
4931
ha_innobase::update_create_info(
4932
/*============================*/
4933
HA_CREATE_INFO* create_info) /* in/out: create info */
4935
if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) {
4936
ha_innobase::info(HA_STATUS_AUTO);
4937
create_info->auto_increment_value = stats.auto_increment_value;
4941
/*********************************************************************
4942
Creates a new table to an InnoDB database. */
4945
ha_innobase::create(
4946
/*================*/
4947
/* out: error number */
4948
const char* name, /* in: table name */
4949
TABLE* form, /* in: information on table
4950
columns and indexes */
4951
HA_CREATE_INFO* create_info) /* in: more information of the
4952
created table, contains also the
4953
create statement string */
4956
dict_table_t* innobase_table;
4961
char name2[FN_REFLEN];
4962
char norm_name[FN_REFLEN];
4963
THD* thd = ha_thd();
4964
ib_longlong auto_inc_value;
4967
DBUG_ENTER("ha_innobase::create");
4969
DBUG_ASSERT(thd != NULL);
4971
if (form->s->fields > 1000) {
4972
/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
4973
but we play safe here */
4975
DBUG_RETURN(HA_ERR_TO_BIG_ROW);
4978
/* Get the transaction associated with the current thd, or create one
4979
if not yet created */
4981
parent_trx = check_trx_exists(thd);
4983
/* In case MySQL calls this in the middle of a SELECT query, release
4984
possible adaptive hash latch to avoid deadlocks of threads */
4986
trx_search_latch_release_if_reserved(parent_trx);
4988
trx = trx_allocate_for_mysql();
4990
trx->mysql_thd = thd;
4991
trx->mysql_query_str = thd_query(thd);
4993
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
4994
trx->check_foreigns = FALSE;
4997
if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
4998
trx->check_unique_secondary = FALSE;
5001
if (lower_case_table_names) {
5002
srv_lower_case_table_names = TRUE;
5004
srv_lower_case_table_names = FALSE;
5007
strcpy(name2, name);
5009
normalize_table_name(norm_name, name2);
5011
/* Latch the InnoDB data dictionary exclusively so that no deadlocks
5012
or lock waits can happen in it during a table create operation.
5013
Drop table etc. do this latching in row0mysql.c. */
5015
row_mysql_lock_data_dictionary(trx);
5017
/* Create the table definition in InnoDB */
5021
if (form->s->row_type != ROW_TYPE_REDUNDANT) {
5022
flags |= DICT_TF_COMPACT;
5025
error = create_table_def(trx, form, norm_name,
5026
create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
5033
/* Look for a primary key */
5035
primary_key_no= (form->s->primary_key != MAX_KEY ?
5036
(int) form->s->primary_key :
5039
/* Our function row_get_mysql_key_number_for_index assumes
5040
the primary key is always number 0, if it exists */
5042
DBUG_ASSERT(primary_key_no == -1 || primary_key_no == 0);
5044
/* Create the keys */
5046
if (form->s->keys == 0 || primary_key_no == -1) {
5047
/* Create an index which is used as the clustered index;
5048
order the rows by their row id which is internally generated
5051
error = create_clustered_index_when_no_primary(
5052
trx, form->s->row_type != ROW_TYPE_REDUNDANT,
5059
if (primary_key_no != -1) {
5060
/* In InnoDB the clustered index must always be created
5062
if ((error = create_index(trx, form, norm_name,
5063
(uint) primary_key_no))) {
5068
for (i = 0; i < form->s->keys; i++) {
5070
if (i != (uint) primary_key_no) {
5072
if ((error = create_index(trx, form, norm_name, i))) {
5078
if (*trx->mysql_query_str) {
5079
error = row_table_add_foreign_constraints(trx,
5080
*trx->mysql_query_str, norm_name,
5081
create_info->options & HA_LEX_CREATE_TMP_TABLE);
5083
error = convert_error_code_to_mysql(error, NULL);
5090
innobase_commit_low(trx);
5092
row_mysql_unlock_data_dictionary(trx);
5094
/* Flush the log to reduce probability that the .frm files and
5095
the InnoDB data dictionary get out-of-sync if the user runs
5096
with innodb_flush_log_at_trx_commit = 0 */
5098
log_buffer_flush_to_disk();
5100
innobase_table = dict_table_get(norm_name, FALSE);
5102
DBUG_ASSERT(innobase_table != 0);
5104
if ((create_info->used_fields & HA_CREATE_USED_AUTO) &&
5105
(create_info->auto_increment_value != 0)) {
5107
/* Query was ALTER TABLE...AUTO_INCREMENT = x; or
5108
CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
5109
definition from the dictionary and get the current value
5110
of the auto increment field. Set a new value to the
5111
auto increment field if the value is greater than the
5112
maximum value in the column. */
5114
auto_inc_value = create_info->auto_increment_value;
5116
dict_table_autoinc_lock(innobase_table);
5117
dict_table_autoinc_initialize(innobase_table, auto_inc_value);
5118
dict_table_autoinc_unlock(innobase_table);
5121
/* Tell the InnoDB server that there might be work for
5124
srv_active_wake_master_thread();
5126
trx_free_for_mysql(trx);
5131
innobase_commit_low(trx);
5133
row_mysql_unlock_data_dictionary(trx);
5135
trx_free_for_mysql(trx);
5140
/*********************************************************************
5141
Discards or imports an InnoDB tablespace. */
5144
ha_innobase::discard_or_import_tablespace(
5145
/*======================================*/
5146
/* out: 0 == success, -1 == error */
5147
my_bool discard) /* in: TRUE if discard, else import */
5149
dict_table_t* dict_table;
5153
DBUG_ENTER("ha_innobase::discard_or_import_tablespace");
5155
ut_a(prebuilt->trx);
5156
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
5157
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
5159
dict_table = prebuilt->table;
5160
trx = prebuilt->trx;
5163
err = row_discard_tablespace_for_mysql(dict_table->name, trx);
5165
err = row_import_tablespace_for_mysql(dict_table->name, trx);
5168
err = convert_error_code_to_mysql(err, NULL);
5173
/*********************************************************************
5174
Deletes all rows of an InnoDB table. */
5177
ha_innobase::delete_all_rows(void)
5178
/*==============================*/
5179
/* out: error number */
5183
DBUG_ENTER("ha_innobase::delete_all_rows");
5185
/* Get the transaction associated with the current thd, or create one
5186
if not yet created, and update prebuilt->trx */
5188
update_thd(ha_thd());
5190
if (thd_sql_command(user_thd) != SQLCOM_TRUNCATE) {
5192
/* We only handle TRUNCATE TABLE t as a special case.
5193
DELETE FROM t will have to use ha_innobase::delete_row(). */
5194
DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND);
5197
/* Truncate the table in InnoDB */
5199
error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
5200
if (error == DB_ERROR) {
5201
/* Cannot truncate; resort to ha_innobase::delete_row() */
5205
error = convert_error_code_to_mysql(error, NULL);
5210
/*********************************************************************
5211
Drops a table from an InnoDB database. Before calling this function,
5212
MySQL calls innobase_commit to commit the transaction of the current user.
5213
Then the current user cannot have locks set on the table. Drop table
5214
operation inside InnoDB will remove all locks any user has on the table
5218
ha_innobase::delete_table(
5219
/*======================*/
5220
/* out: error number */
5221
const char* name) /* in: table name */
5227
THD *thd = ha_thd();
5228
char norm_name[1000];
5230
DBUG_ENTER("ha_innobase::delete_table");
5232
/* Get the transaction associated with the current thd, or create one
5233
if not yet created */
5235
parent_trx = check_trx_exists(thd);
5237
/* In case MySQL calls this in the middle of a SELECT query, release
5238
possible adaptive hash latch to avoid deadlocks of threads */
5240
trx_search_latch_release_if_reserved(parent_trx);
5242
if (lower_case_table_names) {
5243
srv_lower_case_table_names = TRUE;
5245
srv_lower_case_table_names = FALSE;
5248
trx = trx_allocate_for_mysql();
5250
trx->mysql_thd = thd;
5251
trx->mysql_query_str = thd_query(thd);
5253
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
5254
trx->check_foreigns = FALSE;
5257
if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
5258
trx->check_unique_secondary = FALSE;
5261
name_len = strlen(name);
5263
assert(name_len < 1000);
5265
/* Strangely, MySQL passes the table name without the '.frm'
5266
extension, in contrast to ::create */
5268
normalize_table_name(norm_name, name);
5270
/* Drop the table in InnoDB */
5272
error = row_drop_table_for_mysql(norm_name, trx,
5273
thd_sql_command(thd)
5276
/* Flush the log to reduce probability that the .frm files and
5277
the InnoDB data dictionary get out-of-sync if the user runs
5278
with innodb_flush_log_at_trx_commit = 0 */
5280
log_buffer_flush_to_disk();
5282
/* Tell the InnoDB server that there might be work for
5285
srv_active_wake_master_thread();
5287
innobase_commit_low(trx);
5289
trx_free_for_mysql(trx);
5291
error = convert_error_code_to_mysql(error, NULL);
5296
/*********************************************************************
5297
Removes all tables in the named database inside InnoDB. */
5300
innobase_drop_database(
5301
/*===================*/
5302
/* out: error number */
5303
handlerton *hton, /* in: handlerton of Innodb */
5304
char* path) /* in: database path; inside InnoDB the name
5305
of the last directory in the path is used as
5306
the database name: for example, in 'mysql/data/test'
5307
the database name is 'test' */
5315
THD* thd = current_thd;
5317
/* Get the transaction associated with the current thd, or create one
5318
if not yet created */
5320
parent_trx = check_trx_exists(thd);
5322
/* In case MySQL calls this in the middle of a SELECT query, release
5323
possible adaptive hash latch to avoid deadlocks of threads */
5325
trx_search_latch_release_if_reserved(parent_trx);
5327
ptr = strend(path) - 2;
5329
while (ptr >= path && *ptr != '\\' && *ptr != '/') {
5335
namebuf = (char*) my_malloc((uint) len + 2, MYF(0));
5337
memcpy(namebuf, ptr, len);
5339
namebuf[len + 1] = '\0';
5341
innobase_casedn_str(namebuf);
5343
trx = trx_allocate_for_mysql();
5344
trx->mysql_thd = thd;
5345
trx->mysql_query_str = thd_query(thd);
5347
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
5348
trx->check_foreigns = FALSE;
5351
error = row_drop_database_for_mysql(namebuf, trx);
5352
my_free(namebuf, MYF(0));
5354
/* Flush the log to reduce probability that the .frm files and
5355
the InnoDB data dictionary get out-of-sync if the user runs
5356
with innodb_flush_log_at_trx_commit = 0 */
5358
log_buffer_flush_to_disk();
5360
/* Tell the InnoDB server that there might be work for
5363
srv_active_wake_master_thread();
5365
innobase_commit_low(trx);
5366
trx_free_for_mysql(trx);
5367
#ifdef NO_LONGER_INTERESTED_IN_DROP_DB_ERROR
5368
error = convert_error_code_to_mysql(error, NULL);
5376
/*************************************************************************
5377
Renames an InnoDB table. */
5380
ha_innobase::rename_table(
5381
/*======================*/
5382
/* out: 0 or error code */
5383
const char* from, /* in: old name of the table */
5384
const char* to) /* in: new name of the table */
5391
char norm_from[1000];
5393
THD* thd = ha_thd();
5395
DBUG_ENTER("ha_innobase::rename_table");
5397
/* Get the transaction associated with the current thd, or create one
5398
if not yet created */
5400
parent_trx = check_trx_exists(thd);
5402
/* In case MySQL calls this in the middle of a SELECT query, release
5403
possible adaptive hash latch to avoid deadlocks of threads */
5405
trx_search_latch_release_if_reserved(parent_trx);
5407
if (lower_case_table_names) {
5408
srv_lower_case_table_names = TRUE;
5410
srv_lower_case_table_names = FALSE;
5413
trx = trx_allocate_for_mysql();
5414
trx->mysql_thd = thd;
5415
trx->mysql_query_str = thd_query(thd);
5417
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
5418
trx->check_foreigns = FALSE;
5421
name_len1 = strlen(from);
5422
name_len2 = strlen(to);
5424
assert(name_len1 < 1000);
5425
assert(name_len2 < 1000);
5427
normalize_table_name(norm_from, from);
5428
normalize_table_name(norm_to, to);
5430
/* Rename the table in InnoDB */
5432
error = row_rename_table_for_mysql(norm_from, norm_to, trx);
5434
/* Flush the log to reduce probability that the .frm files and
5435
the InnoDB data dictionary get out-of-sync if the user runs
5436
with innodb_flush_log_at_trx_commit = 0 */
5438
log_buffer_flush_to_disk();
5440
/* Tell the InnoDB server that there might be work for
5443
srv_active_wake_master_thread();
5445
innobase_commit_low(trx);
5446
trx_free_for_mysql(trx);
5448
error = convert_error_code_to_mysql(error, NULL);
5453
/*************************************************************************
5454
Estimates the number of index records in a range. */
5457
ha_innobase::records_in_range(
5458
/*==========================*/
5459
/* out: estimated number of
5461
uint keynr, /* in: index number */
5462
key_range *min_key, /* in: start key value of the
5463
range, may also be 0 */
5464
key_range *max_key) /* in: range end key val, may
5468
dict_index_t* index;
5469
uchar* key_val_buff2 = (uchar*) my_malloc(
5471
+ table->s->max_key_length + 100,
5473
ulint buff2_len = table->s->reclength
5474
+ table->s->max_key_length + 100;
5475
dtuple_t* range_start;
5476
dtuple_t* range_end;
5483
DBUG_ENTER("records_in_range");
5485
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
5487
prebuilt->trx->op_info = (char*)"estimating records in index range";
5489
/* In case MySQL calls this in the middle of a SELECT query, release
5490
possible adaptive hash latch to avoid deadlocks of threads */
5492
trx_search_latch_release_if_reserved(prebuilt->trx);
5494
active_index = keynr;
5496
key = table->key_info + active_index;
5498
index = dict_table_get_index_noninline(prebuilt->table, key->name);
5500
range_start = dtuple_create_for_mysql(&heap1, key->key_parts);
5501
dict_index_copy_types(range_start, index, key->key_parts);
5503
range_end = dtuple_create_for_mysql(&heap2, key->key_parts);
5504
dict_index_copy_types(range_end, index, key->key_parts);
5506
row_sel_convert_mysql_key_to_innobase(
5507
range_start, (byte*) key_val_buff,
5508
(ulint)upd_and_key_val_buff_len,
5510
(byte*) (min_key ? min_key->key :
5512
(ulint) (min_key ? min_key->length : 0),
5515
row_sel_convert_mysql_key_to_innobase(
5516
range_end, (byte*) key_val_buff2,
5518
(byte*) (max_key ? max_key->key :
5520
(ulint) (max_key ? max_key->length : 0),
5523
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
5525
mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
5528
if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
5530
n_rows = btr_estimate_n_rows_in_range(index, range_start,
5538
dtuple_free_for_mysql(heap1);
5539
dtuple_free_for_mysql(heap2);
5541
my_free(key_val_buff2, MYF(0));
5543
prebuilt->trx->op_info = (char*)"";
5545
/* The MySQL optimizer seems to believe an estimate of 0 rows is
5546
always accurate and may return the result 'Empty set' based on that.
5547
The accuracy is not guaranteed, and even if it were, for a locking
5548
read we should anyway perform the search to set the next-key lock.
5549
Add 1 to the value to make sure MySQL does not make the assumption! */
5555
DBUG_RETURN((ha_rows) n_rows);
5558
/*************************************************************************
5559
Gives an UPPER BOUND to the number of rows in a table. This is used in
5563
ha_innobase::estimate_rows_upper_bound(void)
5564
/*======================================*/
5565
/* out: upper bound of rows */
5567
dict_index_t* index;
5569
ulonglong local_data_file_length;
5571
DBUG_ENTER("estimate_rows_upper_bound");
5573
/* We do not know if MySQL can call this function before calling
5574
external_lock(). To be safe, update the thd of the current table
5577
update_thd(ha_thd());
5579
prebuilt->trx->op_info = (char*)
5580
"calculating upper bound for table rows";
5582
/* In case MySQL calls this in the middle of a SELECT query, release
5583
possible adaptive hash latch to avoid deadlocks of threads */
5585
trx_search_latch_release_if_reserved(prebuilt->trx);
5587
index = dict_table_get_first_index_noninline(prebuilt->table);
5589
local_data_file_length = ((ulonglong) index->stat_n_leaf_pages)
5592
/* Calculate a minimum length for a clustered index record and from
5593
that an upper bound for the number of rows. Since we only calculate
5594
new statistics in row0mysql.c when a table has grown by a threshold
5595
factor, we must add a safety factor 2 in front of the formula below. */
5597
estimate = 2 * local_data_file_length /
5598
dict_index_calc_min_rec_len(index);
5600
prebuilt->trx->op_info = (char*)"";
5602
DBUG_RETURN((ha_rows) estimate);
5605
/*************************************************************************
5606
How many seeks it will take to read through the table. This is to be
5607
comparable to the number returned by records_in_range so that we can
5608
decide if we should scan the table or use keys. */
5611
ha_innobase::scan_time()
5612
/*====================*/
5613
/* out: estimated time measured in disk seeks */
5615
/* Since MySQL seems to favor table scans too much over index
5616
searches, we pretend that a sequential read takes the same time
5617
as a random disk read, that is, we do not divide the following
5618
by 10, which would be physically realistic. */
5620
return((double) (prebuilt->table->stat_clustered_index_size));
5623
/**********************************************************************
5624
Calculate the time it takes to read a set of ranges through an index
5625
This enables us to optimise reads for clustered indexes. */
5628
ha_innobase::read_time(
5629
/*===================*/
5630
/* out: estimated time measured in disk seeks */
5631
uint index, /* in: key number */
5632
uint ranges, /* in: how many ranges */
5633
ha_rows rows) /* in: estimated number of rows in the ranges */
5636
double time_for_scan;
5638
if (index != table->s->primary_key) {
5640
return(handler::read_time(index, ranges, rows));
5645
return((double) rows);
5648
/* Assume that the read time is proportional to the scan time for all
5649
rows + at most one seek per range. */
5651
time_for_scan = scan_time();
5653
if ((total_rows = estimate_rows_upper_bound()) < rows) {
5655
return(time_for_scan);
5658
return(ranges + (double) rows / (double) total_rows * time_for_scan);
5661
/*************************************************************************
5662
Returns statistics information of the table to the MySQL interpreter,
5663
in various fields of the handle object. */
5668
uint flag) /* in: what information MySQL requests */
5670
dict_table_t* ib_table;
5671
dict_index_t* index;
5672
ha_rows rec_per_key;
5676
char path[FN_REFLEN];
5677
os_file_stat_t stat_info;
5681
/* If we are forcing recovery at a high level, we will suppress
5682
statistics calculation on tables, because that may crash the
5683
server if an index is badly corrupted. */
5685
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
5687
/* We return success (0) instead of HA_ERR_CRASHED,
5688
because we want MySQL to process this query and not
5689
stop, like it would do if it received the error code
5695
/* We do not know if MySQL can call this function before calling
5696
external_lock(). To be safe, update the thd of the current table
5699
update_thd(ha_thd());
5701
/* In case MySQL calls this in the middle of a SELECT query, release
5702
possible adaptive hash latch to avoid deadlocks of threads */
5704
prebuilt->trx->op_info = (char*)"returning various info to MySQL";
5706
trx_search_latch_release_if_reserved(prebuilt->trx);
5708
ib_table = prebuilt->table;
5710
if (flag & HA_STATUS_TIME) {
5711
if (srv_stats_on_metadata) {
5712
/* In sql_show we call with this flag: update
5713
then statistics so that they are up-to-date */
5715
prebuilt->trx->op_info = "updating table statistics";
5717
dict_update_statistics(ib_table);
5719
prebuilt->trx->op_info = "returning various info to MySQL";
5722
my_snprintf(path, sizeof(path), "%s/%s%s",
5723
mysql_data_home, ib_table->name, reg_ext);
5725
unpack_filename(path,path);
5727
/* Note that we do not know the access time of the table,
5728
nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
5730
if (os_file_get_status(path,&stat_info)) {
5731
stats.create_time = stat_info.ctime;
5735
if (flag & HA_STATUS_VARIABLE) {
5736
n_rows = ib_table->stat_n_rows;
5738
/* Because we do not protect stat_n_rows by any mutex in a
5739
delete, it is theoretically possible that the value can be
5740
smaller than zero! TODO: fix this race.
5742
The MySQL optimizer seems to assume in a left join that n_rows
5743
is an accurate estimate if it is zero. Of course, it is not,
5744
since we do not have any locks on the rows yet at this phase.
5745
Since SHOW TABLE STATUS seems to call this function with the
5746
HA_STATUS_TIME flag set, while the left join optimizer does not
5747
set that flag, we add one to a zero value if the flag is not
5748
set. That way SHOW TABLE STATUS will show the best estimate,
5749
while the optimizer never sees the table empty. */
5755
if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
5759
stats.records = (ha_rows)n_rows;
5761
stats.data_file_length = ((ulonglong)
5762
ib_table->stat_clustered_index_size)
5764
stats.index_file_length = ((ulonglong)
5765
ib_table->stat_sum_of_other_index_sizes)
5767
stats.delete_length = 0;
5768
stats.check_time = 0;
5770
if (stats.records == 0) {
5771
stats.mean_rec_length = 0;
5773
stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
5777
if (flag & HA_STATUS_CONST) {
5778
index = dict_table_get_first_index_noninline(ib_table);
5780
if (prebuilt->clust_index_was_generated) {
5781
index = dict_table_get_next_index_noninline(index);
5784
for (i = 0; i < table->s->keys; i++) {
5785
if (index == NULL) {
5786
sql_print_error("Table %s contains fewer "
5787
"indexes inside InnoDB than "
5788
"are defined in the MySQL "
5789
".frm file. Have you mixed up "
5790
".frm files from different "
5791
"installations? See "
5792
"http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n",
5798
for (j = 0; j < table->key_info[i].key_parts; j++) {
5800
if (j + 1 > index->n_uniq) {
5802
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
5803
"statistics for %lu columns. Have you mixed up .frm files from different "
5805
"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n",
5809
index->n_uniq, j + 1);
5813
if (index->stat_n_diff_key_vals[j + 1] == 0) {
5815
rec_per_key = stats.records;
5817
rec_per_key = (ha_rows)(stats.records /
5818
index->stat_n_diff_key_vals[j + 1]);
5821
/* Since MySQL seems to favor table scans
5822
too much over index searches, we pretend
5823
index selectivity is 2 times better than
5826
rec_per_key = rec_per_key / 2;
5828
if (rec_per_key == 0) {
5832
table->key_info[i].rec_per_key[j]=
5833
rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
5834
(ulong) rec_per_key;
5837
index = dict_table_get_next_index_noninline(index);
5841
if (flag & HA_STATUS_ERRKEY) {
5842
ut_a(prebuilt->trx);
5843
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
5845
errkey = (unsigned int) row_get_mysql_key_number_for_index(
5846
(dict_index_t*) trx_get_error_info(prebuilt->trx));
5849
if (flag & HA_STATUS_AUTO && table->found_next_number_field) {
5853
/* The following function call can the first time fail in
5854
a lock wait timeout error because it reserves the auto-inc
5855
lock on the table. If it fails, then someone is already initing
5856
the auto-inc counter, and the second call is guaranteed to
5859
ret = innobase_read_and_init_auto_inc(&auto_inc);
5862
ret = innobase_read_and_init_auto_inc(&auto_inc);
5865
sql_print_error("Cannot get table %s auto-inc"
5866
"counter value in ::info\n",
5872
stats.auto_increment_value = auto_inc;
5875
prebuilt->trx->op_info = (char*)"";
5880
/**************************************************************************
5881
Updates index cardinalities of the table, based on 8 random dives into
5882
each index tree. This does NOT calculate exact statistics on the table. */
5885
ha_innobase::analyze(
5886
/*=================*/
5887
/* out: returns always 0 (success) */
5888
THD* thd, /* in: connection thread handle */
5889
HA_CHECK_OPT* check_opt) /* in: currently ignored */
5891
/* Simply call ::info() with all the flags */
5892
info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
5897
/**************************************************************************
5898
This is mapped to "ALTER TABLE tablename ENGINE=InnoDB", which rebuilds
5899
the table in MySQL. */
5902
ha_innobase::optimize(
5903
/*==================*/
5904
THD* thd, /* in: connection thread handle */
5905
HA_CHECK_OPT* check_opt) /* in: currently ignored */
5907
return(HA_ADMIN_TRY_ALTER);
5910
/***********************************************************************
5911
Tries to check that an InnoDB table is not corrupted. If corruption is
5912
noticed, prints to stderr information about it. In case of corruption
5913
may also assert a failure and crash the server. */
5918
/* out: HA_ADMIN_CORRUPT or
5920
THD* thd, /* in: user thread handle */
5921
HA_CHECK_OPT* check_opt) /* in: check options, currently
5926
DBUG_ASSERT(thd == ha_thd());
5927
ut_a(prebuilt->trx);
5928
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
5929
ut_a(prebuilt->trx == thd_to_trx(thd));
5931
if (prebuilt->mysql_template == NULL) {
5932
/* Build the template; we will use a dummy template
5933
in index scans done in checking */
5935
build_template(prebuilt, NULL, table, this, ROW_MYSQL_WHOLE_ROW);
5938
ret = row_check_table_for_mysql(prebuilt);
5940
if (ret == DB_SUCCESS) {
5941
return(HA_ADMIN_OK);
5944
return(HA_ADMIN_CORRUPT);
5947
/*****************************************************************
5948
Adds information about free space in the InnoDB tablespace to a table comment
5949
which is printed out when a user calls SHOW TABLE STATUS. Adds also info on
5953
ha_innobase::update_table_comment(
5954
/*==============================*/
5955
/* out: table comment + InnoDB free space +
5956
info on foreign keys */
5957
const char* comment)/* in: table comment defined by user */
5959
uint length = (uint) strlen(comment);
5963
/* We do not know if MySQL can call this function before calling
5964
external_lock(). To be safe, update the thd of the current table
5967
if (length > 64000 - 3) {
5968
return((char*)comment); /* string too long */
5971
update_thd(ha_thd());
5973
prebuilt->trx->op_info = (char*)"returning table comment";
5975
/* In case MySQL calls this in the middle of a SELECT query, release
5976
possible adaptive hash latch to avoid deadlocks of threads */
5978
trx_search_latch_release_if_reserved(prebuilt->trx);
5981
/* output the data to a temporary file */
5983
mutex_enter_noninline(&srv_dict_tmpfile_mutex);
5984
rewind(srv_dict_tmpfile);
5986
fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB",
5987
fsp_get_available_space_in_free_extents(
5988
prebuilt->table->space));
5990
dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
5991
prebuilt->trx, prebuilt->table);
5992
flen = ftell(srv_dict_tmpfile);
5995
} else if (length + flen + 3 > 64000) {
5996
flen = 64000 - 3 - length;
5999
/* allocate buffer for the full string, and
6000
read the contents of the temporary file */
6002
str = (char*) my_malloc(length + flen + 3, MYF(0));
6005
char* pos = str + length;
6007
memcpy(str, comment, length);
6011
rewind(srv_dict_tmpfile);
6012
flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
6016
mutex_exit_noninline(&srv_dict_tmpfile_mutex);
6018
prebuilt->trx->op_info = (char*)"";
6020
return(str ? str : (char*) comment);
6023
/***********************************************************************
6024
Gets the foreign key create info for a table stored in InnoDB. */
6027
ha_innobase::get_foreign_key_create_info(void)
6028
/*==========================================*/
6029
/* out, own: character string in the form which
6030
can be inserted to the CREATE TABLE statement,
6031
MUST be freed with ::free_foreign_key_create_info */
6036
ut_a(prebuilt != NULL);
6038
/* We do not know if MySQL can call this function before calling
6039
external_lock(). To be safe, update the thd of the current table
6042
update_thd(ha_thd());
6044
prebuilt->trx->op_info = (char*)"getting info on foreign keys";
6046
/* In case MySQL calls this in the middle of a SELECT query,
6047
release possible adaptive hash latch to avoid
6048
deadlocks of threads */
6050
trx_search_latch_release_if_reserved(prebuilt->trx);
6052
mutex_enter_noninline(&srv_dict_tmpfile_mutex);
6053
rewind(srv_dict_tmpfile);
6055
/* output the data to a temporary file */
6056
dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile,
6057
prebuilt->trx, prebuilt->table);
6058
prebuilt->trx->op_info = (char*)"";
6060
flen = ftell(srv_dict_tmpfile);
6063
} else if (flen > 64000 - 1) {
6067
/* allocate buffer for the string, and
6068
read the contents of the temporary file */
6070
str = (char*) my_malloc(flen + 1, MYF(0));
6073
rewind(srv_dict_tmpfile);
6074
flen = (uint) fread(str, 1, flen, srv_dict_tmpfile);
6078
mutex_exit_noninline(&srv_dict_tmpfile_mutex);
6085
ha_innobase::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
6087
dict_foreign_t* foreign;
6089
DBUG_ENTER("get_foreign_key_list");
6090
ut_a(prebuilt != NULL);
6091
update_thd(ha_thd());
6092
prebuilt->trx->op_info = (char*)"getting list of foreign keys";
6093
trx_search_latch_release_if_reserved(prebuilt->trx);
6094
mutex_enter_noninline(&(dict_sys->mutex));
6095
foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
6097
while (foreign != NULL) {
6099
FOREIGN_KEY_INFO f_key_info;
6100
LEX_STRING *name= 0;
6102
char uname[NAME_LEN+1]; /* Unencoded name */
6103
char db_name[NAME_LEN+1];
6104
const char *tmp_buff;
6106
tmp_buff= foreign->id;
6108
while (tmp_buff[i] != '/')
6111
f_key_info.forein_id = thd_make_lex_string(thd, 0,
6112
tmp_buff, (uint) strlen(tmp_buff), 1);
6113
tmp_buff= foreign->referenced_table_name;
6117
while (tmp_buff[i] != '/')
6119
db_name[i]= tmp_buff[i];
6123
ulen= filename_to_tablename(db_name, uname, sizeof(uname));
6124
f_key_info.referenced_db = thd_make_lex_string(thd, 0,
6129
ulen= filename_to_tablename(tmp_buff, uname, sizeof(uname));
6130
f_key_info.referenced_table = thd_make_lex_string(thd, 0,
6134
tmp_buff= foreign->foreign_col_names[i];
6135
name = thd_make_lex_string(thd, name,
6136
tmp_buff, (uint) strlen(tmp_buff), 1);
6137
f_key_info.foreign_fields.push_back(name);
6138
tmp_buff= foreign->referenced_col_names[i];
6139
name = thd_make_lex_string(thd, name,
6140
tmp_buff, (uint) strlen(tmp_buff), 1);
6141
f_key_info.referenced_fields.push_back(name);
6142
if (++i >= foreign->n_fields)
6147
if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
6150
tmp_buff= "CASCADE";
6152
else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
6155
tmp_buff= "SET NULL";
6157
else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
6160
tmp_buff= "NO ACTION";
6165
tmp_buff= "RESTRICT";
6167
f_key_info.delete_method = thd_make_lex_string(
6168
thd, f_key_info.delete_method, tmp_buff, length, 1);
6171
if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
6174
tmp_buff= "CASCADE";
6176
else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
6179
tmp_buff= "SET NULL";
6181
else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
6184
tmp_buff= "NO ACTION";
6189
tmp_buff= "RESTRICT";
6191
f_key_info.update_method = thd_make_lex_string(
6192
thd, f_key_info.update_method, tmp_buff, length, 1);
6193
if (foreign->referenced_index &&
6194
foreign->referenced_index->name)
6196
f_key_info.referenced_key_name = thd_make_lex_string(
6197
thd, f_key_info.referenced_key_name,
6198
foreign->referenced_index->name,
6199
strlen(foreign->referenced_index->name), 1);
6202
f_key_info.referenced_key_name= 0;
6204
FOREIGN_KEY_INFO *pf_key_info = (FOREIGN_KEY_INFO *)
6205
thd_memdup(thd, &f_key_info, sizeof(FOREIGN_KEY_INFO));
6206
f_key_list->push_back(pf_key_info);
6207
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
6209
mutex_exit_noninline(&(dict_sys->mutex));
6210
prebuilt->trx->op_info = (char*)"";
6215
/*********************************************************************
6216
Checks if ALTER TABLE may change the storage engine of the table.
6217
Changing storage engines is not allowed for tables for which there
6218
are foreign key constraints (parent or child tables). */
6221
ha_innobase::can_switch_engines(void)
6222
/*=================================*/
6226
DBUG_ENTER("ha_innobase::can_switch_engines");
6228
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
6230
prebuilt->trx->op_info =
6231
"determining if there are foreign key constraints";
6232
row_mysql_lock_data_dictionary(prebuilt->trx);
6234
can_switch = !UT_LIST_GET_FIRST(prebuilt->table->referenced_list)
6235
&& !UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
6237
row_mysql_unlock_data_dictionary(prebuilt->trx);
6238
prebuilt->trx->op_info = "";
6240
DBUG_RETURN(can_switch);
6243
/***********************************************************************
6244
Checks if a table is referenced by a foreign key. The MySQL manual states that
6245
a REPLACE is either equivalent to an INSERT, or DELETE(s) + INSERT. Only a
6246
delete is then allowed internally to resolve a duplicate key conflict in
6247
REPLACE, not an update. */
6250
ha_innobase::referenced_by_foreign_key(void)
6251
/*========================================*/
6252
/* out: > 0 if referenced by a FOREIGN KEY */
6254
if (dict_table_referenced_by_foreign_key(prebuilt->table)) {
6262
/***********************************************************************
6263
Frees the foreign key create info for a table stored in InnoDB, if it is
6267
ha_innobase::free_foreign_key_create_info(
6268
/*======================================*/
6269
char* str) /* in, own: create info string to free */
6272
my_free(str, MYF(0));
6276
/***********************************************************************
6277
Tells something additional to the handler about how to do things. */
6282
/* out: 0 or error number */
6283
enum ha_extra_function operation)
6284
/* in: HA_EXTRA_FLUSH or some other flag */
6286
/* Warning: since it is not sure that MySQL calls external_lock
6287
before calling this function, the trx field in prebuilt can be
6290
switch (operation) {
6291
case HA_EXTRA_FLUSH:
6292
if (prebuilt->blob_heap) {
6293
row_mysql_prebuilt_free_blob_heap(prebuilt);
6296
case HA_EXTRA_RESET_STATE:
6297
reset_template(prebuilt);
6299
/* Reset index condition pushdown state */
6300
pushed_idx_cond= FALSE;
6301
pushed_idx_cond_keyno= MAX_KEY;
6302
//in_range_read= FALSE;
6303
prebuilt->idx_cond_func= NULL;
6305
case HA_EXTRA_NO_KEYREAD:
6306
prebuilt->read_just_key = 0;
6308
case HA_EXTRA_KEYREAD:
6309
prebuilt->read_just_key = 1;
6311
case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
6312
prebuilt->keep_other_fields_on_keyread = 1;
6315
/* IMPORTANT: prebuilt->trx can be obsolete in
6316
this method, because it is not sure that MySQL
6317
calls external_lock before this method with the
6318
parameters below. We must not invoke update_thd()
6319
either, because the calling threads may change.
6320
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
6321
case HA_EXTRA_IGNORE_DUP_KEY:
6322
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE;
6324
case HA_EXTRA_WRITE_CAN_REPLACE:
6325
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
6327
case HA_EXTRA_WRITE_CANNOT_REPLACE:
6328
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
6330
case HA_EXTRA_NO_IGNORE_DUP_KEY:
6331
thd_to_trx(ha_thd())->duplicates &=
6332
~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
6334
default:/* Do nothing */
6341
int ha_innobase::reset()
6343
if (prebuilt->blob_heap) {
6344
row_mysql_prebuilt_free_blob_heap(prebuilt);
6346
reset_template(prebuilt);
6347
/* Reset index condition pushdown state */
6348
pushed_idx_cond_keyno= MAX_KEY;
6349
pushed_idx_cond= NULL;
6350
ds_mrr.dsmrr_close();
6351
prebuilt->idx_cond_func= NULL;
6356
/**********************************************************************
6357
MySQL calls this function at the start of each SQL statement inside LOCK
6358
TABLES. Inside LOCK TABLES the ::external_lock method does not work to
6359
mark SQL statement borders. Note also a special case: if a temporary table
6360
is created inside LOCK TABLES, MySQL has not called external_lock() at all
6362
MySQL-5.0 also calls this before each statement in an execution of a stored
6363
procedure. To make the execution more deterministic for binlogging, MySQL-5.0
6364
locks all tables involved in a stored procedure with full explicit table
6365
locks (thd_in_lock_tables(thd) holds in store_lock()) before executing the
6369
ha_innobase::start_stmt(
6370
/*====================*/
6371
/* out: 0 or error code */
6372
THD* thd, /* in: handle to the user thread */
6373
thr_lock_type lock_type)
6379
trx = prebuilt->trx;
6381
/* Here we release the search latch and the InnoDB thread FIFO ticket
6382
if they were reserved. They should have been released already at the
6383
end of the previous statement, but because inside LOCK TABLES the
6384
lock count method does not work to mark the end of a SELECT statement,
6385
that may not be the case. We MUST release the search latch before an
6386
INSERT, for example. */
6388
innobase_release_stat_resources(trx);
6390
/* Reset the AUTOINC statement level counter for multi-row INSERTs. */
6391
trx->n_autoinc_rows = 0;
6393
prebuilt->sql_stat_start = TRUE;
6394
prebuilt->hint_need_to_fetch_extra_cols = 0;
6395
reset_template(prebuilt);
6397
if (!prebuilt->mysql_has_locked) {
6398
/* This handle is for a temporary table created inside
6399
this same LOCK TABLES; since MySQL does NOT call external_lock
6400
in this case, we must use x-row locks inside InnoDB to be
6401
prepared for an update of a row */
6403
prebuilt->select_lock_type = LOCK_X;
6405
if (trx->isolation_level != TRX_ISO_SERIALIZABLE
6406
&& thd_sql_command(thd) == SQLCOM_SELECT
6407
&& lock_type == TL_READ) {
6409
/* For other than temporary tables, we obtain
6410
no lock for consistent read (plain SELECT). */
6412
prebuilt->select_lock_type = LOCK_NONE;
6414
/* Not a consistent read: restore the
6415
select_lock_type value. The value of
6416
stored_select_lock_type was decided in:
6418
2) ::external_lock(),
6419
3) ::init_table_handle_for_HANDLER(), and
6420
4) ::transactional_table_lock(). */
6422
prebuilt->select_lock_type =
6423
prebuilt->stored_select_lock_type;
6427
trx->detailed_error[0] = '\0';
6429
/* Set the MySQL flag to mark that there is an active transaction */
6430
if (trx->active_trans == 0) {
6432
innobase_register_trx_and_stmt(ht, thd);
6433
trx->active_trans = 1;
6435
innobase_register_stmt(ht, thd);
6441
/**********************************************************************
6442
Maps a MySQL trx isolation level code to the InnoDB isolation level code */
6445
innobase_map_isolation_level(
6446
/*=========================*/
6447
/* out: InnoDB isolation level */
6448
enum_tx_isolation iso) /* in: MySQL isolation level code */
6451
case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
6452
case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
6453
case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
6454
case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
6455
default: ut_a(0); return(0);
6459
/**********************************************************************
6460
As MySQL will execute an external lock for every new table it uses when it
6461
starts to process an SQL statement (an exception is when MySQL calls
6462
start_stmt for the handle) we can use this function to store the pointer to
6463
the THD in the handle. We will also use this function to communicate
6464
to InnoDB that a new SQL statement has started and that we must store a
6465
savepoint to our transaction handle, so that we are able to roll back
6466
the SQL statement in case of an error. */
6469
ha_innobase::external_lock(
6470
/*=======================*/
6472
THD* thd, /* in: handle to the user thread */
6473
int lock_type) /* in: lock type */
6477
DBUG_ENTER("ha_innobase::external_lock");
6478
DBUG_PRINT("enter",("lock_type: %d", lock_type));
6482
/* Statement based binlogging does not work in isolation level
6483
READ UNCOMMITTED and READ COMMITTED since the necessary
6484
locks cannot be taken. In this case, we print an
6485
informative error message and return with an error. */
6486
if (lock_type == F_WRLCK)
6488
ulong const binlog_format= thd_binlog_format(thd);
6489
ulong const tx_isolation = thd_tx_isolation(current_thd);
6490
if (tx_isolation <= ISO_READ_COMMITTED &&
6491
binlog_format == BINLOG_FORMAT_STMT)
6494
my_snprintf(buf, sizeof(buf),
6495
"Transaction level '%s' in"
6496
" InnoDB is not safe for binlog mode '%s'",
6497
tx_isolation_names[tx_isolation],
6498
binlog_format_names[binlog_format]);
6499
my_error(ER_BINLOG_LOGGING_IMPOSSIBLE, MYF(0), buf);
6500
DBUG_RETURN(HA_ERR_LOGGING_IMPOSSIBLE);
6505
trx = prebuilt->trx;
6507
prebuilt->sql_stat_start = TRUE;
6508
prebuilt->hint_need_to_fetch_extra_cols = 0;
6510
reset_template(prebuilt);
6512
if (lock_type == F_WRLCK) {
6514
/* If this is a SELECT, then it is in UPDATE TABLE ...
6515
or SELECT ... FOR UPDATE */
6516
prebuilt->select_lock_type = LOCK_X;
6517
prebuilt->stored_select_lock_type = LOCK_X;
6520
if (lock_type != F_UNLCK) {
6521
/* MySQL is setting a new table lock */
6523
trx->detailed_error[0] = '\0';
6525
/* Set the MySQL flag to mark that there is an active
6527
if (trx->active_trans == 0) {
6529
innobase_register_trx_and_stmt(ht, thd);
6530
trx->active_trans = 1;
6531
} else if (trx->n_mysql_tables_in_use == 0) {
6532
innobase_register_stmt(ht, thd);
6535
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
6536
&& prebuilt->select_lock_type == LOCK_NONE
6537
&& thd_test_options(thd,
6538
OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
6540
/* To get serializable execution, we let InnoDB
6541
conceptually add 'LOCK IN SHARE MODE' to all SELECTs
6542
which otherwise would have been consistent reads. An
6543
exception is consistent reads in the AUTOCOMMIT=1 mode:
6544
we know that they are read-only transactions, and they
6545
can be serialized also if performed as consistent
6548
prebuilt->select_lock_type = LOCK_S;
6549
prebuilt->stored_select_lock_type = LOCK_S;
6552
/* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
6553
TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
6554
an InnoDB table lock if it is released immediately at the end
6555
of LOCK TABLES, and InnoDB's table locks in that case cause
6556
VERY easily deadlocks.
6558
We do not set InnoDB table locks if user has not explicitly
6559
requested a table lock. Note that thd_in_lock_tables(thd)
6560
can hold in some cases, e.g., at the start of a stored
6561
procedure call (SQLCOM_CALL). */
6563
if (prebuilt->select_lock_type != LOCK_NONE) {
6565
if (thd_sql_command(thd) == SQLCOM_LOCK_TABLES
6566
&& THDVAR(thd, table_locks)
6567
&& thd_test_options(thd, OPTION_NOT_AUTOCOMMIT)
6568
&& thd_in_lock_tables(thd)) {
6570
ulint error = row_lock_table_for_mysql(
6573
if (error != DB_SUCCESS) {
6574
error = convert_error_code_to_mysql(
6576
DBUG_RETURN((int) error);
6580
trx->mysql_n_tables_locked++;
6583
trx->n_mysql_tables_in_use++;
6584
prebuilt->mysql_has_locked = TRUE;
6589
/* MySQL is releasing a table lock */
6591
trx->n_mysql_tables_in_use--;
6592
prebuilt->mysql_has_locked = FALSE;
6594
/* Release a possible FIFO ticket and search latch. Since we
6595
may reserve the kernel mutex, we have to release the search
6596
system latch first to obey the latching order. */
6598
innobase_release_stat_resources(trx);
6600
/* If the MySQL lock count drops to zero we know that the current SQL
6601
statement has ended */
6603
if (trx->n_mysql_tables_in_use == 0) {
6605
trx->mysql_n_tables_locked = 0;
6606
prebuilt->used_in_HANDLER = FALSE;
6608
if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
6609
if (trx->active_trans != 0) {
6610
innobase_commit(ht, thd, TRUE);
6613
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
6614
&& trx->global_read_view) {
6616
/* At low transaction isolation levels we let
6617
each consistent read set its own snapshot */
6619
read_view_close_for_mysql(trx);
6627
/**********************************************************************
6628
With this function MySQL request a transactional lock to a table when
6629
user issued query LOCK TABLES..WHERE ENGINE = InnoDB. */
6632
ha_innobase::transactional_table_lock(
6633
/*==================================*/
6634
/* out: error code */
6635
THD* thd, /* in: handle to the user thread */
6636
int lock_type) /* in: lock type */
6640
DBUG_ENTER("ha_innobase::transactional_table_lock");
6641
DBUG_PRINT("enter",("lock_type: %d", lock_type));
6643
/* We do not know if MySQL can call this function before calling
6644
external_lock(). To be safe, update the thd of the current table
6649
if (prebuilt->table->ibd_file_missing && !thd_tablespace_op(thd)) {
6650
ut_print_timestamp(stderr);
6652
" InnoDB: MySQL is trying to use a table handle"
6653
" but the .ibd file for\n"
6654
"InnoDB: table %s does not exist.\n"
6655
"InnoDB: Have you deleted the .ibd file"
6656
" from the database directory under\n"
6657
"InnoDB: the MySQL datadir?"
6659
" http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
6660
"InnoDB: how you can resolve the problem.\n",
6661
prebuilt->table->name);
6662
DBUG_RETURN(HA_ERR_CRASHED);
6665
trx = prebuilt->trx;
6667
prebuilt->sql_stat_start = TRUE;
6668
prebuilt->hint_need_to_fetch_extra_cols = 0;
6670
reset_template(prebuilt);
6672
if (lock_type == F_WRLCK) {
6673
prebuilt->select_lock_type = LOCK_X;
6674
prebuilt->stored_select_lock_type = LOCK_X;
6675
} else if (lock_type == F_RDLCK) {
6676
prebuilt->select_lock_type = LOCK_S;
6677
prebuilt->stored_select_lock_type = LOCK_S;
6679
ut_print_timestamp(stderr);
6680
fprintf(stderr, " InnoDB error:\n"
6681
"MySQL is trying to set transactional table lock with corrupted lock type\n"
6682
"to table %s, lock type %d does not exist.\n",
6683
prebuilt->table->name, lock_type);
6684
DBUG_RETURN(HA_ERR_CRASHED);
6687
/* MySQL is setting a new transactional table lock */
6689
/* Set the MySQL flag to mark that there is an active transaction */
6690
if (trx->active_trans == 0) {
6692
innobase_register_trx_and_stmt(ht, thd);
6693
trx->active_trans = 1;
6696
if (THDVAR(thd, table_locks) && thd_in_lock_tables(thd)) {
6697
ulint error = DB_SUCCESS;
6699
error = row_lock_table_for_mysql(prebuilt, NULL, 0);
6701
if (error != DB_SUCCESS) {
6702
error = convert_error_code_to_mysql((int) error, thd);
6703
DBUG_RETURN((int) error);
6706
if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
6708
/* Store the current undo_no of the transaction
6709
so that we know where to roll back if we have
6710
to roll back the next SQL statement */
6712
trx_mark_sql_stat_end(trx);
6719
/****************************************************************************
6720
Here we export InnoDB status variables to MySQL. */
6723
innodb_export_status()
6724
/*==================*/
6726
if (innodb_inited) {
6727
srv_export_innodb_status();
6733
/****************************************************************************
6734
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
6735
Monitor to the client. */
6740
handlerton* hton, /* in: the innodb handlerton */
6741
THD* thd, /* in: the MySQL query thread of the caller */
6742
stat_print_fn *stat_print)
6745
static const char truncated_msg[] = "... truncated...\n";
6746
const long MAX_STATUS_SIZE = 64000;
6747
ulint trx_list_start = ULINT_UNDEFINED;
6748
ulint trx_list_end = ULINT_UNDEFINED;
6750
DBUG_ENTER("innodb_show_status");
6752
trx = check_trx_exists(thd);
6754
innobase_release_stat_resources(trx);
6756
/* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
6759
long flen, usable_len;
6762
mutex_enter_noninline(&srv_monitor_file_mutex);
6763
rewind(srv_monitor_file);
6764
srv_printf_innodb_monitor(srv_monitor_file,
6765
&trx_list_start, &trx_list_end);
6766
flen = ftell(srv_monitor_file);
6767
os_file_set_eof(srv_monitor_file);
6773
if (flen > MAX_STATUS_SIZE) {
6774
usable_len = MAX_STATUS_SIZE;
6779
/* allocate buffer for the string, and
6780
read the contents of the temporary file */
6782
if (!(str = (char*) my_malloc(usable_len + 1, MYF(0)))) {
6783
mutex_exit_noninline(&srv_monitor_file_mutex);
6787
rewind(srv_monitor_file);
6788
if (flen < MAX_STATUS_SIZE) {
6789
/* Display the entire output. */
6790
flen = (long) fread(str, 1, flen, srv_monitor_file);
6791
} else if (trx_list_end < (ulint) flen
6792
&& trx_list_start < trx_list_end
6793
&& trx_list_start + (flen - trx_list_end)
6794
< MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
6795
/* Omit the beginning of the list of active transactions. */
6796
long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
6797
memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
6798
len += sizeof truncated_msg - 1;
6799
usable_len = (MAX_STATUS_SIZE - 1) - len;
6800
fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
6801
len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
6804
/* Omit the end of the output. */
6805
flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
6808
mutex_exit_noninline(&srv_monitor_file_mutex);
6810
bool result = FALSE;
6812
if (stat_print(thd, innobase_hton_name, strlen(innobase_hton_name),
6813
STRING_WITH_LEN(""), str, flen)) {
6816
my_free(str, MYF(0));
6821
/****************************************************************************
6822
Implements the SHOW MUTEX STATUS command. . */
6825
innodb_mutex_show_status(
6826
/*=====================*/
6827
handlerton* hton, /* in: the innodb handlerton */
6828
THD* thd, /* in: the MySQL query thread of the
6830
stat_print_fn* stat_print)
6832
char buf1[IO_SIZE], buf2[IO_SIZE];
6835
ulint rw_lock_count= 0;
6836
ulint rw_lock_count_spin_loop= 0;
6837
ulint rw_lock_count_spin_rounds= 0;
6838
ulint rw_lock_count_os_wait= 0;
6839
ulint rw_lock_count_os_yield= 0;
6840
ulonglong rw_lock_wait_time= 0;
6841
#endif /* UNIV_DEBUG */
6842
uint hton_name_len= strlen(innobase_hton_name), buf1len, buf2len;
6843
DBUG_ENTER("innodb_mutex_show_status");
6845
mutex_enter_noninline(&mutex_list_mutex);
6847
mutex = UT_LIST_GET_FIRST(mutex_list);
6849
while (mutex != NULL) {
6851
if (mutex->mutex_type != 1) {
6852
if (mutex->count_using > 0) {
6853
buf1len= my_snprintf(buf1, sizeof(buf1),
6855
mutex->cmutex_name, mutex->cfile_name);
6856
buf2len= my_snprintf(buf2, sizeof(buf2),
6857
"count=%lu, spin_waits=%lu,"
6858
" spin_rounds=%lu, "
6859
"os_waits=%lu, os_yields=%lu,"
6860
" os_wait_times=%lu",
6862
mutex->count_spin_loop,
6863
mutex->count_spin_rounds,
6864
mutex->count_os_wait,
6865
mutex->count_os_yield,
6866
(ulong) (mutex->lspent_time/1000));
6868
if (stat_print(thd, innobase_hton_name,
6869
hton_name_len, buf1, buf1len,
6871
mutex_exit_noninline(
6878
rw_lock_count += mutex->count_using;
6879
rw_lock_count_spin_loop += mutex->count_spin_loop;
6880
rw_lock_count_spin_rounds += mutex->count_spin_rounds;
6881
rw_lock_count_os_wait += mutex->count_os_wait;
6882
rw_lock_count_os_yield += mutex->count_os_yield;
6883
rw_lock_wait_time += mutex->lspent_time;
6885
#else /* UNIV_DEBUG */
6886
buf1len= my_snprintf(buf1, sizeof(buf1), "%s:%lu",
6887
mutex->cfile_name, (ulong) mutex->cline);
6888
buf2len= my_snprintf(buf2, sizeof(buf2), "os_waits=%lu",
6889
mutex->count_os_wait);
6891
if (stat_print(thd, innobase_hton_name,
6892
hton_name_len, buf1, buf1len,
6894
mutex_exit_noninline(&mutex_list_mutex);
6897
#endif /* UNIV_DEBUG */
6899
mutex = UT_LIST_GET_NEXT(list, mutex);
6902
mutex_exit_noninline(&mutex_list_mutex);
6905
buf2len= my_snprintf(buf2, sizeof(buf2),
6906
"count=%lu, spin_waits=%lu, spin_rounds=%lu, "
6907
"os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
6908
rw_lock_count, rw_lock_count_spin_loop,
6909
rw_lock_count_spin_rounds,
6910
rw_lock_count_os_wait, rw_lock_count_os_yield,
6911
(ulong) (rw_lock_wait_time/1000));
6913
if (stat_print(thd, innobase_hton_name, hton_name_len,
6914
STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
6917
#endif /* UNIV_DEBUG */
6923
bool innobase_show_status(handlerton *hton, THD* thd,
6924
stat_print_fn* stat_print,
6925
enum ha_stat_type stat_type)
6927
switch (stat_type) {
6928
case HA_ENGINE_STATUS:
6929
return innodb_show_status(hton, thd, stat_print);
6930
case HA_ENGINE_MUTEX:
6931
return innodb_mutex_show_status(hton, thd, stat_print);
6938
/****************************************************************************
6939
Handling the shared INNOBASE_SHARE structure that is needed to provide table
6941
****************************************************************************/
6943
static uchar* innobase_get_key(INNOBASE_SHARE* share, size_t *length,
6944
my_bool not_used __attribute__((unused)))
6946
*length=share->table_name_length;
6948
return (uchar*) share->table_name;
6951
static INNOBASE_SHARE* get_share(const char* table_name)
6953
INNOBASE_SHARE *share;
6954
pthread_mutex_lock(&innobase_share_mutex);
6955
uint length=(uint) strlen(table_name);
6957
if (!(share=(INNOBASE_SHARE*) hash_search(&innobase_open_tables,
6958
(uchar*) table_name,
6961
share = (INNOBASE_SHARE *) my_malloc(sizeof(*share)+length+1,
6962
MYF(MY_FAE | MY_ZEROFILL));
6964
share->table_name_length=length;
6965
share->table_name=(char*) (share+1);
6966
strmov(share->table_name,table_name);
6968
if (my_hash_insert(&innobase_open_tables,
6970
pthread_mutex_unlock(&innobase_share_mutex);
6976
thr_lock_init(&share->lock);
6977
pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
6981
pthread_mutex_unlock(&innobase_share_mutex);
6986
static void free_share(INNOBASE_SHARE* share)
6988
pthread_mutex_lock(&innobase_share_mutex);
6990
if (!--share->use_count) {
6991
hash_delete(&innobase_open_tables, (uchar*) share);
6992
thr_lock_delete(&share->lock);
6993
pthread_mutex_destroy(&share->mutex);
6994
my_free(share, MYF(0));
6997
pthread_mutex_unlock(&innobase_share_mutex);
7000
/*********************************************************************
7001
Converts a MySQL table lock stored in the 'lock' field of the handle to
7002
a proper type before storing pointer to the lock into an array of pointers.
7003
MySQL also calls this if it wants to reset some table locks to a not-locked
7004
state during the processing of an SQL query. An example is that during a
7005
SELECT the read lock is released early on the 'const' tables where we only
7006
fetch one row. MySQL does not call this when it releases all locks at the
7007
end of an SQL statement. */
7010
ha_innobase::store_lock(
7011
/*====================*/
7012
/* out: pointer to the next
7013
element in the 'to' array */
7014
THD* thd, /* in: user thread handle */
7015
THR_LOCK_DATA** to, /* in: pointer to an array
7016
of pointers to lock structs;
7017
pointer to the 'lock' field
7018
of current handle is stored
7019
next to this array */
7020
enum thr_lock_type lock_type) /* in: lock type to store in
7021
'lock'; this may also be
7026
/* Note that trx in this function is NOT necessarily prebuilt->trx
7027
because we call update_thd() later, in ::external_lock()! Failure to
7028
understand this caused a serious memory corruption bug in 5.1.11. */
7030
trx = check_trx_exists(thd);
7032
/* NOTE: MySQL can call this function with lock 'type' TL_IGNORE!
7033
Be careful to ignore TL_IGNORE if we are going to do something with
7034
only 'real' locks! */
7036
/* If no MySQL table is in use, we need to set the isolation level
7037
of the transaction. */
7039
if (lock_type != TL_IGNORE
7040
&& trx->n_mysql_tables_in_use == 0) {
7041
trx->isolation_level = innobase_map_isolation_level(
7042
(enum_tx_isolation) thd_tx_isolation(thd));
7044
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
7045
&& trx->global_read_view) {
7047
/* At low transaction isolation levels we let
7048
each consistent read set its own snapshot */
7050
read_view_close_for_mysql(trx);
7054
DBUG_ASSERT(thd == current_thd);
7055
const bool in_lock_tables = thd_in_lock_tables(thd);
7056
const uint sql_command = thd_sql_command(thd);
7058
if (sql_command == SQLCOM_DROP_TABLE) {
7060
/* MySQL calls this function in DROP TABLE though this table
7061
handle may belong to another thd that is running a query. Let
7062
us in that case skip any changes to the prebuilt struct. */
7064
} else if ((lock_type == TL_READ && in_lock_tables)
7065
|| (lock_type == TL_READ_HIGH_PRIORITY && in_lock_tables)
7066
|| lock_type == TL_READ_WITH_SHARED_LOCKS
7067
|| lock_type == TL_READ_NO_INSERT
7068
|| (lock_type != TL_IGNORE
7069
&& sql_command != SQLCOM_SELECT)) {
7071
/* The OR cases above are in this order:
7072
1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
7073
are processing a stored procedure or function, or
7074
2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
7075
3) this is a SELECT ... IN SHARE MODE, or
7076
4) we are doing a complex SQL statement like
7077
INSERT INTO ... SELECT ... and the logical logging (MySQL
7078
binlog) requires the use of a locking read, or
7079
MySQL is doing LOCK TABLES ... READ.
7080
5) we let InnoDB do locking reads for all SQL statements that
7081
are not simple SELECTs; note that select_lock_type in this
7082
case may get strengthened in ::external_lock() to LOCK_X.
7083
Note that we MUST use a locking read in all data modifying
7084
SQL statements, because otherwise the execution would not be
7085
serializable, and also the results from the update could be
7086
unexpected if an obsolete consistent read view would be
7089
ulint isolation_level;
7091
isolation_level = trx->isolation_level;
7093
if ((srv_locks_unsafe_for_binlog
7094
|| isolation_level == TRX_ISO_READ_COMMITTED)
7095
&& isolation_level != TRX_ISO_SERIALIZABLE
7096
&& (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
7097
&& (sql_command == SQLCOM_INSERT_SELECT
7098
|| sql_command == SQLCOM_UPDATE
7099
|| sql_command == SQLCOM_CREATE_TABLE)) {
7101
/* If we either have innobase_locks_unsafe_for_binlog
7102
option set or this session is using READ COMMITTED
7103
isolation level and isolation level of the transaction
7104
is not set to serializable and MySQL is doing
7105
INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
7106
CREATE ... SELECT... without FOR UPDATE or
7107
IN SHARE MODE in select, then we use consistent
7110
prebuilt->select_lock_type = LOCK_NONE;
7111
prebuilt->stored_select_lock_type = LOCK_NONE;
7112
} else if (sql_command == SQLCOM_CHECKSUM) {
7113
/* Use consistent read for checksum table */
7115
prebuilt->select_lock_type = LOCK_NONE;
7116
prebuilt->stored_select_lock_type = LOCK_NONE;
7118
prebuilt->select_lock_type = LOCK_S;
7119
prebuilt->stored_select_lock_type = LOCK_S;
7122
} else if (lock_type != TL_IGNORE) {
7124
/* We set possible LOCK_X value in external_lock, not yet
7125
here even if this would be SELECT ... FOR UPDATE */
7127
prebuilt->select_lock_type = LOCK_NONE;
7128
prebuilt->stored_select_lock_type = LOCK_NONE;
7131
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
7133
/* Starting from 5.0.7, we weaken also the table locks
7134
set at the start of a MySQL stored procedure call, just like
7135
we weaken the locks set at the start of an SQL statement.
7136
MySQL does set in_lock_tables TRUE there, but in reality
7137
we do not need table locks to make the execution of a
7138
single transaction stored procedure call deterministic
7139
(if it does not use a consistent read). */
7141
if (lock_type == TL_READ
7142
&& sql_command == SQLCOM_LOCK_TABLES) {
7143
/* We come here if MySQL is processing LOCK TABLES
7144
... READ LOCAL. MyISAM under that table lock type
7145
reads the table as it was at the time the lock was
7146
granted (new inserts are allowed, but not seen by the
7147
reader). To get a similar effect on an InnoDB table,
7148
we must use LOCK TABLES ... READ. We convert the lock
7149
type here, so that for InnoDB, READ LOCAL is
7150
equivalent to READ. This will change the InnoDB
7151
behavior in mysqldump, so that dumps of InnoDB tables
7152
are consistent with dumps of MyISAM tables. */
7154
lock_type = TL_READ_NO_INSERT;
7157
/* If we are not doing a LOCK TABLE, DISCARD/IMPORT
7158
TABLESPACE or TRUNCATE TABLE then allow multiple
7159
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
7160
< TL_WRITE_CONCURRENT_INSERT.
7162
We especially allow multiple writers if MySQL is at the
7163
start of a stored procedure call (SQLCOM_CALL) or a
7164
stored function call (MySQL does have in_lock_tables
7167
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
7168
&& lock_type <= TL_WRITE)
7170
&& sql_command == SQLCOM_LOCK_TABLES)
7171
&& !thd_tablespace_op(thd)
7172
&& sql_command != SQLCOM_TRUNCATE
7173
&& sql_command != SQLCOM_OPTIMIZE
7174
&& sql_command != SQLCOM_CREATE_TABLE) {
7176
lock_type = TL_WRITE_ALLOW_WRITE;
7179
/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
7180
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
7181
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
7182
to t2. Convert the lock to a normal read lock to allow
7183
concurrent inserts to t2.
7185
We especially allow concurrent inserts if MySQL is at the
7186
start of a stored procedure call (SQLCOM_CALL)
7187
(MySQL does have thd_in_lock_tables() TRUE there). */
7189
if (lock_type == TL_READ_NO_INSERT
7190
&& sql_command != SQLCOM_LOCK_TABLES) {
7192
lock_type = TL_READ;
7195
lock.type = lock_type;
7203
/***********************************************************************
7204
This function initializes the auto-inc counter if it has not been
7205
initialized yet. This function does not change the value of the auto-inc
7206
counter if it already has been initialized. In parameter ret returns
7207
the value of the auto-inc counter. */
7210
ha_innobase::innobase_read_and_init_auto_inc(
7211
/*=========================================*/
7212
/* out: 0 or generic MySQL
7214
longlong* value) /* out: the autoinc value */
7218
int mysql_error = 0;
7219
dict_table_t* innodb_table = prebuilt->table;
7220
ibool trx_was_not_started = FALSE;
7223
ut_a(prebuilt->table);
7225
/* Remember if we are in the beginning of an SQL statement.
7226
This function must not change that flag. */
7227
stmt_start = prebuilt->sql_stat_start;
7229
/* Prepare prebuilt->trx in the table handle */
7230
update_thd(ha_thd());
7232
if (prebuilt->trx->conc_state == TRX_NOT_STARTED) {
7233
trx_was_not_started = TRUE;
7236
/* In case MySQL calls this in the middle of a SELECT query, release
7237
possible adaptive hash latch to avoid deadlocks of threads */
7239
trx_search_latch_release_if_reserved(prebuilt->trx);
7241
dict_table_autoinc_lock(prebuilt->table);
7243
auto_inc = dict_table_autoinc_read(prebuilt->table);
7245
/* Was the AUTOINC counter reset during normal processing, if
7246
so then we simply start count from 1. No need to go to the index.*/
7247
if (auto_inc == 0 && innodb_table->autoinc_inited) {
7249
dict_table_autoinc_initialize(innodb_table, auto_inc);
7252
if (auto_inc == 0) {
7253
dict_index_t* index;
7255
const char* autoinc_col_name;
7257
ut_a(!innodb_table->autoinc_inited);
7259
index = innobase_get_index(table->s->next_number_index);
7261
autoinc_col_name = table->found_next_number_field->field_name;
7263
error = row_search_max_autoinc(
7264
index, autoinc_col_name, &auto_inc);
7266
if (error == DB_SUCCESS) {
7268
dict_table_autoinc_initialize(innodb_table, auto_inc);
7270
ut_print_timestamp(stderr);
7271
fprintf(stderr, " InnoDB: Error: (%lu) Couldn't read "
7272
"the max AUTOINC value from the index (%s).\n",
7273
error, index->name);
7281
dict_table_autoinc_unlock(prebuilt->table);
7283
/* Since MySQL does not seem to call autocommit after SHOW TABLE
7284
STATUS (even if we would register the trx here), we commit our
7285
transaction here if it was started here. This is to eliminate a
7286
dangling transaction. If the user had AUTOCOMMIT=0, then SHOW
7287
TABLE STATUS does leave a dangling transaction if the user does not
7288
himself call COMMIT. */
7290
if (trx_was_not_started) {
7292
innobase_commit_low(prebuilt->trx);
7295
prebuilt->sql_stat_start = stmt_start;
7297
return(mysql_error);
7300
/*******************************************************************************
7301
Read the next autoinc value, initialize the table if it's not initialized.
7302
On return if there is no error then the tables AUTOINC lock is locked.*/
7305
ha_innobase::innobase_get_auto_increment(
7306
ulonglong* value) /* out: autoinc value */
7312
/* Note: If the table is not initialized when we attempt the
7313
read below. We initialize the table's auto-inc counter and
7314
always do a reread of the AUTOINC value. */
7316
error = innobase_autoinc_lock();
7318
if (error == DB_SUCCESS) {
7319
ib_longlong autoinc;
7321
/* Determine the first value of the interval */
7322
autoinc = dict_table_autoinc_read(prebuilt->table);
7324
/* We need to initialize the AUTO-INC value, for
7325
that we release all locks.*/
7329
trx = prebuilt->trx;
7330
dict_table_autoinc_unlock(prebuilt->table);
7332
/* If we had reserved the AUTO-INC
7333
lock in this SQL statement we release
7334
it before retrying.*/
7335
row_unlock_table_autoinc_for_mysql(trx);
7337
/* Just to make sure */
7338
ut_a(!trx->auto_inc_lock);
7342
mysql_error = innobase_read_and_init_auto_inc(
7346
/* Should have read the proper value */
7352
*value = (ulonglong) autoinc;
7354
/* A deadlock error during normal processing is OK
7355
and can be ignored. */
7356
} else if (error != DB_DEADLOCK) {
7358
sql_print_error("InnoDB: Error: %lu in "
7359
"::innobase_get_auto_increment()",
7363
} while (*value == 0 && error == DB_SUCCESS);
7368
/*******************************************************************************
7369
This function initializes the auto-inc counter if it has not been
7370
initialized yet. This function does not change the value of the auto-inc
7371
counter if it already has been initialized. Returns the value of the
7372
auto-inc counter in *first_value, and ULONGLONG_MAX in *nb_reserved_values (as
7373
we have a table-level lock). offset, increment, nb_desired_values are ignored.
7374
*first_value is set to -1 if error (deadlock or lock wait timeout) */
7377
ha_innobase::get_auto_increment(
7378
/*============================*/
7379
ulonglong offset, /* in: */
7380
ulonglong increment, /* in: table autoinc increment */
7381
ulonglong nb_desired_values, /* in: number of values reqd */
7382
ulonglong *first_value, /* out: the autoinc value */
7383
ulonglong *nb_reserved_values) /* out: count of reserved values */
7387
ulonglong autoinc = 0;
7389
/* Prepare prebuilt->trx in the table handle */
7390
update_thd(ha_thd());
7392
error = innobase_get_auto_increment(&autoinc);
7394
if (error != DB_SUCCESS) {
7395
*first_value = (~(ulonglong) 0);
7399
/* This is a hack, since nb_desired_values seems to be accurate only
7400
for the first call to get_auto_increment() for multi-row INSERT and
7401
meaningless for other statements e.g, LOAD etc. Subsequent calls to
7402
this method for the same statement results in different values which
7403
don't make sense. Therefore we store the value the first time we are
7404
called and count down from that as rows are written (see write_row()).
7407
trx = prebuilt->trx;
7409
/* Note: We can't rely on *first_value since some MySQL engines,
7410
in particular the partition engine, don't initialize it to 0 when
7411
invoking this method. So we are not sure if it's guaranteed to
7414
/* Called for the first time ? */
7415
if (trx->n_autoinc_rows == 0) {
7417
trx->n_autoinc_rows = (ulint) nb_desired_values;
7419
/* It's possible for nb_desired_values to be 0:
7420
e.g., INSERT INTO T1(C) SELECT C FROM T2; */
7421
if (nb_desired_values == 0) {
7423
trx->n_autoinc_rows = 1;
7426
set_if_bigger(*first_value, autoinc);
7427
/* Not in the middle of a mult-row INSERT. */
7428
} else if (prebuilt->last_value == 0) {
7429
set_if_bigger(*first_value, autoinc);
7432
*nb_reserved_values = trx->n_autoinc_rows;
7434
/* With old style AUTOINC locking we only update the table's
7435
AUTOINC counter after attempting to insert the row. */
7436
if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
7438
/* Compute the last value in the interval */
7439
prebuilt->last_value = *first_value +
7440
(*nb_reserved_values * increment);
7442
ut_a(prebuilt->last_value >= *first_value);
7444
/* Update the table autoinc variable */
7445
dict_table_autoinc_update(
7446
prebuilt->table, prebuilt->last_value);
7448
/* This will force write_row() into attempting an update
7449
of the table's AUTOINC counter. */
7450
prebuilt->last_value = 0;
7453
/* The increment to be used to increase the AUTOINC value, we use
7454
this in write_row() and update_row() to increase the autoinc counter
7455
for columns that are filled by the user.*/
7456
prebuilt->table->autoinc_increment = increment;
7458
dict_table_autoinc_unlock(prebuilt->table);
7461
/* See comment in handler.h */
7463
ha_innobase::reset_auto_increment(
7464
/*==============================*/
7465
ulonglong value) /* in: new value for table autoinc */
7467
DBUG_ENTER("ha_innobase::reset_auto_increment");
7471
update_thd(ha_thd());
7473
error = row_lock_table_autoinc_for_mysql(prebuilt);
7475
if (error != DB_SUCCESS) {
7476
error = convert_error_code_to_mysql(error, user_thd);
7481
innobase_reset_autoinc(value);
7486
/* See comment in handler.cc */
7488
ha_innobase::get_error_message(int error, String *buf)
7490
trx_t* trx = check_trx_exists(ha_thd());
7492
buf->copy(trx->detailed_error, strlen(trx->detailed_error),
7493
system_charset_info);
7498
/***********************************************************************
7499
Compares two 'refs'. A 'ref' is the (internal) primary key value of the row.
7500
If there is no explicitly declared non-null unique key or a primary key, then
7501
InnoDB internally uses the row id as the primary key. */
7504
ha_innobase::cmp_ref(
7505
/*=================*/
7506
/* out: < 0 if ref1 < ref2, 0 if equal, else
7508
const uchar* ref1, /* in: an (internal) primary key value in the
7509
MySQL key value format */
7510
const uchar* ref2) /* in: an (internal) primary key value in the
7511
MySQL key value format */
7513
enum_field_types mysql_type;
7515
KEY_PART_INFO* key_part;
7516
KEY_PART_INFO* key_part_end;
7521
if (prebuilt->clust_index_was_generated) {
7522
/* The 'ref' is an InnoDB row id */
7524
return(memcmp(ref1, ref2, DATA_ROW_ID_LEN));
7527
/* Do a type-aware comparison of primary key fields. PK fields
7528
are always NOT NULL, so no checks for NULL are performed. */
7530
key_part = table->key_info[table->s->primary_key].key_part;
7532
key_part_end = key_part
7533
+ table->key_info[table->s->primary_key].key_parts;
7535
for (; key_part != key_part_end; ++key_part) {
7536
field = key_part->field;
7537
mysql_type = field->type();
7539
if (mysql_type == MYSQL_TYPE_TINY_BLOB
7540
|| mysql_type == MYSQL_TYPE_MEDIUM_BLOB
7541
|| mysql_type == MYSQL_TYPE_BLOB
7542
|| mysql_type == MYSQL_TYPE_LONG_BLOB) {
7544
/* In the MySQL key value format, a column prefix of
7545
a BLOB is preceded by a 2-byte length field */
7547
len1 = innobase_read_from_2_little_endian(ref1);
7548
len2 = innobase_read_from_2_little_endian(ref2);
7552
result = ((Field_blob*)field)->cmp( ref1, len1,
7555
result = field->key_cmp(ref1, ref2);
7563
ref1 += key_part->store_length;
7564
ref2 += key_part->store_length;
7570
/***********************************************************************
7571
Ask InnoDB if a query to a table can be cached. */
7574
ha_innobase::register_query_cache_table(
7575
/*====================================*/
7576
/* out: TRUE if query caching
7577
of the table is permitted */
7578
THD* thd, /* in: user thread handle */
7579
char* table_key, /* in: concatenation of database name,
7580
the null character '\0',
7581
and the table name */
7582
uint key_length, /* in: length of the full name, i.e.
7583
len(dbname) + len(tablename) + 1 */
7585
call_back, /* out: pointer to function for
7586
checking if query caching
7588
ulonglong *engine_data) /* in/out: data to call_back */
7590
*call_back = innobase_query_caching_of_table_permitted;
7592
return(innobase_query_caching_of_table_permitted(thd, table_key,
7598
ha_innobase::get_mysql_bin_log_name()
7600
return(trx_sys_mysql_bin_log_name);
7604
ha_innobase::get_mysql_bin_log_pos()
7606
/* trx... is ib_longlong, which is a typedef for a 64-bit integer
7607
(__int64 or longlong) so it's ok to cast it to ulonglong. */
7609
return(trx_sys_mysql_bin_log_pos);
7612
/**********************************************************************
7613
This function is used to find the storage length in bytes of the first n
7614
characters for prefix indexes using a multibyte character set. The function
7615
finds charset information and returns length of prefix_len characters in the
7616
index field in bytes.
7618
NOTE: the prototype of this function is copied to data0type.c! If you change
7619
this function, you MUST change also data0type.c! */
7622
innobase_get_at_most_n_mbchars(
7623
/*===========================*/
7624
/* out: number of bytes occupied by the first
7626
ulint charset_id, /* in: character set id */
7627
ulint prefix_len, /* in: prefix length in bytes of the index
7628
(this has to be divided by mbmaxlen to get the
7629
number of CHARACTERS n in the prefix) */
7630
ulint data_len, /* in: length of the string in bytes */
7631
const char* str) /* in: character string */
7633
ulint char_length; /* character length in bytes */
7634
ulint n_chars; /* number of characters in prefix */
7635
CHARSET_INFO* charset; /* charset used in the field */
7637
charset = get_charset((uint) charset_id, MYF(MY_WME));
7640
ut_ad(charset->mbmaxlen);
7642
/* Calculate how many characters at most the prefix index contains */
7644
n_chars = prefix_len / charset->mbmaxlen;
7646
/* If the charset is multi-byte, then we must find the length of the
7647
first at most n chars in the string. If the string contains less
7648
characters than n, then we return the length to the end of the last
7651
if (charset->mbmaxlen > 1) {
7652
/* my_charpos() returns the byte length of the first n_chars
7653
characters, or a value bigger than the length of str, if
7654
there were not enough full characters in str.
7656
Why does the code below work:
7657
Suppose that we are looking for n UTF-8 characters.
7659
1) If the string is long enough, then the prefix contains at
7660
least n complete UTF-8 characters + maybe some extra
7661
characters + an incomplete UTF-8 character. No problem in
7662
this case. The function returns the pointer to the
7663
end of the nth character.
7665
2) If the string is not long enough, then the string contains
7666
the complete value of a column, that is, only complete UTF-8
7667
characters, and we can store in the column prefix index the
7670
char_length = my_charpos(charset, str,
7671
str + data_len, (int) n_chars);
7672
if (char_length > data_len) {
7673
char_length = data_len;
7676
if (data_len < prefix_len) {
7677
char_length = data_len;
7679
char_length = prefix_len;
7683
return(char_length);
7686
/***********************************************************************
7687
This function is used to prepare X/Open XA distributed transaction */
7690
innobase_xa_prepare(
7691
/*================*/
7692
/* out: 0 or error number */
7694
THD* thd, /* in: handle to the MySQL thread of the user
7695
whose XA transaction should be prepared */
7696
bool all) /* in: TRUE - commit transaction
7697
FALSE - the current SQL statement ended */
7700
trx_t* trx = check_trx_exists(thd);
7702
if (thd_sql_command(thd) != SQLCOM_XA_PREPARE &&
7703
(all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
7706
/* For ibbackup to work the order of transactions in binlog
7707
and InnoDB must be the same. Consider the situation
7709
thread1> prepare; write to binlog; ...
7711
thread2> prepare; write to binlog; commit
7714
To ensure this will not happen we're taking the mutex on
7715
prepare, and releasing it on commit.
7717
Note: only do it for normal commits, done via ha_commit_trans.
7718
If 2pc protocol is executed by external transaction
7719
coordinator, it will be just a regular MySQL client
7720
executing XA PREPARE and XA COMMIT commands.
7721
In this case we cannot know how many minutes or hours
7722
will be between XA PREPARE and XA COMMIT, and we don't want
7723
to block for undefined period of time.
7725
pthread_mutex_lock(&prepare_commit_mutex);
7726
trx->active_trans = 2;
7729
if (!THDVAR(thd, support_xa)) {
7734
thd_get_xid(thd, (MYSQL_XID*) &trx->xid);
7736
/* Release a possible FIFO ticket and search latch. Since we will
7737
reserve the kernel mutex, we have to release the search system latch
7738
first to obey the latching order. */
7740
innobase_release_stat_resources(trx);
7742
if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) {
7744
sql_print_error("trx->active_trans == 0, but trx->conc_state != "
7749
|| (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
7751
/* We were instructed to prepare the whole transaction, or
7752
this is an SQL statement end and autocommit is on */
7754
ut_ad(trx->active_trans);
7756
error = (int) trx_prepare_for_mysql(trx);
7758
/* We just mark the SQL statement ended and do not do a
7759
transaction prepare */
7761
/* If we had reserved the auto-inc lock for some
7762
table in this SQL statement we release it now */
7764
row_unlock_table_autoinc_for_mysql(trx);
7766
/* Store the current undo_no of the transaction so that we
7767
know where to roll back if we have to roll back the next
7770
trx_mark_sql_stat_end(trx);
7773
/* Tell the InnoDB server that there might be work for utility
7776
srv_active_wake_master_thread();
7781
/***********************************************************************
7782
This function is used to recover X/Open XA distributed transactions */
7785
innobase_xa_recover(
7786
/*================*/
7787
/* out: number of prepared transactions
7788
stored in xid_list */
7790
XID* xid_list, /* in/out: prepared transactions */
7791
uint len) /* in: number of slots in xid_list */
7793
if (len == 0 || xid_list == NULL) {
7798
return(trx_recover_for_mysql(xid_list, len));
7801
/***********************************************************************
7802
This function is used to commit one X/Open XA distributed transaction
7803
which is in the prepared state */
7806
innobase_commit_by_xid(
7807
/*===================*/
7808
/* out: 0 or error number */
7810
XID* xid) /* in: X/Open XA transaction identification */
7814
trx = trx_get_trx_by_xid(xid);
7817
innobase_commit_low(trx);
7825
/***********************************************************************
7826
This function is used to rollback one X/Open XA distributed transaction
7827
which is in the prepared state */
7830
innobase_rollback_by_xid(
7831
/*=====================*/
7832
/* out: 0 or error number */
7834
XID *xid) /* in: X/Open XA transaction identification */
7838
trx = trx_get_trx_by_xid(xid);
7841
return(innobase_rollback_trx(trx));
7847
/***********************************************************************
7848
Create a consistent view for a cursor based on current transaction
7849
which is created if the corresponding MySQL thread still lacks one.
7850
This consistent view is then used inside of MySQL when accessing records
7854
innobase_create_cursor_view(
7855
/*========================*/
7856
/* out: pointer to cursor view or NULL */
7857
handlerton *hton, /* in: innobase hton */
7858
THD* thd) /* in: user thread handle */
7860
return(read_cursor_view_create_for_mysql(check_trx_exists(thd)));
7863
/***********************************************************************
7864
Close the given consistent cursor view of a transaction and restore
7865
global read view to a transaction read view. Transaction is created if the
7866
corresponding MySQL thread still lacks one. */
7869
innobase_close_cursor_view(
7870
/*=======================*/
7872
THD* thd, /* in: user thread handle */
7873
void* curview)/* in: Consistent read view to be closed */
7875
read_cursor_view_close_for_mysql(check_trx_exists(thd),
7876
(cursor_view_t*) curview);
7879
/***********************************************************************
7880
Set the given consistent cursor view to a transaction which is created
7881
if the corresponding MySQL thread still lacks one. If the given
7882
consistent cursor view is NULL global read view of a transaction is
7883
restored to a transaction read view. */
7886
innobase_set_cursor_view(
7887
/*=====================*/
7889
THD* thd, /* in: user thread handle */
7890
void* curview)/* in: Consistent cursor view to be set */
7892
read_cursor_set_for_mysql(check_trx_exists(thd),
7893
(cursor_view_t*) curview);
7897
bool ha_innobase::check_if_incompatible_data(
7898
HA_CREATE_INFO* info,
7901
if (table_changes != IS_EQUAL_YES) {
7903
return COMPATIBLE_DATA_NO;
7906
/* Check that auto_increment value was not changed */
7907
if ((info->used_fields & HA_CREATE_USED_AUTO) &&
7908
info->auto_increment_value != 0) {
7910
return COMPATIBLE_DATA_NO;
7913
/* Check that row format didn't change */
7914
if ((info->used_fields & HA_CREATE_USED_ROW_FORMAT) &&
7915
get_row_type() != info->row_type) {
7917
return COMPATIBLE_DATA_NO;
7920
return COMPATIBLE_DATA_YES;
7923
static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff)
7925
innodb_export_status();
7926
var->type= SHOW_ARRAY;
7927
var->value= (char *) &innodb_status_variables;
7931
static SHOW_VAR innodb_status_variables_export[]= {
7932
{"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
7933
{NullS, NullS, SHOW_LONG}
7936
static struct st_mysql_storage_engine innobase_storage_engine=
7937
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
7939
/* plugin options */
7940
static MYSQL_SYSVAR_BOOL(checksums, innobase_use_checksums,
7941
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
7942
"Enable InnoDB checksums validation (enabled by default). "
7943
"Disable with --skip-innodb-checksums.",
7946
static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
7947
PLUGIN_VAR_READONLY,
7948
"The common part for InnoDB table spaces.",
7951
static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
7952
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
7953
"Enable InnoDB doublewrite buffer (enabled by default). "
7954
"Disable with --skip-innodb-doublewrite.",
7957
static MYSQL_SYSVAR_ULONG(fast_shutdown, innobase_fast_shutdown,
7958
PLUGIN_VAR_OPCMDARG,
7959
"Speeds up the shutdown process of the InnoDB storage engine. Possible "
7960
"values are 0, 1 (faster)"
7962
NetWare can't close unclosed files, can't automatically kill remaining
7963
threads, etc, so on this OS we disable the crash-like InnoDB shutdown.
7965
" or 2 (fastest - crash-like)"
7967
NULL, NULL, 1, 0, 2, 0);
7969
static MYSQL_SYSVAR_BOOL(file_per_table, innobase_file_per_table,
7970
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
7971
"Stores each InnoDB table to an .ibd file in the database dir.",
7974
static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
7975
PLUGIN_VAR_OPCMDARG,
7976
"Set to 0 (write and flush once per second),"
7977
" 1 (write and flush at each commit)"
7978
" or 2 (write at commit, flush once per second).",
7979
NULL, NULL, 1, 0, 2, 0);
7981
static MYSQL_SYSVAR_STR(flush_method, innobase_unix_file_flush_method,
7982
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7983
"With which method to flush data.", NULL, NULL, NULL);
7985
static MYSQL_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binlog,
7986
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
7987
"Force InnoDB to not use next-key locking, to use only row-level locking.",
7990
#ifdef UNIV_LOG_ARCHIVE
7991
static MYSQL_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir,
7992
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
7993
"Where full logs should be archived.", NULL, NULL, NULL);
7995
static MYSQL_SYSVAR_BOOL(log_archive, innobase_log_archive,
7996
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
7997
"Set to 1 if you want to have logs archived.", NULL, NULL, FALSE);
7998
#endif /* UNIV_LOG_ARCHIVE */
8000
static MYSQL_SYSVAR_STR(log_group_home_dir, innobase_log_group_home_dir,
8001
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8002
"Path to InnoDB log files.", NULL, NULL, NULL);
8004
static MYSQL_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
8005
PLUGIN_VAR_RQCMDARG,
8006
"Percentage of dirty pages allowed in bufferpool.",
8007
NULL, NULL, 90, 0, 100, 0);
8009
static MYSQL_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
8010
PLUGIN_VAR_RQCMDARG,
8011
"Desired maximum length of the purge queue (0 = no limit)",
8012
NULL, NULL, 0, 0, ~0L, 0);
8014
static MYSQL_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
8015
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
8016
"Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)",
8019
static MYSQL_SYSVAR_BOOL(status_file, innobase_create_status_file,
8020
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR,
8021
"Enable SHOW INNODB STATUS output in the innodb_status.<pid> file",
8024
static MYSQL_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata,
8025
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR,
8026
"Enable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)",
8029
static MYSQL_SYSVAR_BOOL(use_adaptive_hash_indexes, innobase_use_adaptive_hash_indexes,
8030
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
8031
"Enable the InnoDB adaptive hash indexes (enabled by default)",
8034
static MYSQL_SYSVAR_LONG(additional_mem_pool_size, innobase_additional_mem_pool_size,
8035
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8036
"Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.",
8037
NULL, NULL, 1*1024*1024L, 512*1024L, ~0L, 1024);
8039
static MYSQL_SYSVAR_ULONG(autoextend_increment, srv_auto_extend_increment,
8040
PLUGIN_VAR_RQCMDARG,
8041
"Data file autoextend increment in megabytes",
8042
NULL, NULL, 8L, 1L, 1000L, 0);
8044
static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
8045
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8046
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
8047
NULL, NULL, 8*1024*1024L, 1024*1024L, LONGLONG_MAX, 1024*1024L);
8049
static MYSQL_SYSVAR_ULONG(commit_concurrency, srv_commit_concurrency,
8050
PLUGIN_VAR_RQCMDARG,
8051
"Helps in performance tuning in heavily concurrent environments.",
8052
NULL, NULL, 0, 0, 1000, 0);
8054
static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
8055
PLUGIN_VAR_RQCMDARG,
8056
"Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
8057
NULL, NULL, 500L, 1L, ~0L, 0);
8059
static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
8060
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8061
"Number of file I/O threads in InnoDB.",
8062
NULL, NULL, 4, 4, 64, 0);
8064
static MYSQL_SYSVAR_LONG(force_recovery, innobase_force_recovery,
8065
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8066
"Helps to save your data in case the disk image of the database becomes corrupt.",
8067
NULL, NULL, 0, 0, 6, 0);
8069
static MYSQL_SYSVAR_LONG(lock_wait_timeout, innobase_lock_wait_timeout,
8070
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8071
"Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back.",
8072
NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
8074
static MYSQL_SYSVAR_LONG(log_buffer_size, innobase_log_buffer_size,
8075
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8076
"The size of the buffer which InnoDB uses to write log to the log files on disk.",
8077
NULL, NULL, 1024*1024L, 256*1024L, ~0L, 1024);
8079
static MYSQL_SYSVAR_LONGLONG(log_file_size, innobase_log_file_size,
8080
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8081
"Size of each log file in a log group.",
8082
NULL, NULL, 5*1024*1024L, 1*1024*1024L, LONGLONG_MAX, 1024*1024L);
8084
static MYSQL_SYSVAR_LONG(log_files_in_group, innobase_log_files_in_group,
8085
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8086
"Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here.",
8087
NULL, NULL, 2, 2, 100, 0);
8089
static MYSQL_SYSVAR_LONG(mirrored_log_groups, innobase_mirrored_log_groups,
8090
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8091
"Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
8092
NULL, NULL, 1, 1, 10, 0);
8094
static MYSQL_SYSVAR_LONG(open_files, innobase_open_files,
8095
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8096
"How many files at the maximum InnoDB keeps open at the same time.",
8097
NULL, NULL, 300L, 10L, ~0L, 0);
8099
static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
8100
PLUGIN_VAR_RQCMDARG,
8101
"Count of spin-loop rounds in InnoDB mutexes",
8102
NULL, NULL, 20L, 0L, ~0L, 0);
8104
static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
8105
PLUGIN_VAR_RQCMDARG,
8106
"Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.",
8107
NULL, NULL, 8, 0, 1000, 0);
8109
static MYSQL_SYSVAR_ULONG(thread_sleep_delay, srv_thread_sleep_delay,
8110
PLUGIN_VAR_RQCMDARG,
8111
"Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep",
8112
NULL, NULL, 10000L, 0L, ~0L, 0);
8114
static MYSQL_SYSVAR_STR(data_file_path, innobase_data_file_path,
8115
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8116
"Path to individual files and their sizes.",
8119
static MYSQL_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode,
8120
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8121
"The AUTOINC lock modes supported by InnoDB:\n"
8122
" 0 => Old style AUTOINC locking (for backward compatibility)\n"
8123
" 1 => New style AUTOINC locking\n"
8124
" 2 => No AUTOINC locking (unsafe for SBR)",
8126
AUTOINC_NEW_STYLE_LOCKING, /* Default setting */
8127
AUTOINC_OLD_STYLE_LOCKING, /* Minimum value */
8128
AUTOINC_NO_LOCKING, 0); /* Maximum value */
8130
static struct st_mysql_sys_var* innobase_system_variables[]= {
8131
MYSQL_SYSVAR(additional_mem_pool_size),
8132
MYSQL_SYSVAR(autoextend_increment),
8133
MYSQL_SYSVAR(buffer_pool_size),
8134
MYSQL_SYSVAR(checksums),
8135
MYSQL_SYSVAR(commit_concurrency),
8136
MYSQL_SYSVAR(concurrency_tickets),
8137
MYSQL_SYSVAR(data_file_path),
8138
MYSQL_SYSVAR(data_home_dir),
8139
MYSQL_SYSVAR(doublewrite),
8140
MYSQL_SYSVAR(fast_shutdown),
8141
MYSQL_SYSVAR(file_io_threads),
8142
MYSQL_SYSVAR(file_per_table),
8143
MYSQL_SYSVAR(flush_log_at_trx_commit),
8144
MYSQL_SYSVAR(flush_method),
8145
MYSQL_SYSVAR(force_recovery),
8146
MYSQL_SYSVAR(locks_unsafe_for_binlog),
8147
MYSQL_SYSVAR(lock_wait_timeout),
8148
#ifdef UNIV_LOG_ARCHIVE
8149
MYSQL_SYSVAR(log_arch_dir),
8150
MYSQL_SYSVAR(log_archive),
8151
#endif /* UNIV_LOG_ARCHIVE */
8152
MYSQL_SYSVAR(log_buffer_size),
8153
MYSQL_SYSVAR(log_file_size),
8154
MYSQL_SYSVAR(log_files_in_group),
8155
MYSQL_SYSVAR(log_group_home_dir),
8156
MYSQL_SYSVAR(max_dirty_pages_pct),
8157
MYSQL_SYSVAR(max_purge_lag),
8158
MYSQL_SYSVAR(mirrored_log_groups),
8159
MYSQL_SYSVAR(open_files),
8160
MYSQL_SYSVAR(rollback_on_timeout),
8161
MYSQL_SYSVAR(stats_on_metadata),
8162
MYSQL_SYSVAR(use_adaptive_hash_indexes),
8163
MYSQL_SYSVAR(status_file),
8164
MYSQL_SYSVAR(support_xa),
8165
MYSQL_SYSVAR(sync_spin_loops),
8166
MYSQL_SYSVAR(table_locks),
8167
MYSQL_SYSVAR(thread_concurrency),
8168
MYSQL_SYSVAR(thread_sleep_delay),
8169
MYSQL_SYSVAR(autoinc_lock_mode),
8173
mysql_declare_plugin(innobase)
8175
MYSQL_STORAGE_ENGINE_PLUGIN,
8176
&innobase_storage_engine,
8179
"Supports transactions, row-level locking, and foreign keys",
8181
innobase_init, /* Plugin Init */
8182
NULL, /* Plugin Deinit */
8184
innodb_status_variables_export,/* status variables */
8185
innobase_system_variables, /* system variables */
8188
mysql_declare_plugin_end;
8190
/****************************************************************************
8191
* DS-MRR implementation
8192
***************************************************************************/
8195
* Multi Range Read interface, DS-MRR calls
8198
int ha_innobase::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
8199
uint n_ranges, uint mode, HANDLER_BUFFER *buf)
8201
return ds_mrr.dsmrr_init(this, &table->key_info[active_index],
8202
seq, seq_init_param, n_ranges, mode, buf);
8205
int ha_innobase::multi_range_read_next(char **range_info)
8207
return ds_mrr.dsmrr_next(this, range_info);
8210
ha_rows ha_innobase::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
8211
void *seq_init_param,
8212
uint n_ranges, uint *bufsz,
8216
/* See comments in ha_myisam::multi_range_read_info_const */
8217
ds_mrr.init(this, table);
8218
return ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz,
8222
int ha_innobase::multi_range_read_info(uint keyno, uint n_ranges, uint keys,
8223
uint *bufsz, uint *flags, COST_VECT *cost)
8225
ds_mrr.init(this, table);
8226
return ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost);
8232
* Index Condition Pushdown interface implementation
8237
/* Index condition check function to be called from within Innobase */
8239
static my_bool index_cond_func_innodb(void *arg)
8241
ha_innobase *h= (ha_innobase*)arg;
8242
if (h->end_range) //was: h->in_range_read
8244
if (h->compare_key2(h->end_range) > 0)
8245
return 2; /* caller should return HA_ERR_END_OF_FILE already */
8247
return (my_bool)h->pushed_idx_cond->val_int();
8253
Item *ha_innobase::idx_cond_push(uint keyno_arg, Item* idx_cond_arg)
8255
if (keyno_arg != primary_key)
8257
pushed_idx_cond_keyno= keyno_arg;
8258
pushed_idx_cond= idx_cond_arg;
8259
in_range_check_pushed_down= TRUE;
8260
return NULL; /* Table handler will check the entire condition */
8262
return idx_cond_arg; /* Table handler will not make any checks */
8266
int ha_innobase::read_range_first(const key_range *start_key,
8267
const key_range *end_key,
8269
bool sorted /* ignored */)
8272
//if (!eq_range_arg)
8273
//in_range_read= TRUE;
8274
res= handler::read_range_first(start_key, end_key, eq_range_arg, sorted);
8276
// in_range_read= FALSE;
8281
int ha_innobase::read_range_next()
8283
int res= handler::read_range_next();
8285
// in_range_read= FALSE;