1
1
/*****************************************************************************
3
Copyright (C) 2007, 2010, Innobase Oy. All Rights Reserved.
3
Copyright (c) 2007, 2009, Innobase Oy. All Rights Reserved.
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 USA
17
17
*****************************************************************************/
28
28
Created July 17, 2007 Vasil Dimov
29
29
*******************************************************/
32
/* Found during the build of 5.5.3 on Linux 2.4 and early 2.6 kernels:
33
The includes "univ.i" -> "my_global.h" cause a different path
34
to be taken further down with pthread functions and types,
35
so they must come first.
36
From the symptoms, this is related to bug#46587 in the MySQL bug DB.
40
31
#if !defined(BUILD_DRIZZLE)
41
32
# include <mysql/plugin.h>
35
#include "mysql_addons.h"
44
38
#include "buf0buf.h"
45
39
#include "dict0dict.h"
46
40
#include "ha0storage.h"
62
56
#include "ut0mem.h"
65
#include <drizzled/session.h>
67
59
/** Initial number of rows in the table cache */
68
60
#define TABLE_CACHE_INITIAL_ROWSNUM 1024
70
62
/** @brief The maximum number of chunks to allocate for a table cache.
72
64
The rows of a table cache are stored in a set of chunks. When a new
73
row is added a new chunk is allocated if necessary. Assuming that the
65
row is added a new chunk is allocated if necessary. Assuming that the
74
66
first one is 1024 rows (TABLE_CACHE_INITIAL_ROWSNUM) and each
75
67
subsequent is N/2 where N is the number of rows we have allocated till
76
68
now, then 39th chunk would accommodate 1677416425 rows and all chunks
196
188
code in handler/i_s.cc. */
197
189
UNIV_INTERN trx_i_s_cache_t* trx_i_s_cache = &trx_i_s_cache_static;
199
/* Key to register the lock/mutex with performance schema */
200
#ifdef UNIV_PFS_RWLOCK
201
UNIV_INTERN mysql_pfs_key_t trx_i_s_cache_lock_key;
202
#endif /* UNIV_PFS_RWLOCK */
204
#ifdef UNIV_PFS_MUTEX
205
UNIV_INTERN mysql_pfs_key_t cache_last_read_mutex_key;
206
#endif /* UNIV_PFS_MUTEX */
208
191
/*******************************************************************//**
209
192
For a record lock that is in waiting state retrieves the only bit that
210
193
is set, for a table lock returns ULINT_UNDEFINED.
259
242
/*******************************************************************//**
260
Frees a table cache. */
265
i_s_table_cache_t* table_cache) /*!< in/out: table cache */
269
for (i = 0; i < MEM_CHUNKS_IN_TABLE_CACHE; i++) {
271
/* the memory is actually allocated in
272
table_cache_create_empty_row() */
273
if (table_cache->chunks[i].base) {
274
mem_free(table_cache->chunks[i].base);
275
table_cache->chunks[i].base = NULL;
280
/*******************************************************************//**
281
243
Returns an empty row from a table cache. The row is allocated if no more
282
244
empty rows are available. The number of used rows is incremented.
283
245
If the memory limit is hit then NULL is returned and nothing is
424
/*******************************************************************//**
425
Validates a row in the locks cache.
426
@return TRUE if valid */
429
i_s_locks_row_validate(
430
/*===================*/
431
const i_s_locks_row_t* row) /*!< in: row to validate */
433
ut_ad(row->lock_trx_id != 0);
434
ut_ad(row->lock_mode != NULL);
435
ut_ad(row->lock_type != NULL);
436
ut_ad(row->lock_table != NULL);
437
ut_ad(row->lock_table_id != 0);
439
if (row->lock_space == ULINT_UNDEFINED) {
441
ut_ad(!strcmp("TABLE", row->lock_type));
442
ut_ad(row->lock_index == NULL);
443
ut_ad(row->lock_data == NULL);
444
ut_ad(row->lock_page == ULINT_UNDEFINED);
445
ut_ad(row->lock_rec == ULINT_UNDEFINED);
448
ut_ad(!strcmp("RECORD", row->lock_type));
449
ut_ad(row->lock_index != NULL);
450
ut_ad(row->lock_data != NULL);
451
ut_ad(row->lock_page != ULINT_UNDEFINED);
452
ut_ad(row->lock_rec != ULINT_UNDEFINED);
457
#endif /* UNIV_DEBUG */
459
385
/*******************************************************************//**
460
386
Fills i_s_trx_row_t object.
461
387
If memory can not be allocated then FALSE is returned.
477
403
which to copy volatile
484
ut_ad(mutex_own(&kernel_mutex));
486
row->trx_id = trx->id;
406
row->trx_id = trx_get_id(trx);
487
407
row->trx_started = (ib_time_t) trx->start_time;
488
408
row->trx_state = trx_get_que_state_str(trx);
489
row->requested_lock_row = requested_lock_row;
490
ut_ad(requested_lock_row == NULL
491
|| i_s_locks_row_validate(requested_lock_row));
493
410
if (trx->wait_lock != NULL) {
494
412
ut_a(requested_lock_row != NULL);
414
row->requested_lock_row = requested_lock_row;
495
415
row->trx_wait_started = (ib_time_t) trx->wait_started;
497
418
ut_a(requested_lock_row == NULL);
420
row->requested_lock_row = NULL;
498
421
row->trx_wait_started = 0;
501
row->trx_weight = (ullint) TRX_WEIGHT(trx);
424
row->trx_weight = (ullint) ut_conv_dulint_to_longlong(TRX_WEIGHT(trx));
503
if (trx->mysql_thd == NULL) {
426
if (trx->mysql_thd != NULL) {
427
row->trx_mysql_thread_id
428
#if defined(BUILD_DRIZZLE)
429
= session_get_thread_id(trx->mysql_thd);
431
= thd_get_thread_id(trx->mysql_thd);
504
434
/* For internal transactions e.g., purge and transactions
505
435
being recovered at startup there is no associated MySQL
506
436
thread data structure. */
507
437
row->trx_mysql_thread_id = 0;
508
row->trx_query = NULL;
512
row->trx_mysql_thread_id = trx->session()->getSessionId();
513
stmt= trx->mysql_thd->getQueryStringCopy(stmt_len);
517
char query[TRX_I_S_TRX_QUERY_MAX_LEN + 1];
519
if (stmt_len > TRX_I_S_TRX_QUERY_MAX_LEN) {
520
stmt_len = TRX_I_S_TRX_QUERY_MAX_LEN;
440
if (trx->mysql_query_str != NULL && *trx->mysql_query_str != NULL) {
442
if (strlen(*trx->mysql_query_str)
443
> TRX_I_S_TRX_QUERY_MAX_LEN) {
445
char query[TRX_I_S_TRX_QUERY_MAX_LEN + 1];
447
memcpy(query, *trx->mysql_query_str,
448
TRX_I_S_TRX_QUERY_MAX_LEN);
449
query[TRX_I_S_TRX_QUERY_MAX_LEN] = '\0';
451
row->trx_query = ha_storage_put_memlim(
452
cache->storage, query,
453
TRX_I_S_TRX_QUERY_MAX_LEN + 1,
454
MAX_ALLOWED_FOR_STORAGE(cache));
457
row->trx_query = ha_storage_put_str_memlim(
458
cache->storage, *trx->mysql_query_str,
459
MAX_ALLOWED_FOR_STORAGE(cache));
523
memcpy(query, stmt, stmt_len);
524
query[stmt_len] = '\0';
526
row->trx_query = static_cast<const char *>(ha_storage_put_memlim(
527
cache->storage, stmt, stmt_len + 1,
528
MAX_ALLOWED_FOR_STORAGE(cache)));
530
462
if (row->trx_query == NULL) {
536
468
row->trx_query = NULL;
542
if (s != NULL && s[0] != '\0') {
544
TRX_I_S_STRING_COPY(s, row->trx_operation_state,
545
TRX_I_S_TRX_OP_STATE_MAX_LEN, cache);
547
if (row->trx_operation_state == NULL) {
553
row->trx_operation_state = NULL;
556
// row->trx_tables_in_use = trx->n_mysql_tables_in_use;
558
row->trx_tables_locked = trx->mysql_n_tables_locked;
560
row->trx_lock_structs = UT_LIST_GET_LEN(trx->trx_locks);
562
row->trx_lock_memory_bytes = mem_heap_get_size(trx->lock_heap);
564
row->trx_rows_locked = lock_number_of_rows_locked(trx);
566
row->trx_rows_modified = trx->undo_no;
568
row->trx_concurrency_tickets = trx->n_tickets_to_enter_innodb;
570
switch (trx->isolation_level) {
571
case TRX_ISO_READ_UNCOMMITTED:
572
row->trx_isolation_level = "READ UNCOMMITTED";
574
case TRX_ISO_READ_COMMITTED:
575
row->trx_isolation_level = "READ COMMITTED";
577
case TRX_ISO_REPEATABLE_READ:
578
row->trx_isolation_level = "REPEATABLE READ";
580
case TRX_ISO_SERIALIZABLE:
581
row->trx_isolation_level = "SERIALIZABLE";
583
/* Should not happen as TRX_ISO_READ_COMMITTED is default */
585
row->trx_isolation_level = "UNKNOWN";
588
row->trx_unique_checks = (ibool) trx->check_unique_secondary;
590
row->trx_foreign_key_checks = (ibool) trx->check_foreigns;
592
s = trx->detailed_error;
594
if (s != NULL && s[0] != '\0') {
596
TRX_I_S_STRING_COPY(s,
597
row->trx_foreign_key_error,
598
TRX_I_S_TRX_FK_ERROR_MAX_LEN, cache);
600
if (row->trx_foreign_key_error == NULL) {
605
row->trx_foreign_key_error = NULL;
608
row->trx_has_search_latch = (ibool) trx->has_search_latch;
610
row->trx_search_latch_timeout = trx->search_latch_timeout;
1379
1236
release trx_i_s_cache_t::last_read_mutex
1380
1237
release trx_i_s_cache_t::rw_lock */
1382
rw_lock_create(trx_i_s_cache_lock_key, &cache->rw_lock,
1383
SYNC_TRX_I_S_RWLOCK);
1239
rw_lock_create(&cache->rw_lock, SYNC_TRX_I_S_RWLOCK);
1385
1241
cache->last_read = 0;
1387
mutex_create(cache_last_read_mutex_key,
1388
&cache->last_read_mutex, SYNC_TRX_I_S_LAST_READ);
1243
mutex_create(&cache->last_read_mutex, SYNC_TRX_I_S_LAST_READ);
1390
1245
table_cache_init(&cache->innodb_trx, sizeof(i_s_trx_row_t));
1391
1246
table_cache_init(&cache->innodb_locks, sizeof(i_s_locks_row_t));
1405
1260
/*******************************************************************//**
1406
Free the INFORMATION SCHEMA trx related cache. */
1411
trx_i_s_cache_t* cache) /*!< in, own: cache to free */
1413
hash_table_free(cache->locks_hash);
1414
ha_storage_free(cache->storage);
1415
table_cache_free(&cache->innodb_trx);
1416
table_cache_free(&cache->innodb_locks);
1417
table_cache_free(&cache->innodb_lock_waits);
1418
memset(cache, 0, sizeof *cache);
1421
/*******************************************************************//**
1422
1261
Issue a shared/read lock on the tables cache. */