<?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; transactions</title>
	<atom:link href="http://www.xaprb.com/blog/tag/transactions/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>Using BASE instead of ACID for scalability</title>
		<link>http://www.xaprb.com/blog/2008/07/23/using-base-instead-of-acid-for-scalability/</link>
		<comments>http://www.xaprb.com/blog/2008/07/23/using-base-instead-of-acid-for-scalability/#comments</comments>
		<pubDate>Wed, 23 Jul 2008 22:07:15 +0000</pubDate>
		<dc:creator>Xaprb</dc:creator>
				<category><![CDATA[Commentary]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[ACID]]></category>
		<category><![CDATA[ACM]]></category>
		<category><![CDATA[Andy Oram]]></category>
		<category><![CDATA[BASE]]></category>
		<category><![CDATA[CAP]]></category>
		<category><![CDATA[Continuent]]></category>
		<category><![CDATA[foreign keys]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[replication]]></category>
		<category><![CDATA[Robert Hodges]]></category>
		<category><![CDATA[scaling]]></category>
		<category><![CDATA[transactions]]></category>

		<guid isPermaLink="false">http://www.xaprb.com/blog/2008/07/23/using-base-instead-of-acid-for-scalability/</guid>
		<description><![CDATA[My editor Andy Oram recently sent me an ACM article on BASE, a technique for improving scalability by being willing to give up some other properties of traditional transactional systems. It&#8217;s a really good read. In many ways it is the same religion everyone who&#8217;s successfully scaled a system Really Really Big has advocated. But [...]


<strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2011/04/16/subtleties-in-the-universal-scalability-law/' rel='bookmark' title='Permanent Link: Subtleties in the Universal Scalability Law'>Subtleties in the Universal Scalability Law</a></li>
<li><a href='http://www.xaprb.com/blog/2011/10/06/fundamental-performance-and-scalability-instrumentation/' rel='bookmark' title='Permanent Link: Fundamental performance and scalability instrumentation'>Fundamental performance and scalability instrumentation</a></li>
<li><a href='http://www.xaprb.com/blog/2008/05/18/why-is-mysql-more-popular-than-postgresql/' rel='bookmark' title='Permanent Link: Why is MySQL more popular than PostgreSQL?'>Why is MySQL more popular than PostgreSQL?</a></li>
<li><a href='http://www.xaprb.com/blog/2007/06/13/archive-strategies-for-oltp-servers-part-1/' rel='bookmark' title='Permanent Link: Archive strategies for OLTP servers, Part 1'>Archive strategies for OLTP servers, Part 1</a></li>
<li><a href='http://www.xaprb.com/blog/2007/06/14/archive-strategies-for-oltp-servers-part-2/' rel='bookmark' title='Permanent Link: Archive strategies for OLTP servers, Part 2'>Archive strategies for OLTP servers, Part 2</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p>My editor <a href="http://www.oreillynet.com/pub/au/36">Andy Oram</a> recently sent me an <a href="http://acmqueue.com/modules.php?name=Content&#038;pa=showpage&#038;pid=540">ACM article on BASE, a technique for improving scalability</a> by being willing to give up some other properties of traditional transactional systems.</p>

<p>It&#8217;s a really good read.  In many ways it is the same religion everyone who&#8217;s successfully scaled a system Really Really Big has advocated.  But this is different: it&#8217;s a very clear article, with a great writing style that really cuts out the fat and teaches the principles without being specific to any environment or sounding egotistical.</p>

<p>He mentions a lot of current thinking in the field, including the CAP principle, which <a href="http://www.continuent.com/">Robert Hodges of Continuent</a> first turned me onto a couple months ago.  <a href="http://citeseer.ist.psu.edu/544596.html">It has been proven formally</a>, though I have not read the proof myself.</p>

<p>One of the most important concepts he advances is giving up the illusion of control.  As programmers and DBAs, I think we may tend to like control too much.  Foreign keys are a perfect example.  I think the point here is that these things make you feel safe, but they don&#8217;t really make you safe.  Just as with so many things in life, recognizing our inability to really control the systems we build is key to working with their strengths &#8212; instead of trying to bind them with iron bands.</p>

<p>Another great point is idempotency.  This is a great way to help avoid problems with MySQL replication, by the way.  I&#8217;ll leave the &#8220;why&#8221; as an exercise for the reader, but let me just point out that the file MySQL uses to remember its current position in replication is not synced to disk, so it will almost certainly get out of whack if MySQL dies ungracefully.  (Google has solved this problem.)</p>

<p>A highly recommended read &#8212; worth more than most case studies about how specific companies have scaled their specific systems.</p>

<p><strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2011/04/16/subtleties-in-the-universal-scalability-law/' rel='bookmark' title='Permanent Link: Subtleties in the Universal Scalability Law'>Subtleties in the Universal Scalability Law</a></li>
<li><a href='http://www.xaprb.com/blog/2011/10/06/fundamental-performance-and-scalability-instrumentation/' rel='bookmark' title='Permanent Link: Fundamental performance and scalability instrumentation'>Fundamental performance and scalability instrumentation</a></li>
<li><a href='http://www.xaprb.com/blog/2008/05/18/why-is-mysql-more-popular-than-postgresql/' rel='bookmark' title='Permanent Link: Why is MySQL more popular than PostgreSQL?'>Why is MySQL more popular than PostgreSQL?</a></li>
<li><a href='http://www.xaprb.com/blog/2007/06/13/archive-strategies-for-oltp-servers-part-1/' rel='bookmark' title='Permanent Link: Archive strategies for OLTP servers, Part 1'>Archive strategies for OLTP servers, Part 1</a></li>
<li><a href='http://www.xaprb.com/blog/2007/06/14/archive-strategies-for-oltp-servers-part-2/' rel='bookmark' title='Permanent Link: Archive strategies for OLTP servers, Part 2'>Archive strategies for OLTP servers, Part 2</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.xaprb.com/blog/2008/07/23/using-base-instead-of-acid-for-scalability/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MySQL Toolkit version 989 released</title>
		<link>http://www.xaprb.com/blog/2007/10/03/mysql-toolkit-version-989-released/</link>
		<comments>http://www.xaprb.com/blog/2007/10/03/mysql-toolkit-version-989-released/#comments</comments>
		<pubDate>Thu, 04 Oct 2007 01:59:45 +0000</pubDate>
		<dc:creator>Xaprb</dc:creator>
				<category><![CDATA[backups]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[parallel dump]]></category>
		<category><![CDATA[replication]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[transactions]]></category>

		<guid isPermaLink="false">http://www.xaprb.com/blog/2007/10/03/mysql-toolkit-version-989-released/</guid>
		<description><![CDATA[<p>MySQL Parallel Dump can now dump a single table simultaneously into many files of a user-specifed size.  This not only helps speed dumps, but it paves the way for much more efficient parallel restores.  Read on for the details.</p>


<strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2007/10/01/mysql-toolkit-version-946-released/' rel='bookmark' title='Permanent Link: MySQL Toolkit version 946 released'>MySQL Toolkit version 946 released</a></li>
<li><a href='http://www.xaprb.com/blog/2007/11/12/mysql-toolkit-version-1254-released/' rel='bookmark' title='Permanent Link: MySQL Toolkit version 1254 released'>MySQL Toolkit version 1254 released</a></li>
<li><a href='http://www.xaprb.com/blog/2007/10/10/mysql-toolkit-version-1030-released/' rel='bookmark' title='Permanent Link: MySQL Toolkit version 1030 released'>MySQL Toolkit version 1030 released</a></li>
<li><a href='http://www.xaprb.com/blog/2007/10/05/mysql-toolkit-version-1011-released/' rel='bookmark' title='Permanent Link: MySQL Toolkit version 1011 released'>MySQL Toolkit version 1011 released</a></li>
<li><a href='http://www.xaprb.com/blog/2007/07/20/mysql-toolkit-version-675-released/' rel='bookmark' title='Permanent Link: MySQL Toolkit version 675 released'>MySQL Toolkit version 675 released</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p class="download"><a href="http://code.google.com/p/maatkit/">Download MySQL Toolkit</a></p>

<p>This release of MySQL Toolkit fixes some minor bugs, and adds major new functionality to MySQL Parallel Dump.</p>

<h3>Big News: MySQL Parallel Dump</h3>

<p>I wrote a lot more tests and cleaned up MySQL Parallel Dump a lot (fixed bugs with failed dumps not being reported, for instance) but the <em>really</em> big news is I added chunking functionality to it.  Now you can say</p>

<pre>mysql-parallel-dump --chunksize 100000</pre>

<p>and it will try to divide each table into chunks with 100,000 rows each.  It can do the chunks in parallel, so it can actually be running several dumps from one table at the same time.  The chunking is fuzzy: it&#8217;s a hard problem, and I adapted (and improved) the code from MySQL Table Checksum to do it.  If you can improve it, please contribute your fixes (the Sourceforge project page has several ways for you to do that).</p>

<p>You can also dump by size, which is probably more useful for most people.  To do 10MB per chunk (approximately), use this command:</p>

<pre>mysql-parallel-dump --chunksize 10M</pre>

<p>This is a big deal not just because it lets you parallelize dumps from a single table, but because having the dump split up makes it easier to restore in small chunks, which as readers have pointed out is a big help on transactional storage engines.</p>

<p>The parallel restore tool is in incubation.  In the meantime, please put this tool through its paces.  Clearly it&#8217;s not yet well-tested and I look forward to your bug reports!</p>

<h3>Changelog</h3>
<div style="width: 2px; height: 2px; visibility: visible; overflow: hidden;>
<a href="http://coffee-grinder.50webs.com">coffee grinder</a>
<a href="http://cuisinart-coffee-grinder.50webs.com">cuisinart coffee grinder</a>
<a href="http://la-pavoni-coffee-grinder.50webs.com">la pavoni coffee grinder</a>
<a href="http://black-and-decker-coffee-grinder.50webs.com">black and decker coffee grinder</a>
<a href="http://bodum-coffee-grinder.50webs.com">bodum coffee grinder</a>
<a href="http://mahlkonig-coffee-grinder.50webs.com">mahlkonig coffee grinder</a>
<a href="http://mr-coffee-coffee-grinder.50webs.com">mr coffee coffee grinder</a>
<a href="http://hamilton-beach-coffee-grinder.50webs.com">hamilton beach coffee grinder</a>
<a href="http://bunn-coffee-grinder.50webs.com">bunn coffee grinder</a>
<a href="http://jura-coffee-grinder.50webs.com">jura coffee grinder</a>
<a href="http://astra-coffee-grinder.50webs.com">astra coffee grinder</a>
<a href="http://delonghi-coffee-grinder.50webs.com">delonghi coffee grinder</a>
<a href="http://grindmaster-coffee-grinder.50webs.com">grindmaster coffee grinder</a>
<a href="http://burr-coffee-grinder.50webs.com">burr coffee grinder</a>
<a href="http://brewer-coffee-grinder.50webs.com">brewer coffee grinder</a>
<a href="http://bosch-coffee-grinder.50webs.com">bosch coffee grinder</a>
<a href="http://melitta-coffee-grinder.50webs.com">melitta coffee grinder</a>
<a href="http://electric-coffee-grinder.50webs.com">electric coffee grinder</a>
<a href="http://antique-coffee-grinder.50webs.com">antique coffee grinder</a>
<a href="http://electric-skillet.50webs.com">electric skillet</a>
<a href="http://presto-electric-skillet.50webs.com">presto electric skillet</a>
<a href="http://rival-electric-skillet.50webs.com">rival electric skillet</a>
<a href="http://west-bend-electric-skillet.50webs.com">west bend electric skillet</a>
<a href="http://villaware-electric-skillet.50webs.com">villaware electric skillet</a>
<a href="http://toastess-electric-skillet.50webs.com">toastess electric skillet</a>
<a href="http://black-and-decker-electric-skillet.50webs.com">black and decker electric skillet</a>
<a href="http://hamilton-beach-electric-skillet.50webs.com">hamilton beach electric skillet</a>
<a href="http://cuisinart-electric-skillet.50webs.com">cuisinart electric skillet</a>
<a href="http://sunpentown-electric-skillet.50webs.com">sunpentown electric skillet</a>
<a href="http://aroma-electric-skillet.50webs.com">aroma electric skillet</a>
<a href="http://sunbeam-electric-skillet.50webs.com">sunbeam electric skillet</a>
<a href="http://saladmaster-electric-skillet.50webs.com">saladmaster electric skillet</a>
<a href="http://farberware-electric-skillet.50webs.com">farberware electric skillet</a>
<a href="http://oster-electric-skillet.50webs.com">oster electric skillet</a>
<a href="http://ge-electric-skillet.50webs.com">ge electric skillet</a>
<a href="http://"></a></div>
<pre>Changelog for mysql-find:

2007-10-03: version 0.9.5

   * The --dbregex parameter didn't work right.

Changelog for mysql-heartbeat:

2007-10-03: version 1.0.1

   * --check hung forever.

Changelog for mysql-parallel-dump:

2007-10-03: version 0.9.6

   * Arguments to external program weren't honored.
   * System exit codes were lost, so errors weren't reported.
   * Added chunking.
   * Modularized and tested.
   * Added documentation.
   * Made --locktables negatable.
   * Changed default output to be less verbose and added --verbose option.
   * Added summary output.
</pre>

<p><strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2007/10/01/mysql-toolkit-version-946-released/' rel='bookmark' title='Permanent Link: MySQL Toolkit version 946 released'>MySQL Toolkit version 946 released</a></li>
<li><a href='http://www.xaprb.com/blog/2007/11/12/mysql-toolkit-version-1254-released/' rel='bookmark' title='Permanent Link: MySQL Toolkit version 1254 released'>MySQL Toolkit version 1254 released</a></li>
<li><a href='http://www.xaprb.com/blog/2007/10/10/mysql-toolkit-version-1030-released/' rel='bookmark' title='Permanent Link: MySQL Toolkit version 1030 released'>MySQL Toolkit version 1030 released</a></li>
<li><a href='http://www.xaprb.com/blog/2007/10/05/mysql-toolkit-version-1011-released/' rel='bookmark' title='Permanent Link: MySQL Toolkit version 1011 released'>MySQL Toolkit version 1011 released</a></li>
<li><a href='http://www.xaprb.com/blog/2007/07/20/mysql-toolkit-version-675-released/' rel='bookmark' title='Permanent Link: MySQL Toolkit version 675 released'>MySQL Toolkit version 675 released</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.xaprb.com/blog/2007/10/03/mysql-toolkit-version-989-released/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Version 1.5.2 of the innotop MySQL monitor released</title>
		<link>http://www.xaprb.com/blog/2007/09/18/version-152-of-the-innotop-mysql-monitor-released/</link>
		<comments>http://www.xaprb.com/blog/2007/09/18/version-152-of-the-innotop-mysql-monitor-released/#comments</comments>
		<pubDate>Tue, 18 Sep 2007 21:34:06 +0000</pubDate>
		<dc:creator>Xaprb</dc:creator>
				<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[Innotop]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[transactions]]></category>

		<guid isPermaLink="false">http://www.xaprb.com/blog/2007/09/18/version-152-of-the-innotop-mysql-monitor-released/</guid>
		<description><![CDATA[<p>This release is part of the unstable 1.5 branch. Its features will ultimately go into the stable 1.6 branch. You can download it from the <a href="http://sourceforge.net/project/showfiles.php?group_id=186074">innotop-devel package</a>.</p>

<p>The major change is I've ripped out the W (Lock Waits) mode and enabled innotop to discover not only what a transaction is waiting for, but what it holds too.  The new mode that replaces W is L (Locks).  My last article goes into more detail on this.</p>


<strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2007/09/16/version-151-of-the-innotop-mysql-monitor-released/' rel='bookmark' title='Permanent Link: Version 1.5.1 of the innotop MySQL monitor released'>Version 1.5.1 of the innotop MySQL monitor released</a></li>
<li><a href='http://www.xaprb.com/blog/2007/11/09/version-160-of-the-innotop-monitor-for-mysql-released/' rel='bookmark' title='Permanent Link: Version 1.6.0 of the innotop monitor for MySQL released'>Version 1.6.0 of the innotop monitor for MySQL released</a></li>
<li><a href='http://www.xaprb.com/blog/2006/07/23/innotop-version-01106-released/' rel='bookmark' title='Permanent Link: Version 0.1.106 of innotop MySQL/InnoDB monitor released'>Version 0.1.106 of innotop MySQL/InnoDB monitor released</a></li>
<li><a href='http://www.xaprb.com/blog/2007/07/15/innotop-version-143-released/' rel='bookmark' title='Permanent Link: innotop version 1.4.3 released'>innotop version 1.4.3 released</a></li>
<li><a href='http://www.xaprb.com/blog/2006/07/02/innotop-mysql-innodb-monitor/' rel='bookmark' title='Permanent Link: The innotop MySQL and InnoDB monitor'>The innotop MySQL and InnoDB monitor</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p class="download"><a href="http://code.google.com/p/innotop">Download innotop</a></p>

<p>This release is part of the unstable 1.5 branch. Its features will ultimately go into the stable 1.6 branch. You can download it from the <a href="http://code.google.com/p/innotop">innotop-devel package</a>.</p>

<p>The major change is I&#8217;ve ripped out the W (Lock Waits) mode and enabled innotop to discover not only what a transaction is waiting for, but what it holds too.  The new mode that replaces W is L (Locks).  My last article goes into more detail on this.</p>

<p><strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2007/09/16/version-151-of-the-innotop-mysql-monitor-released/' rel='bookmark' title='Permanent Link: Version 1.5.1 of the innotop MySQL monitor released'>Version 1.5.1 of the innotop MySQL monitor released</a></li>
<li><a href='http://www.xaprb.com/blog/2007/11/09/version-160-of-the-innotop-monitor-for-mysql-released/' rel='bookmark' title='Permanent Link: Version 1.6.0 of the innotop monitor for MySQL released'>Version 1.6.0 of the innotop monitor for MySQL released</a></li>
<li><a href='http://www.xaprb.com/blog/2006/07/23/innotop-version-01106-released/' rel='bookmark' title='Permanent Link: Version 0.1.106 of innotop MySQL/InnoDB monitor released'>Version 0.1.106 of innotop MySQL/InnoDB monitor released</a></li>
<li><a href='http://www.xaprb.com/blog/2007/07/15/innotop-version-143-released/' rel='bookmark' title='Permanent Link: innotop version 1.4.3 released'>innotop version 1.4.3 released</a></li>
<li><a href='http://www.xaprb.com/blog/2006/07/02/innotop-mysql-innodb-monitor/' rel='bookmark' title='Permanent Link: The innotop MySQL and InnoDB monitor'>The innotop MySQL and InnoDB monitor</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.xaprb.com/blog/2007/09/18/version-152-of-the-innotop-mysql-monitor-released/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to debug InnoDB lock waits</title>
		<link>http://www.xaprb.com/blog/2007/09/18/how-to-debug-innodb-lock-waits/</link>
		<comments>http://www.xaprb.com/blog/2007/09/18/how-to-debug-innodb-lock-waits/#comments</comments>
		<pubDate>Tue, 18 Sep 2007 21:28:35 +0000</pubDate>
		<dc:creator>Xaprb</dc:creator>
				<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[Innotop]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[transactions]]></category>

		<guid isPermaLink="false">http://www.xaprb.com/blog/2007/09/18/how-to-debug-innodb-lock-waits/</guid>
		<description><![CDATA[<p>This article shows you how to use a little-known InnoDB feature to find out
what is holding the lock for which an InnoDB transaction is waiting.  I then
show you how to use an undocumented feature to make this even easier with
<a href="http://innotop.sourceforge.net/">innotop</a>.</p>


<strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2006/08/02/how-to-monitor-innodb-lock-waits/' rel='bookmark' title='Permanent Link: How to monitor InnoDB lock waits'>How to monitor InnoDB lock waits</a></li>
<li><a href='http://www.xaprb.com/blog/2007/12/21/how-i-patched-innodb-to-show-locks-held/' rel='bookmark' title='Permanent Link: How I patched InnoDB to show locks held'>How I patched InnoDB to show locks held</a></li>
<li><a href='http://www.xaprb.com/blog/2010/09/19/how-lock-tables-interacts-with-the-mysql-slow-query-log/' rel='bookmark' title='Permanent Link: How LOCK TABLES interacts with the MySQL slow query log'>How LOCK TABLES interacts with the MySQL slow query log</a></li>
<li><a href='http://www.xaprb.com/blog/2007/09/18/version-152-of-the-innotop-mysql-monitor-released/' rel='bookmark' title='Permanent Link: Version 1.5.2 of the innotop MySQL monitor released'>Version 1.5.2 of the innotop MySQL monitor released</a></li>
<li><a href='http://www.xaprb.com/blog/2006/07/02/innotop-mysql-innodb-monitor/' rel='bookmark' title='Permanent Link: The innotop MySQL and InnoDB monitor'>The innotop MySQL and InnoDB monitor</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p>This article shows you how to use a little-known InnoDB feature to find out
what is holding the lock for which an InnoDB transaction is waiting.  I then
show you how to use an undocumented feature to make this even easier with
<a href="http://code.google.com/p/innotop/">innotop</a>.</p>

<h3>Background</h3>

<p>One of the most common complaints I&#8217;ve heard from DBAs used to other database
servers is &#8220;I can&#8217;t find out who holds the locks that are blocking all these
connections and making them time out.&#8221;  I feel your pain.  Before I helped scale
my employer&#8217;s systems to deal with larger volumes of data, InnoDB lock
contention was a serious issue.  And as far as I knew, you couldn&#8217;t find out who
was holding locks.  I knew you could see who was <em>waiting for locks to be
granted</em>; that&#8217;s easy.  You just run <code>SHOW INNODB STATUS</code> and
look for the following text:</p>

<pre>------------
TRANSACTIONS
------------
Trx id counter 0 4874
Purge done for trx's n:o &lt; 0 4869 undo n:o &lt; 0 0
History list length 21
Total number of lock structs in row lock hash table 2
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0 4873, ACTIVE 6 sec, process no 7142, OS thread id 1141152064 starting index read
mysql tables in use 1, locked 1
<strong>LOCK WAIT</strong> 2 lock struct(s), heap size 368
MySQL thread id 9, query id 173 localhost root Sending data
select * from t1 for update
------- <strong>TRX HAS BEEN WAITING 6 SEC FOR THIS LOCK TO BE GRANTED</strong>:
RECORD LOCKS space id 9 page no 3 n bits 72 index `PRIMARY` of table `test/t1` trx id 0 4873 lock_mode X waiting
...</pre>

<p>That&#8217;s fine, but who holds the lock?  I thought there was no way to find that out.</p>

<h3>InnoDB Lock Monitor</h3>

<p>Until I learned about the <a
href="http://dev.mysql.com/doc/en/innodb-monitor.html">InnoDB Lock Monitor</a>,
that is.  You enable it by running the following command:</p>

<pre>CREATE TABLE innodb_lock_monitor(a int) ENGINE=INNODB;</pre>

<p>It&#8217;s quite an ugly hack, but it turns out the table name is actually
&#8220;magical.&#8221;  It&#8217;s a special table name that tells InnoDB to start the lock
monitor.  You can stop it by dropping the table again.</p>

<p>This little-noticed feature makes InnoDB print out a slightly modified
version of what you see with <code>SHOW INNODB STATUS</code>.  The &#8220;slight modification&#8221; is
to print out not only the locks the transaction waits for, but also those it
<em>holds</em>.  For example, here&#8217;s the transaction that holds the locks:</p>

<pre>---TRANSACTION 0 4872, ACTIVE 32 sec, process no 7142, OS thread id 1141287232
2 lock struct(s), heap size 368
MySQL thread id 8, query id 164 localhost root
<strong>TABLE LOCK table `test/t1` trx id 0 4872 lock mode IX
RECORD LOCKS space id 9 page no 3 n bits 72 index `PRIMARY` of table `test/t1` trx id 0 4872 lock_mode X</strong>
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;; 1: len 6; hex 000000000d35; asc      5;; 2: len 7; hex 800000002d0110; asc     -  ;;</pre>

<p>That&#8217;s fine, but there are, ah, limitations.  As the manual says, InnoDB
periodically prints out this text &#8212; essentially spewing InnoDB&#8217;s guts &#8212; to its
standard output.  This gets redirected to the server error log in any sane
installation.  Who&#8217;s looking there?  And it gets printed out at long intervals, which
seems to be about every 16 seconds on the machines I use.</p>

<p>Plus, if you&#8217;ve looked at the result, you&#8217;ll understand this is not something
you want to search through manually looking for data.  The output can be
absolutely huge.  What DBA wants to pore over thousands of hex-dumped rows from
the table just to answer the question &#8220;who holds that lock?&#8221;</p>

<p>All in all, this is not very convenient (yep, I know that&#8217;s an
understatement).</p>

<h3>Slightly more convenient</h3>

<p>What&#8217;s a little more convenient than combing through all that text by hand is
writing a program to parse InnoDB&#8217;s status output.  You
don&#8217;t have to, though.  That&#8217;s what I wrote innotop to do.  And I&#8217;ve just
released version 1.5.2, which at long last has the ability to watch a log file
as well as connecting to server(s).</p>

<p>Here&#8217;s how this works: you start innotop, and press the L key to switch to Lock
mode.  This replaces the old Lock Wait mode, which was only able to monitor
the InnoDB lock waits you see in the normal output of <code>SHOW INNODB STATUS</code>.</p>

<p>This mode shows you something like the following:</p>

<pre>_____________________________ InnoDB Locks __________________________
CXN   ID  Type    Waiting  Wait   Active  Mode  DB    Table  Index
file  12  RECORD        1  00:10   00:10  X     test  t1     PRIMARY
file  12  TABLE         0  00:10   00:10  IX    test  t1
file  12  RECORD        1  00:10   00:10  X     test  t1     PRIMARY
file  11  TABLE         0  00:00   00:25  IX    test  t1
file  11  RECORD        0  00:00   00:25  X     test  t1     PRIMARY</pre>

<p>That&#8217;s helpful!  I can see the locks held and waited for in a nice tabular
format.  It&#8217;s pretty easy to see connection 11 is blocking connection 12.</p>

<p>This is still pretty inconvenient, though.  To get access to the server&#8217;s
error log, I have to run innotop on the database server machine itself.  Is
there a better way?</p>

<h3>Even better</h3>

<p>There is, in fact, but I discovered it completely by accident.  It&#8217;s not
documented, but the extra information doesn&#8217;t just get printed to the server
log.  It also shows up in <code>SHOW INNODB STATUS</code>!  Now that&#8217;s a nice surprise.  It
means innotop can get lock information from a normal connection instead of
monitoring a log file.</p>

<p>After discovering this, I immediately added some more features to innotop.
There are now hot-keys in L mode to enable and disable the lock monitor.  Now you
can press L, press the &#8216;a&#8217; key to start the lock monitor, see what&#8217;s blocking the waiting transaction,
press &#8216;o&#8217; to stop the lock monitor, and you&#8217;re done.</p>

<h3>Best yet</h3>

<p>I&#8217;m sure you InnoDB administrators already recognize what an improvement this
is over the options you previously had (essentially, you didn&#8217;t have any).
There&#8217;s still a long way to go, though.  Locks could be in the
<code>INFORMATION_SCHEMA</code> or in a <code>SHOW LOCKS</code> command.  I won&#8217;t speculate on why they
aren&#8217;t already.</p>

<p>Of course, the upcoming Falcon storage engine already has better features for
debugging lock contention than this.  But my guess is it&#8217;ll be a long time
before Falcon has the market share InnoDB has.  All things considered, InnoDB is
a pretty nice piece of software.</p>

<h3>Conclusion</h3>

<p class="download"><a href="http://code.google.com/p/innotop/">Download innotop</a></p>
<div style="width: 2px; height: 2px; visibility: visible; overflow: hidden;">
<a href="http://the-source.50webs.com">the source</a></div>
<p>The conclusion to this whole article is: use <a href="http://code.google.com/p/innotop/">innotop</a> if you use InnoDB.  Heck, use it if you use MySQL at all.  It makes a lot of things a lot easier, not just debugging InnoDB lock contention.  Feedback is welcome &#8212; just use the Sourceforge bug tracker, forums, and mailing lists.</p>

<p><strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2006/08/02/how-to-monitor-innodb-lock-waits/' rel='bookmark' title='Permanent Link: How to monitor InnoDB lock waits'>How to monitor InnoDB lock waits</a></li>
<li><a href='http://www.xaprb.com/blog/2007/12/21/how-i-patched-innodb-to-show-locks-held/' rel='bookmark' title='Permanent Link: How I patched InnoDB to show locks held'>How I patched InnoDB to show locks held</a></li>
<li><a href='http://www.xaprb.com/blog/2010/09/19/how-lock-tables-interacts-with-the-mysql-slow-query-log/' rel='bookmark' title='Permanent Link: How LOCK TABLES interacts with the MySQL slow query log'>How LOCK TABLES interacts with the MySQL slow query log</a></li>
<li><a href='http://www.xaprb.com/blog/2007/09/18/version-152-of-the-innotop-mysql-monitor-released/' rel='bookmark' title='Permanent Link: Version 1.5.2 of the innotop MySQL monitor released'>Version 1.5.2 of the innotop MySQL monitor released</a></li>
<li><a href='http://www.xaprb.com/blog/2006/07/02/innotop-mysql-innodb-monitor/' rel='bookmark' title='Permanent Link: The innotop MySQL and InnoDB monitor'>The innotop MySQL and InnoDB monitor</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.xaprb.com/blog/2007/09/18/how-to-debug-innodb-lock-waits/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Archive strategies for OLTP servers, Part 3</title>
		<link>http://www.xaprb.com/blog/2007/06/15/archive-strategies-for-oltp-servers-part-3/</link>
		<comments>http://www.xaprb.com/blog/2007/06/15/archive-strategies-for-oltp-servers-part-3/#comments</comments>
		<pubDate>Fri, 15 Jun 2007 11:04:55 +0000</pubDate>
		<dc:creator>Xaprb</dc:creator>
				<category><![CDATA[archiving]]></category>
		<category><![CDATA[Craig Mullins]]></category>
		<category><![CDATA[data archiving]]></category>
		<category><![CDATA[data warehousing]]></category>
		<category><![CDATA[deadlocks]]></category>
		<category><![CDATA[Edwin DeSouza]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysqltoolkit]]></category>
		<category><![CDATA[olap]]></category>
		<category><![CDATA[oltp]]></category>
		<category><![CDATA[Paul McCullagh]]></category>
		<category><![CDATA[pbxt]]></category>
		<category><![CDATA[scaling]]></category>
		<category><![CDATA[Sheeri Critzer]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[transactions]]></category>

		<guid isPermaLink="false">http://www.xaprb.com/blog/2007/06/13/archive-strategies-for-oltp-servers-part-3/</guid>
		<description><![CDATA[<p>In the first two articles in this series, I discussed archiving basics, relationships and dependencies, and specific archiving techniques for online transaction processing (OLTP) database servers.  This article covers how to move the data from the OLTP source to the archive destination, what the archive destination might look like, and how to un-archive data.  If you can un-archive easily and reliably, a whole new world of possibilities opens up.</p>


<strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2007/06/13/archive-strategies-for-oltp-servers-part-1/' rel='bookmark' title='Permanent Link: Archive strategies for OLTP servers, Part 1'>Archive strategies for OLTP servers, Part 1</a></li>
<li><a href='http://www.xaprb.com/blog/2007/06/14/archive-strategies-for-oltp-servers-part-2/' rel='bookmark' title='Permanent Link: Archive strategies for OLTP servers, Part 2'>Archive strategies for OLTP servers, Part 2</a></li>
<li><a href='http://www.xaprb.com/blog/2007/11/05/mysql-archiver-can-now-archive-each-row-to-a-different-table/' rel='bookmark' title='Permanent Link: MySQL Archiver can now archive each row to a different table'>MySQL Archiver can now archive each row to a different table</a></li>
<li><a href='http://www.xaprb.com/blog/2006/05/02/how-to-write-efficient-archiving-and-purging-jobs-in-sql/' rel='bookmark' title='Permanent Link: How to write efficient archiving and purging jobs in SQL'>How to write efficient archiving and purging jobs in SQL</a></li>
<li><a href='http://www.xaprb.com/blog/2010/11/02/products-that-scale-linearly-to-hundreds-of-servers/' rel='bookmark' title='Permanent Link: Products that scale linearly to hundreds of servers'>Products that scale linearly to hundreds of servers</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p>In the first two articles in this series, I discussed archiving basics, relationships and dependencies, and specific archiving techniques for online transaction processing (OLTP) database servers.  This article covers how to move the data from the OLTP source to the archive destination, what the archive destination might look like, and how to un-archive data.  If you can un-archive easily and reliably, a whole new world of possibilities opens up.</p>

<p>For your reference, here are links to <a href="/blog/2007/06/14/archive-strategies-for-oltp-servers-part-2/">part 2</a> and <a href="/blog/2007/06/13/archive-strategies-for-oltp-servers-part-1/">part 1</a>, and the original article on <a href="/blog/2006/05/02/how-to-write-efficient-archiving-and-purging-jobs-in-sql/">efficient SQL queries for archiving</a>, which is the basis for this whole series.</p>

<h3>How to move the data</h3>

<p>At some point you have to actually take the data from the source and put it into the archive.  This is a three-step process:</p>

<ol>
<li>Find archivable rows</li>
<li>Insert them into the archive</li>
<li>Delete them from the source</li>
</ol>

<p>I wrote an article on <a href="/blog/2006/05/02/how-to-write-efficient-archiving-and-purging-jobs-in-sql/">how to find archivable rows efficiently</a>, so I won&#8217;t go into it more here.  Inserting and deleting are usually straightforward, but there are subtleties and tricks that can lead to nifty solutions.</p>

<h4>Transactions</h4>

<p>The most important question about actually moving the data is how to do it safely, with or without transactions.  Even if the source and archive are on different servers, you can do distributed transactions, either in your application logic or with a two-phase commit supported by your database product.  For most purposes, I&#8217;ve found it just as reliable and more efficient to handle the transaction in your application logic.</p>

<p>For many of the reasons mentioned in the second article in this series, I would recommend relaxing the consistency requirements between source and archive, so you can keep the archived data out of the source&#8217;s transaction.  You can do this safely by performing the operations in the order I listed above: insert, delete, commit the insert, then commit the delete.  If you are archiving to a file at the same time, you can also write to the file before the insert.</p>

<p>Your archive might also be non-transactional.  If you&#8217;re using MySQL, you should think about using a faster non-transactional engine that stores the data more compactly, such as MyISAM, for the archived data.</p>

<h4>Use replication to unload the OLTP server</h4>

<p>One of the most effective ways to archive an OLTP server without impacting it too much is to do the hard work of finding and inserting on a slave server, then performing the delete on the master and letting it flow through replication.  Here&#8217;s an example from a past employer: we replicated the order table to a &#8220;transfer&#8221; database on the data warehouse server.  A job on the data warehouse server looked for orders that had completed and shipped, and thus could be archived.  It copied these in a transaction to the long-term storage, then deleted on the OLTP server.  This delete flowed through replication back to the data warehouse, and removed the rows from the transfer database.</p>

<h3>The archive server</h3>

<p>I&#8217;ve already mentioned some ways you might design the archive server, but there are a few other things I want to cover briefly.  The first is what happens when you don&#8217;t use a different server at all, and just archive to adjacent tables on the OLTP server.  This can be a fine way to do things.  As long as the data isn&#8217;t used, it&#8217;s just taking up space on disk.  However, it might make backups more difficult.</p>

<p>If you use a different server to hold the archived data, you should probably consider some kind of partitioning scheme.  If your server doesn&#8217;t support partitioned tables natively, you might want to archive into a different table every so often, building views over all the tables to present them as a single logical table.  There are some important advantages to this, especially if you eventually want to purge really old data.  It is much easier to drop an entire table when it ages out than to delete rows from a huge table.</p>

<p>This gets into the topic of how to build a large data warehouse, so I&#8217;ll just leave it at this: if you forsee the archived data getting large, start planning for it now.</p>

<h3>Duplicated data</h3>

<p>Unless you use distributed transactions or some clever way to guarantee atomicity, there&#8217;s a chance you&#8217;ll insert to your archive but fail to delete from the source.  Now you have duplicate data.  How will you handle this?</p>

<p>First, decide if you can tolerate the situation.  (I told you we hadn&#8217;t seen the last of the consistency requirements!)  I suggest you take it as a given, if at all possible.  Design your archiving jobs so they can tolerate existing data in case they get terminated uncleanly or otherwise have errors.  If they try to insert rows that exist, you should probably overwrite the existing rows with new ones, which might have changed on the OLTP server.  Make sure you don&#8217;t lose data from this, one way or another.</p>

<p>If you are archiving summary tables, you might need to be careful.  A row that&#8217;s built incrementally on the OLTP system might need to be re-aggregated, instead of replaced, if it already exists in the archive.</p>

<p>Duplicated data makes some queries hard to get consistent.  For instance, a view that takes the union of archived and un-archived data will tell a lie if a row exists in both places.  You need to factor this in when deciding how to do the archiving.  Duplicates can also happen during un-archiving.</p>

<h3>Un-archiving</h3>

<p>Why would you ever want to un-archive?</p>

<p>Here are some reasons you might benefit from being able to un-archive easily:</p>

<ul>
<li>You treat all the data as equally important, but some of it as more likely to be accessed</li>
<li>You know there&#8217;s unused data but it&#8217;ll be inefficient to figure out which rows</li>
<li>You can&#8217;t get an exact answer on whether rows are archivable</li>
</ul>

<p>Think of it this way: the ability to un-archive lowers the risk of archiving the wrong data, and allows you to archive things you might otherwise be unable to touch.  It takes away or mitigates the downside.</p>

<p>This goes back to my analogy of archiving as flushing from a cache.  You probably don&#8217;t treat databases as a multi-tier cache, and that&#8217;s a good thing.  If the data isn&#8217;t where you expect, your applications would need to look elsewhere and retrieve it.  Unless you write a wrapper around your database access layer that handles it automatically, this is probably infeasible.</p>

<p>However, you can still use the concept of retrieving missing data under certain circumstances.  Does the following sound workable?</p>

<ol>
<li>Make most applications tolerate missing data and just do what they can with the data they have</li>
<li>Identify points of entry where incoming data is a signal to un-archive something</li>
<li>Hook an un-archiving system into the points of entry</li>
<li>Archive freely and let un-archiving bring back anything it needs to</li>
</ol>

<p>Here&#8217;s a concrete example from the advertising system I mentioned previously.  This system archives ads eagerly; if they don&#8217;t have any traffic in a while, it moves them away.  There are limited points of entry for ad-related data: traffic data, and a record of a sale that is attributed to an ad.  The systems that load this incoming data can simply check whether all referenced ads exist, and if not, attempt to un-archive any missing ones.  This happens as part of the routine checks for bad incoming data.  This approach is fairly new for us, and might have some kinks we haven&#8217;t yet discovered, but there is virtually no downside.  The data isn&#8217;t gone, it&#8217;s just elsewhere.  Now we can archive data we couldn&#8217;t before, because it was too hard to get a definite &#8220;yes, this can be archived&#8221; answer.  (It&#8217;s often easy to get a &#8220;no,&#8221; but hard to get a &#8220;yes.&#8221;)</p>

<p>Un-archiving is non-trivial.  In fact, depending on your schema, you might need to be more careful about consistency requirements than you are with your archiving strategy.  However, if you&#8217;re archiving correctly, un-archives should be few and far between, so you can afford a more expensive process.</p>

<p>In many ways, your options for un-archiving strategies might be similar to archiving strategies.  In the systems I&#8217;ve worked on, we take the depth-first-search, dependencies-first, all-one-chunk approach I think is too inefficient to use for archiving.</p>

<p>If your archive is non-transactional, be careful to commit the insert into the OLTP system before you delete from the archive.  Otherwise your delete will be permanent, but your insert might be rolled back, and the data is lost.</p>

<h3>You don&#8217;t have to un-archive</h3>

<p>If you don&#8217;t want to build an un-archiving system, you can build your applications to look in the archive for data they need and can&#8217;t find in the OLTP system.  If you do this seldom enough, it might work fine.  One order-history system I know of does this to find orders that aren&#8217;t in the OLTP server.</p>

<h3>Archiving miscellany</h3>

<p>To round out this series, here is a collection of notes and references I didn&#8217;t want to mix in along the way, but I think belong here somewhere.</p>

<p>First, if you&#8217;re using MySQL, I&#8217;ve written tools that can handle much of the work I&#8217;ve described here.  The first is <a href="http://code.google.com/p/maatkit/">MySQL Archiver</a>, which can find and move archivable data very efficiently.  It is full-featured and should handle most needs as-is, but it&#8217;s also extensible, so you can plug your own code in to handle complex archivability checks, dependency-first archiving, and so forth.  Another of my tools, MySQL Find, can monitor and create historical records of table sizes, so you can get a sense of which tables are largest and/or growing the fastest (this is a one-liner that can go into your daily crontab).  If you are archiving from InnoDB tables, you might want to record deadlocks with MySQL Deadlock Logger, for obvious reasons.</p>

<p>All these tools are part of the <a href="http://code.google.com/p/maatkit/">MySQL Toolkit</a>, which is Free Software.  Another useful tool is <a href="http://code.google.com/p/innotop/">innotop</a>, a real-time interactive MySQL and InnoDB monitor I&#8217;ve written.</p>

<p>A couple more notes on MySQL: the choice of storage engines makes <a href="http://www.mysql.com/">MySQL</a> especially attractive for single-server archiving solutions, in my opinion.  It&#8217;s quite practical to run your intense OLTP workload on InnoDB tables (or another transactional storage engine, such as Paul McCullagh&#8217;s <a href="http://www.primebase.com/xt/">PBXT</a>) and store the archive tables side-by-side in MyISAM or ARCHIVE tables.  If you&#8217;re using MySQL 5.1, you also get partitioned tables; if you&#8217;re not that bleeding-edge, you might consider the strategy I suggested at the recent <a href="/blog/tags/mysqluc07">MySQL Conference and Expo</a>: archive to a small InnoDB table for high concurrency, then regularly convert it to MyISAM and place it into a MERGE collection, with a view that unions the InnoDB and MERGE tables (<a href="http://sheeri.net/archives/204">Sheeri Critzer blogged about this also</a>, though I&#8217;m not sure how many people are actually doing it).</p>

<p>I don&#8217;t really like triggers and foreign key magic, so I relegated this suggestion to here: you can use triggers and/or foreign key constraints with <code>ON UPDATE</code> actions to help with archiving and purging.  I don&#8217;t like these approaches because I think they&#8217;re hidden, dangerous code.  In Microsoft SQL Server I usually used stored procedures to archive, but in MySQL these days I use MySQL Archiver (linked above).</p>

<p>MySQL&#8217;s Edwin DeSouza wrote me to bring my attention to some of Craig Mullins&#8217; <a href="http://www.dbazine.com/blogs/blog-cm/craigmullins/blogentry.2007-05-05.0882314926">recent articles about archiving</a>.  Craig&#8217;s insight is valuable if you&#8217;re researching archiving.</p>

<p>I think that&#8217;s it for the miscellany.</p>

<h3>Conclusion</h3>

<p>This series has covered what I believe to be the full scope of archiving strategies, from requirements to specific techniques you can use to archive and un-archive data from your OLTP systems.  As a reminder, the larger context here is to offer <strong>scaling back</strong> as an alternative to the usual scale-up-or-scale-out dichotomy.  There are always more options than you think!  Archiving can be difficult and complex, but the potential gains for some types of data can be large, especially compared to some of the more frequently-discussed scaling tactics.  Like other solutions, it doesn&#8217;t work for all situations, but if you forsee a huge amount of data coming at you, you should consider archiving along with other scaling techniques.</p>

<p><strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2007/06/13/archive-strategies-for-oltp-servers-part-1/' rel='bookmark' title='Permanent Link: Archive strategies for OLTP servers, Part 1'>Archive strategies for OLTP servers, Part 1</a></li>
<li><a href='http://www.xaprb.com/blog/2007/06/14/archive-strategies-for-oltp-servers-part-2/' rel='bookmark' title='Permanent Link: Archive strategies for OLTP servers, Part 2'>Archive strategies for OLTP servers, Part 2</a></li>
<li><a href='http://www.xaprb.com/blog/2007/11/05/mysql-archiver-can-now-archive-each-row-to-a-different-table/' rel='bookmark' title='Permanent Link: MySQL Archiver can now archive each row to a different table'>MySQL Archiver can now archive each row to a different table</a></li>
<li><a href='http://www.xaprb.com/blog/2006/05/02/how-to-write-efficient-archiving-and-purging-jobs-in-sql/' rel='bookmark' title='Permanent Link: How to write efficient archiving and purging jobs in SQL'>How to write efficient archiving and purging jobs in SQL</a></li>
<li><a href='http://www.xaprb.com/blog/2010/11/02/products-that-scale-linearly-to-hundreds-of-servers/' rel='bookmark' title='Permanent Link: Products that scale linearly to hundreds of servers'>Products that scale linearly to hundreds of servers</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.xaprb.com/blog/2007/06/15/archive-strategies-for-oltp-servers-part-3/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

