1
# This program is copyright 2011-2012 Percona Inc.
2
# Feedback and improvements are welcome.
4
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
5
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
6
# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
8
# This program is free software; you can redistribute it and/or modify it under
9
# the terms of the GNU General Public License as published by the Free Software
10
# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar
11
# systems, you can issue `man perlgpl' or `man perlartistic' to read these
14
# You should have received a copy of the GNU General Public License along with
15
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16
# Place, Suite 330, Boston, MA 02111-1307 USA.
17
# ###########################################################################
18
# collect_mysql_info package
19
# ###########################################################################
21
# Package: collect_mysql_info
22
# collect collects mysql information.
25
# THIS LIB REQUIRES log_warn_die.sh, summary_common.sh, and alt_cmds.sh!
28
CMD_MYSQL="${CMD_MYSQL:-""}"
29
CMD_MYSQLDUMP="${CMD_MYSQLDUMP:-""}"
31
# Simply looks for instances of mysqld in the outof of ps.
32
collect_mysqld_instances () {
33
local variables_file="$1"
35
local pids="$(_pidof mysqld)"
37
if [ -n "$pids" ]; then
40
local nice="$( get_nice_of_pid $pid )"
41
local oom="$( get_oom_of_pid $pid )"
42
echo "internal::nice_of_$pid $nice" >> "$variables_file"
43
echo "internal::oom_of_$pid $oom" >> "$variables_file"
46
pids="$(echo $pids | sed -e 's/ /,/g')"
47
ps ww -p "$pids" 2>/dev/null
49
echo "mysqld doesn't appear to be running"
54
# Tries to find the my.cnf file by examining 'ps' output.
55
# You have to specify the port for the instance you are
56
# interested in, in case there are multiple instances.
62
if test -n "$port" && grep -- "/mysqld.*--port=$port" "${file}" >/dev/null 2>&1 ; then
63
cnf_file="$(grep -- "/mysqld.*--port=$port" "${file}" \
64
| awk 'BEGIN{RS=" "; FS="=";} $1 ~ /--defaults-file/ { print $2; }' \
67
cnf_file="$(grep '/mysqld' "${file}" \
68
| awk 'BEGIN{RS=" "; FS="=";} $1 ~ /--defaults-file/ { print $2; }' \
72
if [ ! -n "${cnf_file}" ]; then
73
# "Cannot autodetect config file, trying common locations"
74
cnf_file="/etc/my.cnf";
75
if [ ! -e "${cnf_file}" ]; then
76
cnf_file="/etc/mysql/my.cnf";
78
if [ ! -e "${cnf_file}" ]; then
79
cnf_file="/var/db/mysql/my.cnf";
86
collect_mysql_variables () {
87
$CMD_MYSQL $EXT_ARGV -ss -e 'SHOW /*!40100 GLOBAL*/ VARIABLES'
90
collect_mysql_status () {
91
$CMD_MYSQL $EXT_ARGV -ss -e 'SHOW /*!50000 GLOBAL*/ STATUS'
94
collect_mysql_databases () {
95
$CMD_MYSQL $EXT_ARGV -ss -e 'SHOW DATABASES' 2>/dev/null
98
collect_mysql_plugins () {
99
$CMD_MYSQL $EXT_ARGV -ss -e 'SHOW PLUGINS' 2>/dev/null
102
collect_mysql_slave_status () {
103
$CMD_MYSQL $EXT_ARGV -ssE -e 'SHOW SLAVE STATUS' 2>/dev/null
106
collect_mysql_innodb_status () {
107
$CMD_MYSQL $EXT_ARGV -ssE -e 'SHOW /*!50000 ENGINE*/ INNODB STATUS' 2>/dev/null
110
collect_mysql_processlist () {
111
$CMD_MYSQL $EXT_ARGV -ssE -e 'SHOW FULL PROCESSLIST' 2>/dev/null
114
collect_mysql_users () {
115
$CMD_MYSQL $EXT_ARGV -ss -e 'SELECT COUNT(*), SUM(user=""), SUM(password=""), SUM(password NOT LIKE "*%") FROM mysql.user' 2>/dev/null
118
collect_master_logs_status () {
119
local master_logs_file="$1"
120
local master_status_file="$2"
121
$CMD_MYSQL $EXT_ARGV -ss -e 'SHOW MASTER LOGS' > "$master_logs_file" 2>/dev/null
122
$CMD_MYSQL $EXT_ARGV -ss -e 'SHOW MASTER STATUS' > "$master_status_file" 2>/dev/null
125
# Somewhat different from the others, this one joins the status we got earlier
126
collect_mysql_deferred_status () {
127
local status_file="$1"
128
collect_mysql_status > "$TMPDIR/defer_gatherer"
129
join "$status_file" "$TMPDIR/defer_gatherer"
132
collect_internal_vars () {
133
local mysqld_executables="${1:-""}"
136
if $CMD_MYSQL $EXT_ARGV -e 'SELECT FNV_64("a")' >/dev/null 2>&1; then
142
local now="$($CMD_MYSQL $EXT_ARGV -ss -e 'SELECT NOW()')"
143
local user="$($CMD_MYSQL $EXT_ARGV -ss -e 'SELECT CURRENT_USER()')"
144
local trigger_count=$($CMD_MYSQL $EXT_ARGV -ss -e "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TRIGGERS" 2>/dev/null)
146
echo "pt-summary-internal-mysql_executable $CMD_MYSQL"
147
echo "pt-summary-internal-now $now"
148
echo "pt-summary-internal-user $user"
149
echo "pt-summary-internal-FNV_64 $FNV_64"
150
echo "pt-summary-internal-trigger_count $trigger_count"
152
if [ -e "$mysqld_executables" ]; then
154
while read executable; do
155
echo "pt-summary-internal-mysqld_executable_${i} $(has_symbols "$executable")"
157
done < "$mysqld_executables"
161
# Uses mysqldump and dumps the results to FILE.
162
# args and dbtodump are passed to mysqldump.
163
get_mysqldump_for () {
165
local dbtodump="${2:-"--all-databases"}"
167
$CMD_MYSQLDUMP $EXT_ARGV --no-data --skip-comments \
168
--skip-add-locks --skip-add-drop-table --compact \
169
--skip-lock-all-tables --skip-lock-tables --skip-set-charset \
170
${args} --databases $( local IFS=,; echo ${dbtodump})
173
# Returns a string with arguments to pass to mysqldump.
174
# Takes one argument, which should be a
175
get_mysqldump_args () {
179
# If mysqldump supports triggers, then add options for routines.
180
if $CMD_MYSQLDUMP --help --verbose 2>&1 | grep triggers >/dev/null; then
181
# "mysqldump supports triggers"
185
if [ "${trg_arg}" ]; then
186
# Find out if there are any triggers. If there are none, we will skip
187
# that option to mysqldump, because when mysqldump checks for them, it
188
# can take a long time, one table at a time.
189
local triggers="--skip-triggers"
190
local trg=$(get_var "pt-summary-internal-trigger_count" "$file" )
191
if [ -n "${trg}" ] && [ "${trg}" -gt 0 ]; then
192
triggers="--triggers"
194
trg_arg="${trg_arg} ${triggers}";
199
collect_mysqld_executables () {
200
local mysqld_instances="$1"
202
for pid in $( grep '/mysqld' "$mysqld_instances" | awk '/^ .*[0-9]/{print $1}' ); do
203
ps -o cmd -p $pid | sed -e 's/^\(.*mysqld\) .*/\1/' | grep -v '^CMD$'
207
collect_mysql_info () {
210
collect_mysql_variables > "$dir/mysql-variables"
211
collect_mysql_status > "$dir/mysql-status"
212
collect_mysql_databases > "$dir/mysql-databases"
213
collect_mysql_plugins > "$dir/mysql-plugins"
214
collect_mysql_slave_status > "$dir/mysql-slave"
215
collect_mysql_innodb_status > "$dir/innodb-status"
216
collect_mysql_processlist > "$dir/mysql-processlist"
217
collect_mysql_users > "$dir/mysql-users"
219
collect_mysqld_instances "$dir/mysql-variables" > "$dir/mysqld-instances"
220
collect_mysqld_executables "$dir/mysqld-instances" > "$dir/mysqld-executables"
222
local binlog="$(get_var log_bin "$dir/mysql-variables")"
223
if [ "${binlog}" ]; then
224
# "Got a binlog, going to get MASTER LOGS and MASTER STATUS"
225
collect_master_logs_status "$dir/mysql-master-logs" "$dir/mysql-master-status"
228
local uptime="$(get_var Uptime "$dir/mysql-status")"
229
local current_time="$($CMD_MYSQL $EXT_ARGV -ss -e \
230
"SELECT LEFT(NOW() - INTERVAL ${uptime} SECOND, 16)")"
232
local port="$(get_var port "$dir/mysql-variables")"
233
local cnf_file="$(find_my_cnf_file "$dir/mysqld-instances" ${port})"
235
cat "$cnf_file" > "$dir/mysql-config-file"
237
local pid_file="$(get_var "pid_file" "$dir/mysql-variables")"
238
local pid_file_exists=""
239
[ -e "${pid_file}" ] && pid_file_exists=1
240
echo "pt-summary-internal-pid_file_exists $pid_file_exists" >> "$dir/mysql-variables"
242
# TODO: Do these require a file of their own?
243
echo "pt-summary-internal-current_time $current_time" >> "$dir/mysql-variables"
244
echo "pt-summary-internal-Config_File_path $cnf_file" >> "$dir/mysql-variables"
245
collect_internal_vars "$dir/mysqld-executables" >> "$dir/mysql-variables"
247
if [ -n "${OPT_DATABASES}" ]; then
248
# "--dump-schemas passed in, dumping early"
249
local trg_arg="$( get_mysqldump_args "$dir/mysql-variables" )"
250
get_mysqldump_for "${trg_arg}" "${OPT_DATABASES}" > "$dir/mysqldump"
253
# TODO: gather this data in the same format as normal: TS line, stats
256
collect_mysql_deferred_status "$dir/mysql-status" > "$dir/mysql-status-defer"
258
_d "Forked child is $!"
261
# ###########################################################################
262
# End collect_mysql_info package
263
# ###########################################################################