<?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>Xaprb &#187; CRC32</title>
	<atom:link href="http://www.xaprb.com/blog/tag/crc32/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.xaprb.com/blog</link>
	<description>Stay curious!</description>
	<lastBuildDate>Thu, 09 Feb 2012 03:58:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>How PostgreSQL protects against partial page writes and data corruption</title>
		<link>http://www.xaprb.com/blog/2010/02/08/how-postgresql-protects-against-partial-page-writes-and-data-corruption/</link>
		<comments>http://www.xaprb.com/blog/2010/02/08/how-postgresql-protects-against-partial-page-writes-and-data-corruption/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 19:36:15 +0000</pubDate>
		<dc:creator>Xaprb</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[checkpoint]]></category>
		<category><![CDATA[checksums]]></category>
		<category><![CDATA[CRC32]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[recovery]]></category>
		<category><![CDATA[wal]]></category>

		<guid isPermaLink="false">http://www.xaprb.com/blog/?p=1616</guid>
		<description><![CDATA[I explored two interesting topics today while learning more about Postgres. Partial page writes PostgreSQL&#8217;s partial page write protection is configured by the following setting, which defaults to &#8220;on&#8221;: full_page_writes (boolean) When this parameter is on, the PostgreSQL server writes the entire content of each disk page to WAL during the first modification of that [...]


<strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2008/08/06/how-to-scale-writes-with-master-master-replication-in-mysql/' rel='bookmark' title='Permanent Link: How to scale writes with master-master replication in MySQL'>How to scale writes with master-master replication in MySQL</a></li>
<li><a href='http://www.xaprb.com/blog/2010/06/19/the-little-known-maatkit-man-page/' rel='bookmark' title='Permanent Link: The little-known Maatkit man page'>The little-known Maatkit man page</a></li>
<li><a href='http://www.xaprb.com/blog/2009/02/19/the-magnolia-data-might-not-be-permanently-lost/' rel='bookmark' title='Permanent Link: The Ma.gnolia data might not be permanently lost'>The Ma.gnolia data might not be permanently lost</a></li>
<li><a href='http://www.xaprb.com/blog/2006/01/02/tables-and-data-part-1/' rel='bookmark' title='Permanent Link: Tables and data part 1: CSS and data types'>Tables and data part 1: CSS and data types</a></li>
<li><a href='http://www.xaprb.com/blog/2009/09/29/what-data-types-does-your-innovative-storage-engine-not-support/' rel='bookmark' title='Permanent Link: What data types does your innovative storage engine NOT support?'>What data types does your innovative storage engine NOT support?</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p>I explored two interesting topics today while learning more about Postgres.</p>

<h3>Partial page writes</h3>

<p>PostgreSQL&#8217;s partial page write protection is configured by the following setting, which defaults to &#8220;on&#8221;:</p>

<blockquote cite="http://www.postgresql.org/docs/8.3/static/runtime-config-wal.html#GUC-FULL-PAGE-WRITES"><p>full_page_writes (boolean)</p>

<p>When this parameter is on, the PostgreSQL server writes the entire content of each disk page to WAL during the first modification of that page after a checkpoint&#8230; Storing the full page image guarantees that the page can be correctly restored, but at a price in increasing the amount of data that must be written to WAL. (Because WAL replay always starts from a checkpoint, it is sufficient to do this during the first change of each page after a checkpoint. Therefore, one way to reduce the cost of full-page writes is to increase the checkpoint interval parameters.)</p></blockquote>

<p>Trying to reduce the cost of full-page writes by increasing the checkpoint interval highlights a compromise.  If you decrease the interval, then you&#8217;ll be writing full pages to the WAL quite often.  This should in theory lead to surges in the number of bytes written to the WAL, immediately following each checkpoint. As pages are revisited over time for further changes, the number of bytes written should taper off gradually until the next checkpoint.   Hopefully someone who knows more can confirm this.  Does anyone graph the number of bytes written to their WAL?  That would be a nice illustration to see how dramatic this surging is.</p>

<p>Decreasing the checkpoint interval seems a bit scary, and is bound to have its own costs, for all the usual reasons.  A massive checkpoint once in a while should be really expensive, and would lead to a bad worst-case time for recovery.  Does the new bgwriter implementation in 8.3 fix any of this?  In theory it could, but I don&#8217;t know enough yet to say.  I have heard conflicting opinions on this point.  I have a lot more to read about it before I form my own opinion.</p>

<p>Storing full pages might not really be that expensive.  It could bloat the WAL, but is the cost (in terms of time) really that high?  InnoDB (in MySQL) protects against partial page writes with a double-write strategy: a region in the tablespace is called the doublewrite buffer.  Page writes are first sent to the doublewrite buffer, then to their actual location in the data file.  I don&#8217;t remember where, but I&#8217;ve seen benchmarks showing that this doesn&#8217;t hurt performance, even though it seems counter-intuitive.  Modern disks can do a lot of sequential writes, and the way InnoDB writes its data makes a lot of things sequential.  I doubt that putting full pages into the PostgreSQL WAL is forced to cost a lot, unless there is an implementation-specific aspect that makes it expensive.</p>

<p>The TODO has some <a href="http://wiki.postgresql.org/wiki/Todo#Write-Ahead_Log">items on the WAL</a>, which look interesting &#8212; &#8220;Eliminate need to write full pages to WAL before page modification&#8221; and a couple more items.  I need to understand PostgreSQL&#8217;s recovery process better before I know what these really mean.</p>

<h3>Detecting data corruption</h3>

<p>I was able to verify that the WAL entries have a checksum.  It is a CRC32.  This is in <a href="http://doxygen.postgresql.org/xlog_8c-source.html#l00567">xlog.c</a>.</p>

<p>However, as far as I can understand, the answer for detecting data corruption in normal data pages is &#8220;Postgres doesn&#8217;t do that.&#8221;  I was told on the IRC channel that normal data pages don&#8217;t have checksums.  I am not sure how to verify that, but if it&#8217;s true it seems like a weakness.  I&#8217;ve seen hardware-induced corruption on InnoDB data many times, and it could sometimes only be detected by page checksums.</p>

<p>What happens when a page is corrupt?  It probably depends on where the corruption is.  If a few bytes of the user&#8217;s data is changed, then I assume you could just get different data out of the database than you inserted into it.  But if non-user data is corrupted then do you get bizarre behavior, or do you get a crash or error?  I need to learn more about PostgreSQL&#8217;s data file layout to understand this.  Imagining (I haven&#8217;t verified this) that a page has a pointer to the next page, what happens if that pointer is flipped to refer to some other page, say, a page from a different table?  If TABLE1 and TABLE2 have identical structures but different data, could SELECT * FROM TABLE1 suddenly start showing rows from TABLE2 partway through the results?  Again I need to learn more about this.</p>

<p><strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2008/08/06/how-to-scale-writes-with-master-master-replication-in-mysql/' rel='bookmark' title='Permanent Link: How to scale writes with master-master replication in MySQL'>How to scale writes with master-master replication in MySQL</a></li>
<li><a href='http://www.xaprb.com/blog/2010/06/19/the-little-known-maatkit-man-page/' rel='bookmark' title='Permanent Link: The little-known Maatkit man page'>The little-known Maatkit man page</a></li>
<li><a href='http://www.xaprb.com/blog/2009/02/19/the-magnolia-data-might-not-be-permanently-lost/' rel='bookmark' title='Permanent Link: The Ma.gnolia data might not be permanently lost'>The Ma.gnolia data might not be permanently lost</a></li>
<li><a href='http://www.xaprb.com/blog/2006/01/02/tables-and-data-part-1/' rel='bookmark' title='Permanent Link: Tables and data part 1: CSS and data types'>Tables and data part 1: CSS and data types</a></li>
<li><a href='http://www.xaprb.com/blog/2009/09/29/what-data-types-does-your-innovative-storage-engine-not-support/' rel='bookmark' title='Permanent Link: What data types does your innovative storage engine NOT support?'>What data types does your innovative storage engine NOT support?</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.xaprb.com/blog/2010/02/08/how-postgresql-protects-against-partial-page-writes-and-data-corruption/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>How Maatkit benefits from test-driven development</title>
		<link>http://www.xaprb.com/blog/2008/08/18/how-maatkit-benefits-from-test-driven-development/</link>
		<comments>http://www.xaprb.com/blog/2008/08/18/how-maatkit-benefits-from-test-driven-development/#comments</comments>
		<pubDate>Mon, 18 Aug 2008 13:54:24 +0000</pubDate>
		<dc:creator>Xaprb</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Maatkit]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[CRC32]]></category>
		<category><![CDATA[Daniel Nichter]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Test Driven Development]]></category>
		<category><![CDATA[The Rimm Kaufman Group]]></category>

		<guid isPermaLink="false">http://www.xaprb.com/blog/2008/08/18/how-maatkit-benefits-from-test-driven-development/</guid>
		<description><![CDATA[Over in Maatkit-land, Daniel Nichter and I practice test-first programming, AKA test-driven development. That is, we write tests for each new feature or to catch regressions on each bug we fix. And &#8212; this is crucial &#8212; we write the tests before we write the code.* The tests should initially fail, which is a validation [...]


<strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2009/05/03/a-productivity-tip-for-test-driven-development/' rel='bookmark' title='Permanent Link: A productivity tip for test-driven development'>A productivity tip for test-driven development</a></li>
<li><a href='http://www.xaprb.com/blog/2008/08/19/how-to-unit-test-code-that-interacts-with-a-database/' rel='bookmark' title='Permanent Link: How to unit-test code that interacts with a database'>How to unit-test code that interacts with a database</a></li>
<li><a href='http://www.xaprb.com/blog/2011/07/06/planned-change-in-maatkit-aspersa-development/' rel='bookmark' title='Permanent Link: Planned change in Maatkit &#038; Aspersa development'>Planned change in Maatkit &#038; Aspersa development</a></li>
<li><a href='http://www.xaprb.com/blog/2007/11/26/four-companies-to-sponsor-maatkit-development/' rel='bookmark' title='Permanent Link: Four companies to sponsor Maatkit development'>Four companies to sponsor Maatkit development</a></li>
<li><a href='http://www.xaprb.com/blog/2007/08/24/google-test-automation-conference-day-1/' rel='bookmark' title='Permanent Link: Google Test Automation Conference, Day 1'>Google Test Automation Conference, Day 1</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p>Over in <a href="http://www.maatkit.org/">Maatkit</a>-land, <a href="http://hackmysql.com/">Daniel Nichter</a> and I practice <a href="http://en.wikipedia.org/wiki/Test-driven_development">test-first programming, AKA test-driven development</a>.  That is, we write tests for each new feature or to catch regressions on each bug we fix.  And &#8212; this is crucial &#8212; we write the tests <em>before</em> we write the code.*  The tests should initially fail, which is a validation that the new code actually works and the tests actually verify this.  If we don&#8217;t first write a failing testcase, then our code lacks a very important guarantee: &#8220;if you break this code, then the test case will tell you so.&#8221; (A test that doesn&#8217;t fail when the code fails isn&#8217;t worth writing.)</p>

<span id="more-553"></span>

<p>Most of the time when I do this, I write a test, it fails because I haven&#8217;t written any code yet, and I then go do some kind of clean-room coding.  Then I run the test and it&#8217;s busted, and I have to go back to the code and figure out why, and after a few more tries I get it working.  And then it feels great.  (That&#8217;s the other thing about test-first coding.  It&#8217;s really satisfying, like cooking the perfect dinner, arranging the plates beautifully and then eating.)</p>

<p>This time I wanted to write a pure-Perl implementation of CRC32, and embed it in mk-table-checksum.  We try really hard never to rely on external modules, even modules that ought to be distributed with Perl itself.  That keeps Maatkit as portable as possible and makes sure there is no installation hell.  You can generally just get and run the Maatkit tools with no installation.  So I referred to an existing CRC32 implementation, in <a href="http://search.cpan.org/~fays/Digest-Crc32-0.01/Crc32.pm">Digest::Crc32</a>.  I wrote a test by referring to the value I got from MySQL&#8217;s built-in CRC32:</p>

<pre>mysql> select crc32('hello world');
+----------------------+
| crc32('hello world') |
+----------------------+
|            222957957 | 
+----------------------+
1 row in set (0.00 sec)
</pre>

<p>Here&#8217;s the test:</p>

<pre>is($c-&gt;crc32('hello world'), 222957957, 'CRC32 of hello world');</pre>

<p>CRC32 is CRC32, so my code better agree with a working implementation.  And then I wrote the code, which is a refactoring of the math in the module I linked to above.  And then I ran the test, and it Just Passed with no further ado.  w00t!  This is pretty much a historic first for me!  I thought at first that I&#8217;d screwed something up with the test, but I checked again. This is like getting a hole-in-one for me :-)  So I just thought I&#8217;d share it with you.  It feels <strong>awesome</strong>.</p>

<p>If you&#8217;re not doing test-first coding, you ought to give it a try.  If you are conscientious about writing tests first, your code will always be easy to test.  If you don&#8217;t, you write untestable code.  Then it&#8217;s tough or impossible to ever get tests on it, and you spend the rest of your life wasting time on stupid bugs and slow, fearful development, never knowing what else you are breaking with your &#8220;fixes.&#8221;</p>

<p>Test-driven development is one reason <a href="http://www.rimmkaufman.com/">The Rimm-Kaufman Group&#8217;s</a> in-house bidding system blows away their competition.  (RKG is my previous employer.)  The comprehensive unit-test suite lets you know right away if you&#8217;ve broken something.  That keeps the code clean and makes it possible to be extremely productive.  I remember once when one of my co-workers there implemented a major feature in a very short time.  It was also incredibly helpful when sharding the databases (anyone ever done this without a test suite?  Would you like to share about how much of your systems broke during sharding?  It was almost a non-event at RKG).  The people I worked with before I joined RKG looked at me like an alien when I tried to explain that this was possible.</p>

<p>If you&#8217;re thinking that your code is not &#8220;that kind of code,&#8221; that &#8220;only certain kinds of code lend themselves to unit tests,&#8221; then stop. I&#8217;ve heard this before, and you&#8217;re wrong.  It&#8217;s only &#8220;untestable&#8221; because you didn&#8217;t write tests first.  Write tests first, and your code &#8212; all of it! &#8212; will be &#8220;that kind of code&#8221; that is testable.  It&#8217;s hard.  No one says it&#8217;s not; good programming is much harder than sloppy programming.  But it&#8217;s well worth it.</p>

<p>Converting untested, untestable code into tested code is not so much fun, though.  And in my experience you&#8217;ll rarely be rewarded for it, and your coworkers will not appreciate you raising the bar for them.  Maybe you need a new job.  I hear RKG is hiring.  Did I mention that their codebase is built from the ground up on unit tests?</p>

<p>* OK, we&#8217;re not perfectly disciplined about this, but we&#8217;re pretty good about it.</p>

<p><strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2009/05/03/a-productivity-tip-for-test-driven-development/' rel='bookmark' title='Permanent Link: A productivity tip for test-driven development'>A productivity tip for test-driven development</a></li>
<li><a href='http://www.xaprb.com/blog/2008/08/19/how-to-unit-test-code-that-interacts-with-a-database/' rel='bookmark' title='Permanent Link: How to unit-test code that interacts with a database'>How to unit-test code that interacts with a database</a></li>
<li><a href='http://www.xaprb.com/blog/2011/07/06/planned-change-in-maatkit-aspersa-development/' rel='bookmark' title='Permanent Link: Planned change in Maatkit &#038; Aspersa development'>Planned change in Maatkit &#038; Aspersa development</a></li>
<li><a href='http://www.xaprb.com/blog/2007/11/26/four-companies-to-sponsor-maatkit-development/' rel='bookmark' title='Permanent Link: Four companies to sponsor Maatkit development'>Four companies to sponsor Maatkit development</a></li>
<li><a href='http://www.xaprb.com/blog/2007/08/24/google-test-automation-conference-day-1/' rel='bookmark' title='Permanent Link: Google Test Automation Conference, Day 1'>Google Test Automation Conference, Day 1</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.xaprb.com/blog/2008/08/18/how-maatkit-benefits-from-test-driven-development/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

