<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<?php
/*
  $Id: mysqlar.php.sh 41 2006-02-04 12:41:09Z dewitge $
	
  MySQL Activity Report
  Sample php script

  Copyright 2004 Gert Dewit <gert.dewit@sos.be>
*/

/* 
 * MySQL connection settings, be careful if you use a password !
 * It's safer to create a user who can only connect to the database server
 * and has only usage permissions, no grants on any databases or tables.
 */
  $sqlhost = "localhost";
  $sqluser = "mysqlar";
  $sqlpassword = "";

/* sort a matrix using column as key */
	function matrix_sort($matrix, $column, $limit = 0) {
		foreach ($matrix as $row) {
			$sortarr[] = $row[$column];
		}
		array_multisort($sortarr, SORT_DESC, SORT_NUMERIC, $matrix);
		if($limit > 0) {
			return array_slice($matrix, 0, $limit);
		} else {
			return $matrix;
		}
	}
  $link = mysql_connect($sqlhost, $sqluser, $sqlpassword)
     or die("Could not connect : " . mysql_error());
  list($major, $rest) = split('\.',mysql_get_server_info(),2);
  if($major >= 5) {
      $query = "SHOW global status";
  } else {
      $query = "SHOW status";
  }
  $result = mysql_query($query) or die("Query failed : " . mysql_error());
  $status = array();
  $comms_raw = array();
  while ($var = mysql_fetch_array($result)) {
    $status["$var[0]"] = $var[1];
		if(($var[1] > 0) && (preg_match("/^com_/i", $var[0]))) {
			$comms_raw[] = array(preg_replace("/^com_/i", "", $var[0]), $var[1]);
		}
  }
  $comms = matrix_sort($comms_raw, 1);
  if($major >= 5) {
      $query = "SHOW global variables";
  } else {
      $query = "SHOW variables";
  }
  $result = mysql_query($query) or die("Query failed : " . mysql_error());
  $variables = array();
  while ($var = mysql_fetch_array($result)) {
    $variables["$var[0]"] = $var[1];
  }
  $report = array();
  $report['now'] = strftime("%d-%m-%Y %H:%M");
  $script = "";
  $showtime = 'week';
  $times = array('hour', 'day', 'week', 'month', 'year');
  $tabs = array(
    array('tab', 'Table Cache', 'The <strong>table cache graph</strong> shows the open tables and the table_cache setting.</p><p>If the table_cache graph is hidden by the open_tables graph all table cache entries are in use.'),
    array('tmptab', 'Temporary Tables', 'The <strong>temporary tables graph</strong> shows the number of implicit temporary tables. For the best performance these tables should be created in memory.</p><p>If there are many temporary disk tables (created_tmp_disk_tables), you can increase your tmp_table_size to improve your server&#039;s performance.'),
  );
  $keys = array(
    array('key', 'Key Cache', 'The key cache miss rate (key_read_requests/keyreads) should be lower than 1/100 (10m, 10 mili) indicated by an horizontal ruler and is quite ok for most systems if it&#039;s lower than 1/1000 (1m) also indicated by an horizontal ruler.</p><p>One could raise the key_buffer_size parameter to improve the key cache rate.'),
    array('keybuf', 'Key Buffer', 'The key buffer graph shows the amount of memory that&#039;s in use as key cache.'),
    array('join', 'Full Joins', 'The select_full_join value should allways be 0. If its not 0, you should check the indexes of you tables.</p><p>The <strong>full joins graph</strong> can assist you in finding out <strong>when</strong> there have been full joins.'),
    array('range', 'Range Checks', 'The select_range_check value should allways be 0. If its not 0, you should check the indexes of you tables.</p><p>The <strong>range checks graph</strong> can assist you in finding out <strong>when</strong> there have been joins without keys where the key usage got checked after each row.'),
    array('read', 'Reads', 'The <strong>reads graph</strong> shows the read requests based on a key (handler_read_key) and the read requests based on a fixed position in a datafile (handler_read_rnd).</p><p>The handler_read_key indicates that your queries use properly indexed tables, this value should be high. The handler_read_rnd indicates the opposite and should be as low as possible.'),
    array('slow', 'Slow Queries', 'The <strong>slow queries graph</strong> show the queries that took longer than <strong>long_query_time</strong> seconds (for this server the long_query_time='.@$variables['long_query_time'].' seconds).</p><p>If this value is not 0, you should activate <strong>the slow query log</strong> to find out which queries take that long to complete. The slow query log for your server is '.@$variables['log_long_queries'].'.'),
	);
  $slave = array(
  	array('slave', 'Slave Updates', 'The <strong>slave graph</strong> shows how slave replication is performing, specifically how much traffic the slave is replicating and how close the slave is keeping up to the master. The two lines should track so closely you can see only one. The amount of divergence will show when and how far the slave falls behind and how long it takes to catch up.', ''), 
	array('slavec', 'Slave Tracking', 'This graph shows the real difference between the execution and replication progress.'),
	);
  $rrds = array(
    array('queries', 'Questions', 'The <strong>questions graph</strong> shows the number of questions/minute. It has no direct relation to a tuneable parameter, but can be used as a hint to find out during which periods a more thorough logging should be conducted.</p><p>The most relevant types of questions (SELECT, INSERT, UPDATE and DELETE) are also logged.', ''),
    array('con', 'Connections', 'The <strong>connection graph</strong> shows the active connections and the configured max_connections.</p><p>In a sane configuration you should allways be able to see the max_connections graph. If it is hidden by the active connections graph all connections are in use.', ''),
    array('tab', 'Tables', '', $tabs),
    array('key', 'Indexes', '', $keys),
    array('slave', 'Slave Currency', '', $slave),
  );
  $graph_content = '';
  foreach($rrds as $rrd) {
    $graph_content .= "<h2>".$rrd[1]."</h2>\n";
    $graph_content .= "<p>".$rrd[2]."</p>\n";
    if($rrd[3] != '') { // Non 'Tables' RRDs
      foreach($rrd[3] as $graph) {
        $script .= "
  document.getElementById(\"".$graph[0]."-graphs\").style.display = \"\";
  document.getElementById(\"t".$graph[0]."-graphs\").innerHTML = \"Hide\";
";
        $graph_content .= "<h3>".$graph[1]."</h3>\n";
        $graph_content .= "<p>".$graph[2]."</p>\n";
        $graph_content .= "<h4><a href=\"javascript:toggle('".$graph[0]."-graphs', 't".$graph[0]."-graphs');\"><span id=\"t".$graph[0]."-graphs\"></span>&nbsp;graphs</a></h4>\n";
        $graph_content .= "<div id=\"".$graph[0]."-graphs\">\n";
        foreach($times as $time) {
          if($time == $showtime) {
            $display = "";
            $innerHTML = "Hide";
          } else {
            $display = "none";
            $innerHTML = "Show";
          }
          $script .= "
  document.getElementById(\"".$graph[0]."-".$time."\").style.display = \"".$display."\";
  document.getElementById(\"t".$graph[0]."-".$time."\").innerHTML = \"".$innerHTML."\";
";
          $graph_content .= "<h5><a href=\"javascript:toggle('".$graph[0]."-".$time."', 't".$graph[0]."-".$time."');\"><span id=\"t".$graph[0]."-".$time."\"></span>&nbsp;".$time." graph</a></h5>\n";
          $graph_content .= "<img src=\"".$graph[0]."-".$time.".png\" id=\"".$graph[0]."-".$time."\" />\n";
        }
        $graph_content .= "</div>\n";
      }
    } else { // 'Tables' RRDs
      $script .= "
  document.getElementById(\"".$rrd[0]."-graphs\").style.display = \"\";
  document.getElementById(\"t".$rrd[0]."-graphs\").innerHTML = \"Hide\";
";
      $graph_content .= "<h4><a href=\"javascript:toggle('".$rrd[0]."-graphs', 't".$rrd[0]."-graphs');\"><span id=\"t".$rrd[0]."-graphs\"></span>&nbsp;graphs</a></h4>\n";
      $graph_content .= "<div id=\"".$rrd[0]."-graphs\">\n";
      foreach($times as $time) {
        if($time == $showtime) {
          $display = "";
          $innerHTML = "Hide";
        } else {
          $display = "none";
          $innerHTML = "Show";
        }
        $script .= "
  document.getElementById(\"".$rrd[0]."-".$time."\").style.display = \"".$display."\";
  document.getElementById(\"t".$rrd[0]."-".$time."\").innerHTML = \"".$innerHTML."\";
";
        $graph_content .= "<h5><a href=\"javascript:toggle('".$rrd[0]."-".$time."', 't".$rrd[0]."-".$time."');\"><span id=\"t".$rrd[0]."-".$time."\"></span>&nbsp;".$time." graph</a></h5>\n";
        $graph_content .= "<img src=\"".$rrd[0]."-".$time.".png\" id=\"".$rrd[0]."-".$time."\" />\n";
      }
      $graph_content .= "</div>\n";
    }
  }
?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta http-equiv="Content-Language" content="en-us">
<meta name="author" content="Gert Dewit">
<meta name="Copyright" content="Copyright (c) 2004 Gert Dewit">
<title>MySQL Activity Report - <?php print $report['now']; ?></title>
<style type="text/css" media="all">@import "style.css";</style>
<script>
function toggle(elem_id, tog_id) {
  elem = document.getElementById(elem_id);
  tog = document.getElementById(tog_id);
  if(elem.style.display == "") {
    elem.style.display = "none";
    tog.innerHTML = "Show";
  } else {
    elem.style.display = "";
    tog.innerHTML = "Hide";
  }
}
function hide_all() {
  document.getElementById("status").style.display = "none";
  document.getElementById("tstatus").innerHTML = "Show";

  document.getElementById("variables").style.display = "none";
  document.getElementById("tvariables").innerHTML = "Show";
<?php print $script ?>
}
</script>
</head>
<body onload="javascript:hide_all();" bgcolor="#ffffff">
<div id="header">
<h1>MySQL Activity Report</h1>
<p><?php print $report['now']; ?></p>
</div>
<table id="main" cellpadding="0" cellspacing="0">
<tr>
<td id="graphs" valign="top">
<?php print $graph_content; ?>
</td>
<td id="comments" valign="top">
<h2>Server Info</h2>
<?php
  $report['version'] = $variables['version'];
  $report['uptime'] = floor($status['Uptime'] / 3600);
  $report['up_since'] = strftime("%d-%m-%Y %H:%M", time() - $status['Uptime']);
  $report['con_used'] = (int) ($status['Max_used_connections'] / $variables['max_connections'] * 100);
  $report['tab_used'] = (int) ($status['Open_tables'] / $variables['table_cache'] * 100);
	if($status['Opened_tables'] <= 0) {
		$report['tab_hit'] = 100;
	} else {
		$report['tab_hit'] = (int) ($status['Open_tables'] / $status['Opened_tables'] * 100);
	}
  if($status['Key_reads'] == 0) {
		$report['key_used'] = 0;
	} else {
		$report['key_used'] = (int) ($status['Key_read_requests'] / $status['Key_reads']);
	}
	$report['keybuf_used'] = (int) ($status['Key_blocks_used'] * 1024 / $variables['key_buffer_size'] * 100);
	if(($status['Created_tmp_disk_tables'] == 0) || ($status['Created_tmp_tables'] == 0)) {
		$report['tmpmem'] = 100;
	} else {
		$report['tmpmem'] = (int) (($status['Created_tmp_tables'] - $status['Created_tmp_disk_tables']) / $status['Created_tmp_tables'] * 100);
	}
	print "<p>Your server (<strong>".$sqlhost."</strong>) has been running <strong>MySQL version ".$report['version']."</strong> for <strong>".$report['uptime']." hours</strong> since <strong>".$report['up_since']."</strong>.</p>\n"; 
?>
<h2>General Remarks</h2>
<?php 
 print "<p>Since startup, <strong>".$sqlhost."</strong> received <strong>".$status['Questions']." questions</strong>.</p>\n";
 print "<table cellpadding=\"0\" cellspacing=\"0\">
<tr><th>Question</th><th>Issued</th></tr>\n";
  $lineno = 0;
	foreach($comms as $comm) {
    $class = (++$lineno % 2) ? "odd" : "even";
		print "<tr><td class=\"".$class."\">".$comm[0]."</td><td class=\"".$class."nr\">".$comm[1]."</td></tr>\n";
	}
	print "</table>\n";
?>
<h2>Tuning Tips</h2>
<h3>Server tuning</h3>
<?php
  $earlyhours = 24;
  $earlydays = 7;
  if(($report['uptime'] / 24) < $earlydays) {
    if($report['uptime'] < $earlyhours) {
      print "<p><strong id=\"caution\">Your server has been running for less than ".$earlyhours." hours. The tuning tips can&#039;t be very reliable yet.</strong></p>\n";
    } else {
      print "<p><strong id=\"caution\">Your server has been running for less than ".$earlydays." days. If you&#039;ve got a steady load you can use the advise, otherwise wait a little longer before you use the tuning tips.</strong></p>\n";
    }
  } else {
		print "<p><strong id=\"caution\">Your server seems to be running for more than ".$earlydays." days. It should be OK to use the tips below, but don&#039;t follow the advise blindly because this script is no replacement for common sense.</strong></p>\n";
	}
  print "<ul>\n";
	print "<li><p>The maximum number of used connections is ".$status['Max_used_connections']." which is <strong>".$report['con_used']." % of the configured maximum</strong>.</p>\n";
	if($report['con_used'] > 85) {
		if($report['conused'] > 95) {
			print "<p>You <em>should</em> raize your <strong>max_connections</strong> to avoid user lockout.</p></li>";
		} else {
			print "<p>You <em>could</em> raize your <strong>max_connections</strong> to to avoid user lockout.</p></li>";
		}
	} else {
		if($report['con_used'] < 40) {
			print "<p>Your <strong>max_connections</strong> seems to be too high, maybe you can use it&#039;s resources for something else.</p></li>";
		} else {
			print "<p>Your <strong>max_connections</strong> variable seems to be OK.</p></li>";
		}
	}
	print "<li><p>The <strong>table cache hit rate</strong> is <strong>".$report['tab_hit']." %</strong>, while <strong>".$report['tab_used']." %</strong> of your table cache is in use.</p>\n";
	if($report['tab_used'] > 85) {
		if ($report['tab_used'] > 95) {
			print "<p>You <em>should</em> raize your <strong>table_cache</strong> to improve your server's performance.</p></li>";
		} else {
			print "<p>You <em>could</em> raize your <strong>table_cache</strong> to improve your server's performance.</p></li>";
		}
	} else {
		if($report['tab_used'] < 40) {
			print "<p>Your <strong>table_cache</strong> seems to be too high, maybe you can use it&#039;s resources for something else.</p></li>";
		} else {
			print "<p>Your <strong>table_cache</strong> variable seems to be OK.</p></li>";
		}
	}
  print "<li><p>The <strong>temporary table hit rate</strong> is <strong>".$report['tmpmem']." %</strong>.</p>\n";
  if($report['tmpmem'] < 80) {
    if ($report['tmpmem'] < 60) {
      print "<p>You <em>should</em> raize your <strong>tmp_table_size</strong> to improve your server's performance.</p></li>";
    } else {
      print "<p>You <em>could</em> raize your <strong>tmp_table_size</strong> to improve your server's performance.</p></li>";
    }
  } else {
    if($report['tmpmem'] > 99) {
      print "<p>Your <strong>tmp_table_size</strong> seems to be too high, maybe you can use it&#039;s resources for something else.</p></li>";
    } else {
      print "<p>Your <strong>tmp_table_size</strong> variable seems to be OK.</p></li>";
    }
	}
	if($report['key_used'] > 0) {
		print "<li><p class=\"leader\">The <strong>key cache miss rate</strong> is <strong>1/".$report['key_used']."</strong>.</p>\n";
		if($report['key_used'] < 1000) {
			if ($report['key_used'] < 100) {
				print "<p>You <em>should</em> raize your <strong>key_buffer_size</strong> to improve your server's performance.</p></li>";
			} else {
				print "<p>You <em>could</em> raize your <strong>key_buffer_size</strong> to improve your server's performance.</p></li>";
			}
		} else {
			if(($report['key_used'] > 10000) && ($report['keybuf_used'] < 20)) {
				print "<p class=\"leader\">Your <strong>key_buffer_size</strong> seems to be too high, maybe you can use it&#039;s resources for something else.</p><p>Before you lower it, you should monitor the key buffer usage more closely. It may be possible that the keybuffer gets used at peak load.</p></li>";
			} else {
				print "<p>Your <strong>key_buffer_size</strong> variable seems to be OK.</p></li>";
			}
		}
	}
  print "</ul>\n";
?>
<h3>Database tuning</h3>
<p>The problems identified in this section can&#039;t be solved by tuning the server parameters. If you didn't design the database or wrote the queries yourself, you&#039;ll have to talk to the database developers to solve these.</p>
<ul>
<?php
	if($status['Select_full_join'] > 0) {
		print "<li>You need to check your indexes and queries because you had ".$status['Select_full_join']." full joins (select_full_join).</li>";
	}
	if($status['Select_range_check'] > 0) {
		print "<li>You need to look at your indexes because you had ".$status['Select_range_check']." joins without keys (select_range_check).</li>";
	}
	if($status['Handler_read_key'] < $status['Handler_read_rnd']) {
		print "<li>You need to look at the indexing of your databases because the number of reads without using a key is too high. Reads using a key = ".$status['Handler_read_key']." (handler_read_key), reads not using a key = ".$status['Handler_read_rnd']." (handler_read_rnd).</li>";
	}
	if($status['Slow_queries'] > 0) {
		print "<li class=\"leader\">You&#039;ve got <strong>".$status['Slow_queries']." slow queries.</li>";
		if($variables['log_long_queries'] == "ON") {
			print "<li>Check your slow query log to find out which query is causing trouble.</li>";
		} else {
			print "<li>Activate your slow query log to find out which query is causing trouble.</li>";
		}
	}
?>
</ul>
<p><a href="javascript:toggle('status', 'tstatus');"><span id="tstatus"></span> status</a></p>
<div id="status">
<table cellpadding="0" cellspacing="0">
<tr><th>Parameter</th><th>Value</th></tr>
<?php
  $lineno = 0;
  foreach($status as $key=>$val) {
    $class = (++$lineno % 2) ? "odd" : "even";
    print "<tr><td class=\"".$class."\">".$key."</td><td class=\"".$class."nr\">".$val."</td></tr>\n";
  }
?>
</table>
</div>
<p><a href="javascript:toggle('variables', 'tvariables');"><span id="tvariables"></span> variables</a></p>
<div id="variables">
<table cellpadding="0" cellspacing="0">
<tr><th>Variable</th><th>Value</th></tr>
<?php
  $lineno = 0;
  foreach($variables as $key=>$val) {
    $class = (++$lineno % 2) ? "odd" : "even";
    print "<tr><td class=\"".$class."\">".$key."</td><td class=\"".$class."nr\">".$val."</td></tr>\n";
  }
?>
</table>
</div>
</td>
</tr>
</table>
<div id="footer">
<p>Version : @VERSION@ - copyright &copy; 2004 Gert Dewit - <a href="http://www.sos.be/">Supporting Open Source</a></p>
<a href="http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/"><img src="rrdtool.gif" /></a>
<a href="http://www.mysql.com/"><img src="mysql.gif" /></a>
</div>
</body>
</html>
