maatkit-ruby 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Changelog +0 -0
- data/MIT-LICENSE +21 -0
- data/README +26 -0
- data/lib/maatkit-ruby.rb +11 -0
- data/lib/maatkit-ruby/mk-archiver.rb +473 -0
- data/lib/maatkit-ruby/mk-checksum-filter.rb +122 -0
- data/lib/maatkit-ruby/mk-deadlock-logger.rb +223 -0
- data/lib/maatkit-ruby/mk-duplicate-key-checker.rb +239 -0
- data/lib/maatkit-ruby/mk-error-log.rb +240 -0
- data/lib/maatkit-ruby/mk-fifo-split.rb +130 -0
- data/lib/maatkit-ruby/mk-find.rb +137 -0
- data/lib/maatkit-ruby/mk-heartbeat.rb +300 -0
- data/lib/maatkit-ruby/mk-index-usage.rb +164 -0
- data/lib/maatkit-ruby/mk-kill.rb +124 -0
- data/lib/maatkit-ruby/mk-loadavg.rb +313 -0
- data/lib/maatkit-ruby/mk-log-player.rb +316 -0
- data/lib/maatkit-ruby/mk-merge-mqd-results.rb +248 -0
- data/lib/maatkit-ruby/mk-parallel-dump.rb +400 -0
- data/lib/maatkit-ruby/mk-parallel-restore.rb +133 -0
- data/lib/maatkit-ruby/mk-profile-compact.rb +87 -0
- data/lib/maatkit-ruby/mk-purge-logs.rb +99 -0
- data/lib/maatkit-ruby/mk-query-advisor.rb +105 -0
- data/lib/maatkit-ruby/mk-query-digest.rb +149 -0
- data/lib/maatkit-ruby/mk-query-profiler.rb +106 -0
- data/lib/maatkit-ruby/mk-show-grants.rb +103 -0
- data/lib/maatkit-ruby/mk-slave-delay.rb +102 -0
- data/lib/maatkit-ruby/mk-slave-find.rb +98 -0
- data/lib/maatkit-ruby/mk-slave-move.rb +99 -0
- data/lib/maatkit-ruby/mk-slave-prefetch.rb +124 -0
- data/lib/maatkit-ruby/mk-slave-restart.rb +116 -0
- data/lib/maatkit-ruby/mk-table-checksum.rb +151 -0
- data/lib/maatkit-ruby/mk-table-sync.rb +468 -0
- data/lib/maatkit-ruby/mk-upgrade.rb +118 -0
- data/lib/maatkit-ruby/mk-variable-advisor.rb +99 -0
- data/lib/maatkit-ruby/mk-visual-explain.rb +98 -0
- data/lib/maatkit-ruby/version.rb +17 -0
- data/setup.rb +1585 -0
- data/test/test_helper.rb +2 -0
- data/test/test_maatkit_ruby.rb +11 -0
- metadata +105 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
# = maatkit-ruby - A maatkit gem for Ruby
|
2
|
+
#
|
3
|
+
# Homepage:: http://github.com/jjuliano/maatkit-ruby
|
4
|
+
# Author:: Joel Bryan Juliano
|
5
|
+
# Copyright:: (cc) 2011 Joel Bryan Juliano
|
6
|
+
# License:: MIT
|
7
|
+
|
8
|
+
#
|
9
|
+
# Kill MySQL queries that match certain criteria.
|
10
|
+
#
|
11
|
+
# Maatkit::Kill.new( array, str, array)
|
12
|
+
#
|
13
|
+
class Maatkit::Kill
|
14
|
+
|
15
|
+
attr_accessor :all # FALSE
|
16
|
+
attr_accessor :ask_pass # FALSE
|
17
|
+
attr_accessor :busy_time # (No value)
|
18
|
+
attr_accessor :charset # (No value)
|
19
|
+
attr_accessor :config # /etc/maatkit/maatkit.conf,/etc/maatkit/mk_kill.conf,/home/joel/.maatkit.conf,/home/joel/.mk_kill.conf
|
20
|
+
attr_accessor :daemonize # FALSE
|
21
|
+
attr_accessor :defaults_file # (No value)
|
22
|
+
attr_accessor :execute_command # (No value)
|
23
|
+
attr_accessor :heartbeat # FALSE
|
24
|
+
attr_accessor :help # TRUE
|
25
|
+
attr_accessor :host # (No value)
|
26
|
+
attr_accessor :idle_time # (No value)
|
27
|
+
attr_accessor :ignore_command # (No value)
|
28
|
+
attr_accessor :ignore_db # (No value)
|
29
|
+
attr_accessor :ignore_host # (No value)
|
30
|
+
attr_accessor :ignore_info # (No value)
|
31
|
+
attr_accessor :ignore_self # TRUE
|
32
|
+
attr_accessor :ignore_state # Locked
|
33
|
+
attr_accessor :ignore_user # (No value)
|
34
|
+
attr_accessor :interval # 30
|
35
|
+
attr_accessor :iterations # 1
|
36
|
+
attr_accessor :kill # FALSE
|
37
|
+
attr_accessor :kill_query # FALSE
|
38
|
+
attr_accessor :log # (No value)
|
39
|
+
attr_accessor :match_command # (No value)
|
40
|
+
attr_accessor :match_db # (No value)
|
41
|
+
attr_accessor :match_host # (No value)
|
42
|
+
attr_accessor :match_info # (No value)
|
43
|
+
attr_accessor :match_state # (No value)
|
44
|
+
attr_accessor :match_user # (No value)
|
45
|
+
attr_accessor :only_oldest # TRUE
|
46
|
+
attr_accessor :password # (No value)
|
47
|
+
attr_accessor :pid # (No value)
|
48
|
+
attr_accessor :port # (No value)
|
49
|
+
attr_accessor :print # FALSE
|
50
|
+
attr_accessor :replication_threads # FALSE
|
51
|
+
attr_accessor :run_time # (No value)
|
52
|
+
attr_accessor :set_vars # wait_timeout=10000
|
53
|
+
attr_accessor :socket # (No value)
|
54
|
+
attr_accessor :user # (No value)
|
55
|
+
attr_accessor :version # FALSE
|
56
|
+
attr_accessor :wait_after_kill # (No value)
|
57
|
+
attr_accessor :wait_before_kill # (No value)
|
58
|
+
|
59
|
+
#
|
60
|
+
# Sets the executable path, otherwise the environment path will be used.
|
61
|
+
#
|
62
|
+
attr_accessor :path_to_mk_kill
|
63
|
+
|
64
|
+
#
|
65
|
+
# Returns a new Kill Object
|
66
|
+
#
|
67
|
+
def initialize()
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Execute the command
|
72
|
+
#
|
73
|
+
def start(options = nil)
|
74
|
+
tmp = Tempfile.new('tmp')
|
75
|
+
command = option_string() + options.to_s + " 2> " + tmp.path
|
76
|
+
success = system(command)
|
77
|
+
if success
|
78
|
+
begin
|
79
|
+
while (line = tmp.readline)
|
80
|
+
line.chomp
|
81
|
+
selected_string = line
|
82
|
+
end
|
83
|
+
rescue EOFError
|
84
|
+
tmp.close
|
85
|
+
end
|
86
|
+
return selected_string
|
87
|
+
else
|
88
|
+
tmp.close!
|
89
|
+
return success
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def config
|
94
|
+
option_string()
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def option_string()
|
100
|
+
|
101
|
+
unless @path_to_mk_kill
|
102
|
+
ostring = "mk-kill "
|
103
|
+
else
|
104
|
+
ostring = @path_to_mk_kill + " "
|
105
|
+
end
|
106
|
+
|
107
|
+
self.instance_variables.each do |i|
|
108
|
+
tmp_value = self.instance_variable_get "#{i}"
|
109
|
+
tmp_string = i.gsub("_", "-").gsub("@", "--")
|
110
|
+
unless tmp_string == "--path-to-mk-kill"
|
111
|
+
if (tmp_value.is_a? TrueClass) || (tmp_value.is_a? FalseClass)
|
112
|
+
ostring += "#{tmp_string} "
|
113
|
+
else
|
114
|
+
ostring += "#{tmp_string} #{tmp_value} "
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
return ostring
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
@@ -0,0 +1,313 @@
|
|
1
|
+
# = maatkit-ruby - A maatkit gem for Ruby
|
2
|
+
#
|
3
|
+
# Homepage:: http://github.com/jjuliano/maatkit-ruby
|
4
|
+
# Author:: Joel Bryan Juliano
|
5
|
+
# Copyright:: (cc) 2011 Joel Bryan Juliano
|
6
|
+
# License:: MIT
|
7
|
+
|
8
|
+
#
|
9
|
+
# Watch MySQL load and take action when it gets too high.
|
10
|
+
#
|
11
|
+
# Maatkit::LoadAvg.new( array, str, array)
|
12
|
+
#
|
13
|
+
class Maatkit::LoadAvg
|
14
|
+
|
15
|
+
#
|
16
|
+
# group: Action
|
17
|
+
# Trigger the actions only when all "--watch" items exceed their thresholds.
|
18
|
+
# The default is to trigger the actions when any one of the watched items exceeds its threshold. This
|
19
|
+
# option requires that all watched items exceed their thresholds before any action is triggered.
|
20
|
+
attr_accessor :and # FALSE
|
21
|
+
|
22
|
+
#
|
23
|
+
# Prompt for a password when connecting to MySQL.
|
24
|
+
attr_accessor :ask_pass # FALSE
|
25
|
+
|
26
|
+
#
|
27
|
+
# short form: -A; type: string
|
28
|
+
# Default character set. If the value is utf8, sets Perl's binmode on STDOUT to utf8, passes the
|
29
|
+
# mysql_enable_utf8 option to DBD::mysql, and runs SET NAMES UTF8 after connecting to MySQL. Any other
|
30
|
+
# value sets binmode on STDOUT without the utf8 layer, and runs SET NAMES after connecting to MySQL.
|
31
|
+
attr_accessor :charset # (No value)
|
32
|
+
|
33
|
+
#
|
34
|
+
# type: Array
|
35
|
+
# Read this comma-separated list of config files; if specified, this must be the first option on the
|
36
|
+
# command line.
|
37
|
+
attr_accessor :config # /etc/maatkit/maatkit.conf,/etc/maatkit/mk_loadavg.conf,/home/joel/.maatkit.conf,/home/joel/.mk_loadavg.conf
|
38
|
+
|
39
|
+
#
|
40
|
+
# Fork to the background and detach from the shell. POSIX operating systems only.
|
41
|
+
attr_accessor :daemonize # FALSE
|
42
|
+
|
43
|
+
#
|
44
|
+
# short form: -D; type: string
|
45
|
+
# Database to use.
|
46
|
+
attr_accessor :database # (No value)
|
47
|
+
|
48
|
+
#
|
49
|
+
# short form: -F; type: string
|
50
|
+
# Only read mysql options from the given file. You must give an absolute pathname.
|
51
|
+
attr_accessor :defaults_file # (No value)
|
52
|
+
|
53
|
+
#
|
54
|
+
# type: string; group: Action
|
55
|
+
# Execute this command when watched items exceed their threshold values
|
56
|
+
# This command will be executed every time a "--watch" item (or all items if "--and" is specified)
|
57
|
+
# exceeds its threshold. For example, if you specify "--watch "Server:vmstat:swpd:":0">, then this
|
58
|
+
# command will be executed when the server begins to swap and it will be executed again at each
|
59
|
+
# "--interval" so long as the server is still swapping.
|
60
|
+
# After the command is executed, mk-loadavg has no control over it, so it is responsible for its own info
|
61
|
+
# gathering, logging, interval, etc. Since the command is spawned from mk-loadavg, its STDOUT, STDERR
|
62
|
+
# and STDIN are closed so it doesn't interfere with mk-loadavg. Therefore, the command must redirect its
|
63
|
+
# output to files or some other destination. For example, if you specify "--execute-command 'echo
|
64
|
+
# Hello'", you will not see "Hello" printed anywhere (neither to screen nor "--log") because STDOUT is
|
65
|
+
# closed for the command.
|
66
|
+
# No information from mk-loadavg is passed to the command.
|
67
|
+
# See also "--and".
|
68
|
+
attr_accessor :execute_command # (No value)
|
69
|
+
|
70
|
+
#
|
71
|
+
# Show help and exit.
|
72
|
+
attr_accessor :help # TRUE
|
73
|
+
|
74
|
+
#
|
75
|
+
# short form: -h; type: string
|
76
|
+
# Connect to host.
|
77
|
+
attr_accessor :host # (No value)
|
78
|
+
|
79
|
+
#
|
80
|
+
# type: time; default: 60s; group: Watch
|
81
|
+
# How long to sleep between each check.
|
82
|
+
attr_accessor :interval # 60
|
83
|
+
|
84
|
+
#
|
85
|
+
# type: string
|
86
|
+
# Print all output to this file when daemonized.
|
87
|
+
# Output from "--execute-command" is not printed to this file.
|
88
|
+
attr_accessor :log # (No value)
|
89
|
+
|
90
|
+
#
|
91
|
+
# short form: -p; type: string
|
92
|
+
# Password to use when connecting.
|
93
|
+
attr_accessor :password # (No value)
|
94
|
+
|
95
|
+
#
|
96
|
+
# type: string
|
97
|
+
# Create the given PID file when daemonized. The file contains the process ID of the daemonized
|
98
|
+
# instance. The PID file is removed when the daemonized instance exits. The program checks for the
|
99
|
+
# existence of the PID file when starting; if it exists and the process with the matching PID exists, the
|
100
|
+
# program exits.
|
101
|
+
attr_accessor :pid # (No value)
|
102
|
+
|
103
|
+
#
|
104
|
+
# short form: -P; type: int
|
105
|
+
# Port number to use for connection.
|
106
|
+
attr_accessor :port # (No value)
|
107
|
+
|
108
|
+
#
|
109
|
+
# type: time
|
110
|
+
# Time to run before exiting.
|
111
|
+
# Causes "mk-loadavg" to stop after the specified time has elapsed. Optional suffix: s=seconds,
|
112
|
+
# m=minutes, h=hours, d=days; if no suffix, s is used.
|
113
|
+
attr_accessor :run_time # (No value)
|
114
|
+
|
115
|
+
#
|
116
|
+
# type: string; default: /tmp/mk-loadavg-sentinel
|
117
|
+
# Exit if this file exists.
|
118
|
+
attr_accessor :sentinel # /tmp/mk_loadavg_sentinel
|
119
|
+
|
120
|
+
#
|
121
|
+
# type: string; default: wait_timeout=10000
|
122
|
+
# Set these MySQL variables. Immediately after connecting to MySQL, this string will be appended to SET
|
123
|
+
# and executed.
|
124
|
+
attr_accessor :set_vars # wait_timeout=10000
|
125
|
+
|
126
|
+
#
|
127
|
+
# short form: -S; type: string
|
128
|
+
# Socket file to use for connection.
|
129
|
+
attr_accessor :socket # (No value)
|
130
|
+
|
131
|
+
#
|
132
|
+
# Stop running instances by creating the "--sentinel" file.
|
133
|
+
attr_accessor :stop # FALSE
|
134
|
+
|
135
|
+
#
|
136
|
+
# short form: -u; type: string
|
137
|
+
# User for login if not current user.
|
138
|
+
attr_accessor :user # (No value)
|
139
|
+
|
140
|
+
#
|
141
|
+
# short form: -v
|
142
|
+
# Print information to STDOUT about what is being done.
|
143
|
+
# This can be used as a heartbeat to see that mk-loadavg is still properly watching all its values. If
|
144
|
+
# "--log" is specified, this information will be printed to that file instead.
|
145
|
+
attr_accessor :verbose # FALSE
|
146
|
+
|
147
|
+
#
|
148
|
+
# Show version and exit.
|
149
|
+
attr_accessor :version # FALSE
|
150
|
+
|
151
|
+
#
|
152
|
+
# type: string; default: vmstat 1 2; group: Watch
|
153
|
+
# vmstat command for "--watch" Server:vmstat:...
|
154
|
+
# The vmstat output should look like:
|
155
|
+
# procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
|
156
|
+
# r b # swpd # free # buff cache # si # so # bi # bo # in # cs us sy id wa
|
157
|
+
# 0 0 # # 0 590380 143756 571852 # 0 # 0 # 6 # 9 228 340 4 1 94 1
|
158
|
+
# 0 0 # # 0 590400 143764 571852 # 0 # 0 # 0 # 28 751 818 4 2 90 3
|
159
|
+
# The second line from the top needs to be column headers for subsequent lines. Values are taken from
|
160
|
+
# the last line.
|
161
|
+
# The default, "vmstat 1 2", gets current values. Running just "vmstat" would get average values since
|
162
|
+
# last reboot.
|
163
|
+
attr_accessor :vmstat # vmstat # 1 # 2
|
164
|
+
|
165
|
+
#
|
166
|
+
# type: time; default: 60s
|
167
|
+
# Wait this long to reconnect to MySQL.
|
168
|
+
# If the MySQL server goes away between "--interval" checks, mk-loadavg will attempt to reconnect to
|
169
|
+
# MySQL forever, sleeping this amount of time in between attempts.
|
170
|
+
attr_accessor :wait # 60
|
171
|
+
|
172
|
+
#
|
173
|
+
# type: string; group: Watch
|
174
|
+
# A comma-separated list of watched items and their thresholds (required).
|
175
|
+
# Each watched item is string of arguments separated by colons (like arg:arg). Each argument defines the
|
176
|
+
# watch item: what particular value is watched and how to compare the current value to a threshold value
|
177
|
+
# (N). Multiple watched items can be given by separating them with a comma, and the same watched item
|
178
|
+
# can be given multiple times (but, of course, it only makes sense to do this if the comparison and/or
|
179
|
+
# threshold values are differnt).
|
180
|
+
# The first argument is the most important and is case-sensitive. It defines the module responsible for
|
181
|
+
# watching the value. For example,
|
182
|
+
# --watch Status:...
|
183
|
+
# causes the WatchStatus module to be loaded. The second and subsequent arguments are passed to the
|
184
|
+
# WatchStatus module which parses them. Each watch module requires different arguments. The watch
|
185
|
+
# modules included in mk-loadavg and what arguments they require are listed below.
|
186
|
+
# This is a common error when specifying "--watch" on the commnad line:
|
187
|
+
# # mk-loadavg --watch Server:vmstat:swpd:>:0
|
188
|
+
# # Failed to load --watch WatchServer: Error parsing parameters vmstat:swpd:: No comparison parameter; expected >, < or = at ./mk-loadavg line 3100.
|
189
|
+
# The "--watch" values need to be quoted:
|
190
|
+
# # mk-loadavg --watch "Server:vmstat:swpd:>:0"
|
191
|
+
# Status
|
192
|
+
# # Watch SHOW STATUS, SHOW INNODB STATUS, and SHOW SLAVE STATUS values. The value argument is case-
|
193
|
+
# # sensitive.
|
194
|
+
# # # --watch Status:[status|innodb|slave]:value:[><=]:N
|
195
|
+
# # Examples:
|
196
|
+
# # # --watch "Status:status:Threads_connected:>:16"
|
197
|
+
# # # --watch "Status:innodb:Innodb_buffer_pool_hit_rate:<:0.98"
|
198
|
+
# # # --watch "Status:slave:Seconds_behind_master:>:300"
|
199
|
+
# # You can easily see what values are available for SHOW STATUS and SHOW SLAVE STATUS, but the values
|
200
|
+
# # for SHOW INNODB STATUS are not apparent. Some common values are:
|
201
|
+
# # # Innodb_buffer_pool_hit_rate
|
202
|
+
# # # Innodb_buffer_pool_pages_created_sec
|
203
|
+
# # # Innodb_buffer_pool_pages_dirty
|
204
|
+
# # # Innodb_buffer_pool_pages_read_sec
|
205
|
+
# # # Innodb_buffer_pool_pages_written_sec
|
206
|
+
# # # Innodb_buffer_pool_pending_data_writes
|
207
|
+
# # # Innodb_buffer_pool_pending_dirty_writes
|
208
|
+
# # # Innodb_buffer_pool_pending_fsyncs
|
209
|
+
# # # Innodb_buffer_pool_pending_reads
|
210
|
+
# # # Innodb_buffer_pool_pending_single_writes
|
211
|
+
# # # Innodb_common_memory_allocated
|
212
|
+
# # # Innodb_data_fsyncs_sec
|
213
|
+
# # # Innodb_data_pending_fsyncs
|
214
|
+
# # # Innodb_data_pending_preads
|
215
|
+
# # # Innodb_data_pending_pwrites
|
216
|
+
# # # Innodb_data_reads_sec
|
217
|
+
# # # Innodb_data_writes_sec
|
218
|
+
# # # Innodb_insert_buffer_pending_reads
|
219
|
+
# # # Innodb_rows_read_sec
|
220
|
+
# # # Innodb_rows_updated_sec
|
221
|
+
# # # lock_wait_time
|
222
|
+
# # # mysql_tables_locked
|
223
|
+
# # # mysql_tables_used
|
224
|
+
# # # row_locks
|
225
|
+
# # # io_avg_wait
|
226
|
+
# # # io_wait
|
227
|
+
# # # max_io_wait
|
228
|
+
# # Several of those values can appear multiple times in the SHOW INNODB STATUS output. The value used
|
229
|
+
# # for comparison is always the higest value. So the value for io_wait is the highest io_wait value
|
230
|
+
# # for all the IO threads.
|
231
|
+
# Processlist
|
232
|
+
# # Watch aggregated SHOW PROCESSLIST values.
|
233
|
+
# # # --watch Processlist:[db|user|host|state|command]:value:[count|time]:[><=]:N
|
234
|
+
# # Examples:
|
235
|
+
# # # --watch "Processlist:state:Locked:count:>:5"
|
236
|
+
# # # --watch "Processlist:command:Query:time:<:1"
|
237
|
+
# Server
|
238
|
+
# # Watch server values.
|
239
|
+
# # # --watch Server:loadavg:[1|5|15]:[><=]:N
|
240
|
+
# # # --watch Server:vmstat:[r|b|swpd|free|buff|cache|si|so|bi|bo|in|cs|us|sy|id|wa]:[><=]:N
|
241
|
+
# # Examples:
|
242
|
+
# # # --watch "Server:loadavg:5:>:4.00"
|
243
|
+
# # # --watch "Server:vmstat:swpd:>:0"
|
244
|
+
# # # --watch "Server:vmstat:free:=:0"
|
245
|
+
# # See "--vmstat".
|
246
|
+
attr_accessor :watch # (No value)
|
247
|
+
|
248
|
+
#
|
249
|
+
# Sets the executable path, otherwise the environment path will be used.
|
250
|
+
#
|
251
|
+
attr_accessor :path_to_mk_loadavg
|
252
|
+
|
253
|
+
#
|
254
|
+
# Returns a new LoadAvg Object
|
255
|
+
#
|
256
|
+
def initialize()
|
257
|
+
end
|
258
|
+
|
259
|
+
#
|
260
|
+
# Execute the command
|
261
|
+
#
|
262
|
+
def start(options = nil)
|
263
|
+
tmp = Tempfile.new('tmp')
|
264
|
+
command = option_string() + options.to_s + " 2> " + tmp.path
|
265
|
+
success = system(command)
|
266
|
+
if success
|
267
|
+
begin
|
268
|
+
while (line = tmp.readline)
|
269
|
+
line.chomp
|
270
|
+
selected_string = line
|
271
|
+
end
|
272
|
+
rescue EOFError
|
273
|
+
tmp.close
|
274
|
+
end
|
275
|
+
return selected_string
|
276
|
+
else
|
277
|
+
tmp.close!
|
278
|
+
return success
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
def config
|
283
|
+
option_string()
|
284
|
+
end
|
285
|
+
|
286
|
+
private
|
287
|
+
|
288
|
+
def option_string()
|
289
|
+
|
290
|
+
unless @path_to_mk_loadavg
|
291
|
+
ostring = "mk-loadavg "
|
292
|
+
else
|
293
|
+
ostring = @path_to_mk_loadavg + " "
|
294
|
+
end
|
295
|
+
|
296
|
+
self.instance_variables.each do |i|
|
297
|
+
tmp_value = self.instance_variable_get "#{i}"
|
298
|
+
tmp_string = i.gsub("_", "-").gsub("@", "--")
|
299
|
+
unless tmp_string == "--path-to-mk-loadavg"
|
300
|
+
if (tmp_value.is_a? TrueClass) || (tmp_value.is_a? FalseClass)
|
301
|
+
ostring += "#{tmp_string} "
|
302
|
+
else
|
303
|
+
ostring += "#{tmp_string} #{tmp_value} "
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
return ostring
|
309
|
+
|
310
|
+
end
|
311
|
+
|
312
|
+
end
|
313
|
+
|
@@ -0,0 +1,316 @@
|
|
1
|
+
# = maatkit-ruby - A maatkit gem for Ruby
|
2
|
+
#
|
3
|
+
# Homepage:: http://github.com/jjuliano/maatkit-ruby
|
4
|
+
# Author:: Joel Bryan Juliano
|
5
|
+
# Copyright:: (cc) 2011 Joel Bryan Juliano
|
6
|
+
# License:: MIT
|
7
|
+
|
8
|
+
#
|
9
|
+
# Replay MySQL query logs.
|
10
|
+
#
|
11
|
+
# Maatkit::LogPlayer.new( array, str, array)
|
12
|
+
#
|
13
|
+
class Maatkit::LogPlayer
|
14
|
+
|
15
|
+
#
|
16
|
+
# group: Play
|
17
|
+
# Prompt for a password when connecting to MySQL.
|
18
|
+
attr_accessor :ask_pass # FALSE
|
19
|
+
|
20
|
+
#
|
21
|
+
# type: string; default: ./
|
22
|
+
# Base directory for "--split" session files and "--play" result file.
|
23
|
+
attr_accessor :base_dir # ./
|
24
|
+
|
25
|
+
#
|
26
|
+
# type: string; default: session
|
27
|
+
# Base file name for "--split" session files and "--play" result file.
|
28
|
+
# Each "--split" session file will be saved as <base-file-name>-N.txt, where N is a four digit, zero-
|
29
|
+
# padded session ID. For example: session-0003.txt.
|
30
|
+
# Each "--play" result file will be saved as <base-file-name>-results-PID.txt, where PID is the process
|
31
|
+
# ID of the executing thread.
|
32
|
+
# All files are saved in "--base-dir".
|
33
|
+
attr_accessor :base_file_name # session
|
34
|
+
|
35
|
+
#
|
36
|
+
# group: Play
|
37
|
+
# short form: -A; type: string
|
38
|
+
# Default character set. If the value is utf8, sets Perl's binmode on STDOUT to utf8, passes the
|
39
|
+
# mysql_enable_utf8 option to DBD::mysql, and runs SET NAMES UTF8 after connecting to MySQL. Any other
|
40
|
+
# value sets binmode on STDOUT without the utf8 layer, and runs SET NAMES after connecting to MySQL.
|
41
|
+
attr_accessor :charset # FALSE
|
42
|
+
|
43
|
+
#
|
44
|
+
# type: Array
|
45
|
+
# Read this comma-separated list of config files; if specified, this must be the first option on the
|
46
|
+
# command line.
|
47
|
+
attr_accessor :config # /etc/maatkit/maatkit.conf,/etc/maatkit/mk_log_player.conf,/home/joel/.maatkit.conf,/home/joel/.mk_log_player.conf
|
48
|
+
|
49
|
+
#
|
50
|
+
# short form: -F; type: string
|
51
|
+
# Only read mysql options from the given file.
|
52
|
+
attr_accessor :defaults_file # (No # value)
|
53
|
+
|
54
|
+
#
|
55
|
+
# Print which processes play which session files then exit.
|
56
|
+
attr_accessor :dry_run # FALSE
|
57
|
+
|
58
|
+
#
|
59
|
+
# type: string; group: Split
|
60
|
+
# Discard "--split" events for which this Perl code doesn't return true.
|
61
|
+
# This option only works with "--split".
|
62
|
+
# This option is a string of Perl code or a file containing Perl code that gets compiled into a
|
63
|
+
# subroutine with one argument: $event. This is a hashref. If the given value is a readable file, then
|
64
|
+
# mk-log-player reads the entire file and uses its contents as the code. The file should not contain a
|
65
|
+
# shebang (#!/usr/bin/perl) line.
|
66
|
+
# If the code returns true, the query is split; otherwise it is discarded. The code is the last
|
67
|
+
# statement in the subroutine other than "return $event". The subroutine template is:
|
68
|
+
# sub { $event = shift; filter && return $event; }
|
69
|
+
# Filters given on the command line are wrapped inside parentheses like like "( filter )". For complex,
|
70
|
+
# multi-line filters, you must put the code inside a file so it will not be wrapped inside parentheses.
|
71
|
+
# Either way, the filter must produce syntactically valid code given the template. For example, an if-
|
72
|
+
# else branch given on the command line would not be valid:
|
73
|
+
# --filter 'if () { } else { }' # WRONG
|
74
|
+
# Since it's given on the command line, the if-else branch would be wrapped inside parentheses which is
|
75
|
+
# not syntactically valid. So to accomplish something more complex like this would require putting the
|
76
|
+
# code in a file, for example filter.txt:
|
77
|
+
# my $event_ok; if (...) { $event_ok=1; } else { $event_ok=0; } $event_ok
|
78
|
+
# Then specify "--filter filter.txt" to read the code from filter.txt.
|
79
|
+
# If the filter code won't compile, mk-log-player will die with an error. If the filter code does
|
80
|
+
# compile, an error may still occur at runtime if the code tries to do something wrong (like pattern
|
81
|
+
# match an undefined value). mk-log-player does not provide any safeguards so code carefully!
|
82
|
+
# An example filter that discards everything but SELECT statements:
|
83
|
+
# --filter '$event->{arg} =~ m/^select/i'
|
84
|
+
# This is compiled into a subroutine like the following:
|
85
|
+
# sub { $event = shift; ( $event->{arg} =~ m/^select/i ) && return $event; }
|
86
|
+
# You can find an explanation of the structure of $event at
|
87
|
+
# <http://code.google.com/p/maatkit/wiki/EventAttributes>.
|
88
|
+
attr_accessor :filter # (No # value)
|
89
|
+
|
90
|
+
#
|
91
|
+
# Show help and exit.
|
92
|
+
attr_accessor :help # TRUE
|
93
|
+
|
94
|
+
#
|
95
|
+
# short form: -h; type: string; group: Play
|
96
|
+
# Connect to host.
|
97
|
+
attr_accessor :host # (No # value)
|
98
|
+
|
99
|
+
#
|
100
|
+
# type: int; default: 1; group: Play
|
101
|
+
# How many times each thread should play all its session files.
|
102
|
+
attr_accessor :iterations # 1
|
103
|
+
|
104
|
+
#
|
105
|
+
# type: int; default: 5000000; group: Split
|
106
|
+
# Maximum number of sessions to "--split".
|
107
|
+
# By default, "mk-log-player" tries to split every session from the log file. For huge logs, however,
|
108
|
+
# this can result in millions of sessions. This option causes only the first N number of sessions to be
|
109
|
+
# saved. All sessions after this number are ignored, but sessions split before this number will continue
|
110
|
+
# to have their queries split even if those queries appear near the end of the log and after this number
|
111
|
+
# has been reached.
|
112
|
+
attr_accessor :max_sessions # 5000000
|
113
|
+
|
114
|
+
#
|
115
|
+
# group: Play
|
116
|
+
# Play only SELECT and USE queries; ignore all others.
|
117
|
+
attr_accessor :only_select # FALSE
|
118
|
+
|
119
|
+
#
|
120
|
+
# short form: -p; type: string; group: Play
|
121
|
+
# Password to use when connecting.
|
122
|
+
attr_accessor :password # (No # value)
|
123
|
+
|
124
|
+
#
|
125
|
+
# type: string
|
126
|
+
# Create the given PID file. The file contains the process ID of the script. The PID file is removed
|
127
|
+
# when the script exits. Before starting, the script checks if the PID file already exists. If it does
|
128
|
+
# not, then the script creates and writes its own PID to it. If it does, then the script checks the
|
129
|
+
# following: if the file contains a PID and a process is running with that PID, then the script dies; or,
|
130
|
+
# if there is no process running with that PID, then the script overwrites the file with its own PID and
|
131
|
+
# starts; else, if the file contains no PID, then the script dies.
|
132
|
+
attr_accessor :pid # (No # value)
|
133
|
+
|
134
|
+
#
|
135
|
+
# type: string; group: Play
|
136
|
+
# Play (execute) session files created by "--split".
|
137
|
+
# The argument to play must be a commaxn-separated list of session files created by "--split" or a
|
138
|
+
# directory. If the argument is a directory, ALL files in that directory will be played.
|
139
|
+
attr_accessor :play # (No # value)
|
140
|
+
|
141
|
+
#
|
142
|
+
# short form: -P; type: int; group: Play
|
143
|
+
# Port number to use for connection.
|
144
|
+
attr_accessor :port # (No # value)
|
145
|
+
|
146
|
+
#
|
147
|
+
# group: Play
|
148
|
+
# Print queries instead of playing them; requires "--play".
|
149
|
+
# You must also specify "--play" with "--print". Although the queries will not be executed, "--play" is
|
150
|
+
# required to specify which session files to read.
|
151
|
+
attr_accessor :print # FALSE
|
152
|
+
|
153
|
+
#
|
154
|
+
# Do not print anything; disables "--verbose".
|
155
|
+
attr_accessor :quiet # FALSE
|
156
|
+
|
157
|
+
#
|
158
|
+
# default: yes
|
159
|
+
# Print "--play" results to files in "--base-dir".
|
160
|
+
attr_accessor :results # TRUE
|
161
|
+
|
162
|
+
#
|
163
|
+
# type: int; default: 8; group: Split
|
164
|
+
# Number of session files to create with "--split".
|
165
|
+
# The number of session files should either be equal to the number of "--threads" you intend to "--play"
|
166
|
+
# or be an even multiple of "--threads". This number is important for maximum performance because it:
|
167
|
+
# * allows each thread to have roughly the same amount of sessions to play
|
168
|
+
# * avoids having to open/close many session files
|
169
|
+
# * avoids disk IO overhead by doing large sequential reads
|
170
|
+
# You may want to increase this number beyond "--threads" if each session file becomes too large. For
|
171
|
+
# example, splitting a 20G log into 8 sessions files may yield roughly eight 2G session files.
|
172
|
+
# See also "--max-sessions".
|
173
|
+
attr_accessor :session_files # 8
|
174
|
+
|
175
|
+
#
|
176
|
+
# type: string; group: Play; default: wait_timeout=10000
|
177
|
+
# Set these MySQL variables. Immediately after connecting to MySQL, this string will be appended to SET
|
178
|
+
# and executed.
|
179
|
+
attr_accessor :set_vars # wait_timeout=10000
|
180
|
+
|
181
|
+
#
|
182
|
+
# short form: -S; type: string; group: Play
|
183
|
+
# Socket file to use for connection.
|
184
|
+
attr_accessor :socket # (No # value)
|
185
|
+
|
186
|
+
#
|
187
|
+
# type: string; group: Split
|
188
|
+
# Split log by given attribute to create session files.
|
189
|
+
# Valid attributes are any which appear in the log: Thread_id, Schema, etc.
|
190
|
+
attr_accessor :split # (No # value)
|
191
|
+
|
192
|
+
#
|
193
|
+
# group: Split
|
194
|
+
# Split log without an attribute, write queries round-robin to session files.
|
195
|
+
# This option, if specified, overrides "--split" and causes the log to be split query-by-query, writing
|
196
|
+
# each query to the next session file in round-robin style. If you don't care about "sessions" and just
|
197
|
+
# want to split a lot into N many session files and the relation or order of the queries does not matter,
|
198
|
+
# then use this option.
|
199
|
+
attr_accessor :split_random # FALSE
|
200
|
+
|
201
|
+
#
|
202
|
+
# type: int; default: 2; group: Play
|
203
|
+
# Number of threads used to play sessions concurrently.
|
204
|
+
# Specifies the number of parallel processes to run. The default is 2. On GNU/Linux machines, the
|
205
|
+
# default is the number of times 'processor' appears in /proc/cpuinfo. On Windows, the default is read
|
206
|
+
# from the environment. In any case, the default is at least 2, even when there's only a single
|
207
|
+
# processor.
|
208
|
+
# See also "--session-files".
|
209
|
+
attr_accessor :threads # 2
|
210
|
+
|
211
|
+
#
|
212
|
+
# type: string; group: Split
|
213
|
+
# The type of log to "--split" (default slowlog). The permitted types are
|
214
|
+
# binlog
|
215
|
+
# # Split a binary log file.
|
216
|
+
# genlog
|
217
|
+
# # Split a general log file.
|
218
|
+
# slowlog
|
219
|
+
# # Split a log file in any varation of MySQL slow-log format.
|
220
|
+
attr_accessor :type # slowlog
|
221
|
+
|
222
|
+
#
|
223
|
+
# short form: -u; type: string; group: Play
|
224
|
+
# User for login if not current user.
|
225
|
+
attr_accessor :user # (No # value)
|
226
|
+
|
227
|
+
#
|
228
|
+
# short form: -v; cumulative: yes; default: 0
|
229
|
+
# Increase verbosity; can specifiy multiple times.
|
230
|
+
# This option is disabled by "--quiet".
|
231
|
+
attr_accessor :verbose # 0
|
232
|
+
|
233
|
+
#
|
234
|
+
# Show version and exit.
|
235
|
+
attr_accessor :version # FALSE
|
236
|
+
|
237
|
+
#
|
238
|
+
# type: array; default: 0; group: Play
|
239
|
+
# Not implemented yet.
|
240
|
+
# The wait time is given in seconds with microsecond precision and can be either a single value or a
|
241
|
+
# range. A single value causes an exact wait; example: 0.010 = wait 10 milliseconds. A range causes a
|
242
|
+
# random wait between the given value times; example: 0.001,1 = random wait from 1 millisecond to 1
|
243
|
+
# second.
|
244
|
+
attr_accessor :wait_between_sessions # (No # value)
|
245
|
+
|
246
|
+
#
|
247
|
+
# default: no; group: Play
|
248
|
+
# Print warnings about SQL errors such as invalid queries to STDERR.
|
249
|
+
attr_accessor :warnings # TRUE
|
250
|
+
|
251
|
+
#
|
252
|
+
# Sets the executable path, otherwise the environment path will be used.
|
253
|
+
#
|
254
|
+
attr_accessor :path_to_mk_log_player
|
255
|
+
|
256
|
+
#
|
257
|
+
# Returns a new LogPlayer Object
|
258
|
+
#
|
259
|
+
def initialize()
|
260
|
+
end
|
261
|
+
|
262
|
+
#
|
263
|
+
# Execute the command
|
264
|
+
#
|
265
|
+
def start(options = nil)
|
266
|
+
tmp = Tempfile.new('tmp')
|
267
|
+
command = option_string() + options.to_s + " 2> " + tmp.path
|
268
|
+
success = system(command)
|
269
|
+
if success
|
270
|
+
begin
|
271
|
+
while (line = tmp.readline)
|
272
|
+
line.chomp
|
273
|
+
selected_string = line
|
274
|
+
end
|
275
|
+
rescue EOFError
|
276
|
+
tmp.close
|
277
|
+
end
|
278
|
+
return selected_string
|
279
|
+
else
|
280
|
+
tmp.close!
|
281
|
+
return success
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
def config
|
286
|
+
option_string()
|
287
|
+
end
|
288
|
+
|
289
|
+
private
|
290
|
+
|
291
|
+
def option_string()
|
292
|
+
|
293
|
+
unless @path_to_mk_log_player
|
294
|
+
ostring = "mk-log-player "
|
295
|
+
else
|
296
|
+
ostring = @path_to_mk_log_player + " "
|
297
|
+
end
|
298
|
+
|
299
|
+
self.instance_variables.each do |i|
|
300
|
+
tmp_value = self.instance_variable_get "#{i}"
|
301
|
+
tmp_string = i.gsub("_", "-").gsub("@", "--")
|
302
|
+
unless tmp_string == "--path-to-mk-log-player"
|
303
|
+
if (tmp_value.is_a? TrueClass) || (tmp_value.is_a? FalseClass)
|
304
|
+
ostring += "#{tmp_string} "
|
305
|
+
else
|
306
|
+
ostring += "#{tmp_string} #{tmp_value} "
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
return ostring
|
312
|
+
|
313
|
+
end
|
314
|
+
|
315
|
+
end
|
316
|
+
|