ha_innobase.cc:

  Merge 3.23.52
parent 94e926ac
...@@ -27,6 +27,7 @@ InnoDB */ ...@@ -27,6 +27,7 @@ InnoDB */
#endif #endif
#include "mysql_priv.h" #include "mysql_priv.h"
#include "slave.h"
#ifdef HAVE_INNOBASE_DB #ifdef HAVE_INNOBASE_DB
#include <m_ctype.h> #include <m_ctype.h>
#include <assert.h> #include <assert.h>
...@@ -53,10 +54,12 @@ typedef byte mysql_byte; ...@@ -53,10 +54,12 @@ typedef byte mysql_byte;
/* Include necessary InnoDB headers */ /* Include necessary InnoDB headers */
extern "C" { extern "C" {
#include "../innobase/include/univ.i" #include "../innobase/include/univ.i"
#include "../innobase/include/os0file.h"
#include "../innobase/include/srv0start.h" #include "../innobase/include/srv0start.h"
#include "../innobase/include/srv0srv.h" #include "../innobase/include/srv0srv.h"
#include "../innobase/include/trx0roll.h" #include "../innobase/include/trx0roll.h"
#include "../innobase/include/trx0trx.h" #include "../innobase/include/trx0trx.h"
#include "../innobase/include/trx0sys.h"
#include "../innobase/include/row0ins.h" #include "../innobase/include/row0ins.h"
#include "../innobase/include/row0mysql.h" #include "../innobase/include/row0mysql.h"
#include "../innobase/include/row0sel.h" #include "../innobase/include/row0sel.h"
...@@ -180,7 +183,8 @@ int ...@@ -180,7 +183,8 @@ int
convert_error_code_to_mysql( convert_error_code_to_mysql(
/*========================*/ /*========================*/
/* out: MySQL error code */ /* out: MySQL error code */
int error) /* in: InnoDB error code */ int error, /* in: InnoDB error code */
THD* thd) /* in: user thread handle or NULL */
{ {
if (error == DB_SUCCESS) { if (error == DB_SUCCESS) {
...@@ -199,11 +203,27 @@ convert_error_code_to_mysql( ...@@ -199,11 +203,27 @@ convert_error_code_to_mysql(
return(HA_ERR_NO_ACTIVE_RECORD); return(HA_ERR_NO_ACTIVE_RECORD);
} else if (error == (int) DB_DEADLOCK) { } else if (error == (int) DB_DEADLOCK) {
/* Since we roll back the whole transaction, we must
tell it also to MySQL so that MySQL knows to empty the
cached binlog for this transaction */
if (thd) {
ha_rollback(thd);
}
return(HA_ERR_LOCK_DEADLOCK); return(HA_ERR_LOCK_DEADLOCK);
} else if (error == (int) DB_LOCK_WAIT_TIMEOUT) { } else if (error == (int) DB_LOCK_WAIT_TIMEOUT) {
/* Since we roll back the whole transaction, we must
tell it also to MySQL so that MySQL knows to empty the
cached binlog for this transaction */
if (thd) {
ha_rollback(thd);
}
return(HA_ERR_LOCK_WAIT_TIMEOUT); return(HA_ERR_LOCK_WAIT_TIMEOUT);
} else if (error == (int) DB_NO_REFERENCED_ROW) { } else if (error == (int) DB_NO_REFERENCED_ROW) {
...@@ -313,7 +333,23 @@ check_trx_exists( ...@@ -313,7 +333,23 @@ check_trx_exists(
thd->transaction.stmt.innobase_tid = thd->transaction.stmt.innobase_tid =
(void*)&innodb_dummy_stmt_trx_handle; (void*)&innodb_dummy_stmt_trx_handle;
} else { } else {
ut_a(trx->magic_n == TRX_MAGIC_N); if (trx->magic_n != TRX_MAGIC_N) {
mem_analyze_corruption((byte*)trx);
ut_a(0);
}
}
if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
trx->check_foreigns = FALSE;
} else {
trx->check_foreigns = TRUE;
}
if (thd->options & OPTION_RELAXED_UNIQUE_CHECKS) {
trx->check_unique_secondary = FALSE;
} else {
trx->check_unique_secondary = TRUE;
} }
return(trx); return(trx);
...@@ -359,6 +395,8 @@ innobase_init(void) ...@@ -359,6 +395,8 @@ innobase_init(void)
DBUG_ENTER("innobase_init"); DBUG_ENTER("innobase_init");
os_innodb_umask = (ulint)my_umask;
if (specialflag & SPECIAL_NO_PRIOR) { if (specialflag & SPECIAL_NO_PRIOR) {
srv_set_thread_priorities = FALSE; srv_set_thread_priorities = FALSE;
} else { } else {
...@@ -435,7 +473,7 @@ innobase_init(void) ...@@ -435,7 +473,7 @@ innobase_init(void)
srv_log_archive_on = (ulint) innobase_log_archive; srv_log_archive_on = (ulint) innobase_log_archive;
srv_log_buffer_size = (ulint) innobase_log_buffer_size; srv_log_buffer_size = (ulint) innobase_log_buffer_size;
srv_flush_log_at_trx_commit = (ibool) innobase_flush_log_at_trx_commit; srv_flush_log_at_trx_commit = (ulint) innobase_flush_log_at_trx_commit;
srv_use_native_aio = 0; srv_use_native_aio = 0;
...@@ -470,6 +508,22 @@ innobase_init(void) ...@@ -470,6 +508,22 @@ innobase_init(void)
(void) hash_init(&innobase_open_tables,32,0,0, (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); pthread_mutex_init(&innobase_mutex,MY_MUTEX_INIT_FAST);
/* If this is a replication slave and we needed to do a crash recovery,
set the master binlog position to what InnoDB internally knew about
how far we got transactions durable inside InnoDB. There is a
problem here: if the user used also MyISAM tables, InnoDB might not
know the right position for them.
THIS DOES NOT WORK CURRENTLY because replication seems to initialize
glob_mi also after innobase_init. */
/* if (trx_sys_mysql_master_log_pos != -1) {
ut_memcpy(glob_mi.log_file_name, trx_sys_mysql_master_log_name,
1 + ut_strlen(trx_sys_mysql_master_log_name));
glob_mi.pos = trx_sys_mysql_master_log_pos;
}
*/
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -528,6 +582,17 @@ innobase_get_free_space(void) ...@@ -528,6 +582,17 @@ innobase_get_free_space(void)
/********************************************************************* /*********************************************************************
Commits a transaction in an InnoDB database. */ Commits a transaction in an InnoDB database. */
void
innobase_commit_low(
/*================*/
trx_t* trx) /* in: transaction handle */
{
trx_commit_for_mysql(trx);
}
/*********************************************************************
Commits a transaction in an InnoDB database. */
int int
innobase_commit( innobase_commit(
/*============*/ /*============*/
...@@ -547,8 +612,21 @@ innobase_commit( ...@@ -547,8 +612,21 @@ innobase_commit(
trx = check_trx_exists(thd); trx = check_trx_exists(thd);
if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) { if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
if (thd->slave_thread) {
/* Update the replication position info inside
InnoDB. Note that we cannot presently do this for
CREATE TABLE etc. because MySQL does not tell us the
thd associated with those operations! */
trx->mysql_master_log_file_name =
glob_mi.log_file_name;
trx->mysql_master_log_pos = (ib_longlong)
(glob_mi.pos + glob_mi.event_len
+ glob_mi.pending);
}
trx_commit_for_mysql(trx); innobase_commit_low(trx);
} }
/* Release possible statement level resources */ /* Release possible statement level resources */
...@@ -589,6 +667,8 @@ innobase_report_binlog_offset_and_commit( ...@@ -589,6 +667,8 @@ innobase_report_binlog_offset_and_commit(
trx = (trx_t*)trx_handle; trx = (trx_t*)trx_handle;
ut_a(trx != NULL);
trx->mysql_log_file_name = log_file_name; trx->mysql_log_file_name = log_file_name;
trx->mysql_log_offset = (ib_longlong)end_offset; trx->mysql_log_offset = (ib_longlong)end_offset;
...@@ -629,7 +709,7 @@ innobase_rollback( ...@@ -629,7 +709,7 @@ innobase_rollback(
trx_mark_sql_stat_end(trx); trx_mark_sql_stat_end(trx);
DBUG_RETURN(convert_error_code_to_mysql(error)); DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
} }
/********************************************************************* /*********************************************************************
...@@ -791,10 +871,9 @@ ha_innobase::open( ...@@ -791,10 +871,9 @@ ha_innobase::open(
ib_table = dict_table_get_and_increment_handle_count( ib_table = dict_table_get_and_increment_handle_count(
norm_name, NULL); norm_name, NULL);
if (NULL == ib_table) { if (NULL == ib_table) {
fprintf(stderr, fprintf(stderr,
"InnoDB: Error: cannot find table %s from the internal data dictionary\n" "InnoDB: Error: cannot find table %s from the internal data dictionary\n"
"InnoDB: of InnoDB though the .frm file for the table exists. Maybe you\n" "InnoDB: of InnoDB though the .frm file for the table exists. Maybe you\n"
"InnoDB: have deleted and recreated InnoDB data files but have forgotten\n" "InnoDB: have deleted and recreated InnoDB data files but have forgotten\n"
...@@ -846,6 +925,9 @@ ha_innobase::open( ...@@ -846,6 +925,9 @@ ha_innobase::open(
auto_inc_counter_for_this_stat = 0; auto_inc_counter_for_this_stat = 0;
block_size = 16 * 1024; /* Index block size in InnoDB: used by MySQL
in query optimization */
/* Init table lock structure */ /* Init table lock structure */
thr_lock_data_init(&share->lock,&lock,(void*) 0); thr_lock_data_init(&share->lock,&lock,(void*) 0);
...@@ -1365,7 +1447,8 @@ ha_innobase::write_row( ...@@ -1365,7 +1447,8 @@ ha_innobase::write_row(
if (error != DB_SUCCESS) { if (error != DB_SUCCESS) {
error = convert_error_code_to_mysql(error); error = convert_error_code_to_mysql(error,
user_thd);
goto func_exit; goto func_exit;
} }
...@@ -1381,7 +1464,7 @@ ha_innobase::write_row( ...@@ -1381,7 +1464,7 @@ ha_innobase::write_row(
srv_conc_exit_innodb(prebuilt->trx); srv_conc_exit_innodb(prebuilt->trx);
error = convert_error_code_to_mysql( error = convert_error_code_to_mysql(
error); error, user_thd);
goto func_exit; goto func_exit;
} }
} }
...@@ -1412,7 +1495,8 @@ ha_innobase::write_row( ...@@ -1412,7 +1495,8 @@ ha_innobase::write_row(
if (error != DB_SUCCESS) { if (error != DB_SUCCESS) {
error = convert_error_code_to_mysql(error); error = convert_error_code_to_mysql(error,
user_thd);
goto func_exit; goto func_exit;
} }
...@@ -1452,7 +1536,7 @@ ha_innobase::write_row( ...@@ -1452,7 +1536,7 @@ ha_innobase::write_row(
prebuilt->trx->ignore_duplicates_in_insert = FALSE; prebuilt->trx->ignore_duplicates_in_insert = FALSE;
error = convert_error_code_to_mysql(error); error = convert_error_code_to_mysql(error, user_thd);
/* Tell InnoDB server that there might be work for /* Tell InnoDB server that there might be work for
utility threads: */ utility threads: */
...@@ -1669,7 +1753,7 @@ ha_innobase::update_row( ...@@ -1669,7 +1753,7 @@ ha_innobase::update_row(
srv_conc_exit_innodb(prebuilt->trx); srv_conc_exit_innodb(prebuilt->trx);
error = convert_error_code_to_mysql(error); error = convert_error_code_to_mysql(error, user_thd);
/* Tell InnoDB server that there might be work for /* Tell InnoDB server that there might be work for
utility threads: */ utility threads: */
...@@ -1714,7 +1798,7 @@ ha_innobase::delete_row( ...@@ -1714,7 +1798,7 @@ ha_innobase::delete_row(
srv_conc_exit_innodb(prebuilt->trx); srv_conc_exit_innodb(prebuilt->trx);
error = convert_error_code_to_mysql(error); error = convert_error_code_to_mysql(error, user_thd);
/* Tell the InnoDB server that there might be work for /* Tell the InnoDB server that there might be work for
utility threads: */ utility threads: */
...@@ -1872,7 +1956,7 @@ ha_innobase::index_read( ...@@ -1872,7 +1956,7 @@ ha_innobase::index_read(
error = HA_ERR_KEY_NOT_FOUND; error = HA_ERR_KEY_NOT_FOUND;
table->status = STATUS_NOT_FOUND; table->status = STATUS_NOT_FOUND;
} else { } else {
error = convert_error_code_to_mysql(ret); error = convert_error_code_to_mysql(ret, user_thd);
table->status = STATUS_NOT_FOUND; table->status = STATUS_NOT_FOUND;
} }
...@@ -1891,7 +1975,7 @@ ha_innobase::change_active_index( ...@@ -1891,7 +1975,7 @@ ha_innobase::change_active_index(
InnoDB */ InnoDB */
{ {
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
KEY* key=0; KEY* key;
statistic_increment(ha_read_key_count, &LOCK_status); statistic_increment(ha_read_key_count, &LOCK_status);
...@@ -1912,10 +1996,9 @@ ha_innobase::change_active_index( ...@@ -1912,10 +1996,9 @@ ha_innobase::change_active_index(
if (!prebuilt->index) { if (!prebuilt->index) {
fprintf(stderr, fprintf(stderr,
"InnoDB: Could not find key n:o %u with name %s from dict cache\n" "InnoDB: Could not find key n:o %u with name %s from dict cache\n"
"InnoDB: for table %s\n", keynr, key ? key->name : "NULL", "InnoDB: for table %s\n", keynr, key->name, prebuilt->table->name);
prebuilt->table->name);
DBUG_RETURN(1); return(1);
} }
assert(prebuilt->search_tuple); assert(prebuilt->search_tuple);
...@@ -1931,7 +2014,7 @@ ha_innobase::change_active_index( ...@@ -1931,7 +2014,7 @@ ha_innobase::change_active_index(
build_template(prebuilt, user_thd, table, ROW_MYSQL_WHOLE_ROW); build_template(prebuilt, user_thd, table, ROW_MYSQL_WHOLE_ROW);
DBUG_RETURN(0); return(0);
} }
/************************************************************************** /**************************************************************************
...@@ -1999,7 +2082,7 @@ ha_innobase::general_fetch( ...@@ -1999,7 +2082,7 @@ ha_innobase::general_fetch(
error = HA_ERR_END_OF_FILE; error = HA_ERR_END_OF_FILE;
table->status = STATUS_NOT_FOUND; table->status = STATUS_NOT_FOUND;
} else { } else {
error = convert_error_code_to_mysql(ret); error = convert_error_code_to_mysql(ret, user_thd);
table->status = STATUS_NOT_FOUND; table->status = STATUS_NOT_FOUND;
} }
...@@ -2301,7 +2384,7 @@ create_table_def( ...@@ -2301,7 +2384,7 @@ create_table_def(
error = row_create_table_for_mysql(table, trx); error = row_create_table_for_mysql(table, trx);
error = convert_error_code_to_mysql(error); error = convert_error_code_to_mysql(error, NULL);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -2358,7 +2441,7 @@ create_index( ...@@ -2358,7 +2441,7 @@ create_index(
error = row_create_index_for_mysql(index, trx); error = row_create_index_for_mysql(index, trx);
error = convert_error_code_to_mysql(error); error = convert_error_code_to_mysql(error, NULL);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -2384,7 +2467,7 @@ create_clustered_index_when_no_primary( ...@@ -2384,7 +2467,7 @@ create_clustered_index_when_no_primary(
0, DICT_CLUSTERED, 0); 0, DICT_CLUSTERED, 0);
error = row_create_index_for_mysql(index, trx); error = row_create_index_for_mysql(index, trx);
error = convert_error_code_to_mysql(error); error = convert_error_code_to_mysql(error, NULL);
return(error); return(error);
} }
...@@ -2414,19 +2497,36 @@ ha_innobase::create( ...@@ -2414,19 +2497,36 @@ ha_innobase::create(
DBUG_ENTER("ha_innobase::create"); DBUG_ENTER("ha_innobase::create");
assert(current_thd != NULL);
trx = trx_allocate_for_mysql(); trx = trx_allocate_for_mysql();
if (current_thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
trx->check_foreigns = FALSE;
}
if (current_thd->options & OPTION_RELAXED_UNIQUE_CHECKS) {
trx->check_unique_secondary = FALSE;
}
fn_format(name2, name, "", "",2); // Remove the .frm extension fn_format(name2, name, "", "",2); // Remove the .frm extension
normalize_table_name(norm_name, name2); normalize_table_name(norm_name, name2);
/* Create the table definition in InnoDB */ /* Latch the InnoDB data dictionary exclusive so that no deadlocks
or lock waits can happen in it during a table create operation.
(Drop table etc. do this latching in row0mysql.c.) */
row_mysql_lock_data_dictionary();
/* Create the table definition in InnoDB */
error = create_table_def(trx, form, norm_name); error = create_table_def(trx, form, norm_name);
if (error) { if (error) {
innobase_commit_low(trx);
trx_commit_for_mysql(trx); row_mysql_unlock_data_dictionary();
trx_free_for_mysql(trx); trx_free_for_mysql(trx);
...@@ -2458,7 +2558,9 @@ ha_innobase::create( ...@@ -2458,7 +2558,9 @@ ha_innobase::create(
error = create_clustered_index_when_no_primary(trx, error = create_clustered_index_when_no_primary(trx,
norm_name); norm_name);
if (error) { if (error) {
trx_commit_for_mysql(trx); innobase_commit_low(trx);
row_mysql_unlock_data_dictionary();
trx_free_for_mysql(trx); trx_free_for_mysql(trx);
...@@ -2471,7 +2573,9 @@ ha_innobase::create( ...@@ -2471,7 +2573,9 @@ ha_innobase::create(
first */ first */
if ((error = create_index(trx, form, norm_name, if ((error = create_index(trx, form, norm_name,
(uint) primary_key_no))) { (uint) primary_key_no))) {
trx_commit_for_mysql(trx); innobase_commit_low(trx);
row_mysql_unlock_data_dictionary();
trx_free_for_mysql(trx); trx_free_for_mysql(trx);
...@@ -2485,9 +2589,11 @@ ha_innobase::create( ...@@ -2485,9 +2589,11 @@ ha_innobase::create(
if ((error = create_index(trx, form, norm_name, i))) { if ((error = create_index(trx, form, norm_name, i))) {
trx_commit_for_mysql(trx); innobase_commit_low(trx);
trx_free_for_mysql(trx); row_mysql_unlock_data_dictionary();
trx_free_for_mysql(trx);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -2497,17 +2603,21 @@ ha_innobase::create( ...@@ -2497,17 +2603,21 @@ ha_innobase::create(
error = row_table_add_foreign_constraints(trx, error = row_table_add_foreign_constraints(trx,
create_info->create_statement, norm_name); create_info->create_statement, norm_name);
error = convert_error_code_to_mysql(error); error = convert_error_code_to_mysql(error, NULL);
if (error) { if (error) {
trx_commit_for_mysql(trx); innobase_commit_low(trx);
row_mysql_unlock_data_dictionary();
trx_free_for_mysql(trx); trx_free_for_mysql(trx);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
trx_commit_for_mysql(trx); innobase_commit_low(trx);
row_mysql_unlock_data_dictionary();
/* Flush the log to reduce probability that the .frm files and /* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs the InnoDB data dictionary get out-of-sync if the user runs
...@@ -2575,11 +2685,11 @@ ha_innobase::delete_table( ...@@ -2575,11 +2685,11 @@ ha_innobase::delete_table(
srv_active_wake_master_thread(); srv_active_wake_master_thread();
trx_commit_for_mysql(trx); innobase_commit_low(trx);
trx_free_for_mysql(trx); trx_free_for_mysql(trx);
error = convert_error_code_to_mysql(error); error = convert_error_code_to_mysql(error, NULL);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -2640,10 +2750,10 @@ innobase_drop_database( ...@@ -2640,10 +2750,10 @@ innobase_drop_database(
srv_active_wake_master_thread(); srv_active_wake_master_thread();
trx_commit_for_mysql(trx); innobase_commit_low(trx);
trx_free_for_mysql(trx); trx_free_for_mysql(trx);
error = convert_error_code_to_mysql(error); error = convert_error_code_to_mysql(error, NULL);
return(error); return(error);
} }
...@@ -2693,10 +2803,10 @@ ha_innobase::rename_table( ...@@ -2693,10 +2803,10 @@ ha_innobase::rename_table(
srv_active_wake_master_thread(); srv_active_wake_master_thread();
trx_commit_for_mysql(trx); innobase_commit_low(trx);
trx_free_for_mysql(trx); trx_free_for_mysql(trx);
error = convert_error_code_to_mysql(error); error = convert_error_code_to_mysql(error, NULL);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -2814,7 +2924,7 @@ ha_innobase::estimate_number_of_rows(void) ...@@ -2814,7 +2924,7 @@ ha_innobase::estimate_number_of_rows(void)
estimate = 2 * data_file_length / dict_index_calc_min_rec_len(index); estimate = 2 * data_file_length / dict_index_calc_min_rec_len(index);
DBUG_RETURN((ha_rows) estimate); return((ha_rows) estimate);
} }
/************************************************************************* /*************************************************************************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment