<?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"
	>

<channel>
	<title>Proven Scaling Blog</title>
	<atom:link href="http://provenscaling.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://provenscaling.com/blog</link>
	<description>High performance MySQL consulting</description>
	<pubDate>Tue, 21 Oct 2008 22:35:06 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
	<language>en</language>
			<item>
		<title>MySQL Enterprise 5.0.70 released</title>
		<link>http://provenscaling.com/blog/2008/10/21/mysql-enterprise-5070-released/</link>
		<comments>http://provenscaling.com/blog/2008/10/21/mysql-enterprise-5070-released/#comments</comments>
		<pubDate>Tue, 21 Oct 2008 22:35:06 +0000</pubDate>
		<dc:creator>Mike Griffiths</dc:creator>
		
		<category><![CDATA[Announcements]]></category>

		<category><![CDATA[Enterprise]]></category>

		<category><![CDATA[Mirror]]></category>

		<guid isPermaLink="false">http://provenscaling.com/blog/?p=167</guid>
		<description><![CDATA[Sun has released MySQL Enterprise 5.0.70.  The source and binaries are now available from the Proven Scaling mirror.
This release is a MRU release and is recommended if you are being affected by bugs which are fixed in this release.  A number of server crashes have been addressed.  Details for changes in this [...]]]></description>
			<content:encoded><![CDATA[<p>Sun has released MySQL Enterprise 5.0.70.  The <a href="http://mirror.provenscaling.com/mysql/enterprise/source/5.0/mysql-5.0.70.tar.gz">source</a> and <a href="http://mirror.provenscaling.com/mysql/enterprise/binaries/5.0/5.0.70/">binaries</a> are now available from the <a href="http://mirror.provenscaling.com/">Proven Scaling mirror</a>.</p>
<p>This release is a MRU release and is recommended if you are being affected by bugs which are fixed in this release.  A number of server crashes have been addressed.  Details for changes in this release can be found in the <a href="http://dev.mysql.com/doc/refman/5.0/en/releasenotes-es-5-0-70.html">MySQL Enterprise 5.0.70 release notes</a>.</p>
<p>For more information about the different MySQL release version numbers, see our previous post on <a href="http://provenscaling.com/blog/2008/07/31/understanding-mysql-version-numbers/">version numbers</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://provenscaling.com/blog/2008/10/21/mysql-enterprise-5070-released/feed/</wfw:commentRss>
		</item>
		<item>
		<title>How mysqldump locks tables with different options</title>
		<link>http://provenscaling.com/blog/2008/10/19/how-mysqldump-locks-tables-with-different-options/</link>
		<comments>http://provenscaling.com/blog/2008/10/19/how-mysqldump-locks-tables-with-different-options/#comments</comments>
		<pubDate>Mon, 20 Oct 2008 05:18:34 +0000</pubDate>
		<dc:creator>Eric Bergen</dc:creator>
		
		<category><![CDATA[InnoDB]]></category>

		<category><![CDATA[Maatkit]]></category>

		<category><![CDATA[Replication]]></category>

		<category><![CDATA[mysqldump]]></category>

		<guid isPermaLink="false">http://provenscaling.com/blog/?p=124</guid>
		<description><![CDATA[The mysqldump program, which ships with MySQL, takes data from existing tables and turns it into SQL statements which can then be used to re-create the data later.  It has several different options which dictate its behavior for collecting data.  Some of the most important change its locking behaviour; depending on the options [...]]]></description>
			<content:encoded><![CDATA[<p>The <tt>mysqldump</tt> program, which ships with MySQL, takes data from existing tables and turns it into SQL statements which can then be used to re-create the data later.  It has several different options which dictate its behavior for collecting data.  Some of the most important change its locking behaviour; depending on the options passed to the <tt>mysqldump</tt> command, it may need to lock tables for the entire duration of the dumping process, briefly at the beginning, or not at all.</p>
<p>When using <tt>mysqldump</tt> for backups with a MySQL replication slave, the <tt>master-data</tt> option is often required in order to save the slave replication log file name and position in the backup.  By default, the <tt>master-data</tt> option will execute a <tt>FLUSH TABLES WITH READ LOCK</tt> command&mdash;which disallows writes to any table&mdash;and will keep the read lock for the entire duration of the dump to ensure that the replication position won&#8217;t change during the dump.  This can be problematic, because any clients trying to write to tables during the dump process are locked out.  With MyISAM, this is necessary, but with InnoDB it isn&#8217;t.</p>
<p>With a little help from InnoDB&#8217;s transaction and multi-versioning support, it&#8217;s possible to keep the read lock for a very short period of time&mdash;just long enough to quiesce the system and check the replication status.  InnoDB guarantees that a transaction will see a consistent view of the database after a transaction has started.  If all of the tables being dumped are InnoDB, using the <tt>single-transaction</tt> flag to <tt>mysqldump</tt> will instruct it to only keep a read lock long enough to gather the replication state and start a transaction.  After the transaction has been started, the read lock is released so that the dump and other clients can continue without locking each other out.</p>
<p>On the topic of consistency for a dump, there is an important distinction between the <tt>lock-all-tables</tt> and <tt>lock-tables</tt> options:  With the <tt>lock-all-tables</tt> option, <tt>mysqldump</tt> will use the same type of global read lock it uses when gathering the replication position.  This can be used to ensure a consistent dump when not using replication.  The <tt>lock-tables</tt> option, however, issues a <tt>LOCK TABLES</tt> query for each database it&#8217;s dumping.  If you choose multiple databases to dump, each database will be locked and unlocked in turn. This introduces a race condition: modifications can be made to database A while database B is locked and being dumped.  If you&#8217;re using InnoDB, <tt>single-transaction</tt> is a much better option.</p>
<p>Most people worry about the total time it takes to perform a backup, but the most important timing aspect of any backup is not the time it takes to create the backup, but the time it takes to restore it. Nonetheless, Maatkit includes <tt><a href="http://www.maatkit.org/doc/mk-parallel-dump.html">mk-parallel-dump</a></tt> and <tt><a href="http://www.maatkit.org/doc/mk-parallel-restore.html">mk-parallel-restore</a></tt> which offer a nice speed boost over the traditional MySQL tools. </p>
]]></content:encoded>
			<wfw:commentRss>http://provenscaling.com/blog/2008/10/19/how-mysqldump-locks-tables-with-different-options/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Introducing Flipper for managing MySQL master pairs</title>
		<link>http://provenscaling.com/blog/2008/10/09/introducing-flipper-for-managing-mysql-master-pairs/</link>
		<comments>http://provenscaling.com/blog/2008/10/09/introducing-flipper-for-managing-mysql-master-pairs/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 00:22:17 +0000</pubDate>
		<dc:creator>Mike Griffiths</dc:creator>
		
		<category><![CDATA[Announcements]]></category>

		<category><![CDATA[Availability]]></category>

		<category><![CDATA[Flipper]]></category>

		<category><![CDATA[Master-Master]]></category>

		<guid isPermaLink="false">http://provenscaling.com/blog/?p=117</guid>
		<description><![CDATA[At Proven Scaling, we&#8217;re great fans of using pairs of MySQL servers replicating to each other (commonly known as master-master replication or dual-master replication) as a way of ensuring high availability for MySQL databases.
Deploying servers in this way enables one half of the pair to be taken offline for maintenance work while the other half [...]]]></description>
			<content:encoded><![CDATA[<p>At Proven Scaling, we&#8217;re great fans of using pairs of MySQL servers replicating to each other (commonly known as master-master replication or dual-master replication) as a way of ensuring high availability for MySQL databases.</p>
<p>Deploying servers in this way enables one half of the pair to be taken offline for maintenance work while the other half carries on dealing with queries from clients &mdash; meaning that, for instance, lengthy <tt>ALTER TABLE</tt> operations can be done with no impact on service.  This strategy has been in use at many sites for years, and has been very successful at minimizing downtime.</p>
<p>The usual way of implementing this model is to have IP addresses floating between the two MySQL servers.  Rather than having the clients use the actual IP addresses or hostnames of the servers themselves, these &#8220;floating IPs&#8221; (or &#8220;virtual IPs&#8221;, &#8220;VIPs&#8221;, &#8220;IP aliases&#8221;) are used by clients to access MySQL based on a role (typically &#8220;writable&#8221; and &#8220;read-only&#8221;).  The floating IP addresses can be moved between the servers as required to ensure that each role is always available.</p>
<p>There are some tools already available to manage pairs of MySQL servers, most notably <a href="http://code.google.com/p/mysql-master-master/">mysql-master-master</a> (MMM) and the <a href="http://www.linux-ha.org/">High Availability Linux</a> project.  </p>
<p>Today, we&#8217;re announcing the release of Flipper, a tool for managing access to MySQL servers using master-master replication.</p>
<h3>Reinventing the wheel?</h3>
<p>Although the existing tools have worked well for some people in some situations, we (and our customers) have been frustrated by the number of situations where they&#8217;re not suitable.</p>
<p>Most of the existing tools are specific to Linux, and therefore no good to users of Solaris, FreeBSD and other operating systems.  Most are heavy-weight implementations, with monitoring daemons running all the time.  Configuration is rarely simple, sometimes because some of the available solutions try to be all things to all men, doing things that would be better handled elsewhere.</p>
<p>A lot of the effort that&#8217;s been put into other tools has been aimed at implementing <em>automatic</em> failover.  Sometimes this can be very useful (for instance in stateless applications, restartable services, etc.), but very often this is implemented with little consideration for the possible consequences in a stateful, database environment.</p>
<p>Bringing failed servers back into service prematurely (as often happens with hardware load-balancing solutions) can be disastrous, with bad data being returned to clients, or data received from clients and theoretically committed being lost.  Likewise, servers may be incorrectly diagnosed as having failed, causing a painful, lengthy, and potentially irreversible failover process to take place for what should have been a barely noticeable event.  In some cases, an automatic failover system may change its mind back and forth, causing repeated failover events (known as &#8220;flapping&#8221;).  All in all, we&#8217;re not convinced that completely automatic failover is always a good idea<sup>1</sup>.</p>
<h3>Automated, but manually triggered</h3>
<p>Flipper&#8217;s design comes from a very pragmatic perspective.  It&#8217;s a standalone tool that doesn&#8217;t require constantly running monitoring daemons &mdash; it evaluates the current situation at the moment that it&#8217;s executed, and does only what it&#8217;s told.  It doesn&#8217;t attempt to do anything fancy right now; it just manages moving IP addresses between MySQL nodes and reconfiguring a typical master-master setup, in a safe, controlled manner.  If one of the MySQL masters fails, it will allow you to move services away from the failed master, enabling you to fix the failure.</p>
<p>Flipper has been designed to be as portable as possible.  It&#8217;s capable of running on almost any UNIX-like operating system, as it&#8217;s written in Perl and uses DBD::mysql to communicate with MySQL servers.  Flipper itself doesn&#8217;t necessarily require any special privileges, user accounts, or daemons; it uses <tt>ssh</tt> and <tt>sudo</tt> to run system commands (and you&#8217;d typically want to set up SSH keys, and use <tt>ssh-agent</tt> to avoid typing your passphrase so many times).</p>
<p>We will add additional features in the future, but the system will always remain modular &mdash; you&#8217;ll be able to use whichever parts of it you want.</p>
<h3>Where can I find out more?</h3>
<p>We&#8217;ve set up a new (and currently rather minimal) micro-site for Flipper at <a href="http://provenscaling.com/software/flipper/">provenscaling.com/software/flipper</a> with <a href="http://provenscaling.com/software/flipper/docs/">documentation</a> and links to various resources.</p>
<p>We will also post <a href="http://provenscaling.com/blog/category/software/flipper/">on this blog</a> when there&#8217;s a new release, or some other important Flipper-related news.</p>
<p><sup>1</sup> Of course, we&#8217;d be delighted to hear from anyone who wants to try and convince us that any of the current MySQL automatic failover/HA strategies are error-proof, or anyone who&#8217;s got new ideas about how this can be achieved.</p>
]]></content:encoded>
			<wfw:commentRss>http://provenscaling.com/blog/2008/10/09/introducing-flipper-for-managing-mysql-master-pairs/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Making MySQL more usable: Stored Procedure call stack on error</title>
		<link>http://provenscaling.com/blog/2008/10/07/making-mysql-more-usable-stored-procedure-call-stack-on-error/</link>
		<comments>http://provenscaling.com/blog/2008/10/07/making-mysql-more-usable-stored-procedure-call-stack-on-error/#comments</comments>
		<pubDate>Tue, 07 Oct 2008 19:10:43 +0000</pubDate>
		<dc:creator>Jeremy Cole</dc:creator>
		
		<category><![CDATA[Patches]]></category>

		<category><![CDATA[Stored Procedures]]></category>

		<category><![CDATA[Usability]]></category>

		<guid isPermaLink="false">http://provenscaling.com/blog/?p=47</guid>
		<description><![CDATA[MySQL&#8217;s Stored Procedure implementation is far from perfect.  One of the major problems has been in debugging tools and information available while writing and using the procedures you&#8217;ve written.  In particular there is no real way to return customized error messages, e.g. RAISE or SIGNAL, and no way to find out what error [...]]]></description>
			<content:encoded><![CDATA[<p>MySQL&#8217;s Stored Procedure implementation is far from perfect.  One of the major problems has been in debugging tools and information available while writing and using the procedures you&#8217;ve written.  In particular there is <a href="http://bugs.mysql.com/bug.php?id=11661">no real way to return customized error messages</a>, e.g. <tt>RAISE</tt> or <tt>SIGNAL</tt>, and <a href="http://bugs.mysql.com/bug.php?id=11660">no way to find out what error actually occurred</a>, e.g. accessing <tt>SQLSTATE</tt>.  However, even with the standard error messages that MySQL already produces, there is another major problem: as a caller of the stored procedure, you can&#8217;t tell where the error actually came from.</p>
<p>In order to demonstrate this, let&#8217;s first create a few stored procedures that call each other in order to make things interesting:</p>
<blockquote><pre>
use test;

delimiter ;;
drop procedure if exists s_test;;
create procedure s_test ()
begin
  call s_test_foo();
end;;

drop procedure if exists s_test_foo;;
create procedure s_test_foo ()
begin
  call s_test_bar();
end;;

drop procedure if exists s_test_bar;;
create procedure s_test_bar ()
begin
  select 1 from blarbo;
end;;

delimiter ;
</pre>
</blockquote>
<p>Notice that the final stored procedure tries to select from a table that we haven&#8217;t mentioned yet; that&#8217;s because that table doesn&#8217;t exist.  This should generate an error for us reliably.  Here&#8217;s what happens when we call the stored procedure:</p>
<blockquote><pre>
call test.s_test();

ERROR 1146 (42S02): Table 'test.blarbo' doesn't exist
</pre>
</blockquote>
<p>Now that&#8217;s not very helpful: the user didn&#8217;t try to do anything with <tt>test.blarbo</tt> so he has no idea what has just happened!  Technically it would be much better if the <tt>s_test_bar</tt> procedure could have generated a custom error message&#8230; I&#8217;ll leave that for a future post.</p>
<p>In the past I&#8217;ve discussed a <a href="http://jcole.us/blog/archives/2006/10/01/on-triggers-stored-procedures-and-call-stacks/">patch to add a <tt>CALLER()</tt> function</a>, and this patch is a natural evolution of that code.  We&#8217;ve written a <a href="http://jcole.us/patches/mysql/5.0/draft/show_error_stack_trace.patch">proof of concept patch</a> to add a <tt>SHOW ERROR STACK TRACE</tt> command.  This works by saving the call stack, which is tracked using the code from the old <tt>CALLER()</tt> patch, whenever an error occurs.  Let&#8217;s try it out, after receiving any error from a SQL statement, you may run <tt>SHOW ERROR STACK TRACE</tt> as follows:</p>
<blockquote><pre>
SHOW ERROR STACK TRACE;

+-------+----------------------+
| Depth | Query                |
+-------+----------------------+
|     0 | select 1 from blarbo |
|     1 | call s_test_bar()    |
|     2 | call s_test_foo()    |
|     3 | call test.s_test()   |
+-------+----------------------+
4 rows in set (0.00 sec)
</pre>
</blockquote>
<p>That&#8217;s certainly more useful!  I&#8217;ve still got a few ideas on how to improve it even more:</p>
<ul>
<li>Add something like e.g. <tt>SHOW ERROR VARIABLES FOR 1</tt> which could return the contents of all local variables from a particular stack level from the stack trace.</li>
<li>Add something like e.g. <tt>SHOW ERROR CONTEXT FOR 1</tt> which could return the few lines of code before and after the error from a particular stack level from the stack trace.</li>
</ul>
<p>Essentially, it would be great if you could do most of what <tt>gdb</tt> is capable of when debugging C code.  I hope you like it!</p>
]]></content:encoded>
			<wfw:commentRss>http://provenscaling.com/blog/2008/10/07/making-mysql-more-usable-stored-procedure-call-stack-on-error/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Max allowed packet and connection pooling</title>
		<link>http://provenscaling.com/blog/2008/10/07/max-allowed-packet-and-connection-pooling/</link>
		<comments>http://provenscaling.com/blog/2008/10/07/max-allowed-packet-and-connection-pooling/#comments</comments>
		<pubDate>Tue, 07 Oct 2008 18:03:20 +0000</pubDate>
		<dc:creator>Eric Bergen</dc:creator>
		
		<category><![CDATA[Connection Pooling]]></category>

		<category><![CDATA[Usability]]></category>

		<guid isPermaLink="false">http://provenscaling.com/blog/?p=129</guid>
		<description><![CDATA[The MySQL configuration variable max_allowed_packet controls how large a single MySQL protocol packet (not a network/TCP packet) can be. This variable can be changed to solve &#8220;Packet too large&#8221; errors typically caused by excessively long query strings, such as large multi-row INSERT statements.  It&#8217;s both a session and global variable meaning that different sessions [...]]]></description>
			<content:encoded><![CDATA[<p>The MySQL configuration variable <tt>max_allowed_packet</tt> controls how large a single MySQL protocol packet (not a network/TCP packet) can be. This variable can be changed to solve &#8220;<a href="http://dev.mysql.com/doc/refman/5.0/en/packet-too-large.html">Packet too large</a>&#8221; errors typically caused by excessively long query strings, such as large multi-row <tt>INSERT</tt> statements.  It&#8217;s both a session and global variable meaning that different sessions can set their own limits for for <tt>max_allowed_packet</tt>.</p>
<p>It&#8217;s often assumed that changing global variables in MySQL means that the value changes for each connection.  However, in the case of <tt>max_allowed_packet</tt> and many others, the local setting of the variable is inherited from the global variable when a connection is first established.  This has special implications when using connection pooling. </p>
<p>In a connection pooling environment, connections are pooled on the application server.  When the application needs a connection to the MySQL server, it borrows it from the pool, and returns it when finished.  Typically when a connection is borrowed from the pool, the connection pool library automatically calls its API&#8217;s variant of the &#8220;change user&#8221; API function (which uses the <tt>COM_CHANGE_USER</tt> protocol command) to reset some connection specific parameters. </p>
<p>The session-level <tt>max_allowed_packet</tt> setting for a connection is normally inherited from the global setting when a client first connects, but it isn&#8217;t copied when the user is changed.  This means that even though the global <tt>max_allowed_packet</tt> may have been changed, the applications which are using those connections may not pick up the change until the <em>connection pool&#8217;s</em> connections are forced to reconnect, usually by restarting the application server.</p>
]]></content:encoded>
			<wfw:commentRss>http://provenscaling.com/blog/2008/10/07/max-allowed-packet-and-connection-pooling/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Making MySQL more usable: InnoDB save/restore buffer pool patch</title>
		<link>http://provenscaling.com/blog/2008/10/06/making-mysql-more-usable-innodb-saverestore-buffer-pool-patch/</link>
		<comments>http://provenscaling.com/blog/2008/10/06/making-mysql-more-usable-innodb-saverestore-buffer-pool-patch/#comments</comments>
		<pubDate>Tue, 07 Oct 2008 00:38:18 +0000</pubDate>
		<dc:creator>Jeremy Cole</dc:creator>
		
		<category><![CDATA[InnoDB]]></category>

		<category><![CDATA[Patches]]></category>

		<category><![CDATA[Usability]]></category>

		<guid isPermaLink="false">http://provenscaling.com/blog/?p=62</guid>
		<description><![CDATA[A feature that I and many others have wanted for years is to be able to save the contents of InnoDB&#8217;s buffer pool on shutdown, and restore it on startup.  Why?  After the system has been running for some time, it has spent a lot of effort perfecting the contents of the buffer [...]]]></description>
			<content:encoded><![CDATA[<p>A feature that I and many others have wanted for <strong>years</strong> is to be able to save the contents of InnoDB&#8217;s buffer pool on shutdown, and restore it on startup.  Why?  After the system has been running for some time, it has spent a lot of effort perfecting the contents of the buffer pool, and exactly the right pages are now cached.  When you shut down, that cache is lost, and on restart, InnoDB will have to start over from scratch.  This process is often referred to as &#8220;warming up&#8221; the caches.  This can cause a simple and quick server restart to have an effect on your production system for hours, or in the worst case <em>days</em>.</p>
<p>A good analogy to this cold startup process is that of starting from a dead stop in manual transmission car: While 5th gear is great for cruising at highway speeds, it&#8217;s not really suited for getting you up to speed; that&#8217;s what 1st through 4th gear are for.  In most cars that aren&#8217;t too underpowered, with enough finessing and cajoling you can start from a dead stop in any gear&#8230; revving the engine up high to keep it from stalling, and gently easing the clutch in to get rolling&#8230; but it&#8217;s not pleasant.  Besides the unpleasantness, it also takes <em>much</em> longer to get up to highway speeds compared to progressing through the gears in the normal way.  Additionally, you may start off rolling just fine, but some time before you&#8217;ve gotten up to speed, you hit a small hill&mdash;which in the correct gear would be no problem.  In the wrong gear, the car slows down, starts chugging, and eventually the engine stalls.</p>
<p>Most database systems behave much like cars with only 5th gear.  When tuned properly and appropriately sized, they cruise along perfectly well at &#8220;highway speeds&#8221;; when the caches are &#8220;hot&#8221; and finely tuned.  They are, in the end, largely designed to operate from an in-memory cache; cache misses, and thus disk reads, <em>should</em> be a relative rarity.  If you have too many cache misses, performance is terrible, and the system gets backed up and potentially overloaded.  We&#8217;ve seen all too many times the situation that occurs when a server (say, a read slave from a pool of many) is rebooted with cold caches, and then immediately put into service in a busy environment.  All hell breaks loose.</p>
<p>I have written a <a href="http://provenscaling.com/patches/innodb_plugin/1.0/draft/buffer_pool_save_restore.patch">proof of concept patch</a> (for InnoDB plugin for MySQL 5.1) which adds a facility (admittedly quite hacky in this draft) to save the list of cached pages to a text file on shutdown.  Then, on startup, it restores those pages back into the cache.  Since it saves the pages by page number, rather than by saving the contents of the pages, it is perfectly safe<sup>1</sup> and fairly efficient<sup>2</sup>.  Note that you should probably also use the <a href="http://provenscaling.com/blog/2008/07/29/making-mysql-more-usable-innodb-information-schema-patches/"><tt>information_schema</tt> patch</a> to be able to see that this patch is actually working.</p>
<p>While this feature isn&#8217;t nearly as sexy to show demos of in a static blog, it has a lot of potential in a production environment.  I intend to do a lot more development on it, to provide at least:</p>
<ul>
<li>A facility for changing the file name/path for the save file</li>
<li>The ability to skip the restore step, optionally</li>
<li>The ability to restore only part of the cache before accepting user connections, deferring the remainder of the cache to a background thread which continues running after startup</li>
</ul>
<p>Some other ideas I&#8217;ve had:</p>
<ul>
<li>Use multiple threads to read the pages, which should make much better use of RAIDs</li>
<li>Add runtime commands to save/restore the buffer pool state from a running server, without shutting down</li>
<li>Add an option to save some of the statistics about the pages so that they can be restored &#8220;smarter&#8221; rather than just have all pages stuffed back in the cache with equal priority</li>
</ul>
<p>Does this sound like a useful feature?  What other features should it have?  Do you have problems with cold startup in production?</p>
<p><sup>1</sup> In the worst case, if the file is complete gibberish, the requested pages either won&#8217;t exist, or will contain irrelevant data.  Either case should do no harm.  It wouldn&#8217;t be a bad idea to do some more niceties around the file format: a checksum, magic at the beginning of the file, etc.  The current file format especially is very much a proof of concept.</p>
<p><sup>2</sup> There&#8217;s still a lot of work to do to make things more efficient: ordering pages, using multiple threads to read from different tablespaces, subdividing reads for a tablespace into multiple threads, the possibilities are endless.</p>
]]></content:encoded>
			<wfw:commentRss>http://provenscaling.com/blog/2008/10/06/making-mysql-more-usable-innodb-saverestore-buffer-pool-patch/feed/</wfw:commentRss>
		</item>
		<item>
		<title>MySQL Enterprise 5.0.68 available</title>
		<link>http://provenscaling.com/blog/2008/09/08/mysql-enterprise-5068-available/</link>
		<comments>http://provenscaling.com/blog/2008/09/08/mysql-enterprise-5068-available/#comments</comments>
		<pubDate>Mon, 08 Sep 2008 20:49:37 +0000</pubDate>
		<dc:creator>Eric Bergen</dc:creator>
		
		<category><![CDATA[Announcements]]></category>

		<category><![CDATA[Enterprise]]></category>

		<category><![CDATA[Mirror]]></category>

		<guid isPermaLink="false">http://provenscaling.com/blog/?p=96</guid>
		<description><![CDATA[Sun has released MySQL Enterprise 5.0.68, and the source and binaries are now available from the Proven Scaling mirror. This release is a MRU release and is only recommended if you&#8217;re looking for fixes to specific bugs which are available in this release. For more information about the different MySQL release version numbers, see our [...]]]></description>
			<content:encoded><![CDATA[<p>Sun has released MySQL Enterprise 5.0.68, and the <a href="http://mirror.provenscaling.com/mysql/enterprise/source/5.0/mysql-5.0.68.tar.gz">source</a> and <a href="http://mirror.provenscaling.com/mysql/enterprise/binaries/5.0/5.0.68/">binaries</a> are now available from the <a href="http://mirror.provenscaling.com/">Proven Scaling mirror</a>. This release is a MRU release and is only recommended if you&#8217;re looking for fixes to specific bugs which are available in this release. For more information about the different MySQL release version numbers, see our previous post on <a href="http://provenscaling.com/blog/2008/07/31/understanding-mysql-version-numbers/">version numbers</a>. Details for changes in this release can be found in the <a href="http://dev.mysql.com/doc/refman/5.0/en/releasenotes-es-5-0-68.html">MySQL Enterprise 5.0.68 release notes</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://provenscaling.com/blog/2008/09/08/mysql-enterprise-5068-available/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Understanding MySQL version numbers</title>
		<link>http://provenscaling.com/blog/2008/07/31/understanding-mysql-version-numbers/</link>
		<comments>http://provenscaling.com/blog/2008/07/31/understanding-mysql-version-numbers/#comments</comments>
		<pubDate>Fri, 01 Aug 2008 02:04:14 +0000</pubDate>
		<dc:creator>Eric Bergen</dc:creator>
		
		<category><![CDATA[Community]]></category>

		<category><![CDATA[Enterprise]]></category>

		<category><![CDATA[Mirror]]></category>

		<guid isPermaLink="false">http://provenscaling.com/blog/?p=59</guid>
		<description><![CDATA[We provide quite a few different MySQL releases on the Proven Scaling Mirror. Since MySQL 5.0 is split into &#8220;Community&#8221; and &#8220;Enterprise&#8221;, navigating all of those different releases can be very confusing, making it difficult to choose which release is right for you.
There are three main branches of MySQL being produced by Sun/MySQL: Community, Enterprise [...]]]></description>
			<content:encoded><![CDATA[<p>We provide quite a few different MySQL releases on the <a href="http://mirror.provenscaling.com/">Proven Scaling Mirror</a>. Since MySQL 5.0 is split into &#8220;Community&#8221; and &#8220;Enterprise&#8221;, navigating all of those different releases can be very confusing, making it difficult to choose which release is right for you.</p>
<p>There are three main branches of MySQL being produced by <a href="http://www.mysql.com/">Sun/MySQL</a>: Community, Enterprise MRU, and Enterprise QSP. All Community and Enterprise releases are distributed under the terms of the <a href="http://www.gnu.org/licenses/gpl-2.0.html">GPLv2 license</a>. The changes between each release are tracked in the <a href="http://dev.mysql.com/doc/">MySQL manual</a>. The difference between these branches are subtle but important. </p>
<p><strong>MySQL Community</strong> is a branch of MySQL that is released less frequently, but also contains contributions from developers outside of Sun/MySQL. So far the only notable feature in the Community release is <tt>SHOW PROFILE</tt>, a query-profiling feature originally developed by Proven Scaling. Unless you want the <tt>SHOW PROFILE</tt> feature, there is currently no reason to use this release instead of a newer Enterprise release. </p>
<p><strong>MySQL Enterprise MRU</strong> (commonly called just <strong>MySQL Enterprise</strong>) is a &#8220;Monthly Rapid Update&#8221; that is regularly updated with bug fixes and changes that were developed by MySQL during the previous month. According to MySQL&#8217;s guidance, MRU releases should only be used when a critical fix is needed that hasn&#8217;t yet been included in a QSP release. MRU releases don&#8217;t have any special naming scheme.  At the time of this post the version number of the most recent release is 5.0.66a. You can find the <a href="http://mirror.provenscaling.com/mysql/enterprise/source/5.0/mysql-5.0.66a.tar.gz">source</a> or <a href="http://mirror.provenscaling.com/mysql/enterprise/binaries/5.0/5.0.66a/">binaries</a> of this version on the Proven Scaling mirror.</p>
<p><strong>MySQL Enterprise QSP</strong> is a &#8220;Quarterly Service Pack&#8221; which is released once per quarter. This release contains all the changes in the MRU releases since the previous QSP release. QSP releases can also contain critical bug fixes from MRU releases with higher version numbers than the QSP has. For instance, 5.0.56sp1 contains fixes from 5.0.58 &mdash; this can make it somewhat more difficult to understand whether or not you&#8217;re affected by a particular bug.  Other critical fixes may only be in MRU releases until the next scheduled QSP release.  You can find the <a href="http://mirror.provenscaling.com/mysql/enterprise/source/5.0/mysql-5.0.60sp1.tar.gz">source</a> or <a href="http://mirror.provenscaling.com/mysql/enterprise/binaries/5.0/5.0.60sp1/">binaries</a> of this version on the Proven Scaling mirror.</p>
<p>The format of the release notes pages in the manual has changed between 5.0.56sp1 and 5.0.60sp1. In version 5.0.56sp1 the <a href="http://dev.mysql.com/doc/refman/5.0/en/releasenotes-es-5-0-56sp1.html">release notes page</a> contained all the changes in the previous MRU releases since the last QSP. As of 5.0.60sp1 <a href="http://dev.mysql.com/doc/refman/5.0/en/releasenotes-es-5-0-60sp1.html">the release notes page</a><sup>1</sup> contains only the changes back ported from the next MRU release. It can be confusing when comparing release notes between versions. Be sure to read the paragraph at the top of the release notes page to see what is actually contained within.</p>
<p><sup>1</sup> Note that 5.0.60sp1 has no changes from 5.0.60.  It was merely recompiled with a new version number and released as 5.0.60sp1.</p>
]]></content:encoded>
			<wfw:commentRss>http://provenscaling.com/blog/2008/07/31/understanding-mysql-version-numbers/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Making MySQL more usable: InnoDB information_schema patches</title>
		<link>http://provenscaling.com/blog/2008/07/29/making-mysql-more-usable-innodb-information-schema-patches/</link>
		<comments>http://provenscaling.com/blog/2008/07/29/making-mysql-more-usable-innodb-information-schema-patches/#comments</comments>
		<pubDate>Wed, 30 Jul 2008 01:26:37 +0000</pubDate>
		<dc:creator>Jeremy Cole</dc:creator>
		
		<category><![CDATA[InnoDB]]></category>

		<category><![CDATA[Patches]]></category>

		<category><![CDATA[Usability]]></category>

		<guid isPermaLink="false">http://provenscaling.com/blog/?p=35</guid>
		<description><![CDATA[Lately I&#8217;ve been working on a series of patches to increase the usability of InnoDB, based on the InnoDB plugin for MySQL 5.1.  I have a lot of ideas still, but I&#8217;ve currently gotten two proof of concept patches working.  Both of the patches require a small patch to relocate the buf_chunk_struct struct [...]]]></description>
			<content:encoded><![CDATA[<p>Lately I&#8217;ve been working on a series of patches to increase the usability of InnoDB, based on the <a href="http://www.innodb.com/innodb_plugin/">InnoDB plugin for MySQL 5.1</a>.  I have a lot of ideas still, but I&#8217;ve currently gotten two proof of concept patches working.  Both of the patches require a <a href="http://provenscaling.com/patches/innodb_plugin/1.0/draft/move_buf_chunk_struct.patch">small patch</a> to relocate the <tt>buf_chunk_struct</tt> struct definition which was inadvertently defined in <tt>buf0buf.c</tt> rather than <tt>buf0buf.h</tt>.</p>
<p>Most patches are considered <strong>rough draft, proof of concept quality</strong> at best.  They are suitable for testing, playing around, using them to gain insight about your data, but <em>not</em> for production use.  Use at your own risk!</p>
<h2>Using <tt>information_schema</tt> to view the buffer pool contents</h2>
<p>This <a href="http://provenscaling.com/patches/innodb_plugin/1.0/draft/i_s_innodb_buffer_pool_pages.patch">patch</a> creates several new <tt>information_schema</tt> tables to provide visibility into the contents of the InnoDB buffer pool.  The new tables are: </p>
<ul>
<li><tt>innodb_buffer_pool_pages</tt></li>
<li><tt>innodb_buffer_pool_pages_index</tt></li>
<li><tt>innodb_buffer_pool_pages_blob</tt></li>
</ul>
<p>Note that accessing these tables is <em>not cheap</em>, as the buffer pool must be scanned.</p>
<h3><tt>innodb_buffer_pool_pages</tt></h3>
<p>This table provides some generic information about all pages present in the buffer pool, and is primarily useful for getting statistics about the number and types of pages present at any given point in time.  For example:</p>
<blockquote><pre>
SELECT
  page_type,
  count(*) AS nr
FROM information_schema.innodb_buffer_pool_pages
GROUP BY page_type;

+-----------+------+
| page_type | nr   |
+-----------+------+
| allocated | 4051 |
| bitmap    |    2 |
| blob      |    5 |
| fsp_hdr   |    2 |
| index     |   14 |
| inode     |    2 |
| sys       |    3 |
| trx_sys   |    1 |
| undo_log  |   15 |
+-----------+------+
</pre>
</blockquote>
<h3><tt>innodb_buffer_pool_pages_index</tt></h3>
<p>This table gives you detailed statistics on index pages, which for InnoDB means all data (as part of the primary key) and all defined indexes.  For example (some columns removed for clarity):</p>
<blockquote><pre>
SELECT *
FROM information_schema.innodb_buffer_pool_pages_index;

+-------------+------------------+------------+----------+---------+--------+-----------+--------------+...
| schema_name | table_name       | index_name | space_id | page_no | n_recs | data_size | lru_position |...
+-------------+------------------+------------+----------+---------+--------+-----------+--------------+...
| NULL        | SYS_IBUF_TABLE_0 | CLUST_IND  |        0 |       4 |      0 |         0 |            6 |...
| NULL        | SYS_INDEXES      | CLUST_IND  |        0 |      11 |      8 |       536 |            7 |...
| NULL        | SYS_TABLES       | CLUST_IND  |        0 |       8 |      5 |       351 |           12 |...
| NULL        | SYS_COLUMNS      | CLUST_IND  |        0 |      10 |     24 |      1436 |           14 |...
| NULL        | SYS_TABLES       | ID_IND     |        0 |       9 |      5 |       126 |           15 |...
| NULL        | SYS_FIELDS       | CLUST_IND  |        0 |      12 |      8 |       315 |           16 |...
| NULL        | SYS_FOREIGN      | ID_IND     |        0 |      46 |      0 |         0 |           50 |...
| NULL        | SYS_FOREIGN      | FOR_IND    |        0 |      47 |      0 |         0 |           51 |...
| NULL        | SYS_FOREIGN      | REF_IND    |        0 |      48 |      0 |         0 |           52 |...
| NULL        | SYS_FOREIGN_COLS | ID_IND     |        0 |      49 |      0 |         0 |           53 |...
| test        | bt               | PRIMARY    |       26 |       3 |      3 |        39 |           66 |...
| test        | bt               | PRIMARY    |       26 |       7 |      1 |      8124 |           69 |...
| test        | bt               | PRIMARY    |       26 |       9 |      2 |     16248 |           71 |...
| test        | bt               | PRIMARY    |       26 |       6 |      2 |     16248 |           74 |...
+-------------+------------------+------------+----------+---------+--------+-----------+--------------+...
</pre>
</blockquote>
<p>Besides the obvious value of this, notice that you can see InnoDB&#8217;s internal tables (with <tt>schema_name</tt> as <tt>NULL</tt>) as well!</p>
<h3><tt>innodb_buffer_pool_pages_blob</tt></h3>
<p>This table gives you detailed statistics on <tt>BLOB</tt>-storage pages, which store parts of <tt>BLOB</tt>s that overflow in-row storage (another post on that later, but suffice it to say, if the <tt>BLOB</tt> is larger than 8KB&#8230; sort of).  For example:</p>
<blockquote><pre>
SELECT *
FROM information_schema.innodb_buffer_pool_pages_blob;

+----------+---------+------------+----------+--------------+--------------+-----------+------------+
| space_id | page_no | compressed | part_len | next_page_no | lru_position | fix_count | flush_type |
+----------+---------+------------+----------+--------------+--------------+-----------+------------+
|       26 |       5 |          0 |     9232 |            0 |           72 |         0 |          0 |
|       26 |      10 |          0 |     9232 |            0 |           73 |         0 |          0 |
|       26 |       8 |          0 |     9232 |            0 |           75 |         0 |          0 |
|       26 |      11 |          0 |     9232 |            0 |           76 |         0 |          0 |
|       26 |       4 |          0 |     9232 |            0 |           77 |         0 |          0 |
+----------+---------+------------+----------+--------------+--------------+-----------+------------+
</pre>
</blockquote>
<p>We&#8217;d love to get the table name and <tt>PRIMARY KEY</tt> value associated with each <tt>BLOB</tt>-storage page, but I&#8217;m not sure if that&#8217;s possible.</p>
<h3>An example of the power of these tables</h3>
<p>Have you ever wondered what your <em>page fill rate</em> is?  Probably not, because you didn&#8217;t realize it was either interesting or important, but we worry about these things (and often justifiably so).  In short, page fill rate is the percentage of each page that is filled with data.  Since InnoDB only caches whole pages, if your average page fill rate is 75%, you would be wasting 25% of the space in each page.  That would mean that your table is spread across more pages than necessary, which will waste both disk space and memory you&#8217;ve allocated to the buffer pool.</p>
<p>Here&#8217;s a simple way to figure out the average page fill rate of pages currently in cache:</p>
<blockquote><pre>
SELECT
  schema_name,
  table_name,
  index_name,
  COUNT(*) AS n_pages,
  ROUND(AVG(n_recs), 2) AS recs_per_page,
  ROUND(SUM(data_size)/1048576, 2) AS total_data_size_M,
  ROUND(AVG(data_size/(
    SELECT variable_value
    FROM information_schema.global_status
    WHERE variable_name
    LIKE 'innodb_page_size'
  )) * 100, 2) AS page_fill_pct
FROM
  information_schema.innodb_buffer_pool_pages_index
WHERE 1
AND schema_name IS NOT NULL
GROUP BY
  schema_name,
  table_name,
  index_name
ORDER BY
  total_data_size_M DESC;

+-------------+------------+-----------------+---------+---------------+-------------------+---------------+
| schema_name | table_name | index_name      | n_pages | recs_per_page | total_data_size_M | page_fill_pct |
+-------------+------------+-----------------+---------+---------------+-------------------+---------------+
| test        | n          | GEN_CLUST_INDEX |    4079 |        252.55 |             58.56 |         91.88 |
| test        | bt         | PRIMARY         |       2 |          2.50 |              0.02 |         49.70 |
| test        | p          | PRIMARY         |       1 |          2.00 |              0.00 |          0.52 |
| test        | p          | c               |       1 |          2.00 |              0.00 |          0.37 |
+-------------+------------+-----------------+---------+---------------+-------------------+---------------+
</pre>
</blockquote>
<p>This is showing some statistics for each index from each table in the cache: the number of pages in the cache, the average number of records per page for those cached pages, the total number of megabytes of cache used, and the page fill rate in percent.  There is currently no other way to calculate this information from any statistics or data that InnoDB provides.</p>
<h2>What else?</h2>
<p>What ideas do you have?  What do you think about these features?  Leave a comment to let us know!</p>
]]></content:encoded>
			<wfw:commentRss>http://provenscaling.com/blog/2008/07/29/making-mysql-more-usable-innodb-information-schema-patches/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Announcing the official Proven Scaling Blog</title>
		<link>http://provenscaling.com/blog/2008/07/28/announcing-the-official-proven-scaling-blog/</link>
		<comments>http://provenscaling.com/blog/2008/07/28/announcing-the-official-proven-scaling-blog/#comments</comments>
		<pubDate>Mon, 28 Jul 2008 19:18:43 +0000</pubDate>
		<dc:creator>Proven Scaling Team</dc:creator>
		
		<category><![CDATA[Announcements]]></category>

		<category><![CDATA[Proven Scaling]]></category>

		<guid isPermaLink="false">http://provenscaling.com/blog/?p=4</guid>
		<description><![CDATA[Welcome to Proven Scaling&#8217;s new official home on the web.  We&#8217;ve been meaning to set up a company blog for quite a while, but since we already have personal blogs, it kept getting pushed to the back burner.  Finally, with much ado, it&#8217;s up!
A little about Proven Scaling and our history
Proven Scaling was [...]]]></description>
			<content:encoded><![CDATA[<p>Welcome to Proven Scaling&#8217;s new <em>official</em> home on the web.  We&#8217;ve been meaning to set up a company blog for quite a while, but since we already have personal blogs, it kept getting pushed to the back burner.  Finally, with much ado, it&#8217;s up!</p>
<h2>A little about Proven Scaling and our history</h2>
<p>Proven Scaling was founded by Jeremy Cole and Eric Bergen in May, 2006 in order to provide our skills in MySQL architecture, performance, reliability, and availability to a larger audience.  Currently Proven Scaling consists of:</p>
<ul>
<li>Jeremy Cole &mdash; <a href="http://jcole.us/blog/archives/2006/06/30/leaving-yahoo-storage-consulting/">Jeremy left Yahoo!</a> after 1.5 years, a few months ahead of Eric, to kickstart Proven Scaling in July, 2006.  Previous to Yahoo!, Jeremy worked for MySQL AB for 4.5 years as tech writer, trainer, consultant, and occasional developer.  Jeremy has a personal blog at <a href="http://jcole.us/blog/">jcole.us</a>.</li>
<li>Eric Bergen &mdash; Eric left his 1.5 years at Yahoo! <a href="http://ebergen.net/wordpress/2006/11/10/proven-scaling/">to join Jeremy</a> in September, 2006.  Previous to Yahoo!, Eric was responsible for MySQL and related systems at a major domain registrar.  Eric has a personal blog at <a href="http://ebergen.net/wordpress/">ebergen.net</a></li>
<li>Mike Griffiths &mdash; Based in London, UK, Mike <a href="http://jcole.us/blog/archives/2007/11/29/proven-scaling-goes-global/">joined Proven Scaling</a> in November, 2007.  Before joining Proven Scaling, Mike worked at Yahoo! for 7 years, responsible for MySQL in Europe, Asia and beyond.  Mike has so far steadfastly refused to join the blogosphere, arguing that no-one&#8217;s really interested in his thoughts on sport, DIY, perl hacking, warm English beer and the other things which take up his leisure time.</li>
</ul>
<h2>A lot more than consulting&#8230;</h2>
<p>At Proven Scaling we spend a lot time working on various software projects.  Jeremy and Eric have been <a href="http://provenscaling.com/patches/">publishing their own patches</a> to MySQL and other projects for many years.  One of the primary reasons for forming a company together in the structure that we have is to ensure that we maintain the hardware resources, ability, and time available to work on these projects and provide them to the public in as quick and efficient manner as possible.  In addition to continuing our previous work, Proven Scaling has been working on several new independent projects to solve problems in the MySQL space.</p>
<p>We needed to place to distribute that software along with other widely and not-so-widely available software packages, so we host a software mirror at <a href=http://mirror.provenscaling.com>mirror.provenscaling.com</a>.  This site hosts hard to find copies of various software packages we use every day, in addition to RedHat-friendly (and CentOS friendly) <tt>yum</tt> repositories for many packages.  In fact, one of the reasons we are starting this blog is so that we have an official place to keep you updated as to the contents of our mirror site.  As we update the mirror with new releases of existing software and entirely new software, we will post entries describing the updates.</p>
<h2>What will we blog about?</h2>
<p>You can get some idea of the topics you might see here from Jeremy and Eric&#8217;s MySQL posts on their personal blogs: <a href="http://jcole.us/blog/archives/category/mysql/">MySQL on jcole.us</a> and <a href="http://ebergen.net/wordpress/category/geek/mysql/">MySQL on ebergen.net</a>.</p>
<p>In addition to the updates described above, some of the topics we are especially interested in writing about are:</p>
<ul>
<li>Announcements of new Proven Scaling software and new releases of our software</li>
<li>New patches or ideas for patches to MySQL and other software</li>
<li>Deep dissections of various parts of MySQL and InnoDB</li>
<li>Knowledge gained from working with our customers, such as advice for real-world scenarios or unexpected situations</li>
<li>Many more exciting ideas we&#8217;re working on, which we will share when they are ready!</li>
</ul>
<h2>Sounds good?</h2>
<p>Go ahead and subscribe to <a href="http://provenscaling.com/blog/feed/">our RSS feed</a>, or bookmark this page.  Keep an eye on the author names above, so that you know who&#8217;s writing.</p>
]]></content:encoded>
			<wfw:commentRss>http://provenscaling.com/blog/2008/07/28/announcing-the-official-proven-scaling-blog/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
