summaryrefslogtreecommitdiff
path: root/handler/ha_innodb.cc
diff options
context:
space:
mode:
Diffstat (limited to 'handler/ha_innodb.cc')
-rw-r--r--handler/ha_innodb.cc200
1 files changed, 119 insertions, 81 deletions
diff --git a/handler/ha_innodb.cc b/handler/ha_innodb.cc
index d4ad5f106a2..fd7caf52816 100644
--- a/handler/ha_innodb.cc
+++ b/handler/ha_innodb.cc
@@ -121,7 +121,6 @@ static mysql_mutex_t innobase_share_mutex;
/** to force correct commit order in binlog */
static mysql_mutex_t prepare_commit_mutex;
static ulong commit_threads = 0;
-static mysql_mutex_t commit_threads_m;
static mysql_cond_t commit_cond;
static mysql_mutex_t commit_cond_m;
static bool innodb_inited = 0;
@@ -256,12 +255,10 @@ static const char* innobase_change_buffering_values[IBUF_USE_COUNT] = {
performance schema */
static mysql_pfs_key_t innobase_share_mutex_key;
static mysql_pfs_key_t prepare_commit_mutex_key;
-static mysql_pfs_key_t commit_threads_m_key;
static mysql_pfs_key_t commit_cond_mutex_key;
static mysql_pfs_key_t commit_cond_key;
static PSI_mutex_info all_pthread_mutexes[] = {
- {&commit_threads_m_key, "commit_threads_m", 0},
{&commit_cond_mutex_key, "commit_cond_mutex", 0},
{&innobase_share_mutex_key, "innobase_share_mutex", 0},
{&prepare_commit_mutex_key, "prepare_commit_mutex", 0}
@@ -462,6 +459,19 @@ innobase_purge_changed_page_bitmaps(
/*================================*/
ulonglong lsn); /*!< in: LSN to purge files up to */
+
+/*****************************************************************//**
+Check whether this is a fake change transaction.
+@return TRUE if a fake change transaction */
+static
+my_bool
+innobase_is_fake_change(
+/*====================*/
+ handlerton *hton, /*!< in: InnoDB handlerton */
+ THD* thd); /*!< in: MySQL thread handle of the user for
+ whom the transaction is being committed */
+
+
static const char innobase_hton_name[]= "InnoDB";
/*************************************************************//**
@@ -946,22 +956,18 @@ innodb_srv_conc_exit_innodb(
}
/******************************************************************//**
-Releases possible search latch and InnoDB thread FIFO ticket. These should
-be released at each SQL statement end, and also when mysqld passes the
-control to the client. It does no harm to release these also in the middle
-of an SQL statement. */
+Force a thread to leave InnoDB even if it has spare tickets. */
static inline
void
-innobase_release_stat_resources(
-/*============================*/
- trx_t* trx) /*!< in: transaction object */
+innodb_srv_conc_force_exit_innodb(
+/*==============================*/
+ trx_t* trx) /*!< in: transaction handle */
{
- if (trx->has_search_latch) {
- trx_search_latch_release_if_reserved(trx);
- }
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
if (trx->declared_to_be_inside_innodb) {
- /* Release our possible ticket in the FIFO */
srv_conc_force_exit_innodb(trx);
}
@@ -1117,9 +1123,10 @@ innobase_release_temporary_latches(
trx = thd_to_trx(thd);
- if (trx) {
- innobase_release_stat_resources(trx);
+ if (trx != NULL) {
+ trx_search_latch_release_if_reserved(trx);
}
+
return(0);
}
@@ -1430,6 +1437,23 @@ innobase_convert_from_id(
strconvert(cs, from, system_charset_info, to, (uint) len, &errors);
}
+/**********************************************************************
+Converts an identifier from my_charset_filename to UTF-8 charset. */
+extern "C"
+uint
+innobase_convert_to_system_charset(
+/*===============================*/
+ char* to, /* out: converted identifier */
+ const char* from, /* in: identifier to convert */
+ ulint len, /* in: length of 'to', in bytes */
+ uint* errors) /* out: error return */
+{
+ CHARSET_INFO* cs1 = &my_charset_filename;
+ CHARSET_INFO* cs2 = system_charset_info;
+
+ return(strconvert(cs1, from, cs2, to, len, errors));
+}
+
/******************************************************************//**
Compares NUL-terminated UTF-8 strings case insensitively.
@return 0 if a=b, <0 if a<b, >1 if a>b */
@@ -2136,7 +2160,8 @@ innobase_query_caching_of_table_permitted(
mutex_exit(&kernel_mutex);
}
- innobase_release_stat_resources(trx);
+ trx_search_latch_release_if_reserved(trx);
+ innodb_srv_conc_force_exit_innodb(trx);
if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
@@ -2449,7 +2474,8 @@ ha_innobase::init_table_handle_for_HANDLER(void)
/* Initialize the prebuilt struct much like it would be inited in
external_lock */
- innobase_release_stat_resources(prebuilt->trx);
+ trx_search_latch_release_if_reserved(prebuilt->trx);
+ innodb_srv_conc_force_exit_innodb(prebuilt->trx);
/* If the transaction is not started yet, start it */
@@ -2646,6 +2672,7 @@ innobase_init(
= innobase_flush_changed_page_bitmaps;
innobase_hton->purge_changed_page_bitmaps
= innobase_purge_changed_page_bitmaps;
+ innobase_hton->is_fake_change = innobase_is_fake_change;
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
@@ -3210,8 +3237,6 @@ innobase_change_buffering_inited_ok:
MY_MUTEX_INIT_FAST);
mysql_mutex_init(prepare_commit_mutex_key,
&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
- mysql_mutex_init(commit_threads_m_key,
- &commit_threads_m, MY_MUTEX_INIT_FAST);
mysql_mutex_init(commit_cond_mutex_key,
&commit_cond_m, MY_MUTEX_INIT_FAST);
mysql_cond_init(commit_cond_key, &commit_cond, NULL);
@@ -3260,7 +3285,6 @@ innobase_end(
my_free(internal_innobase_data_file_path);
mysql_mutex_destroy(&innobase_share_mutex);
mysql_mutex_destroy(&prepare_commit_mutex);
- mysql_mutex_destroy(&commit_threads_m);
mysql_mutex_destroy(&commit_cond_m);
mysql_cond_destroy(&commit_cond);
}
@@ -3335,6 +3359,23 @@ innobase_purge_changed_page_bitmaps(
return (my_bool)log_online_purge_changed_page_bitmaps(lsn);
}
+/*****************************************************************//**
+Check whether this is a fake change transaction.
+@return TRUE if a fake change transaction */
+static
+my_bool
+innobase_is_fake_change(
+/*====================*/
+ handlerton *hton __attribute__((unused)),
+ /*!< in: InnoDB handlerton */
+ THD* thd) /*!< in: MySQL thread handle of the user for
+ whom the transaction is being committed */
+{
+ trx_t* trx = check_trx_exists(thd);
+ return trx->fake_changes;
+}
+
+
/****************************************************************//**
Copy the current replication position from MySQL to a transaction. */
static
@@ -3408,7 +3449,8 @@ innobase_start_trx_and_assign_read_view(
search latch. Since we will reserve the kernel mutex, we have to
release the search system latch first to obey the latching order. */
- innobase_release_stat_resources(trx);
+ trx_search_latch_release_if_reserved(trx);
+ innodb_srv_conc_force_exit_innodb(trx);
/* If the transaction is not started yet, start it */
@@ -3726,7 +3768,8 @@ innobase_rollback(
reserve the kernel mutex, we have to release the search system latch
first to obey the latching order. */
- innobase_release_stat_resources(trx);
+ trx_search_latch_release_if_reserved(trx);
+ innodb_srv_conc_force_exit_innodb(trx);
trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
@@ -3740,6 +3783,9 @@ innobase_rollback(
|| !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
error = trx_rollback_for_mysql(trx);
+ if (trx_has_prepare_commit_mutex(trx)) {
+ mysql_mutex_unlock(&prepare_commit_mutex);
+ }
trx_deregister_from_2pc(trx);
} else {
error = trx_rollback_last_sql_stat_for_mysql(trx);
@@ -3766,7 +3812,8 @@ innobase_rollback_trx(
reserve the kernel mutex, we have to release the search system latch
first to obey the latching order. */
- innobase_release_stat_resources(trx);
+ trx_search_latch_release_if_reserved(trx);
+ innodb_srv_conc_force_exit_innodb(trx);
/* If we had reserved the auto-inc lock for some table (if
we come here to roll back the latest SQL statement) we
@@ -3806,7 +3853,8 @@ innobase_rollback_to_savepoint(
reserve the kernel mutex, we have to release the search system latch
first to obey the latching order. */
- innobase_release_stat_resources(trx);
+ trx_search_latch_release_if_reserved(trx);
+ innodb_srv_conc_force_exit_innodb(trx);
/* TODO: use provided savepoint data area to store savepoint data */
@@ -3881,7 +3929,8 @@ innobase_savepoint(
reserve the kernel mutex, we have to release the search system latch
first to obey the latching order. */
- innobase_release_stat_resources(trx);
+ trx_search_latch_release_if_reserved(trx);
+ innodb_srv_conc_force_exit_innodb(trx);
/* Cannot happen outside of transaction */
DBUG_ASSERT(trx_is_registered_for_2pc(trx));
@@ -4636,16 +4685,17 @@ UNIV_INTERN
int
ha_innobase::open(
/*==============*/
- const char* name, /*!< in: table name */
- int mode, /*!< in: not used */
- uint test_if_locked) /*!< in: not used */
-{
- dict_table_t* ib_table;
- char norm_name[1000];
- THD* thd;
- char* is_part = NULL;
- ibool par_case_name_set = FALSE;
- char par_case_name[MAX_FULL_NAME_LEN + 1];
+ const char* name, /*!< in: table name */
+ int mode, /*!< in: not used */
+ uint test_if_locked) /*!< in: not used */
+{
+ dict_table_t* ib_table;
+ char norm_name[1000];
+ THD* thd;
+ char* is_part = NULL;
+ ibool par_case_name_set = FALSE;
+ char par_case_name[MAX_FULL_NAME_LEN + 1];
+ dict_err_ignore_t ignore_err = DICT_ERR_IGNORE_NONE;
DBUG_ENTER("ha_innobase::open");
@@ -4689,8 +4739,15 @@ ha_innobase::open(
is_part = strstr(norm_name, "#P#");
#endif /* __WIN__ */
+ /* Check whether FOREIGN_KEY_CHECKS is set to 0. If so, the table
+ can be opened even if some FK indexes are missing. If not, the table
+ can't be opened in the same situation */
+ if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
+ ignore_err = DICT_ERR_IGNORE_FK_NOKEY;
+ }
+
/* Get pointer to a table object in InnoDB dictionary cache */
- ib_table = dict_table_get(norm_name, TRUE);
+ ib_table = dict_table_get(norm_name, TRUE, ignore_err);
if (UNIV_UNLIKELY(ib_table && ib_table->is_corrupt &&
srv_pass_corrupt_table <= 1)) {
@@ -4746,7 +4803,7 @@ ha_innobase::open(
}
ib_table = dict_table_get(
- par_case_name, FALSE);
+ par_case_name, FALSE, ignore_err);
}
if (ib_table) {
#ifndef __WIN__
@@ -8240,7 +8297,8 @@ ha_innobase::create(
log_buffer_flush_to_disk();
- innobase_table = dict_table_get(norm_name, FALSE);
+ innobase_table = dict_table_get(norm_name, FALSE,
+ DICT_ERR_IGNORE_NONE);
DBUG_ASSERT(innobase_table != 0);
@@ -9134,6 +9192,8 @@ ha_innobase::info_low(
prebuilt->trx->op_info = "updating table statistics";
+ DEBUG_SYNC_C("info_before_stats_update");
+
dict_update_statistics(
ib_table,
FALSE, /* update even if initialized */
@@ -9613,6 +9673,9 @@ ha_innobase::check(
(ulong) n_rows,
(ulong) n_rows_in_table);
is_ok = FALSE;
+ row_mysql_lock_data_dictionary(prebuilt->trx);
+ dict_set_corrupted(index);
+ row_mysql_unlock_data_dictionary(prebuilt->trx);
}
}
@@ -10161,7 +10224,8 @@ ha_innobase::start_stmt(
that may not be the case. We MUST release the search latch before an
INSERT, for example. */
- innobase_release_stat_resources(trx);
+ trx_search_latch_release_if_reserved(trx);
+ innodb_srv_conc_force_exit_innodb(trx);
/* Reset the AUTOINC statement level counter for multi-row INSERTs. */
trx->n_autoinc_rows = 0;
@@ -10356,7 +10420,8 @@ ha_innobase::external_lock(
may reserve the kernel mutex, we have to release the search
system latch first to obey the latching order. */
- innobase_release_stat_resources(trx);
+ trx_search_latch_release_if_reserved(trx);
+ innodb_srv_conc_force_exit_innodb(trx);
/* If the MySQL lock count drops to zero we know that the current SQL
statement has ended */
@@ -10535,7 +10600,8 @@ innodb_show_status(
trx = check_trx_exists(thd);
- innobase_release_stat_resources(trx);
+ trx_search_latch_release_if_reserved(trx);
+ innodb_srv_conc_force_exit_innodb(trx);
/* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
bytes of text. */
@@ -11519,7 +11585,14 @@ innobase_xa_prepare(
return(0);
}
- if (trx->fake_changes) {
+ if (UNIV_UNLIKELY(trx->fake_changes)) {
+
+ if (all || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT
+ | OPTION_BEGIN))) {
+
+ thd->stmt_da->reset_diagnostics_area();
+ return(HA_ERR_WRONG_COMMAND);
+ }
return(0);
}
@@ -11529,7 +11602,8 @@ innobase_xa_prepare(
reserve the kernel mutex, we have to release the search system latch
first to obey the latching order. */
- innobase_release_stat_resources(trx);
+ trx_search_latch_release_if_reserved(trx);
+ innodb_srv_conc_force_exit_innodb(trx);
if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
@@ -13491,7 +13565,6 @@ test_innobase_convert_name()
}
}
}
-
#endif /* UNIV_COMPILE_TEST_FUNCS */
/**********************************************************************
@@ -13505,43 +13578,8 @@ innobase_convert_to_filename_charset(
ulint len) /* in: length of 'to', in bytes */
{
uint errors;
- uint rlen;
CHARSET_INFO* cs_to = &my_charset_filename;
CHARSET_INFO* cs_from = system_charset_info;
- rlen = strconvert(cs_from, from, cs_to, to, len, &errors);
-
- if (errors) {
- fprintf(stderr, "InnoDB: There was a problem in converting"
- "'%s' in charset %s to charset %s", from, cs_from->name,
- cs_to->name);
- }
-
- return(rlen);
-}
-
-/**********************************************************************
-Converts an identifier from my_charset_filename to UTF-8 charset. */
-extern "C"
-uint
-innobase_convert_to_system_charset(
-/*===============================*/
- char* to, /* out: converted identifier */
- const char* from, /* in: identifier to convert */
- ulint len, /* in: length of 'to', in bytes */
- uint* errors) /* out: error return */
-{
- uint rlen;
- CHARSET_INFO* cs1 = &my_charset_filename;
- CHARSET_INFO* cs2 = system_charset_info;
-
- rlen = strconvert(cs1, from, cs2, to, len, errors);
-
- if (*errors) {
- fprintf(stderr, "InnoDB: There was a problem in converting"
- "'%s' in charset %s to charset %s", from, cs1->name,
- cs2->name);
- }
-
- return(rlen);
+ return(strconvert(cs_from, from, cs_to, to, len, &errors));
}