ha_innobase.cc:

  Merge 3.23.52
parent 94e926ac
......@@ -27,6 +27,7 @@ InnoDB */
#endif
#include "mysql_priv.h"
#include "slave.h"
#ifdef HAVE_INNOBASE_DB
#include <m_ctype.h>
#include <assert.h>
......@@ -53,10 +54,12 @@ typedef byte mysql_byte;
/* Include necessary InnoDB headers */
extern "C" {
#include "../innobase/include/univ.i"
#include "../innobase/include/os0file.h"
#include "../innobase/include/srv0start.h"
#include "../innobase/include/srv0srv.h"
#include "../innobase/include/trx0roll.h"
#include "../innobase/include/trx0trx.h"
#include "../innobase/include/trx0sys.h"
#include "../innobase/include/row0ins.h"
#include "../innobase/include/row0mysql.h"
#include "../innobase/include/row0sel.h"
......@@ -180,7 +183,8 @@ int
convert_error_code_to_mysql(
/*========================*/
/* 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) {
......@@ -199,11 +203,27 @@ convert_error_code_to_mysql(
return(HA_ERR_NO_ACTIVE_RECORD);
} 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);
} 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);
} else if (error == (int) DB_NO_REFERENCED_ROW) {
......@@ -313,7 +333,23 @@ check_trx_exists(
thd->transaction.stmt.innobase_tid =
(void*)&innodb_dummy_stmt_trx_handle;
} 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);
......@@ -359,6 +395,8 @@ innobase_init(void)
DBUG_ENTER("innobase_init");
os_innodb_umask = (ulint)my_umask;
if (specialflag & SPECIAL_NO_PRIOR) {
srv_set_thread_priorities = FALSE;
} else {
......@@ -435,7 +473,7 @@ innobase_init(void)
srv_log_archive_on = (ulint) innobase_log_archive;
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;
......@@ -470,6 +508,22 @@ innobase_init(void)
(void) hash_init(&innobase_open_tables,32,0,0,
(hash_get_key) innobase_get_key,0,0);
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);
}
......@@ -528,6 +582,17 @@ innobase_get_free_space(void)
/*********************************************************************
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
innobase_commit(
/*============*/
......@@ -547,8 +612,21 @@ innobase_commit(
trx = check_trx_exists(thd);
if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
if (thd->slave_thread) {
trx_commit_for_mysql(trx);
/* 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);
}
innobase_commit_low(trx);
}
/* Release possible statement level resources */
......@@ -589,6 +667,8 @@ innobase_report_binlog_offset_and_commit(
trx = (trx_t*)trx_handle;
ut_a(trx != NULL);
trx->mysql_log_file_name = log_file_name;
trx->mysql_log_offset = (ib_longlong)end_offset;
......@@ -629,7 +709,7 @@ innobase_rollback(
trx_mark_sql_stat_end(trx);
DBUG_RETURN(convert_error_code_to_mysql(error));
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
}
/*********************************************************************
......@@ -791,7 +871,6 @@ ha_innobase::open(
ib_table = dict_table_get_and_increment_handle_count(
norm_name, NULL);
if (NULL == ib_table) {
fprintf(stderr,
......@@ -846,6 +925,9 @@ ha_innobase::open(
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 */
thr_lock_data_init(&share->lock,&lock,(void*) 0);
......@@ -1365,7 +1447,8 @@ ha_innobase::write_row(
if (error != DB_SUCCESS) {
error = convert_error_code_to_mysql(error);
error = convert_error_code_to_mysql(error,
user_thd);
goto func_exit;
}
......@@ -1381,7 +1464,7 @@ ha_innobase::write_row(
srv_conc_exit_innodb(prebuilt->trx);
error = convert_error_code_to_mysql(
error);
error, user_thd);
goto func_exit;
}
}
......@@ -1412,7 +1495,8 @@ ha_innobase::write_row(
if (error != DB_SUCCESS) {
error = convert_error_code_to_mysql(error);
error = convert_error_code_to_mysql(error,
user_thd);
goto func_exit;
}
......@@ -1452,7 +1536,7 @@ ha_innobase::write_row(
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
utility threads: */
......@@ -1669,7 +1753,7 @@ ha_innobase::update_row(
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
utility threads: */
......@@ -1714,7 +1798,7 @@ ha_innobase::delete_row(
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
utility threads: */
......@@ -1872,7 +1956,7 @@ ha_innobase::index_read(
error = HA_ERR_KEY_NOT_FOUND;
table->status = STATUS_NOT_FOUND;
} else {
error = convert_error_code_to_mysql(ret);
error = convert_error_code_to_mysql(ret, user_thd);
table->status = STATUS_NOT_FOUND;
}
......@@ -1891,7 +1975,7 @@ ha_innobase::change_active_index(
InnoDB */
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
KEY* key=0;
KEY* key;
statistic_increment(ha_read_key_count, &LOCK_status);
......@@ -1912,10 +1996,9 @@ ha_innobase::change_active_index(
if (!prebuilt->index) {
fprintf(stderr,
"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",
prebuilt->table->name);
"InnoDB: for table %s\n", keynr, key->name, prebuilt->table->name);
DBUG_RETURN(1);
return(1);
}
assert(prebuilt->search_tuple);
......@@ -1931,7 +2014,7 @@ ha_innobase::change_active_index(
build_template(prebuilt, user_thd, table, ROW_MYSQL_WHOLE_ROW);
DBUG_RETURN(0);
return(0);
}
/**************************************************************************
......@@ -1999,7 +2082,7 @@ ha_innobase::general_fetch(
error = HA_ERR_END_OF_FILE;
table->status = STATUS_NOT_FOUND;
} else {
error = convert_error_code_to_mysql(ret);
error = convert_error_code_to_mysql(ret, user_thd);
table->status = STATUS_NOT_FOUND;
}
......@@ -2301,7 +2384,7 @@ create_table_def(
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);
}
......@@ -2358,7 +2441,7 @@ create_index(
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);
}
......@@ -2384,7 +2467,7 @@ create_clustered_index_when_no_primary(
0, DICT_CLUSTERED, 0);
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);
}
......@@ -2414,19 +2497,36 @@ ha_innobase::create(
DBUG_ENTER("ha_innobase::create");
assert(current_thd != NULL);
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
normalize_table_name(norm_name, name2);
/* 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);
if (error) {
innobase_commit_low(trx);
trx_commit_for_mysql(trx);
row_mysql_unlock_data_dictionary();
trx_free_for_mysql(trx);
......@@ -2458,7 +2558,9 @@ ha_innobase::create(
error = create_clustered_index_when_no_primary(trx,
norm_name);
if (error) {
trx_commit_for_mysql(trx);
innobase_commit_low(trx);
row_mysql_unlock_data_dictionary();
trx_free_for_mysql(trx);
......@@ -2471,7 +2573,9 @@ ha_innobase::create(
first */
if ((error = create_index(trx, form, norm_name,
(uint) primary_key_no))) {
trx_commit_for_mysql(trx);
innobase_commit_low(trx);
row_mysql_unlock_data_dictionary();
trx_free_for_mysql(trx);
......@@ -2485,7 +2589,9 @@ ha_innobase::create(
if ((error = create_index(trx, form, norm_name, i))) {
trx_commit_for_mysql(trx);
innobase_commit_low(trx);
row_mysql_unlock_data_dictionary();
trx_free_for_mysql(trx);
......@@ -2497,17 +2603,21 @@ ha_innobase::create(
error = row_table_add_foreign_constraints(trx,
create_info->create_statement, norm_name);
error = convert_error_code_to_mysql(error);
error = convert_error_code_to_mysql(error, NULL);
if (error) {
trx_commit_for_mysql(trx);
innobase_commit_low(trx);
row_mysql_unlock_data_dictionary();
trx_free_for_mysql(trx);
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
the InnoDB data dictionary get out-of-sync if the user runs
......@@ -2575,11 +2685,11 @@ ha_innobase::delete_table(
srv_active_wake_master_thread();
trx_commit_for_mysql(trx);
innobase_commit_low(trx);
trx_free_for_mysql(trx);
error = convert_error_code_to_mysql(error);
error = convert_error_code_to_mysql(error, NULL);
DBUG_RETURN(error);
}
......@@ -2640,10 +2750,10 @@ innobase_drop_database(
srv_active_wake_master_thread();
trx_commit_for_mysql(trx);
innobase_commit_low(trx);
trx_free_for_mysql(trx);
error = convert_error_code_to_mysql(error);
error = convert_error_code_to_mysql(error, NULL);
return(error);
}
......@@ -2693,10 +2803,10 @@ ha_innobase::rename_table(
srv_active_wake_master_thread();
trx_commit_for_mysql(trx);
innobase_commit_low(trx);
trx_free_for_mysql(trx);
error = convert_error_code_to_mysql(error);
error = convert_error_code_to_mysql(error, NULL);
DBUG_RETURN(error);
}
......@@ -2814,7 +2924,7 @@ ha_innobase::estimate_number_of_rows(void)
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