MK-LOG-PLAYER(1)

NAME
mk-log-player - Split and play MySQL slow logs.

SYNOPSIS
Split slow.log on Thread_id into 16 session files, save in ./sessions:

  mk-log-player --split Thread_id --session-files 16 --base-dir ./sessions slow.log

Play all those sessions on host1, save results in ./results:

  mk-log-player --play ./sessions --base-dir ./results h=host1

Use mk-query-digest to summarize the results:

  mk-query-digest ./results/*

RISKS
The following section is included to inform users about the potential risks, whether known or unknown, of using this tool. The two main categories of risks are those created by the nature of the tool (e.g. read-only tools vs. read-write tools) and those created by bugs.

"--play" is meant to load a server as much as possible, for stress-testing purposes. It is not designed to be used on production servers.

At the time of this release, we know of no bugs that could cause serious harm to users.

The authoritative source for updated information is always the online issue tracking system. Issues that affect this tool will be marked as such. You can see a list of such issues at the following URL: <http://www.maatkit.org/bugs/mk-log-player>.

See also "BUGS" for more information on filing bugs and getting help.

DESCRIPTION
mk-log-player does two things: it splits MySQL slow logs into session files and it plays (executes) queries in session files on a MySQL server. Only session files can be played; slow logs cannot be played directly without being split.

A session is a group of queries from the slow log that all share a common attribute, usually Thead_id. The common attribute is specified with "--split". Multiple sessions are saved into a single sesssion file. See "--session-files", "--max-sessions", "--base-file-name" and "--base-dir". These session files are played with "--play".

mk-log-player will "--play" session files in parallel using N number of "--threads". (They're not technically threads, but we call them that anyway.) Each thread will play all the sessions in its given session files. The sessions are played as fast as possible--there are no delays--because the goal is to stress-test and load-test the server. So be careful using this script on a production server!

Each "--play" thread writes its results to a separate file. These result files are in slow log format so they can be aggregated and summarized with mk-query-digest. See "OUTPUT".

OUTPUT
Both "--split" and "--play" have two outputs: status messages printed to STDOUT to let you know what the script is doing, and session or result files written to separate files saved in "--base-dir". You can suppress all output to STDOUT for each with "--quiet", or increase output with "--verbose".

The session files written by "--split" are simple text files containing queries grouped into sessions. For example:

  -- START SESSION 10

  use foo

  SELECT col FROM foo_tbl

The format of these session files is important: each query must be a single line separated by a single blank line. And the "-- START SESSION" comment tells mk-log-player where individual sessions begin and end so that "--play" can correctly fake Thread_id in its result files.

The result files written by "--play" are in slow log format with a minimal header: the only attributes printed are Thread_id, Query_time and Schema.

OPTIONS
Specify at least one of "--play", "--split" or "--split-random".

"--play" and "--split" are mutually exclusive.

--ask-pass
    group: Play

    Prompt for a password when connecting to MySQL.

--base-dir
    type: string; default: ./

    Base directory for "--split" session files and "--play" result file.

--base-file-name
    type: string; default: session

    Base file name for "--split" session files and "--play" result file.

    Each "--split" session file will be saved as <base-file-name>-N.txt, where N is a four digit, zero-padded session ID. For example: session-0003.txt.

    Each "--play" result file will be saved as <base-file-name>-results-PID.txt, where PID is the process ID of the executing thread.

    All files are saved in "--base-dir".

--charset
    group: Play

    short form: -A; type: string

    Default character set. If the value is utf8, sets Perl's binmode on STDOUT to utf8, passes the mysql_enable_utf8 option to DBD::mysql, and runs SET NAMES UTF8 after connecting to MySQL. Any other value sets binmode on STDOUT without the utf8 layer, and runs SET NAMES after connecting to MySQL.

--config
    type: Array

    Read this comma-separated list of config files; if specified, this must be the first option on the command line.

--defaults-file
    short form: -F; type: string

    Only read mysql options from the given file.

--dry-run
    Print which processes play which session files then exit.

--filter
    type: string; group: Split

    Discard "--split" events for which this Perl code doesn't return true.

    This option only works with "--split".

    This option is a string of Perl code or a file containing Perl code that gets compiled into a subroutine with one argument: $event. This is a hashref. If the given value is a readable file, then mk-log-player reads the entire file and uses its contents as the code. The file should not contain a shebang (#!/usr/bin/perl) line.

    If the code returns true, the query is split; otherwise it is discarded. The code is the last statement in the subroutine other than "return $event". The subroutine template is:

      sub { $event = shift; filter && return $event; }

    Filters given on the command line are wrapped inside parentheses like like "( filter )". For complex, multi-line filters, you must put the code inside a file so it will not be wrapped inside parentheses. Either way, the filter must produce syntactically valid code given the template. For example, an if-else branch given on the command line would not be valid:

      --filter 'if () { } else { }'  # WRONG

    Since it's given on the command line, the if-else branch would be wrapped inside parentheses which is not syntactically valid. So to accomplish something more complex like this would require putting the code in a file, for example filter.txt:

      my $event_ok; if (...) { $event_ok=1; } else { $event_ok=0; } $event_ok

    Then specify "--filter filter.txt" to read the code from filter.txt.

    If the filter code won't compile, mk-log-player will die with an error. If the filter code does compile, an error may still occur at runtime if the code tries to do something wrong (like pattern match an undefined value). mk-log-player does not provide any safeguards so code carefully!

    An example filter that discards everything but SELECT statements:

      --filter '$event->{arg} =~ m/^select/i'

    This is compiled into a subroutine like the following:

      sub { $event = shift; ( $event->{arg} =~ m/^select/i ) && return $event; }

    You can find an explanation of the structure of $event at <http://code.google.com/p/maatkit/wiki/EventAttributes>.

--help
    Show help and exit.

--host
    short form: -h; type: string; group: Play

    Connect to host.

--iterations
    type: int; default: 1; group: Play

    How many times each thread should play all its session files.

--max-sessions
    type: int; default: 5000000; group: Split

    Maximum number of sessions to "--split".

    By default, "mk-log-player" tries to split every session from the log file. For huge logs, however, this can result in millions of sessions. This option causes only the first N number of sessions to be saved. All sessions after this number are ignored, but sessions split before this number will continue to have their queries split even if those queries appear near the end of the log and after this number has been reached.

--only-select
    group: Play

    Play only SELECT and USE queries; ignore all others.

--password
    short form: -p; type: string; group: Play

    Password to use when connecting.

--pid
    type: string

    Create the given PID file. The file contains the process ID of the script. The PID file is removed when the script exits. Before starting, the script checks if the PID file already exists. If it does not, then the script creates and writes its own PID to it. If it does, then the script checks the following: if the file contains a PID and a process is running with that PID, then the script dies; or, if there is no process running with that PID, then the script overwrites the file with its own PID and starts; else, if the file contains no PID, then the script dies.

--play
    type: string; group: Play

    Play (execute) session files created by "--split".

    The argument to play must be a commaxn-separated list of session files created by "--split" or a directory. If the argument is a directory, ALL files in that directory will be played.

--port
    short form: -P; type: int; group: Play

    Port number to use for connection.

--print
    group: Play

    Print queries instead of playing them; requires "--play".

    You must also specify "--play" with "--print". Although the queries will not be executed, "--play" is required to specify which session files to read.

--quiet
    Do not print anything; disables "--verbose".

--[no]results
    default: yes

    Print "--play" results to files in "--base-dir".

--session-files
    type: int; default: 8; group: Split

    Number of session files to create with "--split".

    The number of session files should either be equal to the number of "--threads" you intend to "--play" or be an even multiple of "--threads". This number is important for maximum performance because it:
      * allows each thread to have roughly the same amount of sessions to play
      * avoids having to open/close many session files
      * avoids disk IO overhead by doing large sequential reads

    You may want to increase this number beyond "--threads" if each session file becomes too large. For example, splitting a 20G log into 8 sessions files may yield roughly eight 2G session files.

    See also "--max-sessions".

--set-vars
    type: string; group: Play; default: wait_timeout=10000

    Set these MySQL variables. Immediately after connecting to MySQL, this string will be appended to SET and executed.

--socket
    short form: -S; type: string; group: Play

    Socket file to use for connection.

--split
    type: string; group: Split

    Split log by given attribute to create session files.

    Valid attributes are any which appear in the log: Thread_id, Schema, etc.

--split-random
    group: Split

    Split log without an attribute, write queries round-robin to session files.

    This option, if specified, overrides "--split" and causes the log to be split query-by-query, writing each query to the next session file in round-robin style. If you don't care about "sessions" and just want to split a lot into N many session files and the relation or order of the queries does not matter, then use this option.

--threads
    type: int; default: 2; group: Play

    Number of threads used to play sessions concurrently.

    Specifies the number of parallel processes to run. The default is 2. On GNU/Linux machines, the default is the number of times 'processor' appears in /proc/cpuinfo. On Windows, the default is read from the environment. In any case, the default is at least 2, even when there's only a single processor.

    See also "--session-files".

--type
    type: string; group: Split

    The type of log to "--split" (default slowlog). The permitted types are

    binlog
        Split a binary log file.

    genlog
        Split a general log file.

    slowlog
        Split a log file in any varation of MySQL slow-log format.

--user
    short form: -u; type: string; group: Play

    User for login if not current user.

--verbose
    short form: -v; cumulative: yes; default: 0

    Increase verbosity; can specifiy multiple times.

    This option is disabled by "--quiet".

--version
    Show version and exit.

--wait-between-sessions
    type: array; default: 0; group: Play

    Not implemented yet.

    The wait time is given in seconds with microsecond precision and can be either a single value or a range. A single value causes an exact wait; example: 0.010 = wait 10 milliseconds. A range causes a random wait between the given value times; example: 0.001,1 = random wait from 1 millisecond to 1 second.

--[no]warnings
    default: no; group: Play

    Print warnings about SQL errors such as invalid queries to STDERR.

DSN OPTIONS
These DSN options are used to create a DSN. Each option is given like "option=value". The options are case-sensitive, so P and p are not the same option. There cannot be whitespace before or after the "=" and if the value contains whitespace it must be quoted. DSN options are comma-separated. See the maatkit manpage for full details.

•   A

    dsn: charset; copy: yes

    Default character set.

•   D

    dsn: database; copy: yes

    Default database.

•   F

    dsn: mysql_read_default_file; copy: yes

    Only read default options from the given file

•   h

    dsn: host; copy: yes

    Connect to host.

•   p

    dsn: password; copy: yes

    Password to use when connecting.

•   P

    dsn: port; copy: yes

    Port number to use for connection.

•   S

    dsn: mysql_socket; copy: yes

    Socket file to use for connection.

•   u

    dsn: user; copy: yes

    User for login if not current user.

DOWNLOADING
You can download Maatkit from Google Code at <http://code.google.com/p/maatkit/>, or you can get any of the tools easily with a command like the following:

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

Where "toolname" can be replaced with the name (or fragment of a name) of any of the Maatkit tools. Once downloaded, they're ready to run; no installation is needed. The first URL gets the latest released version of the tool, and the second gets the latest trunk code from Subversion.

ENVIRONMENT
The environment variable "MKDEBUG" enables verbose debugging output in all of the Maatkit tools:

   MKDEBUG=1 mk-....

SYSTEM REQUIREMENTS
You need Perl and some core packages that ought to be installed in any reasonably new version of Perl.

BUGS
For list of known bugs see <http://www.maatkit.org/bugs/mk-log-player>.

Please use Google Code Issues and Groups to report bugs or request support: <http://code.google.com/p/maatkit/>. You can also join #maatkit on Freenode to discuss Maatkit.

Please include the complete command-line used to reproduce the problem you are seeing, the version of all MySQL servers involved, the complete output of the tool when run with "--version", and if possible, debugging output produced by running with the "MKDEBUG=1" environment variable.

COPYRIGHT, LICENSE AND WARRANTY
This program is copyright 2008-2010 Percona Inc. Feedback and improvements are welcome.

THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2; OR the Perl Artistic License. On UNIX and similar systems, you can issue `man perlgpl' or `man perlartistic' to read these licenses.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

AUTHOR
Daniel Nichter

ABOUT MAATKIT
This tool is part of Maatkit, a toolkit for power users of MySQL. Maatkit was created by Baron Schwartz; Baron and Daniel Nichter are the primary code contributors. Both are employed by Percona. Financial support for Maatkit development is primarily provided by Percona and its clients.

VERSION
This manual page documents Ver 1.0.7 Distrib 6224 $Revision: 6208 $.