diff options
Diffstat (limited to 'storage/innobase/handler/ha_innodb.cc')
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 198 |
1 files changed, 173 insertions, 25 deletions
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 66a28ea56b7..a74fa32da58 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2445,7 +2445,11 @@ innobase_mysql_tmpfile( } return hDup; #else +#ifdef F_DUPFD_CLOEXEC + int fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 0); +#else int fd2 = dup(fd); +#endif my_close(fd, MYF(MY_WME)); if (fd2 < 0) { set_my_errno(errno); @@ -3080,6 +3084,83 @@ AUTOCOMMIT==0 or we are inside BEGIN ... COMMIT. Thus transactions no longer put restrictions on the use of the query cache. */ +/** Check if mysql can allow the transaction to read from/store to +the query cache. +@param[in] table table object +@param[in] trx transaction object +@return whether the storing or retrieving from the query cache is permitted */ +static bool innobase_query_caching_table_check_low( + const dict_table_t* table, + trx_t* trx) +{ + /* The following conditions will decide the query cache + retrieval or storing into: + + (1) There should not be any locks on the table. + (2) Someother trx shouldn't invalidate the cache before this + transaction started. + (3) Read view shouldn't exist. If exists then the view + low_limit_id should be greater than or equal to the transaction that + invalidates the cache for the particular table. + + For read-only transaction: should satisfy (1) and (3) + For read-write transaction: should satisfy (1), (2), (3) */ + + if (lock_table_get_n_locks(table)) { + return false; + } + + if (trx->id && trx->id < table->query_cache_inv_trx_id) { + return false; + } + + return !trx->read_view.is_open() + || trx->read_view.low_limit_id() + >= table->query_cache_inv_trx_id; +} + +/** Checks if MySQL at the moment is allowed for this table to retrieve a +consistent read result, or store it to the query cache. +@param[in,out] trx transaction +@param[in] norm_name concatenation of database name, + '/' char, table name +@return whether storing or retrieving from the query cache is permitted */ +static bool innobase_query_caching_table_check( + trx_t* trx, + const char* norm_name) +{ + dict_table_t* table = dict_table_open_on_name( + norm_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE); + + if (table == NULL) { + return false; + } + + /* Start the transaction if it is not started yet */ + trx_start_if_not_started(trx, false); + + bool allow = innobase_query_caching_table_check_low(table, trx); + + dict_table_close(table, FALSE, FALSE); + + if (allow) { + /* If the isolation level is high, assign a read view for the + transaction if it does not yet have one */ + + if (trx->isolation_level >= TRX_ISO_REPEATABLE_READ + && !srv_read_only_mode + && !trx->read_view.is_open()) { + + /* Start the transaction if it is not started yet */ + trx_start_if_not_started(trx, false); + + trx->read_view.open(trx); + } + } + + return allow; +} + /******************************************************************//** The MySQL query cache uses this to check from InnoDB if the query cache at the moment is allowed to operate on an InnoDB table. The SQL query must @@ -3155,7 +3236,7 @@ innobase_query_caching_of_table_permitted( innobase_register_trx(innodb_hton_ptr, thd, trx); - return(row_search_check_if_query_cache_permitted(trx, norm_name)); + return innobase_query_caching_table_check(trx, norm_name); } /*****************************************************************//** @@ -8222,13 +8303,12 @@ report_error: error, m_prebuilt->table->flags, m_user_thd); #ifdef WITH_WSREP - if (!error_result && - wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE && - wsrep_on(m_user_thd) && - !wsrep_consistency_check(m_user_thd) && - !wsrep_thd_ignore_table(m_user_thd)) { - if (wsrep_append_keys(m_user_thd, false, record, NULL)) - { + if (!error_result + && wsrep_on(m_user_thd) + && wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE + && !wsrep_consistency_check(m_user_thd) + && !wsrep_thd_ignore_table(m_user_thd)) { + if (wsrep_append_keys(m_user_thd, false, record, NULL)) { DBUG_PRINT("wsrep", ("row key failed")); error_result = HA_ERR_INTERNAL_ERROR; goto wsrep_error; @@ -18723,8 +18803,10 @@ wsrep_innobase_kill_one_trx( thd_get_thread_id(thd), victim_trx->id); - WSREP_DEBUG("Aborting query: %s", - (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void"); + WSREP_DEBUG("Aborting query: %s conf %d trx: %lu", + (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void", + wsrep_thd_conflict_state(thd, FALSE), + wsrep_thd_ws_handle(thd)->trx_id); wsrep_thd_LOCK(thd); DBUG_EXECUTE_IF("sync.wsrep_after_BF_victim_lock", @@ -18787,7 +18869,7 @@ wsrep_innobase_kill_one_trx( wsrep_t *wsrep= get_wsrep(); rcode = wsrep->abort_pre_commit( wsrep, bf_seqno, - (wsrep_trx_id_t)victim_trx->id + (wsrep_trx_id_t)wsrep_thd_ws_handle(thd)->trx_id ); switch (rcode) { @@ -18912,12 +18994,14 @@ wsrep_abort_transaction( my_bool signal) { DBUG_ENTER("wsrep_innobase_abort_thd"); - trx_t* victim_trx = thd_to_trx(victim_thd); - trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL; - WSREP_DEBUG("abort transaction: BF: %s victim: %s", - wsrep_thd_query(bf_thd), - wsrep_thd_query(victim_thd)); + trx_t* victim_trx = thd_to_trx(victim_thd); + trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL; + + WSREP_DEBUG("abort transaction: BF: %s victim: %s victim conf: %d", + wsrep_thd_query(bf_thd), + wsrep_thd_query(victim_thd), + wsrep_thd_conflict_state(victim_thd, FALSE)); if (victim_trx) { lock_mutex_enter(); @@ -20700,6 +20784,77 @@ innobase_get_field_from_update_vector( return (NULL); } + +/** + Allocate a heap and record for calculating virtual fields + Used mainly for virtual fields in indexes + +@param[in] thd MariaDB THD +@param[in] index Index in use +@param[out] heap Heap that holds temporary row +@param[in,out] mysql_table MariaDB table +@param[out] rec Pointer to allocated MariaDB record +@param[out] storage Internal storage for blobs etc + +@return FALSE ok +@return TRUE malloc failure +*/ + +bool innobase_allocate_row_for_vcol( + THD * thd, + dict_index_t* index, + mem_heap_t** heap, + TABLE** table, + byte** record, + VCOL_STORAGE** storage) +{ + TABLE *maria_table; + String *blob_value_storage; + if (!*table) + *table= innobase_find_mysql_table_for_vc(thd, index->table); + maria_table= *table; + if (!*heap && !(*heap= mem_heap_create(srv_page_size))) + { + *storage= 0; + return TRUE; + } + *record= static_cast<byte*>(mem_heap_alloc(*heap, + maria_table->s->reclength)); + *storage= static_cast<VCOL_STORAGE*> + (mem_heap_alloc(*heap, sizeof(**storage))); + blob_value_storage= static_cast<String*> + (mem_heap_alloc(*heap, + maria_table->s->virtual_not_stored_blob_fields * + sizeof(String))); + if (!*record || !*storage || !blob_value_storage) + { + *storage= 0; + return TRUE; + } + (*storage)->maria_table= maria_table; + (*storage)->innobase_record= *record; + (*storage)->maria_record= maria_table->field[0]->record_ptr(); + (*storage)->blob_value_storage= blob_value_storage; + + maria_table->move_fields(maria_table->field, *record, + (*storage)->maria_record); + maria_table->remember_blob_values(blob_value_storage); + + return FALSE; +} + + +/** Free memory allocated by innobase_allocate_row_for_vcol() */ + +void innobase_free_row_for_vcol(VCOL_STORAGE *storage) +{ + TABLE *maria_table= storage->maria_table; + maria_table->move_fields(maria_table->field, storage->maria_record, + storage->innobase_record); + maria_table->restore_blob_values(storage->blob_value_storage); +} + + /** Get the computed value by supplying the base column values. @param[in,out] row the data row @param[in] col virtual column @@ -20725,12 +20880,12 @@ innobase_get_computed_value( const dict_field_t* ifield, THD* thd, TABLE* mysql_table, + byte* mysql_rec, const dict_table_t* old_table, upd_t* parent_update, dict_foreign_t* foreign) { byte rec_buf2[REC_VERSION_56_MAX_INDEX_COL_LEN]; - byte* mysql_rec; byte* buf; dfield_t* field; ulint len; @@ -20743,6 +20898,7 @@ innobase_get_computed_value( ut_ad(index->table->vc_templ); ut_ad(thd != NULL); + ut_ad(mysql_table); const mysql_row_templ_t* vctempl = index->table->vc_templ->vtempl[ @@ -20760,14 +20916,6 @@ innobase_get_computed_value( buf = rec_buf2; } - if (!mysql_table) { - mysql_table = innobase_find_mysql_table_for_vc(thd, index->table); - } - - ut_ad(mysql_table); - - mysql_rec = mysql_table->record[0]; - for (ulint i = 0; i < col->num_base; i++) { dict_col_t* base_col = col->base_col[i]; const dfield_t* row_field = NULL; |