1 /*****************************************************************************
2 
3 Copyright (c) 2007, 2015, Oracle and/or its affiliates. All Rights Reserved.
4 Copyright (c) 2017, 2021, MariaDB Corporation.
5 
6 This program is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free Software
8 Foundation; version 2 of the License.
9 
10 This program is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along with
15 this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
17 
18 *****************************************************************************/
19 
20 /**************************************************//**
21 @file include/trx0i_s.h
22 INFORMATION SCHEMA innodb_trx, innodb_locks and
23 innodb_lock_waits tables cache structures and public
24 functions.
25 
26 Created July 17, 2007 Vasil Dimov
27 *******************************************************/
28 
29 #ifndef trx0i_s_h
30 #define trx0i_s_h
31 
32 #include "trx0types.h"
33 #include "dict0types.h"
34 #include "buf0types.h"
35 
36 /** The maximum amount of memory that can be consumed by innodb_trx,
37 innodb_locks and innodb_lock_waits information schema tables. */
38 #define TRX_I_S_MEM_LIMIT		16777216 /* 16 MiB */
39 
40 /** The maximum length of a string that can be stored in
41 i_s_locks_row_t::lock_data */
42 #define TRX_I_S_LOCK_DATA_MAX_LEN	8192
43 
44 /** The maximum length of a string that can be stored in
45 i_s_trx_row_t::trx_query */
46 #define TRX_I_S_TRX_QUERY_MAX_LEN	1024
47 
48 /** The maximum length of a string that can be stored in
49 i_s_trx_row_t::trx_foreign_key_error */
50 #define TRX_I_S_TRX_FK_ERROR_MAX_LEN	256
51 
52 /** Safely copy strings in to the INNODB_TRX table's
53 string based columns */
54 #define TRX_I_S_STRING_COPY(data, field, constraint, tcache)	\
55 do {								\
56 	if (strlen(data) > constraint) {			\
57 		char	buff[constraint + 1];			\
58 		strncpy(buff, data, constraint);		\
59 		buff[constraint] = '\0';			\
60 								\
61 		field = static_cast<const char*>(		\
62 			ha_storage_put_memlim(			\
63 			(tcache)->storage, buff, constraint + 1,\
64 			MAX_ALLOWED_FOR_STORAGE(tcache)));	\
65 	} else {						\
66 		field = static_cast<const char*>(		\
67 			ha_storage_put_str_memlim(		\
68 			(tcache)->storage, data,		\
69 			MAX_ALLOWED_FOR_STORAGE(tcache)));	\
70 	}							\
71 } while (0)
72 
73 /** A row of INFORMATION_SCHEMA.innodb_locks */
74 struct i_s_locks_row_t;
75 
76 /** Objects of trx_i_s_cache_t::locks_hash */
77 struct i_s_hash_chain_t;
78 
79 /** Objects of this type are added to the hash table
80 trx_i_s_cache_t::locks_hash */
81 struct i_s_hash_chain_t {
82 	i_s_locks_row_t*	value;	/*!< row of
83 					INFORMATION_SCHEMA.innodb_locks*/
84 	i_s_hash_chain_t*	next;	/*!< next item in the hash chain */
85 };
86 
87 /** This structure represents INFORMATION_SCHEMA.innodb_locks row */
88 struct i_s_locks_row_t {
89 	trx_id_t	lock_trx_id;	/*!< transaction identifier */
90 	const char*	lock_table;	/*!< table name from
91 					lock_get_table_name() */
92 	/** index name of a record lock; NULL for table locks */
93 	const char*	lock_index;
94 	/** page identifier of the record; (0,0) if !lock_index */
95 	page_id_t	lock_page;
96 	/** heap number of the record; 0 if !lock_index */
97 	uint16_t	lock_rec;
98 	/** lock mode corresponding to lock_mode_values_typelib */
99 	uint8_t		lock_mode;
100 	/** (some) content of the record, if available in the buffer pool;
101 	NULL if !lock_index */
102 	const char*	lock_data;
103 
104 	/** The following are auxiliary and not included in the table */
105 	/* @{ */
106 	table_id_t	lock_table_id;
107 					/*!< table identifier from
108 					lock_get_table_id */
109 	i_s_hash_chain_t hash_chain;	/*!< hash table chain node for
110 					trx_i_s_cache_t::locks_hash */
111 	/* @} */
112 };
113 
114 /** This structure represents INFORMATION_SCHEMA.innodb_trx row */
115 struct i_s_trx_row_t {
116 	trx_id_t		trx_id;		/*!< transaction identifier */
117 	const char*		trx_state;	/*!< transaction state from
118 						trx_get_que_state_str() */
119 	time_t			trx_started;	/*!< trx_t::start_time */
120 	const i_s_locks_row_t*	requested_lock_row;
121 					/*!< pointer to a row
122 					in innodb_locks if trx
123 					is waiting, or NULL */
124 	time_t		trx_wait_started; /*!< trx_t->lock.wait_started */
125 	uintmax_t	trx_weight;	/*!< TRX_WEIGHT() */
126 	ulint		trx_mysql_thread_id; /*!< thd_get_thread_id() */
127 	const char*	trx_query;	/*!< MySQL statement being
128 					executed in the transaction */
129 	CHARSET_INFO*	trx_query_cs;	/*!< the charset of trx_query */
130 	const char*	trx_operation_state; /*!< trx_t::op_info */
131 	ulint		trx_tables_in_use;/*!< n_mysql_tables_in_use in
132 					 trx_t */
133 	ulint		trx_tables_locked;
134 					/*!< mysql_n_tables_locked in
135 					trx_t */
136 	ulint		trx_lock_structs;/*!< list len of trx_locks in
137 					trx_t */
138 	ulint		trx_lock_memory_bytes;
139 					/*!< mem_heap_get_size(
140 					trx->lock_heap) */
141 	ulint		trx_rows_locked;/*!< lock_number_of_rows_locked() */
142 	uintmax_t	trx_rows_modified;/*!< trx_t::undo_no */
143 	uint		trx_isolation_level;
144 					/*!< trx_t::isolation_level */
145 	bool		trx_unique_checks;
146 					/*!< check_unique_secondary in trx_t*/
147 	bool		trx_foreign_key_checks;
148 					/*!< check_foreigns in trx_t */
149 	const char*	trx_foreign_key_error;
150 					/*!< detailed_error in trx_t */
151 	bool		trx_is_read_only;
152 					/*!< trx_t::read_only */
153 	bool		trx_is_autocommit_non_locking;
154 					/*!< trx:t::is_autocommit_non_locking()
155 					*/
156 };
157 
158 /** This structure represents INFORMATION_SCHEMA.innodb_lock_waits row */
159 struct i_s_lock_waits_row_t {
160 	const i_s_locks_row_t*	requested_lock_row;	/*!< requested lock */
161 	const i_s_locks_row_t*	blocking_lock_row;	/*!< blocking lock */
162 };
163 
164 /** Cache of INFORMATION_SCHEMA table data */
165 struct trx_i_s_cache_t;
166 
167 /** Auxiliary enum used by functions that need to select one of the
168 INFORMATION_SCHEMA tables */
169 enum i_s_table {
170 	I_S_INNODB_TRX,		/*!< INFORMATION_SCHEMA.innodb_trx */
171 	I_S_INNODB_LOCKS,	/*!< INFORMATION_SCHEMA.innodb_locks */
172 	I_S_INNODB_LOCK_WAITS	/*!< INFORMATION_SCHEMA.innodb_lock_waits */
173 };
174 
175 /** This is the intermediate buffer where data needed to fill the
176 INFORMATION SCHEMA tables is fetched and later retrieved by the C++
177 code in handler/i_s.cc. */
178 extern trx_i_s_cache_t*	trx_i_s_cache;
179 
180 /*******************************************************************//**
181 Initialize INFORMATION SCHEMA trx related cache. */
182 void
183 trx_i_s_cache_init(
184 /*===============*/
185 	trx_i_s_cache_t*	cache);	/*!< out: cache to init */
186 /*******************************************************************//**
187 Free the INFORMATION SCHEMA trx related cache. */
188 void
189 trx_i_s_cache_free(
190 /*===============*/
191 	trx_i_s_cache_t*	cache);	/*!< in/out: cache to free */
192 
193 /*******************************************************************//**
194 Issue a shared/read lock on the tables cache. */
195 void
196 trx_i_s_cache_start_read(
197 /*=====================*/
198 	trx_i_s_cache_t*	cache);	/*!< in: cache */
199 
200 /*******************************************************************//**
201 Release a shared/read lock on the tables cache. */
202 void
203 trx_i_s_cache_end_read(
204 /*===================*/
205 	trx_i_s_cache_t*	cache);	/*!< in: cache */
206 
207 /*******************************************************************//**
208 Issue an exclusive/write lock on the tables cache. */
209 void
210 trx_i_s_cache_start_write(
211 /*======================*/
212 	trx_i_s_cache_t*	cache);	/*!< in: cache */
213 
214 /*******************************************************************//**
215 Release an exclusive/write lock on the tables cache. */
216 void
217 trx_i_s_cache_end_write(
218 /*====================*/
219 	trx_i_s_cache_t*	cache);	/*!< in: cache */
220 
221 
222 /*******************************************************************//**
223 Retrieves the number of used rows in the cache for a given
224 INFORMATION SCHEMA table.
225 @return number of rows */
226 ulint
227 trx_i_s_cache_get_rows_used(
228 /*========================*/
229 	trx_i_s_cache_t*	cache,	/*!< in: cache */
230 	enum i_s_table		table);	/*!< in: which table */
231 
232 /*******************************************************************//**
233 Retrieves the nth row in the cache for a given INFORMATION SCHEMA
234 table.
235 @return row */
236 void*
237 trx_i_s_cache_get_nth_row(
238 /*======================*/
239 	trx_i_s_cache_t*	cache,	/*!< in: cache */
240 	enum i_s_table		table,	/*!< in: which table */
241 	ulint			n);	/*!< in: row number */
242 
243 /*******************************************************************//**
244 Update the transactions cache if it has not been read for some time.
245 @return 0 - fetched, 1 - not */
246 int
247 trx_i_s_possibly_fetch_data_into_cache(
248 /*===================================*/
249 	trx_i_s_cache_t*	cache);	/*!< in/out: cache */
250 
251 /*******************************************************************//**
252 Returns true, if the data in the cache is truncated due to the memory
253 limit posed by TRX_I_S_MEM_LIMIT.
254 @return TRUE if truncated */
255 bool
256 trx_i_s_cache_is_truncated(
257 /*=======================*/
258 	trx_i_s_cache_t*	cache);	/*!< in: cache */
259 /** The maximum length of a resulting lock_id_size in
260 trx_i_s_create_lock_id(), not including the terminating NUL.
261 ":%lu:%lu:%lu" -> 63 chars */
262 #define TRX_I_S_LOCK_ID_MAX_LEN	(TRX_ID_MAX_LEN + 63)
263 
264 /*******************************************************************//**
265 Crafts a lock id string from a i_s_locks_row_t object. Returns its
266 second argument. This function aborts if there is not enough space in
267 lock_id. Be sure to provide at least TRX_I_S_LOCK_ID_MAX_LEN + 1 if you
268 want to be 100% sure that it will not abort.
269 @return resulting lock id */
270 char*
271 trx_i_s_create_lock_id(
272 /*===================*/
273 	const i_s_locks_row_t*	row,	/*!< in: innodb_locks row */
274 	char*			lock_id,/*!< out: resulting lock_id */
275 	ulint			lock_id_size);/*!< in: size of the lock id
276 					buffer */
277 
278 #endif /* trx0i_s_h */
279