InnoDB Progress Information
MySQL has since version 5.7 had support for progress information for some queries. As promised in my previous post, I will here discuss how you can use that to get progress information for ALTER TABLE
on InnoDB tables.
Background and Setup
Progress information is implemented through the Performance Schema using the stage events. In version 8.0.12 there are currently seven stages that can provide this information for ALTER TABLE
statements on InnoDB tables. In MySQL 8, it is easy to list the stages capable of reporting progress information by using the setup_instruments
Performance Schema table:
mysql> SELECT NAME, ENABLED, TIMED
FROM performance_schema.setup_instruments
WHERE NAME LIKE 'stage/innodb/alter table%'
AND PROPERTIES = 'progress';
+------------------------------------------------------+---------+-------+
| NAME | ENABLED | TIMED |
+------------------------------------------------------+---------+-------+
| stage/innodb/alter table (end) | YES | YES |
| stage/innodb/alter table (flush) | YES | YES |
| stage/innodb/alter table (insert) | YES | YES |
| stage/innodb/alter table (log apply index) | YES | YES |
| stage/innodb/alter table (log apply table) | YES | YES |
| stage/innodb/alter table (merge sort) | YES | YES |
| stage/innodb/alter table (read PK and internal sort) | YES | YES |
+------------------------------------------------------+---------+-------+
7 rows in set (0.00 sec)
This also shows how the setup_instruments
table in MySQL 8 has some additional information about the instruments such as properties and documentation (not included in the output). Adding this information is still work in progress.
MySQL 5.7 does not provide as easy a way to obtain the instruments providing progress information. Instead you need to consult the reference manual. However, the principle in using the feature is the same.
As you can see, all of the instruments are enabled and timed by default. What is not enabled by default, however, is the consumer that can make the information available:
mysql> SELECT NAME, ENABLED,
sys.ps_is_consumer_enabled(NAME) AS EnabledWithHierarchy
FROM performance_schema.setup_consumers
WHERE NAME = 'events_stages_current';
+-----------------------+---------+----------------------+
| NAME | ENABLED | EnabledWithHierarchy |
+-----------------------+---------+----------------------+
| events_stages_current | NO | NO |
+-----------------------+---------+----------------------+
1 row in set (0.01 sec)
Since the consumers form a hierarchical system, the sys
schema function ps_is_consumer_enabled()
is used to show whether the consumer is enabled taking the whole hierarchy into consideration.
In order to use the progress information, you need to enable the events_stages_current
consumer. This is the consumer that is responsible for keeping the performance_schema.events_stages_current
table up to date, i.e. record the current (or latest if there is no current stage) for each thread. With the default Performance Schema settings, the rest of the hierarchy is enabled. To enable event_stages_current
and verify it will be consuming instruments, you can use the following queries:
mysql> UPDATE performance_schema.setup_consumers
SET ENABLED = 'YES'
WHERE NAME = 'events_stages_current';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT NAME, ENABLED,
sys.ps_is_consumer_enabled(NAME) AS EnabledWithHierarchy
FROM performance_schema.setup_consumers
WHERE NAME = 'events_stages_current';
+-----------------------+---------+----------------------+
| NAME | ENABLED | EnabledWithHierarchy |
+-----------------------+---------+----------------------+
| events_stages_current | YES | YES |
+-----------------------+---------+----------------------+
1 row in set (0.00 sec)
That is it. Now you can monitor the progress of the queries that uses the stages with progress information.
Monitoring Progress
The base for monitoring the progress information is the performance_schema.events_stages_current
table. There are two columns of interest for this discussion:
WORK_COMPLETED
: The amount of work that is reported to have been completed.WORK_ESTIMATED
: The estimated amount of work that needs to be done.
For InnoDB ALTER TABLE
the estimated amount of work is for the entire operation. That said, the estimate may be revised during the process, so it may happen that the if you calculate the percentage it decreases as time goes. However, in general the percentage (100% * WORK_COMPLETED/WORK_ESTIMATED
) will increase steadily until the operation completes at 100%.
To learn more about how the progress information works, the following pages in the manual are recommended:
- Stage Event Progress Information
- Monitoring ALTER TABLE Progress for InnoDB Tables Using Performance Schema
For now, let's look at an example.
Example
For the example, the salaries
table in the employees
sample database will be used. The table is sufficiently large that it will be possible to query the progress while adding a column using the INPLACE
algorithm. As discussed in MySQL 8.0.12: Instant ALTER TABLE, it is possible to add a column instantly, but for the purpose of this example, the INPLACE
algorithm illustrates the progress information feature better. The query that will be executed is:
ALTER TABLE salaries ADD COLUMN new_col int NOT NULL DEFAULT 0, ALGORITHM=INPLACE;
The performance_schema.events_stages_current
table can be joined with the performance_schema.events_statements_current
to show the query and progress. For example:
mysql> SELECT stmt.THREAD_ID, stmt.SQL_TEXT, stage.EVENT_NAME AS State,
stage.WORK_COMPLETED, stage.WORK_ESTIMATED,
ROUND(100*stage.WORK_COMPLETED/stage.WORK_ESTIMATED, 2) AS CompletedPct
FROM performance_schema.events_statements_current stmt
INNER JOIN performance_schema.events_stages_current stage
ON stage.THREAD_ID = stmt.THREAD_ID
AND stage.NESTING_EVENT_ID = stmt.EVENT_ID\G
*************************** 1. row ***************************
THREAD_ID: 63857
SQL_TEXT: ALTER TABLE salaries ADD COLUMN new_col int NOT NULL DEFAULT 0, ALGORITHM=INPLACE
State: stage/innodb/alter table (read PK and internal sort)
WORK_COMPLETED: 8906
WORK_ESTIMATED: 27351
CompletedPct: 32.56
1 row in set (0.00 sec)
There is another way though. Instead of using the performance_schema.events_stages_current
table directly, an easier way is to use the sys.session
view. This is an advanced process list that includes much more information than the usual SHOW PROCESSLIST
statement including progress information. The performance of sys.session
has been improved with more than an order of magnitude in MySQL 8 by the addition of indexes to the Performance Schema tables making it highly useful.
Querying the sys.session
view for sessions showing progress information while the ALTER TABLE
is in progress returns an output similar to the following example:
mysql> SET @sys.statement_truncate_len = 85;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT thd_id, conn_id, db, command, state, current_statement,
statement_latency, progress, current_memory, program_name
FROM sys.session
WHERE progress IS NOT NULL\G
*************************** 1. row ***************************
thd_id: 63857
conn_id: 63818
db: employees
command: Query
state: alter table (merge sort)
current_statement: ALTER TABLE salaries ADD COLUMN new_col int NOT NULL DEFAULT 0, ALGORITHM=INPLACE
statement_latency: 4.22 s
progress: 49.39
current_memory: 464.27 KiB
program_name: MySQLWorkbench
1 row in set (0.06 sec)
In the example, the @sys.statement_truncate_len
user variable is set to 85. By default the sys
schema ensures the current statement is at most 64 characters long. In order to avoid truncation in this case, the truncate length is increased to 85.
The example output shows that the progress is at around 49%. It is important to note that is an estimate and not an exact number. The ALTER TABLE
is performing a merge sort at the time, and the query has been running for 4.22 seconds.
A couple of other interesting columns are included. It can be seen the connection is using 464KiB at the time. In MySQL 8 memory instrumentation is enabled by default (in MySQL 5.7 you need to enable it yourself). Additionally, the name of the program executing the query is MySQLWorkbench, that is the query originates from MySQL Workbench.
So, next time you plan a large ALTER TABLE
operation, consider enabling the events_stages_current
consumer, so you can follow the progress.
Lovely article Jesper. Thank you!
Thank you Subhajit. I am glad you liked it.