<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>code.openark.org &#187; scripts</title>
	<atom:link href="http://code.openark.org/blog/tag/scripts/feed" rel="self" type="application/rss+xml" />
	<link>http://code.openark.org/blog</link>
	<description>Blog by Shlomi Noach</description>
	<lastBuildDate>Tue, 07 Sep 2010 05:53:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>mycheckpoint (rev. 190): HTTP server; interactive charts</title>
		<link>http://code.openark.org/blog/mysql/mycheckpoint-rev-190-http-server-interactive-charts</link>
		<comments>http://code.openark.org/blog/mysql/mycheckpoint-rev-190-http-server-interactive-charts#comments</comments>
		<pubDate>Tue, 07 Sep 2010 05:53:01 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Monitoring]]></category>
		<category><![CDATA[mycheckpoint]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=2866</guid>
		<description><![CDATA[Revision 190 of mycheckpoint, a MySQL monitoring solution, has been released. New and updated in this revision: HTTP server: mycheckpoint can now act as a web server. Point your browser and start browsing through HTML reports. See mock up demo. Interactive charts: HTML line charts are now interactive, presenting with accurate data as you move [...]]]></description>
			<content:encoded><![CDATA[<p>Revision <strong>190</strong> of <a href="../../forge/mycheckpoint">mycheckpoint</a>, a MySQL monitoring solution, has  been released. New and updated in this revision:</p>
<ul>
<li><strong>HTTP server</strong>: <em>mycheckpoint</em> can now act as a web server. Point your browser and start browsing through HTML reports. See mock up <a href="http://code.openark.org/forge/wp-content/uploads/2010/09/r190/mcp_sql00/sv_report_html_brief.html"><strong>demo</strong></a>.</li>
<li><strong>Interactive charts</strong>: HTML line charts are now interactive, presenting with accurate data as you move over them. See <a href="http://code.openark.org/forge/wp-content/uploads/2010/09/r190/mcp_sql00_samples/sv_report_html_brief.html"><strong>sample</strong></a>.</li>
<li><strong>Enhanced auto-deploy</strong>: now auto-recognizing failed upgrades.</li>
<li><strong>Reduced footprint</strong>: much code taken out of the views, leading to faster loading times.</li>
<li><strong>Better configuration file use</strong>: now supporting all command line options in config file.</li>
<li><strong>Remote host monitoring accessibility</strong>: now supporting complete configurable accessibility details.</li>
<li><strong>Bug fixes</strong>: thanks to the bug reporters!</li>
</ul>
<p><em>mycheckpoint</em> is free, simple, easy to use (now easier with HTTP server) and <strong>useful</strong>. I encourage you to try it out: even compared with other existing and emerging monitoring tools, I believe you will find it a breeze; it&#8217;s low impact and lightness appealing; it&#8217;s alerts mechanism assuring; its geeky SQL-based nature with ability to drill down to fine details &#8212; geeky-kind-of-attractive.</p>
<p>&lt;/encouragement&gt;</p>
<h4>HTTP server</h4>
<p>You can now run <em>mycheckpoint</em> in <em>http</em> mode:</p>
<blockquote>
<pre>bash$ <strong>mycheckpoint http</strong></pre>
</blockquote>
<p><em>mycheckpoint</em> will listen on port <strong>12306</strong>, and will present you with easy browsing through the reports of your <em>mycheckpoint</em> databases.<span id="more-2866"></span></p>
<p>The <em>http</em> server automatically detects those schemata used by mycheckpoint, and utilizes the existing HTML views, integrating them into the greater web framework.</p>
<p>While in <em>http</em> mode, mycheckpoint does nothing besides serving web pages. It does not actively exercise monitoring: you must still use the usual cron jobs or other scheduled tasks by which you invoke <em>mycheckpoint</em> for monitoring.</p>
<p>The http server is directed at a single MySQL server, as with the following example:</p>
<blockquote>
<pre>bash$ <strong>mycheckpoint --host=slave1.localdomain --port=3306 --http-port=12306 http</strong></pre>
</blockquote>
<p>It is assumed that this server has the monitoring schemata.</p>
<p>See mock up <a href="http://code.openark.org/forge/wp-content/uploads/2010/09/r190/mcp_sql00/sv_report_html_brief.html"><strong>demo</strong></a>. The demo uses presents with real output from a mycheckpoint HTTP server; I haven&#8217;t got the means to put up a live demo.</p>
<h4>Interactive charts</h4>
<p>The <em>openark line charts</em>, used in the HTML reports, are now interactive. As you scroll over, the legend presents you with series values.</p>
<p>No more <em>&#8220;I have this huge spike once every 4 hours, which reduces all other values to something that looks like zero but is actually NOT&#8221;</em>. Hover, and see the real values.</p>
<p>See <a href="http://code.openark.org/forge/wp-content/uploads/2010/09/r190/mcp_sql00_samples/sv_report_html_brief.html"><strong>sample</strong></a>.</p>
<h4>Enhanced auto-deploy</h4>
<p>The idea with mycheckpoint is that it should know how to self upgrade the schema on version upgrade (much like automatic WordPress upgrades). mycheckpoint does bookkeeping of installed versions within the database, and upgrades by simple comparison.</p>
<p>It now, following a couple of reported bugs, also recognizes failure of partial, failed upgrades. This adds to the automation of <em>mycheckpoint</em>&#8216;s installation.</p>
<h4>Reduced footprint</h4>
<p>Some of <em>mycheckpoint</em>&#8216;s views are complicated, and lead to a large amount of code in view declaration. This leads to increased table definition size (large <strong>.frm</strong> files). There has been some work to reduce this size where possible. Work is still ongoing, but some 30% has been taken off already. This leads to faster table (view) load time.</p>
<h4>Better configuration file use</h4>
<p>Any argument supported on the command line is now also supported in the config style. Much like is handled with MySQL. For example, one can issue:</p>
<blockquote>
<pre>mycheckpoint --monitored-host=sql02.mydb.com  --monitored-user=monitor --monitored-password=123456</pre>
</blockquote>
<p>But now also:</p>
<blockquote>
<pre>mycheckpoint</pre>
</blockquote>
<p>With the following in <strong>/etc/mycheckpoint.cnf</strong>:</p>
<blockquote>
<pre>[mycheckpoint]
monitored_host     = sql02.mydb.com
monitored_user     = monitor
monitored_password = 123456
</pre>
</blockquote>
<p>Rules are:</p>
<ul>
<li>If an option is specified on command line, it takes precedence over anything else.</li>
<li>Otherwise, if it&#8217;s specified in the configuration file, value is read from file.</li>
<li>Otherwise use default value is used.</li>
<li>On command line, option format is<strong> xxx-yyy-zzz</strong>: words split with dash/minus character.</li>
<li>On configuration file, option format is <strong>xxx_yyy_zzz</strong>: words split with underscore. Unlike MySQL configuration format, dashes cannot be used.</li>
<li>If an option is specified multiple times on configuration file &#8212; well &#8212; I have the answer, but I won&#8217;t tell. Just don&#8217;t do it. It&#8217;s bad for your health.</li>
</ul>
<h4>Future plans</h4>
<p>Work is going on. These are the non-scheduled future tasks I see:</p>
<ul>
<li>Monitoring InnoDB Plugin &amp; XtraDB status.</li>
<li>A proper <em>man</em> page.</li>
<li>Anything else that interests me &amp; the users.</li>
</ul>
<h4>Try it out</h4>
<p>Try out <em>mycheckpoint</em>. It’s a different kind of monitoring   solution. Simple monitoring (charting) is immediate. For more interesting results you will need basic SQL skills, and in return you’ll get a lot   of power under your hands.</p>
<ul>
<li>Download mycheckpoint <a href="https://code.google.com/p/mycheckpoint/">here</a></li>
<li>Visit the project’s <a href="../../forge/mycheckpoint">homepage</a></li>
<li>Browse the <a href="../../forge/mycheckpoint/documentation">documentation</a></li>
<li>Report <a href="https://code.google.com/p/mycheckpoint/issues/list">bugs</a></li>
</ul>
<p><em>mycheckpoint</em> is released under the <a href="http://www.opensource.org/licenses/bsd-license.php">New BSD  License</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/mycheckpoint-rev-190-http-server-interactive-charts/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>mylvmbackup HOWTO: minimal privileges &amp; filesystem copy</title>
		<link>http://code.openark.org/blog/mysql/mylvmbackup-howto-minimal-privileges-filesystem-copy</link>
		<comments>http://code.openark.org/blog/mysql/mylvmbackup-howto-minimal-privileges-filesystem-copy#comments</comments>
		<pubDate>Tue, 17 Aug 2010 17:42:40 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Backup]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=2839</guid>
		<description><![CDATA[This HOWTO discusses two (unrelated) issues with mylvmbackup: The minimal privileges required to take MySQL backups with mylvmbackup. Making (non compressed) file system copy of one&#8217;s data files. Minimal privileges Some just give mylvmbackup the root account, which is far too permissive. We now consider what the minimal requirements of mylvmbackup are. The queries mylvmbackup [...]]]></description>
			<content:encoded><![CDATA[<p>This HOWTO discusses two (unrelated) issues with <a href="http://www.lenzg.net/mylvmbackup/"><em>mylvmbackup</em></a>:</p>
<ul>
<li>The minimal privileges required to take MySQL backups with <em>mylvmbackup.</em></li>
<li>Making (non compressed) file system copy of one&#8217;s data files.</li>
</ul>
<h4>Minimal privileges</h4>
<p>Some just give <em>mylvmbackup</em> the root account, which is far too permissive. We now consider what the minimal requirements of <em>mylvmbackup</em> are.</p>
<p>The queries <em>mylvmbackup</em> issues are:</p>
<ul>
<li><strong>FLUSH TABLES</strong></li>
<li><strong>FLUSH TABLES WITH READ LOCK</strong></li>
<li><strong>SHOW MASTER STATUS</strong></li>
<li><strong>SHOW SLAVE STATUS</strong></li>
<li><strong>UNLOCK TABLES</strong></li>
</ul>
<p>Both <strong>SHOW MASTER STATUS</strong> &amp; <strong>SHOW SLAVE STATUS</strong> require either the <strong>SUPER</strong> or <strong>REPLICATION CLIENT</strong> privilege. Since <strong>SUPER</strong> is more powerful, we choose <strong>REPLICATION CLIENT</strong>.</p>
<p>The <strong>FLUSH TABLES</strong> * and <strong>UNLOCK TABLES</strong> require the <strong>RELOAD</strong> privilege.</p>
<p>However, we are not done yet. <em>mylvmbackup</em> connects to the <strong>mysql</strong> database, which means we must also have some privilege there, too. We choose the <strong>SELECT</strong> privilege.</p>
<p><span id="more-2839"></span>Finally, here are the commands to create a <em>mylvmbackup</em> user with minimal privileges:</p>
<blockquote>
<pre>CREATE USER 'mylvmbackup'@'localhost' IDENTIFIED BY '12345';
GRANT RELOAD, REPLICATION CLIENT ON *.* TO 'mylvmbackup'@'localhost';
GRANT SELECT ON mysql.* TO 'mylvmbackup'@'localhost';
</pre>
</blockquote>
<p>In the <strong>mylvmbackup.conf</strong> file, the correlating rows are:</p>
<blockquote>
<pre>[mysql]
user=mylvmbackup
password=12345
host=localhost
</pre>
</blockquote>
<h4>Filesystem copy</h4>
<p>By default, <em>mylvmbackup</em> creates a <strong>.tar.gz</strong> compressed backup file of your data. This is good if the reason you&#8217;re running <em>mylvmbackup</em> is to, well, make a backup. However, as with all backups, one may be making the backup so as to create a replication server. But in this case you don&#8217;t really want compressed data: you want the data extracted on the replication server, just as it is on the original host.</p>
<p><em>mylvmbackup</em> supports backing up the files using <em>rsync</em>.</p>
<p>To copy MySQL data to a remote host, configure the following in the mylvmbackup.conf file:</p>
<blockquote>
<pre>[fs]
backupdir=shlomi@backuphost:/data/backup/mysql
[misc]
backuptype=rsync
</pre>
</blockquote>
<p>You may be prompted to enter password, unless you have the user&#8217;s public key stored on the remote host.</p>
<p>Normally, <em>rsync</em> is considered as <strong>r</strong>emote-<strong>sync</strong>, but it also works on local file systems. If you have a remote directory mounted on your file system (e.g. with <em>nfs</em>), you can use the fact that <em>rsync</em> works just as well with local file systems:</p>
<blockquote>
<pre>[fs]
backupdir=/mnt/backup/mysql
[misc]
backuptype=rsync
</pre>
</blockquote>
<p>Voila! Your backup is complete.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/mylvmbackup-howto-minimal-privileges-filesystem-copy/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Another Python MySQL template</title>
		<link>http://code.openark.org/blog/mysql/another-python-mysql-template</link>
		<comments>http://code.openark.org/blog/mysql/another-python-mysql-template#comments</comments>
		<pubDate>Wed, 11 Aug 2010 05:51:57 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[scripts]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=2815</guid>
		<description><![CDATA[Following up on Matt Reid&#8217;s simple python, mysql connection and iteration, I would like to share one of my own, which is the base for mycheckpoint &#38; openark kit scripts. It is oriented to provide with clean access to the data: the user is not expected to handle cursors and connections. Result sets are returned [...]]]></description>
			<content:encoded><![CDATA[<p>Following up on Matt Reid&#8217;s <a href="http://themattreid.com/wordpress/?p=330">simple python, mysql connection and iteration</a>, I would like to share one of my own, which is the base for mycheckpoint &amp; openark kit scripts.</p>
<p>It is oriented to provide with clean access to the data: the user is not expected to handle cursors and connections. Result sets are returned as python lists and dictionaries. It is also config file aware and comes with built in command line options.</p>
<p>I hope it comes to use: <a href="http://code.openark.org/blog/wp-content/uploads/2010/08/my.py">my.py</a></p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/another-python-mysql-template/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tips for taking MySQL backups using LVM</title>
		<link>http://code.openark.org/blog/mysql/tips-for-taking-mysql-backups-using-lvm</link>
		<comments>http://code.openark.org/blog/mysql/tips-for-taking-mysql-backups-using-lvm#comments</comments>
		<pubDate>Tue, 03 Aug 2010 06:45:29 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Backup]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[scripts]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=2717</guid>
		<description><![CDATA[LVM uses copy-on-write to implement snapshots. Whenever you&#8217;re writing data to some page, LVM copies the original page (the way it looked like when the snapshot was taken) to the snapshot volume. The snapshot volume must be large enough to accommodate all pages written to for the duration of the snapshot&#8217;s lifetime. In other words, [...]]]></description>
			<content:encoded><![CDATA[<p>LVM uses copy-on-write to implement snapshots. Whenever you&#8217;re writing data to some page, LVM copies the original page (the way it looked like when the snapshot was taken) to the snapshot volume. The snapshot volume must be large enough to accommodate all pages written to for the duration of the snapshot&#8217;s lifetime. In other words, you must be able to copy the data somewhere outside (tape, NFS, rsync, etc.) in less time than it would take for the snapshot to fill up.</p>
<p>While LVM allows for hot backups of MySQL, it still poses an impact on the disks. An LVM snapshot backup may not go unnoticed by the MySQL users.</p>
<p>Some general guidelines for making life easier with LVM backups follow.</p>
<h4>Lighter, longer snapshots</h4>
<p>If you&#8217;re confident that you have enough space on your snapshot volume, you may take the opportunity to make for a <em>longer</em> backup time. Why? Because you would then be able to reduce the stress from the file system. Use <strong>ionice</strong> when copying your data from the snapshot volume:</p>
<blockquote>
<pre>ionice -c 2 cp -R /mnt/mysql_snapshot /mnt/backup/daily/20100719/
</pre>
</blockquote>
<p><em>[Update: this is only on the cfq I/O scheduler; thanks, Vojtech]</em></p>
<h4>Are you running out of space?</h4>
<p>Monitor snapshot&#8217;s allocated size: if there&#8217;s just one snapshot, do it like this:<span id="more-2717"></span></p>
<blockquote>
<pre>lvdisplay | grep Allocated                                                                                                                  Mon Jul 19 09:51:29 2010

 Allocated to snapshot  3.63%
</pre>
</blockquote>
<p>Don&#8217;t let it reach 100%.</p>
<h4>Avoid running out of space</h4>
<p>To make sure you don&#8217;t run out of snapshot allocated size, stop all administrative scripts.</p>
<ul>
<li>Are you running your weekly purging of old data? You will be writing a lot of pages, and all will have to fit in the snapshot.</li>
<li>Building your reports? You may be creating large temporary tables; make sure these are not on the snapshot volume.</li>
<li>Rebuilding your Sphinx fulltext index? Make sure it is not on the snapshot volume, or postpone till after backup.</li>
</ul>
<p>You will gain not only snapshot space, but also faster backups.</p>
<h4>Someone did the job before you</h4>
<p>Use <a href="http://www.lenzg.net/mylvmbackup/">mylvmbackup</a>: the MySQL LVM backup script by Lenz Grimmer. Or do it manually: follow this old-yet-relevant <a href="http://www.mysqlperformanceblog.com/2006/08/21/using-lvm-for-mysql-backup-and-replication-setup/">post</a> by Peter Zaitsev.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/tips-for-taking-mysql-backups-using-lvm/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>mycheckpoint (rev. 132): custom monitoring, custom charts, process list dump</title>
		<link>http://code.openark.org/blog/mysql/mycheckpoint-rev-132-custom-monitoring-custom-charts-process-list-dump</link>
		<comments>http://code.openark.org/blog/mysql/mycheckpoint-rev-132-custom-monitoring-custom-charts-process-list-dump#comments</comments>
		<pubDate>Fri, 04 Jun 2010 09:17:27 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Graphs]]></category>
		<category><![CDATA[Monitoring]]></category>
		<category><![CDATA[mycheckpoint]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[scripts]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=2463</guid>
		<description><![CDATA[Revision 132 of mycheckpoint has been released. New and updated in this revision: Custom monitoring: monitoring &#38; charting for user defined queries HTML reports for custom monitoring Process list dump upon alert notifications Custom monitoring &#38; charts Custom monitoring allows the user to supply with a query, the results of which will be monitored. That [...]]]></description>
			<content:encoded><![CDATA[<p>Revision <strong>132</strong> of <a href="../../forge/mycheckpoint">mycheckpoint</a> has been released. New and updated in this revision:</p>
<ul>
<li>Custom monitoring: monitoring &amp; charting for user defined queries</li>
<li>HTML reports for custom monitoring</li>
<li>Process list dump upon alert notifications</li>
</ul>
<h4>Custom monitoring &amp; charts</h4>
<p>Custom monitoring allows the user to supply with a query, the results of which will be monitored.</p>
<p>That is, <em>mycheckpoint</em> monitors the status variables, replication status, OS metrics. But it cannot by itself monitor one&#8217;s <em>application</em>. Which is why a user may supply with such query as:</p>
<blockquote><pre class="brush: sql;">
SELECT COUNT(*) FROM shopping_cart WHERE is_pending=1
</pre>
</blockquote>
<p>Such a query will tell an online store how many customers are in the midst of shopping. There is no argument that this number is worth monitoring for. Given the above query, <em>mycheckpoint</em> will execute it per sample, and store the query&#8217;s result along with all sampled data, to be then aggregated by complex views to answer for:</p>
<ul>
<li>What was the value per given sample?</li>
<li>What is the value difference for each sample?</li>
<li>What is the change per second, i.e. the rate?</li>
</ul>
<p>mycheckpoint goes one step forward, and explicity records another metric:</p>
<ul>
<li>How much time did it take to take that sample?</li>
</ul>
<p><span id="more-2463"></span>As another example, a query worth testing for rate:</p>
<blockquote><pre class="brush: sql;">
SELECT MAX(shopping_cart_id) FROM shopping_cart
</pre>
</blockquote>
<p>The above will provide with the last id. Assuming this is <strong>AUTO_INCREMENT</strong>, and assuming we&#8217;re on <strong>auto_increment_increment=1</strong>, two samples will allow us to get the number of created carts between those samples. Now, here&#8217;s a metric I&#8217;d like to read:</p>
<ul>
<li>How many carts are created per second, for each hour of the day?</li>
</ul>
<p>We get all these for free with mycheckpoint, which already does this analysis. All we need to provide is the query, and how we would like it to be visualized (visualization is optional, it is not the only way to diagnose monitored data) graphically:</p>
<blockquote><pre class="brush: sql;">
INSERT INTO
 custom_query (custom_query_id, enabled, query_eval, description, chart_type, chart_order)
 VALUES (0, 1, 'SELECT COUNT(*) FROM store.shopping_cart WHERE is_pending=1', 'Number of pending carts', 'value', 0);

INSERT INTO
 custom_query (custom_query_id, enabled, query_eval, description, chart_type, chart_order)
 VALUES (1, 1, 'SELECT MAX(shopping_cart_id) FROM store.shopping_cart', 'Created carts rate', 'value_psec', 0);
</pre>
</blockquote>
<p>We can later query for these values, just like we do for normal monitored values:</p>
<blockquote><pre class="brush: sql;">
mysql&gt; SELECT id, ts, created_tmp_tables_psec, custom_0, custom_1_psec FROM sv_sample WHERE ts &gt;= NOW() - INTERVAL 1 HOUR;
+-------+---------------------+-------------------------+----------+---------------+
| id    | ts                  | created_tmp_tables_psec | custom_0 | custom_1_psec |
+-------+---------------------+-------------------------+----------+---------------+
| 50730 | 2010-05-21 19:05:01 |                   16.64 |      448 |          3.02 |
| 50731 | 2010-05-21 19:10:02 |                   20.97 |       89 |          1.73 |
| 50732 | 2010-05-21 19:15:01 |                   15.70 |      367 |          3.56 |
| 50733 | 2010-05-21 19:20:01 |                   18.32 |       54 |          1.43 |
| 50734 | 2010-05-21 19:25:01 |                   16.42 |       91 |          1.96 |
| 50735 | 2010-05-21 19:30:02 |                   21.93 |      233 |          2.11 |
| 50736 | 2010-05-21 19:35:02 |                   14.58 |      176 |          1.91 |
| 50737 | 2010-05-21 19:40:01 |                   21.61 |      168 |          1.93 |
| 50738 | 2010-05-21 19:45:01 |                   16.05 |      241 |          2.44 |
| 50739 | 2010-05-21 19:50:01 |                   19.70 |       46 |          1.19 |
| 50740 | 2010-05-21 19:55:01 |                   15.85 |      177 |          2.28 |
| 50741 | 2010-05-21 20:00:01 |                   19.04 |        8 |          0.82 |
+-------+---------------------+-------------------------+----------+---------------+
</pre>
</blockquote>
<p>Of course, it is also possible to harness <em>mycheckpoint</em>&#8216;s views power to generate charts:</p>
<blockquote>
<pre>mysql&gt; SELECT custom_1_psec FROM sv_report_chart_sample\G
<img class="alignnone" title="custom_1_psec" src="http://chart.apis.google.com/chart?cht=lc&amp;chs=400x200&amp;chts=303030,12&amp;chtt=Latest+24+hours:+May+19,+20:10++-++May+20,+20:10&amp;chf=c,s,ffffff&amp;chdl=custom_1_psec&amp;chdlp=b&amp;chco=ff8c00&amp;chd=s:QfXQmZQhXTmWVkWRobPpWUtQPVROaOOUMJPOKdJHQJFJEDJJEGCAIEFJHFFEGGDQHGJGMJPPMNZNRWR_ZUWfR_nSjuUcaXa3OgxRl4UivWZ5UhtWX4VgnUTYktiVW9WanUVxVYlgXwVdicXpb&amp;chxt=x,y&amp;chxr=1,0,5.120000&amp;chxl=0:||+||00:00||+||04:00||+||08:00||+||12:00||+||16:00||+||20:00|&amp;chxs=0,505050,10,0,lt&amp;chg=4.17,25,1,2,3.47,0&amp;chxp=0,3.47,7.64,11.81,15.98,20.15,24.32,28.49,32.66,36.83,41.00,45.17,49.34,53.51,57.68,61.85,66.02,70.19,74.36,78.53,82.70,86.87,91.04,95.21,99.38" alt="" width="400" height="200" />
</pre>
</blockquote>
<p>The rules are:</p>
<ul>
<li>There can (currently) only be 18 custom queries.</li>
<li>The <strong>custom_query_id</strong> must range 0-17 (to be lifted soon).</li>
<li>A custom query must return with <em>exactly</em> one row, with <em>exactly</em> one column, which is a kind of <em>integer</em>.</li>
</ul>
<p>Please read <a href="http://code.openark.org/blog/mysql/things-to-monitor-on-mysql-the-users-perspective">my earlier post</a> on custom monitoring to get more background.</p>
<h4>Custom monitoring HTML reports</h4>
<p>Custom monitoring comes with a HTML reports, featuring requested charts. See a <a href="http://code.openark.org/blog/wp-content/uploads/2010/05/mcp_custom_report-128.html">sample custom report</a>.</p>
<p>In this sample report, a few queries are monitored for value (pending rentals, pending downloads) and a few for rates (downloads per second, emails per second etc.).</p>
<p>Custom HTML reports come in two flavors:</p>
<ul>
<li>Brief reports, featuring last 24 hours, as in the example above. These are handled by the <strong>sv_custom_html_brief</strong> view.</li>
<li>Full reports, featuring last 24 hours, last 10 days, known history. These take longer to generate, and are handled by the <strong>sv_custom_html</strong> view.</li>
</ul>
<p>The sample report was generated by issuing:</p>
<blockquote>
<pre>SELECT html FROM sv_custom_html_brief;</pre>
</blockquote>
<p>I won&#8217;t go into details here as for how this view generates the HTML code. There is a myriad of view dependencies, with many interesting tricks on the way. But do remember it&#8217;s <em>just a view</em>. You don&#8217;t need an application (not even <em>mycheckpoint</em> itself) to generate the report. All it takes is a query.</p>
<h4>Processlist dump</h4>
<p>When an alert notification fires (an email is prepared to inform on some alert condition), a processlist dump summary is taken and included in email report. It may be useful to understand why the slave is lagging, or exactly why there are so many active threads.</p>
<p>The dump summary presents the processlist much as you would see it on SHOW PROCESSLIST, but only lists the active threads, noting down how many sleeping processes there are (PS, thread &amp; process are the same in the terminology of MySQL connections). An example dump looks like this:</p>
<blockquote>
<pre>PROCESSLIST summary:

     Id: 3
   User: system user
   Host:
     db: NULL
Command: Connect
   Time: 3168098
  State: Waiting for master to send event
   Info: NULL
-------

     Id: 4
   User: system user
   Host:
     db: prod_db
Command: Connect
   Time: 612
  State: Updating
   Info: UPDATE user SET is_offline = 1 WHERE id IN (50440010,50440011)
-------

     Id: 8916579
   User: prod_user
   Host: localhost
     db: prod_db
Command: Query
   Time: 1
  State: Sending data
   Info: INSERT IGNORE INTO archive.stat_archive (id, origin, path, ts, content
-------

     Id: 8916629
   User: mycheckpoint
   Host: localhost
     db: NULL
Command: Query
   Time: 0
  State: NULL
   Info: SHOW PROCESSLIST
-------
Sleeping: 3 processes
</pre>
</blockquote>
<h4>Future plans</h4>
<p>Work is going on. These are the non-scheduled future tasks I see:</p>
<ul>
<li>Monitoring InnoDB Plugin &amp; XtraDB status.</li>
<li>Interactive charts. See my <a href="http://code.openark.org/blog/mysql/static-charts-vs-interactive-charts">earlier post</a>.</li>
<li>Monitoring for swap activity (Linux only).</li>
<li>Enhanced custom queries handling, including auto-deploy upon change of custom queries.</li>
<li>A proper <em>man</em> page.</li>
<li>Anything else that interests me.</li>
</ul>
<h4>Try it out</h4>
<p>Try out <em>mycheckpoint</em>. It’s a different kind of monitoring solution. You will need basic SQL skills, and in return you&#8217;ll get a lot of power under your hands.</p>
<ul>
<li>Download mycheckpoint <a href="https://code.google.com/p/mycheckpoint/">here</a></li>
<li>Visit the project’s <a href="../../forge/mycheckpoint">homepage</a></li>
<li>Browse the <a href="../../forge/mycheckpoint/documentation">documentation</a></li>
<li>Report <a href="https://code.google.com/p/mycheckpoint/issues/list">bugs</a></li>
</ul>
<p><em>mycheckpoint</em> is released under the <a href="http://www.opensource.org/licenses/bsd-license.php">New BSD License</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/mycheckpoint-rev-132-custom-monitoring-custom-charts-process-list-dump/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>EXPLAIN: missing db info</title>
		<link>http://code.openark.org/blog/mysql/explain-missing-db-info</link>
		<comments>http://code.openark.org/blog/mysql/explain-missing-db-info#comments</comments>
		<pubDate>Tue, 11 May 2010 04:57:02 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Analysis]]></category>
		<category><![CDATA[Execution plan]]></category>
		<category><![CDATA[logs]]></category>
		<category><![CDATA[openark kit]]></category>
		<category><![CDATA[scripts]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=2368</guid>
		<description><![CDATA[I&#8217;m further developing a general log hook, which can stream queries from the general log. A particular direction I&#8217;m taking is to filter queries by their type of actions. For example, the tool (oak-hook-general-log) can be instructed to only stream out those queries which involve creation of a temporary table; or those which cause for [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m further developing a general log hook, which can stream queries from the general log.</p>
<p>A particular direction I&#8217;m taking is to filter queries by their type of actions. For example, the tool (<a href="http://code.google.com/p/openarkkit/source/browse/trunk/openarkkit/src/oak/oak-hook-general-log.py">oak-hook-general-log</a>) can be instructed to only stream out those queries which involve creation of a temporary table; or those which cause for a filesort, or full index scan, etc.</p>
<p>This is done by evaluating of query execution plans on the fly. I suspect the <a href="http://www.mysql.com/why-mysql/white-papers/mysql_wp_queryanalyzer.php">MySQL query analyzer</a> roughly does the same (as a small part of what it does).</p>
<p>It&#8217;s almost nothing one cannot do with sed/awk. However, I bumped into a couple of problems:</p>
<ol>
<li>The general log (and the <strong>mysql.general_log table</strong>, in  particular) does not indicate the particular database one is using for the query. Since slow log does indicate this data, I <a href="http://bugs.mysql.com/bug.php?id=52554">filed a bug</a> on this. I currently solve this by crossing connection id with the process list, where the current database is listed. It&#8217;s shaky, but mostly works.</li>
<li>Just realized: there&#8217;s no DB info in the <strong>EXPLAIN</strong> output! It&#8217;s weird, since I&#8217;ve been EXPLAINing queries for years now. But I&#8217;ve always had the advantage of <em>knowing</em> the schema used: either because I was manually executing the query on a known schema, or <a href="http://www.maatkit.org/doc/mk-query-digest.html">mk-query-digest</a> was kind enough to let me know.</li>
</ol>
<p><span id="more-2368"></span>For example, look at the following imaginary query, involving both the <strong>world</strong> and <strong>sakila</strong> databases:</p>
<blockquote>
<pre>mysql&gt; use test;
Database changed
mysql&gt; EXPLAIN SELECT * FROM world.Country JOIN sakila.city WHERE Country.Capital = city.city_id;
+----+-------------+---------+--------+---------------+---------+---------+-----------------------+------+-------------+
| id | select_type | table   | type   | possible_keys | key     | key_len | ref                   | rows | Extra       |
+----+-------------+---------+--------+---------------+---------+---------+-----------------------+------+-------------+
|  1 | SIMPLE      | Country | ALL    | NULL          | NULL    | NULL    | NULL                  |  239 |             |
|  1 | SIMPLE      | city    | eq_ref | PRIMARY       | PRIMARY | 2       | world.Country.Capital |    1 | Using where |
+----+-------------+---------+--------+---------------+---------+---------+-----------------------+------+-------------+
2 rows in set (0.00 sec)
</pre>
</blockquote>
<p>The query is imaginary, since the tables don&#8217;t actually have anything in common. But look at the <strong>EXPLAIN</strong> result: can you tell where <strong>city</strong> came from? <strong>Country</strong> can somehow be parsed from the <strong>ref</strong> column, but no help on <strong>city</strong>.</p>
<p>Moreover, table aliases show on the <strong>EXPLAIN</strong> plan (which is good), but with no reference to the original table.</p>
<p>So, is it back to parsing of the SQL query? I&#8217;m <span style="text-decoration: line-through;">lazy</span> reluctant to do that. It&#8217;s error prone, and one needs to implement, or use, a good parser, which also accepts MySQL dialect. Haven&#8217;t looked into this yet.</p>
<p>I&#8217;m currently at a standstill with regard to automated query execution plan evaluation where database cannot be determined.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/explain-missing-db-info/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>oak-hook-general-log: streaming general log</title>
		<link>http://code.openark.org/blog/mysql/oak-hook-general-log-streaming-general-log</link>
		<comments>http://code.openark.org/blog/mysql/oak-hook-general-log-streaming-general-log#comments</comments>
		<pubDate>Sun, 21 Mar 2010 08:45:58 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[logs]]></category>
		<category><![CDATA[openark kit]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[scripts]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=2253</guid>
		<description><![CDATA[I&#8217;m seeking input on a new openark kit utility I&#8217;ve started to implement. The tool, oak-hook-general-log, will hook up to a MySQL (&#62;= 5.1) server, and stream the general log into standard output. It looks like this: bash$ python src/oak/oak-hook-general-log.py --socket=/tmp/mysql.sock --user=root 2010-03-21 10:18:42     root[root] @ localhost []       79      1       Query   SELECT COUNT(*) FROM City [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m seeking input on a new <a href="http://code.openark.org/forge/openark-kit">openark kit</a> utility I&#8217;ve started to implement.</p>
<p>The tool, <strong>oak-hook-general-log</strong>, will hook up to a MySQL (&gt;= 5.1) server, and stream the general log into standard output. It looks like this:</p>
<blockquote>
<pre>bash$ python src/oak/oak-hook-general-log.py --socket=/tmp/mysql.sock --user=root
2010-03-21 10:18:42     root[root] @ localhost []       79      1       Query   SELECT COUNT(*) FROM City
2010-03-21 10:18:48     root[root] @ localhost []       79      1       Query   DELETE FROM City WHERE id=1000
2010-03-21 10:18:54     root[root] @ localhost []       79      1       Query   SHOW PROCESSLIST
2010-03-21 10:19:06     root[root] @ localhost []       79      1       Quit
2010-03-21 10:19:07     root[root] @ localhost []       93      1       Connect root@localhost on
2010-03-21 10:19:07     root[root] @ localhost []       93      1       Query   select @@version_comment limit 1
2010-03-21 10:22:33     root[root] @ localhost []       93      1       Query   SELECT City.Name, Country.Name FROM Country JOIN City ON Country.Capit
2010-03-21 10:22:58     root[root] @ localhost []       93      1       Quit
</pre>
</blockquote>
<p>Since output is written to <strong>stdout</strong>, one can further:</p>
<blockquote>
<pre>bash$ python src/oak/oak-hook-general-log.py --socket=/tmp/mysql.sock --user=root | grep Connect
bash$ python src/oak/oak-hook-general-log.py --socket=/tmp/mysql.sock --user=root | grep webuser@webhost</pre>
</blockquote>
<p>What the tool does is to enable table logs, and periodically rotate the <strong>mysql.general_log</strong> table, read and dump its content.</p>
<p><span id="more-2253"></span>The tool:</p>
<ul>
<li>Stores and restores the original log state (general log enabled/disabled, log output).</li>
<li>Disables printing of its own queries to the general log.</li>
<li>Automatically times out (timeout configurable) so as not to enter a situation where the general log is forgotten to be turned on.</li>
<li>Can discard pre-existing data on the <strong>mysql.general_log</strong> table.</li>
<li>Will cleanup the <strong>mysql.slow_log</strong> table, if it wasn&#8217;t originally used (turning on table logs applies to both general log and slow log).</li>
</ul>
<p>What would you have the tool do further? Should it provide filtering, or should we just use <strong>grep</strong>/<strong>sed</strong>/<strong>awk</strong> for that? Any internal aggregation of data?</p>
<p>I would love to hear your thoughts. Meanwhile, <a href="http://code.google.com/p/openarkkit/source/browse/trunk/openarkkit/src/oak/oak-hook-general-log.py">view or grab the python script file</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/oak-hook-general-log-streaming-general-log/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>mk-schema-change? Check out ideas from oak-online-alter-table</title>
		<link>http://code.openark.org/blog/mysql/mk-schema-change-check-out-ideas-from-oak-online-alter-table</link>
		<comments>http://code.openark.org/blog/mysql/mk-schema-change-check-out-ideas-from-oak-online-alter-table#comments</comments>
		<pubDate>Wed, 10 Mar 2010 18:28:29 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[openark kit]]></category>
		<category><![CDATA[Schema]]></category>
		<category><![CDATA[scripts]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=2144</guid>
		<description><![CDATA[In response to Mark Callaghan&#8217;s post mk-schema-change. I apologize for not commenting on the post itself, I do not hold a Facebook account. Anyway this is a long write, so it may as well deserve a post of its own. Some of the work Mark is describing already exists under openark kit&#8216;s oak-online-alter-table. Allow me [...]]]></description>
			<content:encoded><![CDATA[<p>In response to Mark Callaghan&#8217;s post <a href="http://www.facebook.com/note.php?note_id=356997370932">mk-schema-change</a>.</p>
<p>I apologize for not commenting on the post itself, I do not hold a Facebook account. Anyway this is a long write, so it may as well deserve a post of its own.</p>
<p>Some of the work Mark is describing already exists under <a href="http://code.openark.org/forge/openark-kit">openark kit</a>&#8216;s <a href="http://code.openark.org/forge/openark-kit/oak-online-alter-table">oak-online-alter-table</a>. Allow me to explain what I have gained there, and how the issue can be further pursued. There is relevance to Mark&#8217;s suggestion.</p>
<p><em>oak-online-alter-table</em> uses a combination of locks, chunks and triggers to achieve an almost non-blocking <strong>ALTER TABLE</strong> effect. I had a very short opportunity to speak with Mark on last year&#8217;s conference, in between bites. Mark stated that anything involving triggers was irrelevant in his case.</p>
<p>The triggers are a pain, but I believe a few other insights from <em>oak-online-alter-table</em> can be of interest.<span id="more-2144"></span></p>
<h4>The first attempt</h4>
<p>My first attempt with the script assumed:</p>
<ul>
<li>Table has an <strong>AUTO_INCREMENT PRIMARY KEY</strong> column</li>
<li>New rows always gain ascending <strong>PRIMARY KEY</strong> values</li>
<li><strong>PRIMARY KEY</strong> never changes for an existing row</li>
<li><strong>PRIMARY KEY</strong> values are never reused</li>
<li>Rows may be deleted at will</li>
<li>No triggers exist on the table</li>
<li>No <strong>FOREIGN KEY</strong>s exist on the table.</li>
</ul>
<p>So the idea was: when one wants to do an <strong>ALTER TABLE</strong>:</p>
<ol>
<li>Create a <em>ghost</em> table with the new structure.</li>
<li>Read the minimum and maximum PK values.</li>
<li>Create <strong>AFTER INSERT</strong>, <strong>AFTER UPDATE</strong>, <strong>AFTER DELETE</strong> triggers on the original table. These triggers will propagate the changes onto the <em>ghost</em> table.</li>
<li>Working out slowly, and in small chunks, copy rows within recorded min-max values range into the <em>ghost</em> table. The interesting part is where the script makes sure there&#8217;s no contradiction between these actions and those of the triggers, (whichever came first!). This is largely solved using <strong>INSERT IGNORE</strong> and <strong>REPLACE INTO</strong> in the proper context.</li>
<li>Working out slowly and in chunks again, we <em>remove</em> rows from the <em>ghost</em> table, which are no longer existent in the original table.</li>
<li>Once all chunking is complete, <strong>RENAME</strong> original table to *_old, and <em>ghost</em> table in place of the original table.</li>
</ol>
<p>Steps <strong>4</strong> &amp; <strong>5</strong> are similar in concept to transactional recovery through <em>redo logs</em> and <em>undo logs</em>.</p>
<h4>The next attempt</h4>
<p>Next phase removed the <strong>AUTO_INCREMENT</strong> requirement, as well as the &#8220;no reuse of PK&#8221;. In fact, the only remaining constraints were:</p>
<ul>
<li>There is some <strong>UNIQUE KEY</strong> on the table which is unaffected by the <strong>ALTER</strong> operation</li>
<li>No triggers exist on the table</li>
<li>No <strong>FOREIGN KEY</strong>s exist on the table.</li>
</ul>
<p>The steps are in general very similar to those listed previously, only now a more elaborate chunking method is used with possible non-integer, possible multi-column chunking algorithm. Also, the triggers take care of changes in <strong>UNIQUE KEY</strong> values themselves.</p>
<h4>mk-schema-change?</h4>
<p>Have a look at the <a href="http://code.google.com/p/openarkkit/w/list">wiki pages</a> for OnlineAlterTable*. There is some discussion on concurrency issues; on transactional behavior, which explains why <em>oak-online-alter-table</em> performs correctly. Some of these are very relvant, I believe, to Mark&#8217;s suggestion. In particular, making the chunks copy; retaining transactional integrity, etc.</p>
<p>To remove any doubt, <em>oak-online-alter-table</em> is<em> </em> <strong>not production ready</strong> or anywhere near. Use at your own risk. I&#8217;ve seen it work, and I&#8217;ve seen it crash. I got little feedback and thus little chance to fix things. I also didn&#8217;t touch the code for quite a few months now, so I&#8217;m a little rusty myself.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/mk-schema-change-check-out-ideas-from-oak-online-alter-table/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>mycheckpoint rev. 76: OS monitoring, auto deploy, brief HTML and 24/7 reports</title>
		<link>http://code.openark.org/blog/mysql/mycheckpoint-rev-76-os-monitoring-auto-deploy-brief-html-and-247-reports</link>
		<comments>http://code.openark.org/blog/mysql/mycheckpoint-rev-76-os-monitoring-auto-deploy-brief-html-and-247-reports#comments</comments>
		<pubDate>Tue, 05 Jan 2010 08:55:14 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Graphs]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Monitoring]]></category>
		<category><![CDATA[mycheckpoint]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[scripts]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=1784</guid>
		<description><![CDATA[Revision 76 of mycheckpoint comes with quite a few improvements, including: OS monitoring (CPU, load average, memory) Auto-deploy Improved charting Brief HTML reports 24/7 charts OS Monitoring When monitoring the local machine, mycheckpoint now monitors CPU utilization, load average, memory and swap space. This only applies to the Linux operating system; there is currently no [...]]]></description>
			<content:encoded><![CDATA[<p>Revision <strong>76</strong> of <a href="http://code.openark.org/forge/mycheckpoint">mycheckpoint</a> comes with quite a few improvements, including:</p>
<ul>
<li>OS monitoring (CPU, load average, memory)</li>
<li>Auto-deploy</li>
<li>Improved charting</li>
<li>Brief HTML reports</li>
<li>24/7 charts</li>
</ul>
<h4>OS Monitoring</h4>
<p>When monitoring the local machine, <em>mycheckpoint</em> now monitors CPU utilization, load average, memory and swap space.</p>
<p>This only applies to the Linux operating system; there is currently no plan to work this out for other operating systems.</p>
<p>Examples:</p>
<blockquote>
<pre>mysql&gt; SELECT <strong>os_cpu_utilization_percent</strong> FROM sv_report_chart_sample;

<img class="size-full wp-image-1794 alignnone" title="mycheckpoint-chart-cpu-sample" src="http://code.openark.org/blog/wp-content/uploads/2009/12/mycheckpoint-chart-cpu-sample.png" alt="mycheckpoint-chart-cpu-sample" width="400" height="200" /></pre>
</blockquote>
<blockquote>
<pre>mysql&gt; SELECT ts, <strong>os_loadavg</strong> FROM mycheckpoint.sv_report_sample;
+---------------------+------------+
| 2009-12-27 11:45:01 |       1.78 |
| 2009-12-27 11:50:01 |       2.48 |
| 2009-12-27 11:55:01 |       2.35 |
...
+---------------------+------------+</pre>
</blockquote>
<blockquote>
<pre>mysql&gt; SELECT report FROM mycheckpoint.sv_report_human_sample ORDER BY id DESC LIMIT 1 \G
*************************** 1. row ***************************
report:
Report period: 2009-12-27 13:20:01 to 2009-12-27 13:25:01. Period is 5 minutes (0.08 hours)
Uptime: 100.0% (Up: 334 days, 06:37:28 hours)

<strong>OS:
 Load average: 1.67
 CPU utilization: 25.2%
 Memory: 7486.4MB used out of 7985.6484MB (Active: 6685.8906MB)
 Swap: 3835.2MB used out of 8189.3750MB</strong>
...</pre>
</blockquote>
<h4>Auto-deploy</h4>
<p><em>mycheckpoint</em> now has a version recognition mechanism. There is no need to call <em>mycheckpoint</em> with the &#8220;<strong>deploy</strong>&#8221; argument on first install or after upgrade. <em>mycheckpoint</em> will recognize a change of version and will auto-deploy before moving on to monitoring your system.</p>
<p><span id="more-1784"></span>It is still possible, though, to use &#8220;<strong>deploy</strong>&#8220;, in case you just want to make sure an upgrade takes place, without issuing a monitoring action.</p>
<h4>Improved charting</h4>
<p>Further improvements and bug fixes made to the Google charts, including the implementation of missing values charting.</p>
<h4>Brief HTML report</h4>
<p>In contrast with the full blown HTML report (see <a href="http://code.openark.org/forge/wp-content/uploads/2009/12/mycheckpoint_report-72.html">sample</a>), which presents hourly/daily/weekly reports for the many metrics, the new brief report only presents with a few hourly based charts. These include InnoDB performance, DML, OS metrics, and replication status.</p>
<p>To get a brief HTML report, issue:</p>
<blockquote>
<pre>mysql&gt; SELECT html FROM sv_report_html_brief;

<a href="http://code.openark.org/forge/wp-content/uploads/2009/12/mycheckpoint-brief-report.html"><img class="alignnone size-full wp-image-1839" title="mycehckpoint-report-html-brief-screenshot-small" src="http://code.openark.org/blog/wp-content/uploads/2010/01/mycehckpoint-report-html-brief-screenshot-small2.png" alt="" width="611" height="409" /></a>
</pre>
</blockquote>
<p>See <a href="http://code.openark.org/forge/wp-content/uploads/2009/12/mycheckpoint-brief-report.html">sample brief HTML report</a>.</p>
<h4>24/7 charts</h4>
<p>24/7 charts present the various metrics on a 24&#215;7 matrix, which allows for diagnostics of usage throughout the day and week. For example, it makes it easier to see how things slow down on Saturday/Sunday; how load increases on 10:00am every day, etc.</p>
<p>24/7 charts are provided by the <strong>sv_report_chart_24_7</strong> view.</p>
<blockquote>
<pre>DESC sv_report_chart_24_7;
+---------------------------------------+----------+------+-----+---------+-------+
| Field                                 | Type     | Null | Key | Default | Extra |
+---------------------------------------+----------+------+-----+---------+-------+
| innodb_read_hit_percent               | longblob | YES  |     | NULL    |       |
| innodb_buffer_pool_reads_psec         | longblob | YES  |     | NULL    |       |
| innodb_buffer_pool_pages_flushed_psec | longblob | YES  |     | NULL    |       |
| innodb_os_log_written_psec            | longblob | YES  |     | NULL    |       |
| innodb_row_lock_waits_psec            | longblob | YES  |     | NULL    |       |
| mega_bytes_sent_psec                  | longblob | YES  |     | NULL    |       |
| mega_bytes_received_psec              | longblob | YES  |     | NULL    |       |
| key_read_hit_percent                  | longblob | YES  |     | NULL    |       |
| key_write_hit_percent                 | longblob | YES  |     | NULL    |       |
| com_select_psec                       | longblob | YES  |     | NULL    |       |
| com_insert_psec                       | longblob | YES  |     | NULL    |       |
| com_delete_psec                       | longblob | YES  |     | NULL    |       |
| com_update_psec                       | longblob | YES  |     | NULL    |       |
| com_replace_psec                      | longblob | YES  |     | NULL    |       |
| com_set_option_percent                | longblob | YES  |     | NULL    |       |
| com_commit_percent                    | longblob | YES  |     | NULL    |       |
| slow_queries_percent                  | longblob | YES  |     | NULL    |       |
| select_scan_psec                      | longblob | YES  |     | NULL    |       |
| select_full_join_psec                 | longblob | YES  |     | NULL    |       |
| select_range_psec                     | longblob | YES  |     | NULL    |       |
| table_locks_waited_psec               | longblob | YES  |     | NULL    |       |
| opened_tables_psec                    | longblob | YES  |     | NULL    |       |
| created_tmp_tables_psec               | longblob | YES  |     | NULL    |       |
| created_tmp_disk_tables_psec          | longblob | YES  |     | NULL    |       |
| connections_psec                      | longblob | YES  |     | NULL    |       |
| aborted_connects_psec                 | longblob | YES  |     | NULL    |       |
| threads_created_psec                  | longblob | YES  |     | NULL    |       |
| seconds_behind_master                 | longblob | YES  |     | NULL    |       |
| os_loadavg                            | longblob | YES  |     | NULL    |       |
| os_cpu_utilization_percent            | longblob | YES  |     | NULL    |       |
| os_mem_used_mb                        | longblob | YES  |     | NULL    |       |
| os_mem_active_mb                      | longblob | YES  |     | NULL    |       |
| os_swap_used_mb                       | longblob | YES  |     | NULL    |       |
+---------------------------------------+----------+------+-----+---------+-------</pre>
</blockquote>
<p>Example:</p>
<blockquote>
<pre>mysql&gt; SELECT com_select_psec, innodb_buffer_pool_pages_flushed_psec FROM mycheckpoint.<strong>sv_report_chart_24_7</strong> \G
<img class="alignnone size-full wp-image-1798" title="mycheckpoint-chart-247-sample" src="http://code.openark.org/blog/wp-content/uploads/2009/12/mycheckpoint-chart-247-sample1.png" alt="mycheckpoint-chart-247-sample" width="400" height="200" />
<img class="alignnone size-full wp-image-1830" title="mycheckpoint-24-7-chart-sample2" src="http://code.openark.org/blog/wp-content/uploads/2010/01/mycheckpoint-24-7-chart-sample2.png" alt="" width="400" height="200" />
</pre>
</blockquote>
<h4>Trying mycheckpoint</h4>
<ul>
<li>Get <em>mycheckpoint</em> from the <a href="https://code.google.com/p/mycheckpoint/">mycheckpoint Google Code project page</a>.</li>
<li>Read the <a href="http://code.openark.org/forge/mycheckpoint/documentation">documentation</a>.</li>
<li>Report <a href="https://code.google.com/p/mycheckpoint/issues/list">issues</a>!</li>
</ul>
<h4>Future plans</h4>
<p>I haven&#8217;t got any major immediate issues; planning on user customization of charts and HTML reports. Considering thresholds and alerting for the future.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/mycheckpoint-rev-76-os-monitoring-auto-deploy-brief-html-and-247-reports/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>On restoring a single table from mysqldump</title>
		<link>http://code.openark.org/blog/mysql/on-restoring-a-single-table-from-mysqldump</link>
		<comments>http://code.openark.org/blog/mysql/on-restoring-a-single-table-from-mysqldump#comments</comments>
		<pubDate>Tue, 01 Dec 2009 08:25:00 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Backup]]></category>
		<category><![CDATA[Books]]></category>
		<category><![CDATA[mysqldump]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[scripts]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=1630</guid>
		<description><![CDATA[Following Restore one table from an ALL database dump and Restore a Single Table From mysqldump, I would like to add my own thoughts and comments on the subject. I also wish to note performance issues with the two suggested solutions, and offer improvements. Problem relevance While the problem is interesting, I just want to [...]]]></description>
			<content:encoded><![CDATA[<p>Following <a href="http://everythingmysql.ning.com/profiles/blogs/restore-one-table-from-an-all">Restore one table from an ALL database dump</a> and <a href="http://gtowey.blogspot.com/2009/11/restore-single-table-from-mysqldump.html">Restore a Single Table From mysqldump</a>, I would like to add my own thoughts and comments on the subject.</p>
<p>I also wish to note performance issues with the two suggested solutions, and offer improvements.</p>
<h4>Problem relevance</h4>
<p>While the problem is interesting, I just want to note that it is relevant in very specific database dimensions. Too small &#8211; and it doesn&#8217;t matter how you solve it (e.g. just open vi/emacs and copy+paste). Too big &#8211; and it would not be worthwhile to restore from <em>mysqldump</em> anyway. I would suggest that the problem is interesting in the whereabouts of a few dozen GB worth of data.</p>
<h4>Problem recap</h4>
<p>Given a dump file (generated by mysqldump), how do you restore a single table, without making any changes to other tables?</p>
<p>Let&#8217;s review the two referenced solutions. I&#8217;ll be using the <a href="http://dev.mysql.com/doc/employee/en/employee.html">employees db</a> on <a href="https://launchpad.net/mysql-sandbox">mysql-sandbox</a> for testing. I&#8217;ll choose a very small table to restore: <strong>departments</strong> (only a few rows in this table).</p>
<h4>Security based solution</h4>
<p><a href="http://everythingmysql.ning.com/profiles/blogs/restore-one-table-from-an-all"><strong>Chris</strong></a> offers to create a special purpose account, which will only have write (CREATE, INSERT, etc.) privileges on the particular table to restore. Cool hack! But, I&#8217;m afraid, not too efficient, for two reasons:<span id="more-1630"></span></p>
<ol>
<li>MySQL needs to process all irrelevant queries (ALTER, INSERT, &#8230;) only to disallow them due to access violation errors.</li>
<li>Assuming restore is from remote host, we overload the network with all said irrelevant queries.</li>
</ol>
<p>Just how inefficient? Let&#8217;s time it:</p>
<blockquote>
<pre>mysql&gt; grant usage on *.* to 'restoreuser'@'localhost';
mysql&gt; grant select on *.* to 'restoreuser'@'localhost';
mysql&gt; grant all on employees.departments to 'restoreuser'@'localhost';

$ time mysql --user=restoreuser --socket=/tmp/mysql_sandbox21701.sock --force employees &lt; /tmp/employees.sql
...
ERROR 1142 (42000) at line 343: INSERT command denied to user 'restoreuser'@'localhost' for table 'titles'
ERROR 1142 (42000) at line 344: ALTER command denied to user 'restoreuser'@'localhost' for table 'titles'
...
(lot's of these messages)
...

real    <strong>0m31.945s</strong>
user    0m6.328s
sys     0m0.508s</pre>
</blockquote>
<p>So, at about <strong>30</strong> seconds to restore a 9 rows table.</p>
<h4>Text filtering based solution.</h4>
<p><a href="http://gtowey.blogspot.com/2009/11/restore-single-table-from-mysqldump.html"><strong>gtowey</strong></a> offers parsing the dump file beforehand:</p>
<ul>
<li>First, parse with <em>grep</em>, to detect rows where tables are referenced within dump file</li>
<li>Second, parse with <em>sed</em>, extracting relevant rows.</li>
</ul>
<p>Let&#8217;s time this one:</p>
<blockquote>
<pre>$ time grep -n 'Table structure' /tmp/employees.sql
23:-- Table structure for table `departments`
48:-- Table structure for table `dept_emp`
89:-- Table structure for table `dept_manager`
117:-- Table structure for table `employees`
161:-- Table structure for table `salaries`
301:-- Table structure for table `titles`

real    <strong>0m0.397s</strong>
user    0m0.232s
sys     0m0.164s

$ time sed -n 23,48p /tmp/employees.sql | ./use employees

real    <strong>0m0.562s</strong>
user    0m0.380s
sys     0m0.176s</pre>
</blockquote>
<p>Much faster: about <strong>1</strong> second, compared to <strong>30</strong> seconds from above.</p>
<p>Nevertheless, I find two issues here:</p>
<ol>
<li>A correctness problem: this solution somewhat assumes that there&#8217;s only a single table with desired name. I say &#8220;somewhat&#8221; since it leaves this for the user.</li>
<li>An efficiency problem: it reads the dump file <em>twice</em>. First parsing it with <em>grep</em>, then with <em>sed</em>.</li>
</ol>
<h4>A third solution</h4>
<p><em>sed</em> is much stronger than presented. In fact, the inquiry made by <em>grep</em> in gtowey&#8217;s solution can be easily handled by <em>sed</em>:</p>
<blockquote>
<pre>$ time sed -n "/^-- Table structure for table \`departments\`/,/^-- Table structure for table/p" /tmp/employees.sql | ./use employees

real    <strong>0m0.573s</strong>
user    0m0.416s
sys     0m0.152s</pre>
</blockquote>
<p>So, the <strong>&#8220;/^&#8211; Table structure for table \`departments\`/,/^&#8211; Table structure for table/p&#8221;</strong> part tells <em>sed</em> to only print those rows starting from the <strong>departments</strong> table structure, and ending in the next table structure (this is for clarity: had department been the last table, there would not be a next table, but we could nevertheless solve this using other anchors).</p>
<p>And, we only do it in <strong>0.57</strong> seconds: about half the time of previous attempt.</p>
<p>Now, just to be more correct, we only wish to consider the <strong>employees.department</strong> table. So, <em>assuming</em> there&#8217;s more than one database dumped (and, by consequence, <strong>USE</strong> statements in the dump-file), we use:</p>
<blockquote>
<pre>cat /tmp/employees.sql | sed -n "/^USE \`employees\`/,/^USE \`/p" | sed -n "/^-- Table structure for table \`departments\`/,/^-- Table structure for table/p" | ./use employees</pre>
</blockquote>
<h4>Further notes</h4>
<ul>
<li>All tests used warmed-up caches.</li>
<li>The sharp eyed readers would notice that <strong>departments</strong> is the first table in the dump file. Would that give an unfair advantage to the parsing-based restore methods? The answer is no. I&#8217;ve created an <strong>xdepartments</strong> table, to be located at the end of the dump. The difference in time is neglectful and inconclusive; we&#8217;re still at ~0.58-0.59 seconds. The effect will be more visible on really large dumps; but then, so would the security-based effects.</li>
</ul>
<p>[<strong>UPDATE</strong>: see also following similar post: <a href="http://blog.tsheets.com/2008/tips-tricks/extract-a-single-table-from-a-mysqldump-file.html">Extract a Single Table from a mysqldump File</a>]</p>
<h4>Conclusion</h4>
<p><a href="http://www.amazon.com/Classic-Shell-Scripting-Arnold-Robbins/dp/0596005954/ref=sr_1_1"><img class="alignright" title="classic-shell-scripting" src="http://code.openark.org/blog/wp-content/uploads/2009/12/classic-shell-scripting.png" alt="classic-shell-scripting" width="144" height="189" /></a>Its is always best to test on large datasets, to get a feel on performance.</p>
<p>It&#8217;s best to save MySQL the trouble of parsing &amp; ignoring statements. Scripting utilities like <em>sed</em>, <em>awk</em> &amp; <em>grep</em> have been around for ages, and are well optimized. They excel at text processing.</p>
<p>I&#8217;ve used <em>sed</em> many times in transforming dump outputs; for example, in converting MyISAM to InnoDB tables; to convert Antelope InnoDB tables to Barracuda format, etc. grep &amp; awk are also very useful.</p>
<p>May I recommend, at this point, reading <a href="http://www.amazon.com/Classic-Shell-Scripting-Arnold-Robbins/dp/0596005954/ref=sr_1_1">Classic Shell Scripting</a>, a very easy to follow book, which lists the most popular command line utilities like <em>grep</em>, <em>sed</em>, <em>awk</em>, <em>sort</em>, (countless more) and shell scripting in general. While most of these utilities are well known, the book excels in providing suprisingly practical, simple solution to common tasks.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/on-restoring-a-single-table-from-mysqldump/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
