summaryrefslogtreecommitdiff
path: root/storage/xtradb/trx/trx0i_s.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/xtradb/trx/trx0i_s.c')
-rw-r--r--storage/xtradb/trx/trx0i_s.c158
1 files changed, 142 insertions, 16 deletions
diff --git a/storage/xtradb/trx/trx0i_s.c b/storage/xtradb/trx/trx0i_s.c
index 5bc8302d0c0..c18b747da6d 100644
--- a/storage/xtradb/trx/trx0i_s.c
+++ b/storage/xtradb/trx/trx0i_s.c
@@ -38,8 +38,6 @@ Created July 17, 2007 Vasil Dimov
#include <mysql/plugin.h>
-#include "mysql_addons.h"
-
#include "buf0buf.h"
#include "dict0dict.h"
#include "ha0storage.h"
@@ -193,6 +191,15 @@ INFORMATION SCHEMA tables is fetched and later retrieved by the C++
code in handler/i_s.cc. */
UNIV_INTERN trx_i_s_cache_t* trx_i_s_cache = &trx_i_s_cache_static;
+/* Key to register the lock/mutex with performance schema */
+#ifdef UNIV_PFS_RWLOCK
+UNIV_INTERN mysql_pfs_key_t trx_i_s_cache_lock_key;
+#endif /* UNIV_PFS_RWLOCK */
+
+#ifdef UNIV_PFS_MUTEX
+UNIV_INTERN mysql_pfs_key_t cache_last_read_mutex_key;
+#endif /* UNIV_PFS_MUTEX */
+
/*******************************************************************//**
For a record lock that is in waiting state retrieves the only bit that
is set, for a table lock returns ULINT_UNDEFINED.
@@ -408,6 +415,42 @@ table_cache_create_empty_row(
return(row);
}
+#ifdef UNIV_DEBUG
+/*******************************************************************//**
+Validates a row in the locks cache.
+@return TRUE if valid */
+static
+ibool
+i_s_locks_row_validate(
+/*===================*/
+ const i_s_locks_row_t* row) /*!< in: row to validate */
+{
+ ut_ad(row->lock_trx_id != 0);
+ ut_ad(row->lock_mode != NULL);
+ ut_ad(row->lock_type != NULL);
+ ut_ad(row->lock_table != NULL);
+ ut_ad(row->lock_table_id != 0);
+
+ if (row->lock_space == ULINT_UNDEFINED) {
+ /* table lock */
+ ut_ad(!strcmp("TABLE", row->lock_type));
+ ut_ad(row->lock_index == NULL);
+ ut_ad(row->lock_data == NULL);
+ ut_ad(row->lock_page == ULINT_UNDEFINED);
+ ut_ad(row->lock_rec == ULINT_UNDEFINED);
+ } else {
+ /* record lock */
+ ut_ad(!strcmp("RECORD", row->lock_type));
+ ut_ad(row->lock_index != NULL);
+ /* row->lock_data == NULL if buf_page_try_get() == NULL */
+ ut_ad(row->lock_page != ULINT_UNDEFINED);
+ ut_ad(row->lock_rec != ULINT_UNDEFINED);
+ }
+
+ return(TRUE);
+}
+#endif /* UNIV_DEBUG */
+
/*******************************************************************//**
Fills i_s_trx_row_t object.
If memory can not be allocated then FALSE is returned.
@@ -431,26 +474,26 @@ fill_trx_row(
{
const char* stmt;
size_t stmt_len;
+ const char* s;
- row->trx_id = trx_get_id(trx);
+ ut_ad(mutex_own(&kernel_mutex));
+
+ row->trx_id = trx->id;
row->trx_started = (ib_time_t) trx->start_time;
row->trx_state = trx_get_que_state_str(trx);
+ row->requested_lock_row = requested_lock_row;
+ ut_ad(requested_lock_row == NULL
+ || i_s_locks_row_validate(requested_lock_row));
if (trx->wait_lock != NULL) {
-
ut_a(requested_lock_row != NULL);
-
- row->requested_lock_row = requested_lock_row;
row->trx_wait_started = (ib_time_t) trx->wait_started;
} else {
-
ut_a(requested_lock_row == NULL);
-
- row->requested_lock_row = NULL;
row->trx_wait_started = 0;
}
- row->trx_weight = (ullint) ut_conv_dulint_to_longlong(TRX_WEIGHT(trx));
+ row->trx_weight = (ullint) TRX_WEIGHT(trx);
if (trx->mysql_thd == NULL) {
/* For internal transactions e.g., purge and transactions
@@ -458,14 +501,13 @@ fill_trx_row(
thread data structure. */
row->trx_mysql_thread_id = 0;
row->trx_query = NULL;
- return(TRUE);
+ goto thd_done;
}
row->trx_mysql_thread_id = thd_get_thread_id(trx->mysql_thd);
stmt = innobase_get_stmt(trx->mysql_thd, &stmt_len);
if (stmt != NULL) {
-
char query[TRX_I_S_TRX_QUERY_MAX_LEN + 1];
if (stmt_len > TRX_I_S_TRX_QUERY_MAX_LEN) {
@@ -476,9 +518,11 @@ fill_trx_row(
query[stmt_len] = '\0';
row->trx_query = ha_storage_put_memlim(
- cache->storage, stmt, stmt_len + 1,
+ cache->storage, query, stmt_len + 1,
MAX_ALLOWED_FOR_STORAGE(cache));
+ row->trx_query_cs = innobase_get_charset(trx->mysql_thd);
+
if (row->trx_query == NULL) {
return(FALSE);
@@ -488,6 +532,79 @@ fill_trx_row(
row->trx_query = NULL;
}
+thd_done:
+ s = trx->op_info;
+
+ if (s != NULL && s[0] != '\0') {
+
+ TRX_I_S_STRING_COPY(s, row->trx_operation_state,
+ TRX_I_S_TRX_OP_STATE_MAX_LEN, cache);
+
+ if (row->trx_operation_state == NULL) {
+
+ return(FALSE);
+ }
+ } else {
+
+ row->trx_operation_state = NULL;
+ }
+
+ row->trx_tables_in_use = trx->n_mysql_tables_in_use;
+
+ row->trx_tables_locked = trx->mysql_n_tables_locked;
+
+ row->trx_lock_structs = UT_LIST_GET_LEN(trx->trx_locks);
+
+ row->trx_lock_memory_bytes = mem_heap_get_size(trx->lock_heap);
+
+ row->trx_rows_locked = lock_number_of_rows_locked(trx);
+
+ row->trx_rows_modified = trx->undo_no;
+
+ row->trx_concurrency_tickets = trx->n_tickets_to_enter_innodb;
+
+ switch (trx->isolation_level) {
+ case TRX_ISO_READ_UNCOMMITTED:
+ row->trx_isolation_level = "READ UNCOMMITTED";
+ break;
+ case TRX_ISO_READ_COMMITTED:
+ row->trx_isolation_level = "READ COMMITTED";
+ break;
+ case TRX_ISO_REPEATABLE_READ:
+ row->trx_isolation_level = "REPEATABLE READ";
+ break;
+ case TRX_ISO_SERIALIZABLE:
+ row->trx_isolation_level = "SERIALIZABLE";
+ break;
+ /* Should not happen as TRX_ISO_READ_COMMITTED is default */
+ default:
+ row->trx_isolation_level = "UNKNOWN";
+ }
+
+ row->trx_unique_checks = (ibool) trx->check_unique_secondary;
+
+ row->trx_foreign_key_checks = (ibool) trx->check_foreigns;
+
+ s = trx->detailed_error;
+
+ if (s != NULL && s[0] != '\0') {
+
+ TRX_I_S_STRING_COPY(s,
+ row->trx_foreign_key_error,
+ TRX_I_S_TRX_FK_ERROR_MAX_LEN, cache);
+
+ if (row->trx_foreign_key_error == NULL) {
+
+ return(FALSE);
+ }
+ } else {
+ row->trx_foreign_key_error = NULL;
+ }
+
+ row->trx_has_search_latch = (ibool) trx->has_search_latch;
+
+ row->trx_search_latch_timeout = trx->search_latch_timeout;
+
return(TRUE);
}
@@ -729,6 +846,7 @@ fill_locks_row(
row->lock_table_id = lock_get_table_id(lock);
row->hash_chain.value = row;
+ ut_ad(i_s_locks_row_validate(row));
return(TRUE);
}
@@ -749,6 +867,9 @@ fill_lock_waits_row(
relevant blocking lock
row in innodb_locks */
{
+ ut_ad(i_s_locks_row_validate(requested_lock_row));
+ ut_ad(i_s_locks_row_validate(blocking_lock_row));
+
row->requested_lock_row = requested_lock_row;
row->blocking_lock_row = blocking_lock_row;
@@ -820,6 +941,7 @@ locks_row_eq_lock(
or ULINT_UNDEFINED if the lock
is a table lock */
{
+ ut_ad(i_s_locks_row_validate(row));
#ifdef TEST_NO_LOCKS_ROW_IS_EVER_EQUAL_TO_LOCK_T
return(0);
#else
@@ -877,7 +999,7 @@ search_innodb_locks(
/* auxiliary variable */
hash_chain,
/* assertion on every traversed item */
- ,
+ ut_ad(i_s_locks_row_validate(hash_chain->value)),
/* this determines if we have found the lock */
locks_row_eq_lock(hash_chain->value, lock, heap_no));
@@ -917,6 +1039,7 @@ add_lock_to_cache(
dst_row = search_innodb_locks(cache, lock, heap_no);
if (dst_row != NULL) {
+ ut_ad(i_s_locks_row_validate(dst_row));
return(dst_row);
}
#endif
@@ -954,6 +1077,7 @@ add_lock_to_cache(
} /* for()-loop */
#endif
+ ut_ad(i_s_locks_row_validate(dst_row));
return(dst_row);
}
@@ -1251,11 +1375,13 @@ trx_i_s_cache_init(
release trx_i_s_cache_t::last_read_mutex
release trx_i_s_cache_t::rw_lock */
- rw_lock_create(&cache->rw_lock, SYNC_TRX_I_S_RWLOCK);
+ rw_lock_create(trx_i_s_cache_lock_key, &cache->rw_lock,
+ SYNC_TRX_I_S_RWLOCK);
cache->last_read = 0;
- mutex_create(&cache->last_read_mutex, SYNC_TRX_I_S_LAST_READ);
+ mutex_create(cache_last_read_mutex_key,
+ &cache->last_read_mutex, SYNC_TRX_I_S_LAST_READ);
table_cache_init(&cache->innodb_trx, sizeof(i_s_trx_row_t));
table_cache_init(&cache->innodb_locks, sizeof(i_s_locks_row_t));