Tools Database Tuning with Maatkit Lead image: tiero, 123RF
tiero, 123RF
 

Maatkit tools for database administrators

Order into Chaos

The Maatkit tool suite helps administrators with performance tuning and various tasks for MySQL and other databases. By Falko Benthin

Maatkit [1], which was named after Maat, the Egyptian goddess of order and justice, gives administrators and developers a comprehensive collection of command-line tools written in Perl that helps extend the functionality of database management systems (DBMSs) and facilitates management tasks.

For example, you can check to see whether replication is working correctly, identify and repair damaged files, quickly export tables into files, parse data from files, or output the privileges assigned to individual database users.

Most of the features were written for MySQL [2]; however, Maatkit does support other free database management systems, including PostgreSQL [3] and Memcached [4].

Maatkit was developed in 2006 by Baron Schwartz. Since 2008, Daniel Nichter has been the main developer, although Schwartz still contributes suggestions for new tools and features. Both Schwartz and Nichter work for database specialist Percona, which has often impressed users in the past with performance-boosting patches for MySQL [5].

Maatkit installs with just a couple of keystrokes. Many package repositories include the tool selection, but, if this is not the case with your distribution, you can download the source code and DEB or RPM packages off the project website. To download and start using an individual tool quickly, you can also try:

wget http://www.maatkit.org/get/ toolname

Maatkit currently includes 30 tools; Admin magazine picked a couple of them for closer inspection.

Fast Dump and Restore

Wherever you need to roll out a new system, you need to test it thoroughly up front, preferably with real data. Because the data typically will be accessible, you can transfer the individual databases to the system you need to test.

MySQL includes the mysqldump tool for creating a dump of the database. This action just copies the content of a database, or all databases, to a file, which the other system then just reads.

The mysqldump command does this reliably, but slowly, because it backs up all the databases and tables sequentially. If you have a system with seven databases and only one of them is slightly larger, doing

time mysqldump --skip-opt --create-options --database datenkrake wikkawiki piwik sprzblog mysql limesurvey -uroot -ppassword > backup.sql

will take 21 seconds to complete:

real    0m21.626s
user    0m0.000s
sys    0m0.000s

In the case of larger databases on non-replicated servers, mysqldump is practically no longer an option because it locks the tables for the duration of the backup (to ensure consistency).

Maatkit has the mk-parallel-dump command to accelerate this process by transferring the data to files in parallel – assuming you have a system with multiple CPU cores.

By default, mk-parallel-dump uses two threads to copy the databases, but you can increase this number, assuming your hardware supports this, by setting the --threads option, thus substantially speeding up the dump.

On my test system, mk-parallel-dump did the same job nearly twice as quickly as mysqldump (Listing 1).

Listing 1: Parallel Dump

01 $ mk-parallel-dump -uroot -ppassword --database datenkrake,wikkawiki,piwik,sprzblog,mysql,limesurvey  --base-dir=db-backup/
02
03 CHUNK  TIME  EXIT  SKIPPED DATABASE.TABLE
04    db 11.43     0        0 datenkrake
05    db  1.34     0        0 limesurvey
06    db  2.75     0        0 sprzblog
07    db  2.67     0        0 mysql
08    db  3.45     0        0 piwik
09    db  2.50     0        0 wikkawiki
10   all 13.63     0        0 -

Schwartz warns database administrators not to use mk-parallel-dump as a backup solution. If you work with really large tables, you will soon notice why. The tool accesses mysqldump but without necessarily enabling its Quick option. Thus, the data must fit into the available RAM before it is written to a file. If the tables are too big to allow this, the system will start to swap, or mk-parallel-dump will throw errors before continuing.

If you don't see the error message, or you run mk-parallel-dump as a cron job, you might be in for a nasty surprise when you try to restore the results. The counterpart to mk-parallel-dump is mk-parallel-restore, which writes the tables you copied back to the database and again uses multiple threads to do so.

Stress Test for the DBMS

If you want to test the performance of your database management system, the Maatkit suite includes the mk-log-player tool. To see what the tool actually does, type:

mk-log-player --split Thread_id --type genlog --only-select --base-dir=stresstest /var/log/mysql/mysql.log

This command line tells Maatkit to explore the MySQL logfile for write access and create contiguous session files organized by thread in the stresstest directory. Then you can run these in parallel against the database management system (Figure 1). Tests like this make sense if you need to assess different configurations of your database management system.

The mk-log-player command extracts queries from logfiles; administrators can then send them in parallel to the database.
Figure 1: The mk-log-player command extracts queries from logfiles; administrators can then send them in parallel to the database.

After creating the sessions, you can type:

mk-log-player --play -uroot -ppassword ./stresstest --base-dir results h=localhost

to send them to the database. By default, mk-log-player will issue all the database queries stored in the sessions to the database in two parallel threads. Note how long the database management system takes to process the queries and write the results for each thread to a separate file in slow log format, which you can then read with mk-query-digest.

Finding Slow Queries

Once you have a sufficient volume of logfiles, you can evaluate the files with mk-query-digest. By default, the tool will use the slow query format, although it can also interpret normal logfiles and binary logs or – if you can't access the database server directly – evaluate traffic captured by tcpdump. Each query is fingerprinted so that you can group identical queries, such as SELECTs or UPDATEs, and evaluate them separately.

The output from mk-query-digest on the basis of the stress test shown in Figure 2, shows that some 19,200 queries composed of 55 different commands were issued. The system, a server with 768MB of RAM and a Pentium 3 CPU, took a total of 22 seconds to answer – the longest response took 32 milliseconds and the shortest was 126 microseconds – with a mean server query response time of less than 1 millisecond.

Output from mk-query-digest, showing what the database management system is capable of doing.
Figure 2: Output from mk-query-digest, showing what the database management system is capable of doing.

Lower down, the tool lists the 19 queries that occupied the most server time. In this example, the database management system took longest to serve the Piwik web analysis tool (Figure 3).

The mk-query-digest output shows the queries that are keeping the system busy.
Figure 3: The mk-query-digest output shows the queries that are keeping the system busy.

Following the overview is a more detailed analysis for the 19 "top consumers" that provides an idea of where bottlenecks are occurring and whether you can optimize for them. The mk-query-digest command offers more than 50 command-line options that database administrators can use to specify, for example, whether they want to query a specific database at a specific time of day or see the results in a different order.

When the Going Gets Tough

Occasionally, database servers run queries very slowly or not at all because something is amiss in the system. The mk-loadavg tool can analyze a variety of server performance indicators.

If the results are interesting, the tool will tell the administrator or query other system values and log them for analysis purposes. An interesting event could mean an active MySQL thread exceeding a defined threshold, the server starting to swap, the CPU running at full load, or a lack of responsiveness from the database management system.

The call in Listing 2 runs as a daemon and queries the InnoDB status every 60 seconds. If more than 15 read requests are waiting to be processed, the tool uses a mail-to-text gateway to send a text message to the administrator, who can then resolve the issue.

Listing 2: mk-loadavg

mk-loadavg -uroot -ppassword --watch "Status:innodb:Innodb_buffer_pool_pending_reads:>:15" --daemonize --pid /var/run/mk-loadavg.pid/--execute-command 'echo "DB Server hangs" | mail -s "falko@web.de" 017966666666@sms.web.de'

Unused Indexes

Indexes should normally accelerate access to the records stored in your tables. As the system grows, or when you change something, indexes you used previously can become redundant. Creating and updating them still takes up valuable space and time, so you should find out which indexes are not being used for queries. To do so, all you need is a slow logfile. If mysql-slow.log doesn't reveal much, you can also convert the normal logfile to slow log format with the use of mk-query-digest:

mk-query-digest --type genlog --print /var/log/mysql/mysql.log.1 > index.log

Then,

mk-index-usage index.log -uroot -password --host localhost

analyzes the logfile and checks for unused indexes.

As a result, the tool suggests removing non-unique indexes and provides the matching ALTER-TABLE instruction (Figure 4). The mk-index-usage command is not restricted to non-unique indexes; you can use the --drop option to extend the criteria to primary and unique types of indexes, and you can restrict the tool's activity to selected tables and store the results in a database.

The mk-index-usage command lists unused indexes and provides SQL instructions for deleting them.
Figure 4: The mk-index-usage command lists unused indexes and provides SQL instructions for deleting them.

Heartbeat

If you use replicated systems, you might not immediately notice a slave failure. Maatkit includes the mk-heartbeat tool, which tests once only or continually to discover whether a slave is still alive. To do so, enter the following line

mk-heartbeat --database --update --uroot -ppassword

which writes continually (once a second by default) to a definable table on the master (Figure 5). Then, in a second (parallel) step, issue

The mk-heartbeat tool uses a tiny table on the master to keep the system's pulse beating.
Figure 5: The mk-heartbeat tool uses a tiny table on the master to keep the system's pulse beating.
mk-heartbeat --database maatkit --monitor -ureply -ppassword -h slave

to check when the slave applied the change.

A table lists how quickly the server responds on average (see Figure 6). Time windows of 1, 5, and 15 minutes are used by default to evaluate responsiveness; however, you can change the defaults as needed. If a component fails, or if the synchronization process is too slow, you will soon notice.

The mk-heartbeat tool immediately notices any delays to replication by reporting average server response time.
Figure 6: The mk-heartbeat tool immediately notices any delays to replication by reporting average server response time.

Besides continual monitoring, you can run --check instead of --monitor for an individual query, and --daemonize lets you run heartbeat monitoring as a background process.

Staff and interns come and go, applications are retried, and you can soon forget former staff and their database access privileges.

Some users don't immediately forget their passwords after leaving an organization, which can lead to a security risk.

In another scenario, you might want to transfer the rights for one database management system to another. The mk-show-grants tool lets you query the privileges you have granted in just a couple of seconds.

The results of the query are a list of SQL instructions, just as with many other Maatkit tools. In the case of more extensive database management systems, you can send the output to a comma-separated list, restrict the list to privileges for specific users (--only), or exclude users from the evaluation process (--ignore).

The --revoke switch generates REVOKE instructions to match the GRANT instructions that it discovers (see Figure 7).

The mk-show-grants command not only shows who has privileges for the database management system but also gives you the SQL instructions to revoke them, if needed.
Figure 7: The mk-show-grants command not only shows who has privileges for the database management system but also gives you the SQL instructions to revoke them, if needed.

Conclusions

The tools I looked at in this article represent just a tiny subset of the Maatkit suite. For more information, you can browse Maatkit's documentation. All of the tools are based on production needs, have been tested multiple times, and can save administrators a huge amount of work.