<?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>stevehollis.com &#187; transactions</title>
	<atom:link href="http://www.stevehollis.com/tag/transactions/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.stevehollis.com</link>
	<description>Barking on about PHP, MySQL and Zend Framework</description>
	<lastBuildDate>Mon, 05 Apr 2010 18:07:04 +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>Practical Nested Transactions with Zend_Db and MySQL</title>
		<link>http://www.stevehollis.com/2010/03/practical-nested-transactions-with-zend_db-and-mysql/</link>
		<comments>http://www.stevehollis.com/2010/03/practical-nested-transactions-with-zend_db-and-mysql/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 16:05:35 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[transactions]]></category>
		<category><![CDATA[zend_db]]></category>
		<category><![CDATA[zf]]></category>

		<guid isPermaLink="false">http://www.stevehollis.com/?p=35</guid>
		<description><![CDATA[The need to save dependent or child models appears frequently in object oriented applications. In such cases, it&#8217;s usually desirable to group all the save operations for a parent and its children into a single atomic transaction. Many RDBMS brands support transactions, but few can handle these kind of &#8220;nested&#8221; transactions. This article discusses how [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.stevehollis.com/wp-content/uploads/2010/03/firebug1.png"><img class="alignright size-full wp-image-45" title="Debugging Zend_Db with Firebug" src="http://www.stevehollis.com/wp-content/uploads/2010/03/firebug1.png" alt="Debugging Zend_Db with Firebug" width="300" height="192" /></a>The need to save dependent or child models appears frequently in object oriented applications. In such cases, it&#8217;s usually desirable to group all the save operations for a parent and its children into a single atomic transaction. Many RDBMS brands support transactions, but few can handle these kind of &#8220;nested&#8221; transactions.</p>
<p>This article discusses how to extend Zend_Db_Adapter to give the illusion of nested transactions &#8211; a handy workaround for use in object oriented applications. Although I focus on MySQL, it should be possible to apply these concepts to any other database flavour which supports transactions. There are some limitations to this approach, but I&#8217;ve found it to be very useful in practice.</p>
<h3>A Brief Introduction to Transactions</h3>
<p>You can&#8217;t work with database backed web apps for very long without coming across the concept of database transactions.</p>
<p>Transactions (<a href="http://en.wikipedia.org/wiki/Database_transaction">http://en.wikipedia.org/wiki/Database_transaction</a>) are a way of encapsulating a group of database queries, typically INSERT and UPDATE statements, so that they all must complete successfully in order for the changes to be written (&#8220;committed&#8221;) to the database. If any single query fails, any changes to the database can be &#8220;rolled back&#8221; to how they were when the transaction began.</p>
<p>This has great practical value. Many operations consist of several steps where the changes should only be applied if every step is successful. The classic example is transferring funds between two bank accounts, which is a three stage process:</p>
<ol>
<li>Checking that the sender&#8217;s account has a balance greater than the amount to be transferred.</li>
<li>Subtracting that amount from the sender&#8217;s account</li>
<li>And, finally, adding it to the recipient&#8217;s account.</li>
</ol>
<p>The SQL for this transaction might go something like:<br />
<code></p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;"><span style="color: #990099; font-weight: bold;">START</span> <span style="color: #990099; font-weight: bold;">TRANSACTION</span><span style="color: #000033;">;</span>
<span style="color: #990099; font-weight: bold;">SELECT</span> balance <span style="color: #990099; font-weight: bold;">FROM</span> account <span style="color: #990099; font-weight: bold;">WHERE</span> account_number <span style="color: #CC0099;">=</span> <span style="color: #008080;">123456789</span><span style="color: #000033;">;</span>
<span style="color: #990099; font-weight: bold;">UPDATE</span> account <span style="color: #990099; font-weight: bold;">SET</span> balance <span style="color: #CC0099;">=</span> balance <span style="color: #CC0099;">-</span> <span style="color: #008080;">100.00</span> <span style="color: #990099; font-weight: bold;">WHERE</span> account_number <span style="color: #CC0099;">=</span> <span style="color: #008080;">123456789</span><span style="color: #000033;">;</span>
<span style="color: #990099; font-weight: bold;">UPDATE</span> account <span style="color: #990099; font-weight: bold;">SET</span> balance <span style="color: #CC0099;">=</span> balance <span style="color: #CC0099;">+</span> <span style="color: #008080;">100.00</span> <span style="color: #990099; font-weight: bold;">WHERE</span> account_number <span style="color: #CC0099;">=</span> <span style="color: #008080;">987654321</span><span style="color: #000033;">;</span>
<span style="color: #990099; font-weight: bold;">COMMIT</span><span style="color: #000033;">;</span></pre></div></div>

<p></code><br />
If an error is thrown at any point in the process, the ROLLBACK statement can be used to revert the database to its state before the transaction began.</p>
<p>In an application that doesn&#8217;t use transactions, a typical approach might be to check the return value of each query or enclose it in a try&#8230;catch block:<br />
<code></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">try <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$balance</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fetchOne</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;SELECT `balance` FROM `account` WHERE `account_number` = 123456789&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">update</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'account'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'balance'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Db_Expr<span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;`balance` + 100&quot;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;`account_number` = 123456789&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">update</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'account'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'balance'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Db_Expr<span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;`balance` - 100&quot;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;`account_number` = 987654321&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> catch <span style="color: #009900;">&#40;</span> Zend_Db_Exception <span style="color: #000088;">$e</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$e</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMessage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p></code><br />
The problem with this approach is that although we know the operation failed, we don&#8217;t know <strong>when</strong> it failed. Perhaps the first update statement was executed, but the second one wasn&#8217;t. Perhaps the database connection was lost before we even started. The end result is that we may have introduced inconsistencies into our data that, even with this simple example, are going to be hard to track down and correct.</p>
<p>Using transactions we can ensure that each step is carried out successfully or the whole operation fails.<br />
<code></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">try <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">beginTransaction</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$balance</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fetchOne</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;SELECT `balance` FROM `account` WHERE `account_number` = 123456789&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">update</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'account'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'balance'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Db_Expr<span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;`balance` + 100&quot;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;`account_number` = 123456789&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">update</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'account'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'balance'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Db_Expr<span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;`balance` - 100&quot;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;`account_number` = 987654321&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">commit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> catch <span style="color: #009900;">&#40;</span> Zend_Db_Exception <span style="color: #000088;">$e</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">rollBack</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">throw</span> <span style="color: #000088;">$e</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p></code><br />
By calling the beginTransaction() method, we temporarily delay any actual modifications to the database. If each query is successful, the changes are committed using the commit() method. But if an exception is thrown, the changes are reverted using rollback().</p>
<h3>The Problem</h3>
<p>Although transactions are a useful tool, sadly they don&#8217;t always fit well into an object oriented application.</p>
<p>It&#8217;s common to delegate the actual persistence (inserting and updating) of models to a save method which, in turn, goes on to save child objects. Say we have a simple address book application which allows you to enter multiple notes for each contact. The save method for the Contact model might look something like this:<br />
<code></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> save<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$db</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_db<span style="color: #339933;">;</span>
&nbsp;
    try <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">beginTransaction</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #666666; font-style: italic;">// new model</span>
	    <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">insert</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'contact'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getData</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #666666; font-style: italic;">// existing model</span>
	    <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">update</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'contact'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getData</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">quoteInto</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'`id` = ?'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #666666; font-style: italic;">// save the contact's note</span>
	<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getNotes</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$note</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #000088;">$note</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">commit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> catch <span style="color: #009900;">&#40;</span> Zend_Db_Exception <span style="color: #000088;">$e</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">rollBack</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
         <span style="color: #b1b100;">throw</span> <span style="color: #000088;">$e</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p></code><br />
The save method for the Note class is similar, starting a transaction and saving the individual note.</p>
<p>Herein lies the problem: <strong>attempting to start an new transaction implicitly commits the current transaction</strong> (<a href="http://dev.mysql.com/doc/refman/5.0/en/implicit-commit.html">http://dev.mysql.com/doc/refman/5.0/en/implicit-commit.html</a>). Without ugly hacks which tie the models directly to the database operations, it becomes difficult to establish which object started the transaction and when it should be committed.</p>
<h3>The Solution</h3>
<p><em>Disclaimer: This solution is adapted from the extended Pdo_MySql adapter in Varien&#8217;s Magento e-commerce product. A similar approach is adopted by Bryce Lohr&#8217;s <a title="Nested Table Support" href="http://framework.zend.com/wiki/display/ZFPROP/Nested+Transaction+Support+for+Zend_Db_Adapter_Abstract+-+Bryce+Lohr" target="_blank">Nested Table Support</a> for Zend_Db proposal. You should read Bill Karwin&#8217;s comments about that proposal and understand the limitations of this method before implementing it. <strong>That said</strong>, I still believe this is a useful and practical way of simulating nested transactions and I have used it a number of times.</em></p>
<p>A simple solution to the problem is to keep track of the &#8220;depth&#8221; of the transaction, that is, how many times the beginTransaction() method has been called. That way, we can hold off committing the changes to the database until we are certain that all the save operations have completed successfully.</p>
<p>Since transactions apply to the whole database connection, the most logical place to manage this process is in the DB adapter class. To do this, we extend our adapter class like so:<br />
<code></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> App_Zend_Db_Adapter_Mysqli <span style="color: #000000; font-weight: bold;">extends</span> Zend_Db_Adapter_Mysqli
<span style="color: #009900;">&#123;</span>
    <span style="color: #009933; font-style: italic;">/**
     * Current Transaction Level
     *
     * @var int
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$_transactionLevel</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Begin new DB transaction for connection
     *
     * @return App_Zend_Db_Adapter_Mysqli
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> beginTransaction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_transactionLevel <span style="color: #339933;">===</span> <span style="color: #cc66cc;">0</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            parent<span style="color: #339933;">::</span><span style="color: #004000;">beginTransaction</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_transactionLevel<span style="color: #339933;">++;</span>
&nbsp;
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Commit DB transaction
     *
     * @return App_Zend_Db_Adapter_Mysqli
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> commit<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_transactionLevel <span style="color: #339933;">===</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            parent<span style="color: #339933;">::</span><span style="color: #004000;">commit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_transactionLevel<span style="color: #339933;">--;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Rollback DB transaction
     *
     * @return App_Zend_Db_Adapter_Mysqli
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> rollback<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_transactionLevel <span style="color: #339933;">===</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            parent<span style="color: #339933;">::</span><span style="color: #004000;">rollback</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_transactionLevel<span style="color: #339933;">--;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Get adapter transaction level state. Return 0 if all transactions are complete
     *
     * @return int
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getTransactionLevel<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_transactionLevel<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p></code><br />
Update your bootstrap to use the extended class et voila &#8211; a single START TRANSACTION and COMMIT or ROLLBACK is sent to MySQL, regardless of how many levels of nested pseudo-transactions have been created.</p>
<p><strong>Please Note:</strong></p>
<ul>
<li>It&#8217;s important that each child save() method re-throws the exception so that transaction depth is reduced by successive calls to rollBack(). The end result is that the originally called save() method then performs the actual rollback.</li>
<li>All the tables used in the transaction <strong>must</strong> use a storage engine that supports transactions. For MySQL, this will most likely mean using InnoDB. To convert a MyISAM or other table type to InnoDB, use &#8220;ALTER TABLE table ENGINE = InnoDB&#8221;. It could take some time to rebuild the indexes on large tables. There are other considerations about the use of InnoDB &#8211; please consult the MySQL manual.</li>
<li>If the tables used don&#8217;t support transactions, it&#8217;ll just fail silently. Bad times. I highly recommend using Firebug and Zend_Db_Profiler to monitor database queries during development (see <a href="http://framework.zend.com/manual/en/zend.db.profiler.html">http://framework.zend.com/manual/en/zend.db.profiler.html</a>);</li>
</ul>
<p>I hope you find the above useful &#8211; if so, please leave a comment. If not, please be gentle&#8230; it&#8217;s my first blog post!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevehollis.com/2010/03/practical-nested-transactions-with-zend_db-and-mysql/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
	</channel>
</rss>

