mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
merge with 3.23.50
BitKeeper/etc/logging_ok: auto-union BUILD/SETUP.sh: Auto merged Build-tools/Do-compile: Auto merged Build-tools/Do-rpm: Auto merged configure.in: Auto merged include/mysql_com.h: Auto merged innobase/btr/btr0btr.c: Auto merged innobase/btr/btr0cur.c: Auto merged innobase/btr/btr0sea.c: Auto merged innobase/dict/dict0dict.c: Auto merged innobase/dict/dict0load.c: Auto merged innobase/fil/fil0fil.c: Auto merged innobase/fsp/fsp0fsp.c: Auto merged innobase/include/srv0srv.h: Auto merged innobase/include/sync0rw.ic: Auto merged innobase/log/log0log.c: Auto merged innobase/rem/rem0cmp.c: Auto merged innobase/row/row0ins.c: Auto merged innobase/row/row0sel.c: Auto merged innobase/row/row0upd.c: Auto merged innobase/srv/srv0srv.c: Auto merged innobase/srv/srv0start.c: Auto merged myisam/myisampack.c: Auto merged mysql-test/t/range.test: Auto merged scripts/mysqldumpslow.sh: Auto merged sql/ha_innodb.h: Auto merged sql/handler.cc: Auto merged sql/handler.h: Auto merged sql/item.cc: Auto merged sql/item.h: Auto merged sql/item_func.cc: Auto merged sql/item_func.h: Auto merged sql/lock.cc: Auto merged sql/share/Makefile.am: Auto merged sql/sql_rename.cc: Auto merged sql/sql_select.cc: Auto merged sql/sql_show.cc: Auto merged support-files/mysql.spec.sh: Auto merged Docs/manual.texi: merge client/mysql.cc: merge client/mysqldump.c: merge innobase/buf/buf0buf.c: merge innobase/os/os0file.c: merge innobase/row/row0mysql.c: merge mysql-test/r/range.result: merge sql/ha_innodb.cc: merge sql/log_event.h: merge sql/mysqld.cc: merge sql/sql_base.cc: merge sql/sql_load.cc: merge
This commit is contained in:
502
sql/ha_innodb.cc
502
sql/ha_innodb.cc
@ -76,17 +76,32 @@ bool innodb_skip = 0;
|
||||
uint innobase_init_flags = 0;
|
||||
ulong innobase_cache_size = 0;
|
||||
|
||||
/* The default values for the following, type long, start-up parameters
|
||||
are declared in mysqld.cc: */
|
||||
|
||||
long innobase_mirrored_log_groups, innobase_log_files_in_group,
|
||||
innobase_log_file_size, innobase_log_buffer_size,
|
||||
innobase_buffer_pool_size, innobase_additional_mem_pool_size,
|
||||
innobase_file_io_threads, innobase_lock_wait_timeout,
|
||||
innobase_thread_concurrency, innobase_force_recovery;
|
||||
innobase_thread_concurrency, innobase_force_recovery;
|
||||
|
||||
char *innobase_data_home_dir;
|
||||
char *innobase_log_group_home_dir, *innobase_log_arch_dir;
|
||||
char *innobase_unix_file_flush_method;
|
||||
my_bool innobase_flush_log_at_trx_commit, innobase_log_archive,
|
||||
innobase_use_native_aio, innobase_fast_shutdown;
|
||||
/* The default values for the following char* start-up parameters
|
||||
are determined in innobase_init below: */
|
||||
|
||||
/* innobase_data_file_path=ibdata:15,idata2:1,... */
|
||||
|
||||
char* innobase_data_home_dir = NULL;
|
||||
char* innobase_log_group_home_dir = NULL;
|
||||
char* innobase_log_arch_dir = NULL;
|
||||
char* innobase_unix_file_flush_method = NULL;
|
||||
|
||||
/* Below we have boolean-valued start-up parameters, and their default
|
||||
values */
|
||||
|
||||
my_bool innobase_flush_log_at_trx_commit = FALSE;
|
||||
my_bool innobase_log_archive = FALSE;
|
||||
my_bool innobase_use_native_aio = FALSE;
|
||||
my_bool innobase_fast_shutdown = TRUE;
|
||||
|
||||
/*
|
||||
Set default InnoDB size to 64M, to let users use InnoDB without having
|
||||
@ -337,227 +352,6 @@ ha_innobase::update_thd(
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Reads the data files and their sizes from a character string given in
|
||||
the .cnf file. */
|
||||
static
|
||||
bool
|
||||
innobase_parse_data_file_paths_and_sizes(void)
|
||||
/*==========================================*/
|
||||
/* out: TRUE if ok, FALSE if parsing
|
||||
error */
|
||||
{
|
||||
char* str;
|
||||
char* endp;
|
||||
char* path;
|
||||
ulint size;
|
||||
ulint i = 0;
|
||||
|
||||
str = internal_innobase_data_file_path;
|
||||
|
||||
/* First calculate the number of data files and check syntax:
|
||||
path:size[M];path:size[M]... . Note that a Windows path may
|
||||
contain a drive name and a ':'. */
|
||||
|
||||
while (*str != '\0') {
|
||||
path = str;
|
||||
|
||||
while ((*str != ':' && *str != '\0')
|
||||
|| (*str == ':'
|
||||
&& (*(str + 1) == '\\' || *(str + 1) == '/'))) {
|
||||
str++;
|
||||
}
|
||||
|
||||
if (*str == '\0') {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
str++;
|
||||
|
||||
size = strtoul(str, &endp, 10);
|
||||
|
||||
str = endp;
|
||||
|
||||
if ((*str != 'M') && (*str != 'G')) {
|
||||
size = size / (1024 * 1024);
|
||||
} else if (*str == 'G') {
|
||||
size = size * 1024;
|
||||
str++;
|
||||
} else {
|
||||
str++;
|
||||
}
|
||||
|
||||
if (strlen(str) >= 6
|
||||
&& *str == 'n'
|
||||
&& *(str + 1) == 'e'
|
||||
&& *(str + 2) == 'w') {
|
||||
str += 3;
|
||||
}
|
||||
|
||||
if (strlen(str) >= 3
|
||||
&& *str == 'r'
|
||||
&& *(str + 1) == 'a'
|
||||
&& *(str + 2) == 'w') {
|
||||
str += 3;
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
if (*str == ';') {
|
||||
str++;
|
||||
} else if (*str != '\0') {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
srv_data_file_names = (char**)ut_malloc(i * sizeof(void*));
|
||||
srv_data_file_sizes = (ulint*)ut_malloc(i * sizeof(ulint));
|
||||
srv_data_file_is_raw_partition = (ulint*)ut_malloc(i * sizeof(ulint));
|
||||
|
||||
srv_n_data_files = i;
|
||||
|
||||
/* Then store the actual values to our arrays */
|
||||
|
||||
str = internal_innobase_data_file_path;
|
||||
i = 0;
|
||||
|
||||
while (*str != '\0') {
|
||||
path = str;
|
||||
|
||||
/* Note that we must ignore the ':' in a Windows path */
|
||||
|
||||
while ((*str != ':' && *str != '\0')
|
||||
|| (*str == ':'
|
||||
&& (*(str + 1) == '\\' || *(str + 1) == '/'))) {
|
||||
str++;
|
||||
}
|
||||
|
||||
if (*str == ':') {
|
||||
/* Make path a null-terminated string */
|
||||
*str = '\0';
|
||||
str++;
|
||||
}
|
||||
|
||||
size = strtoul(str, &endp, 10);
|
||||
|
||||
str = endp;
|
||||
|
||||
if ((*str != 'M') && (*str != 'G')) {
|
||||
size = size / (1024 * 1024);
|
||||
} else if (*str == 'G') {
|
||||
size = size * 1024;
|
||||
str++;
|
||||
} else {
|
||||
str++;
|
||||
}
|
||||
|
||||
srv_data_file_is_raw_partition[i] = 0;
|
||||
|
||||
if (strlen(str) >= 6
|
||||
&& *str == 'n'
|
||||
&& *(str + 1) == 'e'
|
||||
&& *(str + 2) == 'w') {
|
||||
str += 3;
|
||||
srv_data_file_is_raw_partition[i] = SRV_NEW_RAW;
|
||||
}
|
||||
|
||||
if (strlen(str) >= 3
|
||||
&& *str == 'r'
|
||||
&& *(str + 1) == 'a'
|
||||
&& *(str + 2) == 'w') {
|
||||
str += 3;
|
||||
|
||||
if (srv_data_file_is_raw_partition[i] == 0) {
|
||||
srv_data_file_is_raw_partition[i] = SRV_OLD_RAW;
|
||||
}
|
||||
}
|
||||
|
||||
srv_data_file_names[i] = path;
|
||||
srv_data_file_sizes[i] = size;
|
||||
|
||||
i++;
|
||||
|
||||
if (*str == ';') {
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Reads log group home directories from a character string given in
|
||||
the .cnf file. */
|
||||
static
|
||||
bool
|
||||
innobase_parse_log_group_home_dirs(void)
|
||||
/*====================================*/
|
||||
/* out: TRUE if ok, FALSE if parsing
|
||||
error */
|
||||
{
|
||||
char* str;
|
||||
char* path;
|
||||
ulint i = 0;
|
||||
|
||||
str = innobase_log_group_home_dir;
|
||||
|
||||
/* First calculate the number of directories and check syntax:
|
||||
path;path;... */
|
||||
|
||||
while (*str != '\0') {
|
||||
path = str;
|
||||
|
||||
while (*str != ';' && *str != '\0') {
|
||||
str++;
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
if (*str == ';') {
|
||||
str++;
|
||||
} else if (*str != '\0') {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (i != (ulint) innobase_mirrored_log_groups) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
srv_log_group_home_dirs = (char**) ut_malloc(i * sizeof(void*));
|
||||
|
||||
/* Then store the actual values to our array */
|
||||
|
||||
str = innobase_log_group_home_dir;
|
||||
i = 0;
|
||||
|
||||
while (*str != '\0') {
|
||||
path = str;
|
||||
|
||||
while (*str != ';' && *str != '\0') {
|
||||
str++;
|
||||
}
|
||||
|
||||
if (*str == ';') {
|
||||
*str = '\0';
|
||||
str++;
|
||||
}
|
||||
|
||||
srv_log_group_home_dirs[i] = path;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Opens an InnoDB database. */
|
||||
|
||||
@ -581,9 +375,9 @@ innobase_init(void)
|
||||
else
|
||||
{
|
||||
/* It's better to use current lib, to keep path's short */
|
||||
current_lib[0]=FN_CURLIB;
|
||||
current_lib[1]=FN_LIBCHAR;
|
||||
current_lib[2]=0;
|
||||
current_lib[0] = FN_CURLIB;
|
||||
current_lib[1] = FN_LIBCHAR;
|
||||
current_lib[2] = 0;
|
||||
default_path=current_lib;
|
||||
}
|
||||
|
||||
@ -605,12 +399,17 @@ innobase_init(void)
|
||||
|
||||
srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
|
||||
default_path);
|
||||
srv_logs_home = (char*) "";
|
||||
srv_arch_dir = (innobase_log_arch_dir ? innobase_log_arch_dir :
|
||||
default_path);
|
||||
|
||||
ret = innobase_parse_data_file_paths_and_sizes();
|
||||
|
||||
ret = (bool)
|
||||
srv_parse_data_file_paths_and_sizes(innobase_data_file_path,
|
||||
&srv_data_file_names,
|
||||
&srv_data_file_sizes,
|
||||
&srv_data_file_is_raw_partition,
|
||||
&srv_n_data_files,
|
||||
&srv_auto_extend_last_data_file,
|
||||
&srv_last_file_size_max);
|
||||
if (ret == FALSE) {
|
||||
sql_print_error("InnoDB: syntax error in innodb_data_file_path");
|
||||
DBUG_RETURN(TRUE);
|
||||
@ -618,12 +417,18 @@ innobase_init(void)
|
||||
|
||||
if (!innobase_log_group_home_dir)
|
||||
innobase_log_group_home_dir= default_path;
|
||||
ret = innobase_parse_log_group_home_dirs();
|
||||
|
||||
if (ret == FALSE) {
|
||||
DBUG_RETURN(TRUE);
|
||||
ret = (bool)
|
||||
srv_parse_log_group_home_dirs(innobase_log_group_home_dir,
|
||||
&srv_log_group_home_dirs);
|
||||
|
||||
if (ret == FALSE || innobase_mirrored_log_groups != 1) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: syntax error in innodb_log_group_home_dir\n"
|
||||
"InnoDB: or a wrong number of mirrored log groups\n");
|
||||
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
srv_unix_file_flush_method_str = (innobase_unix_file_flush_method ?
|
||||
innobase_unix_file_flush_method :
|
||||
(char*)"fdatasync");
|
||||
@ -664,10 +469,11 @@ innobase_init(void)
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
(void) hash_init(&innobase_open_tables,32,0,0,
|
||||
(hash_get_key) innobase_get_key,0,0);
|
||||
(hash_get_key) innobase_get_key,0,0);
|
||||
pthread_mutex_init(&innobase_mutex,MY_MUTEX_INIT_FAST);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
@ -1353,33 +1159,43 @@ build_template(
|
||||
|
||||
clust_index = dict_table_get_first_index_noninline(prebuilt->table);
|
||||
|
||||
if (!prebuilt->in_update_remember_pos) {
|
||||
if (!prebuilt->hint_no_need_to_fetch_extra_cols) {
|
||||
/* We have a hint that we should at least fetch all
|
||||
columns in the key, or all columns in the table */
|
||||
|
||||
if (prebuilt->read_just_key) {
|
||||
/* MySQL has instructed us that it is enough to
|
||||
fetch the columns in the key */
|
||||
|
||||
fetch_all_in_key = TRUE;
|
||||
} else {
|
||||
/* We are building a temporary table: fetch all
|
||||
columns */
|
||||
columns; the reason is that MySQL may use the
|
||||
clustered index key to store rows, but the mechanism
|
||||
we use below to detect required columns does not
|
||||
reveal that. Actually, it might be enough to
|
||||
fetch only all in the key also in this case! */
|
||||
|
||||
templ_type = ROW_MYSQL_WHOLE_ROW;
|
||||
}
|
||||
}
|
||||
|
||||
if (prebuilt->select_lock_type == LOCK_X) {
|
||||
/* TODO: should fix the code in sql_update so that we could do
|
||||
with fetching only the needed columns */
|
||||
/* We always retrieve the whole clustered index record if we
|
||||
use exclusive row level locks, for example, if the read is
|
||||
done in an UPDATE statement. */
|
||||
|
||||
templ_type = ROW_MYSQL_WHOLE_ROW;
|
||||
}
|
||||
|
||||
if (templ_type == ROW_MYSQL_REC_FIELDS) {
|
||||
/* In versions < 3.23.50 we always retrieved the clustered
|
||||
index record if prebuilt->select_lock_type == LOCK_S,
|
||||
but there is really not need for that, and in some cases
|
||||
performance could be seriously degraded because the MySQL
|
||||
optimizer did not know about our convention! */
|
||||
|
||||
if (prebuilt->select_lock_type != LOCK_NONE) {
|
||||
/* Let index be the clustered index */
|
||||
|
||||
index = clust_index;
|
||||
} else {
|
||||
index = prebuilt->index;
|
||||
}
|
||||
index = prebuilt->index;
|
||||
} else {
|
||||
index = clust_index;
|
||||
}
|
||||
@ -1475,12 +1291,6 @@ skip_field:
|
||||
(index->table->cols + templ->col_no)->clust_pos;
|
||||
}
|
||||
}
|
||||
|
||||
if (templ_type == ROW_MYSQL_REC_FIELDS
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
|
||||
prebuilt->need_to_access_clustered = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@ -1513,7 +1323,9 @@ ha_innobase::write_row(
|
||||
}
|
||||
|
||||
if (table->next_number_field && record == table->record[0]) {
|
||||
|
||||
/* This is the case where the table has an
|
||||
auto-increment column */
|
||||
|
||||
/* Fetch the value the user possibly has set in the
|
||||
autoincrement field */
|
||||
|
||||
@ -1597,12 +1409,6 @@ ha_innobase::write_row(
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the 'in_update_remember_pos' flag to FALSE to
|
||||
make sure all columns are fetched in the select done by
|
||||
update_auto_increment */
|
||||
|
||||
prebuilt->in_update_remember_pos = FALSE;
|
||||
|
||||
update_auto_increment();
|
||||
|
||||
if (auto_inc == 0) {
|
||||
@ -1626,7 +1432,7 @@ ha_innobase::write_row(
|
||||
}
|
||||
|
||||
/* We have to set sql_stat_start to TRUE because
|
||||
update_auto_increment has called a select, and
|
||||
update_auto_increment may have called a select, and
|
||||
has reset that flag; row_insert_for_mysql has to
|
||||
know to set the IX intention lock on the table, something
|
||||
it only does at the start of each statement */
|
||||
@ -1866,9 +1672,7 @@ ha_innobase::update_row(
|
||||
/* This is not a delete */
|
||||
prebuilt->upd_node->is_delete = FALSE;
|
||||
|
||||
if (!prebuilt->in_update_remember_pos) {
|
||||
assert(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
|
||||
}
|
||||
assert(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
|
||||
|
||||
srv_conc_enter_innodb(prebuilt->trx);
|
||||
|
||||
@ -1914,7 +1718,6 @@ ha_innobase::delete_row(
|
||||
/* This is a delete */
|
||||
|
||||
prebuilt->upd_node->is_delete = TRUE;
|
||||
prebuilt->in_update_remember_pos = TRUE;
|
||||
|
||||
srv_conc_enter_innodb(prebuilt->trx);
|
||||
|
||||
@ -2124,19 +1927,20 @@ ha_innobase::change_active_index(
|
||||
|
||||
active_index = keynr;
|
||||
|
||||
if (keynr != MAX_KEY && table->keys > 0)
|
||||
{
|
||||
if (keynr != MAX_KEY && table->keys > 0) {
|
||||
key = table->key_info + active_index;
|
||||
|
||||
prebuilt->index=dict_table_get_index_noninline(prebuilt->table, key->name);
|
||||
if (!prebuilt->index)
|
||||
{
|
||||
sql_print_error("Innodb could not find key n:o %u with name %s from dict cache for table %s", keynr, key->name, prebuilt->table->name);
|
||||
return(1);
|
||||
}
|
||||
prebuilt->index = dict_table_get_index_noninline(
|
||||
prebuilt->table, key->name);
|
||||
} else {
|
||||
prebuilt->index = dict_table_get_first_index_noninline(
|
||||
prebuilt->table);
|
||||
}
|
||||
|
||||
if (!prebuilt->index) {
|
||||
sql_print_error("Innodb could not find key n:o %u with name %s from dict cache for table %s", keynr, key->name, prebuilt->table->name);
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
prebuilt->index = dict_table_get_first_index_noninline(prebuilt->table);
|
||||
|
||||
assert(prebuilt->search_tuple != 0);
|
||||
|
||||
@ -2647,7 +2451,9 @@ ha_innobase::create(
|
||||
|
||||
/* Create the table definition in InnoDB */
|
||||
|
||||
if ((error = create_table_def(trx, form, norm_name))) {
|
||||
error = create_table_def(trx, form, norm_name);
|
||||
|
||||
if (error) {
|
||||
|
||||
trx_commit_for_mysql(trx);
|
||||
|
||||
@ -3222,13 +3028,59 @@ ha_innobase::update_table_comment(
|
||||
pos += sprintf(pos, "InnoDB free: %lu kB",
|
||||
(ulong) innobase_get_free_space());
|
||||
|
||||
/* We assume 150 bytes of space to print info */
|
||||
|
||||
dict_print_info_on_foreign_keys(pos, 500, prebuilt->table);
|
||||
/* We assume 450 - length bytes of space to print info */
|
||||
|
||||
if (length < 450) {
|
||||
dict_print_info_on_foreign_keys(FALSE, pos, 450 - length,
|
||||
prebuilt->table);
|
||||
}
|
||||
|
||||
return(str);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Gets the foreign key create info for a table stored in InnoDB. */
|
||||
|
||||
char*
|
||||
ha_innobase::get_foreign_key_create_info(void)
|
||||
/*==========================================*/
|
||||
/* out, own: character string in the form which
|
||||
can be inserted to the CREATE TABLE statement,
|
||||
MUST be freed with ::free_foreign_key_create_info */
|
||||
{
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
|
||||
char* str;
|
||||
|
||||
if (prebuilt == NULL) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: cannot get create info for foreign keys\n");
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
str = (char*)ut_malloc(10000);
|
||||
|
||||
str[0] = '\0';
|
||||
|
||||
dict_print_info_on_foreign_keys(TRUE, str, 9000, prebuilt->table);
|
||||
|
||||
return(str);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Frees the foreign key create info for a table stored in InnoDB, if it is
|
||||
non-NULL. */
|
||||
|
||||
void
|
||||
ha_innobase::free_foreign_key_create_info(
|
||||
/*======================================*/
|
||||
char* str) /* in, own: create info string to free */
|
||||
{
|
||||
if (str) {
|
||||
ut_free(str);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Tells something additional to the handler about how to do things. */
|
||||
|
||||
@ -3254,7 +3106,7 @@ ha_innobase::extra(
|
||||
prebuilt->read_just_key = 0;
|
||||
break;
|
||||
case HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE:
|
||||
prebuilt->in_update_remember_pos = FALSE;
|
||||
prebuilt->hint_no_need_to_fetch_extra_cols = FALSE;
|
||||
break;
|
||||
case HA_EXTRA_KEYREAD:
|
||||
prebuilt->read_just_key = 1;
|
||||
@ -3301,7 +3153,7 @@ ha_innobase::external_lock(
|
||||
trx = prebuilt->trx;
|
||||
|
||||
prebuilt->sql_stat_start = TRUE;
|
||||
prebuilt->in_update_remember_pos = TRUE;
|
||||
prebuilt->hint_no_need_to_fetch_extra_cols = TRUE;
|
||||
|
||||
prebuilt->read_just_key = 0;
|
||||
|
||||
@ -3320,6 +3172,16 @@ ha_innobase::external_lock(
|
||||
thd->transaction.all.innodb_active_trans = 1;
|
||||
trx->n_mysql_tables_in_use++;
|
||||
|
||||
if (thd->tx_isolation == ISO_SERIALIZABLE
|
||||
&& prebuilt->select_lock_type == LOCK_NONE) {
|
||||
|
||||
/* To get serializable execution we let InnoDB
|
||||
conceptually add 'LOCK IN SHARE MODE' to all SELECTs
|
||||
which otherwise would have been consistent reads */
|
||||
|
||||
prebuilt->select_lock_type = LOCK_S;
|
||||
}
|
||||
|
||||
if (prebuilt->select_lock_type != LOCK_NONE) {
|
||||
|
||||
trx->mysql_n_tables_locked++;
|
||||
@ -3427,8 +3289,8 @@ ha_innobase::store_lock(
|
||||
lock_type == TL_READ_NO_INSERT) {
|
||||
/* This is a SELECT ... IN SHARE MODE, or
|
||||
we are doing a complex SQL statement like
|
||||
INSERT INTO ... SELECT ... and the logical logging
|
||||
requires the use of a locking read */
|
||||
INSERT INTO ... SELECT ... and the logical logging (MySQL
|
||||
binlog) requires the use of a locking read */
|
||||
|
||||
prebuilt->select_lock_type = LOCK_S;
|
||||
} else {
|
||||
@ -3468,37 +3330,59 @@ ha_innobase::get_auto_increment()
|
||||
/*=============================*/
|
||||
/* out: the next auto-increment column value */
|
||||
{
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||
longlong nr;
|
||||
int error;
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||
longlong nr;
|
||||
int error;
|
||||
|
||||
(void) extra(HA_EXTRA_KEYREAD);
|
||||
index_init(table->next_number_index);
|
||||
/* Also SHOW TABLE STATUS calls this function. Previously, when we did
|
||||
always read the max autoinc key value, setting x-locks, users were
|
||||
surprised that SHOW TABLE STATUS could end up in a deadlock with
|
||||
ordinary SQL queries. We avoid these deadlocks if the auto-inc
|
||||
counter for the table has been initialized by fetching the value
|
||||
from the table struct in dictionary cache. */
|
||||
|
||||
/* We use an exclusive lock when we read the max key value from the
|
||||
auto-increment column index. This is because then build_template will
|
||||
advise InnoDB to fetch all columns. In SHOW TABLE STATUS the query
|
||||
id of the auto-increment column is not changed, and previously InnoDB
|
||||
did not fetch it, causing SHOW TABLE STATUS to show wrong values
|
||||
for the autoinc column. */
|
||||
assert(prebuilt->table);
|
||||
|
||||
nr = dict_table_autoinc_read(prebuilt->table);
|
||||
|
||||
prebuilt->select_lock_type = LOCK_X;
|
||||
prebuilt->trx->mysql_n_tables_locked += 1;
|
||||
if (nr != 0) {
|
||||
|
||||
error=index_last(table->record[1]);
|
||||
return(nr + 1);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
nr = 1;
|
||||
} else {
|
||||
nr = (longlong) table->next_number_field->
|
||||
val_int_offset(table->rec_buff_length) + 1;
|
||||
}
|
||||
(void) extra(HA_EXTRA_KEYREAD);
|
||||
index_init(table->next_number_index);
|
||||
|
||||
(void) extra(HA_EXTRA_NO_KEYREAD);
|
||||
/* We use an exclusive lock when we read the max key value from the
|
||||
auto-increment column index. This is because then build_template will
|
||||
advise InnoDB to fetch all columns. In SHOW TABLE STATUS the query
|
||||
id of the auto-increment column is not changed, and previously InnoDB
|
||||
did not fetch it, causing SHOW TABLE STATUS to show wrong values
|
||||
for the autoinc column. */
|
||||
|
||||
index_end();
|
||||
prebuilt->select_lock_type = LOCK_X;
|
||||
|
||||
return(nr);
|
||||
/* Play safe and also give in another way the hint to fetch
|
||||
all columns in the key: */
|
||||
|
||||
prebuilt->hint_no_need_to_fetch_extra_cols = FALSE;
|
||||
|
||||
prebuilt->trx->mysql_n_tables_locked += 1;
|
||||
|
||||
error = index_last(table->record[1]);
|
||||
|
||||
if (error) {
|
||||
nr = 1;
|
||||
} else {
|
||||
nr = (longlong) table->next_number_field->
|
||||
val_int_offset(table->rec_buff_length) + 1;
|
||||
}
|
||||
|
||||
(void) extra(HA_EXTRA_NO_KEYREAD);
|
||||
|
||||
index_end();
|
||||
|
||||
return(nr);
|
||||
}
|
||||
|
||||
#endif /* HAVE_INNOBASE_DB */
|
||||
|
Reference in New Issue
Block a user