Spec-Zone .ru
спецификации, руководства, описания, API

14.2.4.3. InnoDB INFORMATION_SCHEMA tables

The INFORMATION_SCHEMA is a MySQL feature that helps you monitor server activity to diagnose capacity and performance issues. Several InnoDB-related INFORMATION_SCHEMA tables (INNODB_CMP, INNODB_CMP_RESET, INNODB_CMPMEM, INNODB_CMPMEM_RESET, INNODB_TRX, INNODB_LOCKS and INNODB_LOCK_WAITS) contain live information about compressed InnoDB tables, the compressed InnoDB buffer pool, all transactions currently executing inside InnoDB, the locks that transactions hold and those that are blocking transactions waiting for access to a resource (a table or row).

This section describes the InnoDB-related Information Schema tables and shows some examples of their use.

14.2.4.3.1. Information Schema Tables about Compression

Two new pairs of Information Schema tables can give you some insight into how well compression is working overall. One pair of tables contains information about the number of compression operations and the amount of time spent performing compression. Another pair of tables contains information on the way memory is allocated for compression.

14.2.4.3.1.1. INNODB_CMP and INNODB_CMP_RESET

The INNODB_CMP and INNODB_CMP_RESET tables contain status information on the operations related to compressed tables, which are covered in Section 5.4.6, "Working with InnoDB Compressed Tables". The compressed page size is in the column PAGE_SIZE.

These two tables have identical contents, but reading from INNODB_CMP_RESET resets the statistics on compression and uncompression operations. For example, if you archive the output of INNODB_CMP_RESET every 60 minutes, you see the statistics for each hourly period. If you monitor the output of INNODB_CMP (making sure never to read INNODB_CMP_RESET), you see the cumulated statistics since InnoDB was started.

For the table definition, see Table 20.1, "Columns of INNODB_CMP and INNODB_CMP_RESET".

14.2.4.3.1.2. INNODB_CMPMEM andINNODB_CMPMEM_RESET

The INNODB_CMPMEM and INNODB_CMPMEM_RESET tables contain status information on the compressed pages that reside in the buffer pool. Please consult Section 5.4.6, "Working with InnoDB Compressed Tables" for further information on compressed tables and the use of the buffer pool. The INNODB_CMP and INNODB_CMP_RESET tables should provide more useful statistics on compression.

Internal Details

InnoDB uses a buddy allocator system to manage memory allocated to pages of various sizes, from 1KB to 16KB. Each row of the two tables described here corresponds to a single page size.

These two tables have identical contents, but reading from INNODB_CMPMEM_RESET resets the statistics on relocation operations. For example, if every 60 minutes you archived the output of INNODB_CMPMEM_RESET, it would show the hourly statistics. If you never read INNODB_CMPMEM_RESET and monitored the output of INNODB_CMPMEM instead, it would show the cumulated statistics since InnoDB was started.

For the table definition, see Table 20.3, "Columns of INNODB_CMPMEM and INNODB_CMPMEM_RESET".

14.2.4.3.1.3. Using the Compression Information Schema Tables

Example 14.2. Using the Compression Information Schema Tables

The following is sample output from a database that contains compressed tables (see Section 5.4.6, "Working with InnoDB Compressed Tables", INNODB_CMP, INNODB_CMP_PER_INDEX, and INNODB_CMPMEM).

The following table shows the contents of INFORMATION_SCHEMA.INNODB_CMP under a light workload. The only compressed page size that the buffer pool contains is 8K. Compressing or uncompressing pages has consumed less than a second since the time the statistics were reset, because the columns COMPRESS_TIME and UNCOMPRESS_TIME are zero.

page size compress ops compress ops ok compress time uncompress ops uncompress time
1024 0 0 0 0 0
2048 0 0 0 0 0
4096 0 0 0 0 0
8192 1048 921 0 61 0
16384 0 0 0 0 0

According to INNODB_CMPMEM, there are 6169 compressed 8KB pages in the buffer pool. The only other allocated block size is 64 bytes. The smallest PAGE_SIZE in INNODB_CMPMEM is used for block descriptors of those compressed pages for which no uncompressed page exists in the buffer pool. We see that there are 5910 such pages. Indirectly, we see that 259 (6169-5910) compressed pages also exist in the buffer pool in uncompressed form.

The following table shows the contents of INFORMATION_SCHEMA.INNODB_CMPMEM under a light workload. Some memory is unusable due to fragmentation of the memory allocator for compressed pages: SUM(PAGE_SIZE*PAGES_FREE)=6784. This is because small memory allocation requests are fulfilled by splitting bigger blocks, starting from the 16K blocks that are allocated from the main buffer pool, using the buddy allocation system. The fragmentation is this low because some allocated blocks have been relocated (copied) to form bigger adjacent free blocks. This copying of SUM(PAGE_SIZE*RELOCATION_OPS) bytes has consumed less than a second (SUM(RELOCATION_TIME)=0).

page size pages used pages free relocation ops relocation time
64 5910 0 2436 0
128 0 1 0 0
256 0 0 0 0
512 0 1 0 0
1024 0 0 0 0
2048 0 1 0 0
4096 0 1 0 0
8192 6169 0 5 0
16384 0 0 0 0

14.2.4.3.2. Information Schema Tables about Transactions

Three InnoDB-related Information Schema tables make it easy to monitor transactions and diagnose possible locking problems. The three tables are INNODB_TRX, INNODB_LOCKS, and INNODB_LOCK_WAITS.

  • INNODB_TRX

    Contains information about every transaction currently executing inside InnoDB, including whether the transaction is waiting for a lock, when the transaction started, and the particular SQL statement the transaction is executing.

    For the table definition, see Table 20.4, "INNODB_TRX Columns".

  • INNODB_LOCKS

    Each transaction in InnoDB that is waiting for another transaction to release a lock (INNODB_TRX.TRX_STATE='LOCK WAIT') is blocked by exactly one "blocking lock request". That blocking lock request is for a row or table lock held by another transaction in an incompatible mode. The waiting or blocked transaction cannot proceed until the other transaction commits or rolls back, thereby releasing the requested lock. For every blocked transaction, INNODB_LOCKS contains one row that describes each lock the transaction has requested, and for which it is waiting. INNODB_LOCKS also contains one row for each lock that is blocking another transaction, whatever the state of the transaction that holds the lock ('RUNNING', 'LOCK WAIT', 'ROLLING BACK' or 'COMMITTING'). The lock that is blocking a transaction is always held in a mode (read vs. write, shared vs. exclusive) incompatible with the mode of requested lock.

    For the table definition, see Table 20.5, "INNODB_LOCKS Columns".

  • INNODB_LOCK_WAITS

    Using this table, you can tell which transactions are waiting for a given lock, or for which lock a given transaction is waiting. This table contains one or more rows for each blocked transaction, indicating the lock it has requested and any locks that are blocking that request. The REQUESTED_LOCK_ID refers to the lock that a transaction is requesting, and the BLOCKING_LOCK_ID refers to the lock (held by another transaction) that is preventing the first transaction from proceeding. For any given blocked transaction, all rows in INNODB_LOCK_WAITS have the same value for REQUESTED_LOCK_ID and different values for BLOCKING_LOCK_ID.

    For the table definition, see Table 20.6, "INNODB_LOCK_WAITS Columns".

14.2.4.3.2.1. Using the Transaction Information Schema Tables

Example 14.3. Identifying Blocking Transactions

It is sometimes helpful to be able to identify which transaction is blocking another. You can use the Information Schema tables to find out which transaction is waiting for another, and which resource is being requested.

Suppose you have the following scenario, with three users running concurrently. Each user (or session) corresponds to a MySQL thread, and executes one transaction after another. Consider the state of the system when these users have issued the following commands, but none has yet committed its transaction:

  • User A:

    BEGIN;SELECT a FROM t FOR UPDATE;SELECT SLEEP(100);
  • User B:

    SELECT b FROM t FOR UPDATE;
  • User C:

    SELECT c FROM t FOR UPDATE;

In this scenario, you can use this query to see who is waiting for whom:

SELECT r.trx_id waiting_trx_id,         r.trx_mysql_thread_id waiting_thread,       r.trx_query waiting_query,       b.trx_id blocking_trx_id,        b.trx_mysql_thread_id blocking_thread,       b.trx_query blocking_query   FROM       information_schema.innodb_lock_waits w   INNER JOIN information_schema.innodb_trx b  ON      b.trx_id = w.blocking_trx_id  INNER JOIN information_schema.innodb_trx r  ON  r.trx_id = w.requesting_trx_id;
waiting trx id waiting thread waiting query blocking trx id blocking thread blocking query
A4 6 SELECT b FROM t FOR UPDATE A3 5 SELECT SLEEP(100)
A5 7 SELECT c FROM t FOR UPDATE A3 5 SELECT SLEEP(100)
A5 7 SELECT c FROM t FOR UPDATE A4 6 SELECT b FROM t FOR UPDATE

In the above result, you can identify users by the "waiting query" or "blocking query". As you can see:

  • User B (trx id 'A4', thread 6) and User C (trx id 'A5', thread 7) are both waiting for User A (trx id 'A3', thread 5).

  • User C is waiting for User B as well as User A.

You can see the underlying data in the tables INNODB_TRX, INNODB_LOCKS, and INNODB_LOCK_WAITS.

The following table shows some sample contents of INFORMATION_SCHEMA.INNODB_TRX.

trx id trx state trx started trx requested lock id trx wait started trx weight trx mysql thread id trx query
A3 RUN­NING 2008-01-15 16:44:54 NULL NULL 2 5 SELECT SLEEP(100)
A4 LOCK WAIT 2008-01-15 16:45:09 A4:1:3:2 2008-01-15 16:45:09 2 6 SELECT b FROM t FOR UPDATE
A5 LOCK WAIT 2008-01-15 16:45:14 A5:1:3:2 2008-01-15 16:45:14 2 7 SELECT c FROM t FOR UPDATE

The following table shows some sample contents of INFORMATION_SCHEMA.INNODB_LOCKS.

lock id lock trx id lock mode lock type lock table lock index lock space lock page lock rec lock data
A3:1:3:2 A3 X RECORD `test`.`t` `PRIMARY` 1 3 2 0x0200
A4:1:3:2 A4 X RECORD `test`.`t` `PRIMARY` 1 3 2 0x0200
A5:1:3:2 A5 X RECORD `test`.`t` `PRIMARY` 1 3 2 0x0200

The following table shows some sample contents of INFORMATION_SCHEMA.INNODB_LOCK_WAITS.

requesting trx id requested lock id blocking trx id blocking lock id
A4 A4:1:3:2 A3 A3:1:3:2
A5 A5:1:3:2 A3 A3:1:3:2
A5 A5:1:3:2 A4 A4:1:3:2

Example 14.4. More Complex Example of Transaction Data in Information Schema Tables

Sometimes you would like to correlate the internal InnoDB locking information with session-level information maintained by MySQL. For example, you might like to know, for a given InnoDB transaction ID, the corresponding MySQL session ID and name of the user that may be holding a lock, and thus blocking another transaction.

The following output from the INFORMATION_SCHEMA tables is taken from a somewhat loaded system.

As can be seen in the following tables, there are several transactions running.

The following INNODB_LOCKS and INNODB_LOCK_WAITS tables shows that:

  • Transaction 77F (executing an INSERT) is waiting for transactions 77E, 77D and 77B to commit.

  • Transaction 77E (executing an INSERT) is waiting for transactions 77D and 77B to commit.

  • Transaction 77D (executing an INSERT) is waiting for transaction 77B to commit.

  • Transaction 77B (executing an INSERT) is waiting for transaction 77A to commit.

  • Transaction 77A is running, currently executing SELECT.

  • Transaction E56 (executing an INSERT) is waiting for transaction E55 to commit.

  • Transaction E55 (executing an INSERT) is waiting for transaction 19C to commit.

  • Transaction 19C is running, currently executing an INSERT.

Note that there may be an inconsistency between queries shown in the two tables INNODB_TRX.TRX_QUERY and PROCESSLIST.INFO. The current transaction ID for a thread, and the query being executed in that transaction, may be different in these two tables for any given thread. See Section 14.2.4.3.4.3, "Possible Inconsistency with PROCESSLIST" for an explanation.

The following table shows the contents of INFORMATION_SCHEMA.PROCESSLIST in a system running a heavy workload.

ID USER HOST DB COMMAND TIME STATE INFO
384 root localhost test Query 10 update insert into t2 values …
257 root localhost test Query 3 update insert into t2 values …
130 root localhost test Query 0 update insert into t2 values …
61 root localhost test Query 1 update insert into t2 values …
8 root localhost test Query 1 update insert into t2 values …
4 root localhost test Query 0 preparing SELECT * FROM processlist
2 root localhost test Sleep 566 NULL

The following table shows the contents of INFORMATION_SCHEMA.INNODB_TRX in a system running a heavy workload.

trx id trx state trx started trx requested lock id trx wait started trx weight trx mysql thread id trx query
77F LOCK WAIT 2008-01-15 13:10:16 77F:806 2008-01-15 13:10:16 1 876 insert into t09 (D, B, C) values …
77E LOCK WAIT 2008-01-15 13:10:16 77E:806 2008-01-15 13:10:16 1 875 insert into t09 (D, B, C) values …
77D LOCK WAIT 2008-01-15 13:10:16 77D:806 2008-01-15 13:10:16 1 874 insert into t09 (D, B, C) values …
77B LOCK WAIT 2008-01-15 13:10:16 77B:733​:12:1 2008-01-15 13:10:16 4 873 insert into t09 (D, B, C) values …
77A RUN­NING 2008-01-15 13:10:16 NULL NULL 4 872 select b, c from t09 where …
E56 LOCK WAIT 2008-01-15 13:10:06 E56:743​:6:2 2008-01-15 13:10:06 5 384 insert into t2 values …
E55 LOCK WAIT 2008-01-15 13:10:06 E55:743​:38:2 2008-01-15 13:10:13 965 257 insert into t2 values …
19C RUN­NING 2008-01-15 13:09:10 NULL NULL 2900 130 insert into t2 values …
E15 RUN­NING 2008-01-15 13:08:59 NULL NULL 5395 61 insert into t2 values …
51D RUN­NING 2008-01-15 13:08:47 NULL NULL 9807 8 insert into t2 values …

The following table shows the contents of INFORMATION_SCHEMA.INNODB_LOCK_WAITS in a system running a heavy workload.

requesting trx id requested lock id blocking trx id blocking lock id
77F 77F:806 77E 77E:806
77F 77F:806 77D 77D:806
77F 77F:806 77B 77B:806
77E 77E:806 77D 77D:806
77E 77E:806 77B 77B:806
77D 77D:806 77B 77B:806
77B 77B:733:12:1 77A 77A:733:12:1
E56 E56:743:6:2 E55 E55:743:6:2
E55 E55:743:38:2 19C 19C:743:38:2

The following table shows the contents of INFORMATION_SCHEMA.INNODB_LOCKS in a system running a heavy workload.

lock id lock trx id lock mode lock type lock table lock index lock space lock page lock rec lock data
77F:806 77F AUTO​_INC TABLE `test`​.`t09` NULL NULL NULL NULL NULL
77E:806 77E AUTO​_INC TABLE `test`​.`t09` NULL NULL NULL NULL NULL
77D:806 77D AUTO​_INC TABLE `test`​.`t09` NULL NULL NULL NULL NULL
77B:806 77B AUTO​_INC TABLE `test`​.`t09` NULL NULL NULL NULL NULL
77B:733​:12:1 77B X RECORD `test`​.`t09` `PRIMARY` 733 12 1 supremum pseudo-record
77A:733​:12:1 77A X RECORD `test`​.`t09` `PRIMARY` 733 12 1 supremum pseudo-record
E56:743​:6:2 E56 S RECORD `test`​.`t2` `PRIMARY` 743 6 2 0, 0
E55:743​:6:2 E55 X RECORD `test`​.`t2` `PRIMARY` 743 6 2 0, 0
E55:743​:38:2 E55 S RECORD `test`​.`t2` `PRIMARY` 743 38 2 1922, 1922
19C:743​:38:2 19C X RECORD `test`​.`t2` `PRIMARY` 743 38 2 1922, 1922

14.2.4.3.3. Information Schema Tables about Full-Text Search

A set of related INFORMATION_SCHEMA tables contains information about FULLTEXT search indexes on InnoDB tables:

14.2.4.3.4. Special Locking Considerations for InnoDBINFORMATION_SCHEMA Tables

14.2.4.3.4.1. Understanding InnoDB Locking

When a transaction updates a row in a table, or locks it with SELECT FOR UPDATE, InnoDB establishes a list or queue of locks on that row. Similarly, InnoDB maintains a list of locks on a table for table-level locks transactions hold. If a second transaction wants to update a row or lock a table already locked by a prior transaction in an incompatible mode, InnoDB adds a lock request for the row to the corresponding queue. For a lock to be acquired by a transaction, all incompatible lock requests previously entered into the lock queue for that row or table must be removed (the transactions holding or requesting those locks either commit or roll back).

A transaction may have any number of lock requests for different rows or tables. At any given time, a transaction may be requesting a lock that is held by another transaction, in which case it is blocked by that other transaction. The requesting transaction must wait for the transaction that holds the blocking lock to commit or rollback. If a transaction is not waiting for a a lock, it is in the 'RUNNING' state. If a transaction is waiting for a lock, it is in the 'LOCK WAIT' state.

The INNODB_LOCKS table holds one or more row for each 'LOCK WAIT' transaction, indicating any lock requests that are preventing its progress. This table also contains one row describing each lock in a queue of locks pending for a given row or table. The INNODB_LOCK_WAITS table shows which locks already held by a transaction are blocking locks requested by other transactions.

14.2.4.3.4.2. Granularity of INFORMATION_SCHEMA Data

The data exposed by the transaction and locking tables represent a glimpse into fast-changing data. This is not like other (user) tables, where the data changes only when application-initiated updates occur. The underlying data is internal system-managed data, and can change very quickly.

For performance reasons, and to minimize the chance of misleading JOINs between the INFORMATION_SCHEMA tables, InnoDB collects the required transaction and locking information into an intermediate buffer whenever a SELECT on any of the tables is issued. This buffer is refreshed only if more than 0.1 seconds has elapsed since the last time the buffer was read. The data needed to fill the three tables is fetched atomically and consistently and is saved in this global internal buffer, forming a point-in-time "snapshot". If multiple table accesses occur within 0.1 seconds (as they almost certainly do when MySQL processes a join among these tables), then the same snapshot is used to satisfy the query.

A correct result is returned when you JOIN any of these tables together in a single query, because the data for the three tables comes from the same snapshot. Because the buffer is not refreshed with every query of any of these tables, if you issue separate queries against these tables within a tenth of a second, the results are the same from query to query. On the other hand, two separate queries of the same or different tables issued more than a tenth of a second apart may see different results, since the data come from different snapshots.

Because InnoDB must temporarily stall while the transaction and locking data is collected, too frequent queries of these tables can negatively impact performance as seen by other users.

As these tables contain sensitive information (at least INNODB_LOCKS.LOCK_DATA and INNODB_TRX.TRX_QUERY), for security reasons, only the users with the PROCESS privilege are allowed to SELECT from them.

14.2.4.3.4.3. Possible Inconsistency with PROCESSLIST

As just described, while the transaction and locking data is correct and consistent when these INFORMATION_SCHEMA tables are populated. For example, the query in INNODB_TRX is always consistent with the rest of INNODB_TRX, INNODB_LOCKS and INNODB_LOCK_WAITS when the data comes from the same snapshot. However, the underlying data changes so fast that similar glimpses at other, similarly fast-changing data, may not be in synchrony. Thus, you should be careful in comparing the data in the InnoDB transaction and locking tables with that in the PROCESSLIST table. The data from the PROCESSLIST table does not come from the same snapshot as the data about locking and transactions. Even if you issue a single SELECT (joining INNODB_TRX and PROCESSLIST, for example), the content of those tables is generally not consistent. INNODB_TRX may reference rows that are not present in PROCESSLIST or the currently executing SQL query of a transaction, shown in INNODB_TRX.TRX_QUERY may differ from the one in PROCESSLIST.INFO.