<?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>Webmonkey &#187; Databases</title>
    <atom:link href="http://www.webmonkey.com/category/databases/feed/" rel="self" type="application/rss+xml" />
    <link>http://www.webmonkey.com</link>
    <description>The Web Developer&#039;s Resource</description>
    <lastBuildDate>Mon, 06 May 2013 17:29:19 +0000</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <generator>http://wordpress.org/?v=3.4.2</generator>
    
    <item>
        <title>Behind the Scenes at Instagram: Tools for Building Reliable Web Services</title>
        <link>http://www.webmonkey.com/2012/04/behind-the-scenes-at-instagram-tools-for-building-reliable-web-services/</link>
        <comments>http://www.webmonkey.com/2012/04/behind-the-scenes-at-instagram-tools-for-building-reliable-web-services/#comments</comments>
        <pubDate>Tue, 10 Apr 2012 16:58:59 +0000</pubDate>

                <dc:creator>Scott Gilbertson</dc:creator>

        <guid isPermaLink="false">http://www.webmonkey.com/?p=55514</guid>
        		<category><![CDATA[Backend]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Instagram]]></category>
            <enclosure url="http://www.webmonkey.com/wp-content/uploads/2012/04/Instagram_logo-200x100.png" type="image/png" length="48000" />
                    <description><![CDATA[<div class="rss_thumbnail"><img src="http://www.webmonkey.com/wp-content/uploads/2012/04/Instagram_logo.png" alt="Behind the Scenes at Instagram: Tools for Building Reliable Web Services" /></div>Want to build a web service that sells for a cool billion dollars? Instagram's developers have some advice for you: Choose your tools wisely.]]></description>

            <content:encoded><![CDATA[<p><!-- wpautop enabled --><img class="aligncenter size-full wp-image-55519" title="Instagram_logo" src="http://www.webmonkey.com/wp-content/uploads/2012/04/Instagram_logo.png" alt="" width="200" height="200" />In case you missed it, yesterday <a href="http://www.wired.com/epicenter/2012/04/facebook-buys-instagram/">Facebook acquired Instagram</a>, a photo-sharing service with some 30 million users and hundreds of millions of images on its servers.</p>
<p>The reported sale price of one billion dollars no doubt has many developers dreaming of riches, but how do you build a service and scale it to the size and success of Instagram? At least part of the answer lies in choosing your tools wisely.</p>
<p>Fortunately for outside developers, Instagram&#8217;s devs have been documenting the tools they used all along. The company&#8217;s <a href="http://instagram-engineering.tumblr.com/">engineering blog</a> <a href="http://instagram-engineering.tumblr.com/post/13649370142/what-powers-instagram-hundreds-of-instances-dozens-of">outlined its development stack</a> last year and has further detailed <a href="http://instagram-engineering.tumblr.com/post/12202313862/storing-hundreds-of-millions-of-simple-key-value-pairs">how it uses</a> several of the tools it&#8217;s chosen.</p>
<p>Instagram uses an interesting mashup of tried-and-true technologies alongside more cutting-edge tools, mixing SQL databases with NoSQL tools like Redis, and chosing to host its traditional Ubuntu servers in Amazon&#8217;s cloud.</p>
<p>In a blog post last year Instagram <a href="http://instagram-engineering.tumblr.com/post/13649370142/what-powers-instagram-hundreds-of-instances-dozens-of">outlined its core principles</a> when it comes to chosing tools, writing, &#8220;keep it very simple, don&#8217;t reinvent the wheel [and] go with proven and solid technologies when you can.&#8221;</p>
<p>In other words, go with the boring stuff that just works.</p>
<p>For Instagram that means a Django-based stack that runs on Ubuntu 11.04 servers and uses PostgreSQL for storage. There are several additional layers for load balancing, push notifications, queues and other tasks, but overwhelmingly Instagram&#8217;s stack consists of stolid, proven tools.</p>
<p>Among the newer stuff is Instagram&#8217;s use of <a href="http://redis.io/">Redis</a> to store <a href="http://instagram-engineering.tumblr.com/post/12202313862/storing-hundreds-of-millions-of-simple-key-value-pairs">hundreds of millions of key-value pairs</a> for fast feeds, and <a href="http://gunicorn.org/">Gunicorn</a> instead of Apache as a web server.</p>
<p>All in all it&#8217;s a very impressive setup that has, thus far, helped Instagram avoid the down time that has plague many similar services hit with the same kind of exponential growth. (Twitter, I&#8217;m looking at you.) For more details on how Instagram looks behind the scenes and which tools the company uses, be sure to check out <a href="http://instagram-engineering.tumblr.com/post/13649370142/what-powers-instagram-hundreds-of-instances-dozens-of">the blog post</a> as well as <a href="http://instagram-engineering.tumblr.com/archive">the archives</a>.</p>
<div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2012/04/behind-the-scenes-at-instagram-tools-for-building-reliable-web-services/feed/</wfw:commentRss>
        <slash:comments>0</slash:comments>

        
    </item>
    
    <item>
        <title>OpenStreetBlock Gives Geodata the Human Touch</title>
        <link>http://www.webmonkey.com/2011/04/openstreetblock-gives-geodata-the-human-touch/</link>
        <comments>http://www.webmonkey.com/2011/04/openstreetblock-gives-geodata-the-human-touch/#comments</comments>
        <pubDate>Thu, 07 Apr 2011 17:27:18 +0000</pubDate>

                <dc:creator>Scott Gilbertson</dc:creator>

        <guid isPermaLink="false">http://www.webmonkey.com/?p=50509</guid>
        		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Web Services]]></category>
		<category><![CDATA[geodata]]></category>
		<category><![CDATA[maps]]></category>
            <enclosure url="http://www.webmonkey.com/wp-content/uploads/2011/04/openstreetblock.jpg" type="image/jpeg" length="48000" />
                    <description><![CDATA[<div class="rss_thumbnail"><img src="http://www.webmonkey.com/wp-content/uploads/2011/04/openstreetblock.jpg" alt="OpenStreetBlock Gives Geodata the Human Touch" /></div>Location-based web services are all the rage right now, but for most of us the actual geographic location isn&#8217;t very interesting &#8212; do you know where &#8220;40.737813,-73.997887&#8243; is off the top of your head? No? How about &#8220;West 14th Street bet. 6th Ave. and 7th Ave?&#8221; For the geographic web to become useful geodata has [...]]]></description>

            <content:encoded><![CDATA[<p><!-- wpautop enabled -->
<p><a href="http://www.webmonkey.com/wp-content/uploads/2011/04/openstreetblock.jpg"><img src="http://www.webmonkey.com/wp-content/uploads/2011/04/openstreetblock.jpg" alt="" title="openstreetblock" width="520" height="316" class="aligncenter size-full wp-image-50510" /></a>Location-based web services are all the rage right now, but for most of us the actual geographic location isn&#8217;t very interesting &#8212; do you know where &#8220;40.737813,-73.997887&#8243; is off the top of your head? No? How about &#8220;West 14th Street bet. 6th Ave. and 7th Ave?&#8221;</p>
<p>For the geographic web to become useful geodata has to be converted into something humans actually understand. Enter <a href="http://transit.frumin.net/openstreetblock/">OpenStreetBlock</a>.</p>
<p>OpenStreetBlock is a new web service that takes geographic coordinates (latitude/longitude pairs) and turns them into an actual city block description. The result is textual information which, in many cases, will be even more meaningful to your users than the ubiquitous pin on a map.</p>
<p>If you&#8217;d like to play around with a sampling of data from New York, head over to <a href="http://transit.frumin.net/openstreetblock/">OpenStreetBlock and try out the New York demos</a>.</p>
<p>If you&#8217;ve ever wanted to <a href="http://www.webmonkey.com/2009/07/source_code_offers_a_glimpse_of_the_magic_behind_everyblockdotcom/">build your own version of EveryBlock</a> &#8212; which pinpoints events, news stories and public data at the city-block level &#8212; OpenStreetBlock will go a long way toward getting you there. So long as you can pull geo coordinates out of your source data, OpenStreetBlock can turn that into more meaningful information.</p>
<p>Under the hood OpenStreetBlock relies on OpenStreetMap data and uses PHP in conjunction with a geographic database to turn your coordinates into block descriptions.</p>
<p>As cool as OpenStreetBlock is, getting it up and running on your own site will require a bit of work. Luckily, there are some good tutorials available that will walk you through the process of installing and setting up many of the prerequisites like PostgreSQL and PostGIS (I&#8217;ll assume you already have an Apache server with PHP installed).</p>
<p>To get started with OpenStreetBlock, <a href="https://github.com/fruminator/openstreetblock">grab the code from GitHub</a>. The next thing you&#8217;ll need is a PostgreSQL database with all the PostGIS tools installed. Luckily those are also prerequisites for GeoDjango, so head over to the <a href="http://docs.djangoproject.com/en/dev/ref/contrib/gis/install/#spatial-database">GeoDjango installation page</a>, skip the Django-specific parts and just follow the Postgres and PostGIS installation instructions.</p>
<p>Next you&#8217;ll need to download <a href="http://wiki.openstreetmap.org/wiki/Osmosis">Osmosis</a> and <a href="http://wiki.openstreetmap.org/wiki/Osm2pgsql">Osm2pgsql</a> to convert OpenStreetMap data into something Postgres can handle. Head over to <a href="http://www.openstreetmap.org/">OpenStreetMap</a>, zoom into an area you&#8217;d like to query with OpenStreetBlock and then choose &#8220;export.&#8221; Select the OpenStreetMap XML Data option and save the file.</p>
<p>From there you can check out the guide to importing the OpenStreetMap XML Data in the <a href="https://github.com/fruminator/openstreetblock/blob/master/README">OpenStreetBlock read me</a>. </p>
<p><strong>See Also:</strong><br/></p>
<ul>
<li><a href="http://www.webmonkey.com/2010/03/where-20-simplegeo-to-launch-itunes-for-geodata/">Where 2.0: SimpleGeo to Launch &#8216;iTunes for Geodata&#8217;</a></li>
<li><a href="http://www.webmonkey.com/2009/07/source_code_offers_a_glimpse_of_the_magic_behind_everyblockdotcom/">EveryBlock Source Code Release Offers Glimpse of the Magic Behind the Curtain</a></li>
<li><a href="http://www.webmonkey.com/2010/01/user-contributed_announcements_give_everyblock_a_human_touch/">User-Contributed Announcements Give EveryBlock a Human Touch</a></li>
<li><a href="http://www.webmonkey.com/2010/08/beautiful-websites-stamens-pretty-maps/">Beautiful Websites: Stamen&#8217;s Pretty Maps</a></li>
</ul>
<div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2011/04/openstreetblock-gives-geodata-the-human-touch/feed/</wfw:commentRss>
        <slash:comments>0</slash:comments>

        
    </item>
    
    <item>
        <title>Open Data&#8217;s Access Problem, and How to Solve it</title>
        <link>http://www.webmonkey.com/2010/09/open-datas-access-problem-and-how-to-solve-it/</link>
        <comments>http://www.webmonkey.com/2010/09/open-datas-access-problem-and-how-to-solve-it/#comments</comments>
        <pubDate>Wed, 22 Sep 2010 19:05:34 +0000</pubDate>

                <dc:creator>Scott Gilbertson</dc:creator>

        <guid isPermaLink="false">http://www.webmonkey.com/?p=48785</guid>
        		<category><![CDATA[Databases]]></category>
		<category><![CDATA[APIs]]></category>
		<category><![CDATA[Gov20]]></category>
		<category><![CDATA[government]]></category>
		<category><![CDATA[Gurstein]]></category>
		<category><![CDATA[Open data]]></category>
            <enclosure url="http://www.webmonkey.com/wp-content/uploads/2010/09/punchcard580.jpg" type="image/jpeg" length="48000" />
                    <description><![CDATA[<div class="rss_thumbnail"><img src="http://www.webmonkey.com/wp-content/uploads/2010/09/punchcard580.jpg" alt="Open Data&#8217;s Access Problem, and How to Solve it" /></div>The recent Gov 2.0 summit in Washington D.C. saw several promising new announcements which will help government agencies share code and best practices for making public data available to developers. The idea behind new projects like Challenge.gov, the FCC&#8217;s new developer tools and the Civic Commons is that by giving developers access to data previously [...]]]></description>

            <content:encoded><![CDATA[<p><!-- wpautop enabled -->
<p><img src="http://www.webmonkey.com/wp-content/uploads/2010/09/punchcard580.jpg" alt="" title="punchcard" /></p>
<p>The recent <a href="http://www.gov2summit.com/gov2010">Gov 2.0 summit</a> in Washington D.C. saw several promising new announcements which will help government agencies share code and best practices for making public data available to developers.</p>
<p>The idea behind new projects like <a href="http://challenge.gov/">Challenge.gov</a>, the <a href="http://reboot.fcc.gov/developer/">FCC&#8217;s new developer tools</a> and the <a href="http://civiccommons.com/2010/09/introducing-civic-commons/">Civic Commons</a> is that by giving developers access to data previously stored in dusty filing cabinets, they can create tools to give ordinary citizens greater access to that data.</p>
<p>Unfortunately, not everything open data project leads to good things. It is critical that if open data is made available on the web, it must be accompanied by some effort to ensure everyone can access it.</p>
<p>We&#8217;ve seen an explosion in creative hacks that use this newly available data to provide excellent online resources. Public data sites like <a href="http://www.webmonkey.com/2008/01/everyblock_launches_hyper-local_news_service_for_big_cities/">EveryBlock</a>, or the Sunlight Foundation&#8217;s <a href="http://www.webmonkey.com/2010/03/sunlight-labs-offering-5k-for-best-government-data-mashups/">Design for America contest</a> have highlighted some of the amazing ways open data can make our lives better. Whether it&#8217;s finding out crime stats, real estate values, health hazards and business license statuses in your neighborhood, or visualizing how the government is spending your tax dollars through innovative maps, open data and what you can do with it is the current hotness among web developers.</p>
<p>Most of the benefits are close to home &#8212; in the U.S., just about everyone has access to online government resources thanks to web-enabled computers in free public libraries.</p>
<p>But extend that argument to the rest of the world and the number of people that really have access to the data drops significantly. If you don&#8217;t have an easy way to get online, you can&#8217;t benefit from open data.</p>
<p>Michael Gurstein, Executive Director of the <a href="http://www.communityinformatics.net/">Center for Community Informatics Research</a>, recently highlighted some of the <a href="http://gurstein.wordpress.com/2010/09/02/open-data-empowering-the-empowered-or-effective-data-use-for-everyone/">problems with open data accessibility</a>.</p>
<p>Gurstein points out a number of assumptions about open data that are often overlooked by those most enthusiastic about making such data publicly available.</p>
<p>Worse, he shows how such data can be used against you.</p>
<p><span id="more-48785"></span></p>
<p>Gurstein&#8217;s example of the dark side of open data is Bangalore, India&#8217;s digitization of land records, which gives every citizen a way to see who owns what in Bangalgore. On the surface, it seems like a good thing, but the upper classes and corporations have been using the land records data to gain ownership of land from the unknowing poor.</p>
<p>The data, writes Gurstein, allowed the well-to-do to instruct surveyors and lawyers how to most effectively &#8220;challenge titles, exploit gaps in title, take advantage of mistakes in documentation, identify opportunities and targets for bribery&#8221; among other things. Details are in <a href="http://casumm.files.wordpress.com/2008/09/bhoomi-e-governance.pdf">this PDF</a>.</p>
<p>It isn&#8217;t necessary to go all the way to India to find examples of open data leading to unintended consequences.</p>
<p>In an e-mail exchange, Gurstein told me of a similar case in Nova Scotia where efforts to make titles, deeds and other land data led to very same situation &#8212; companies pouring over 19th century deeds, ancient maps and other newly available data, finding oversights, misfiled papers and other means to seize land from owners.</p>
<p>Of course unintended consequences aren&#8217;t a reason to stop making data available. For Gurstein, the solution is to make sure that open data isn&#8217;t just thrown onto the web, but that universal accessibility is built in so it can really benefit everyone.</p>
<p>How that is done will vary considerably by location and the type of data in question, but without such efforts Gurstein worries that &#8220;the outcome of &#8216;open data&#8217; may be quite the opposite to that which is anticipated (and presumably desired) by its strongest proponents.&#8221;</p>
<p>It might come as a shock to some of the more enthusiastic open data proponents, but there is more to open data than just dredging it out of the Indiana Jones-style warehouses where it currently gathers dust. Putting it online for &#8220;anyone&#8221; access and just walking away isn&#8217;t necessarily a recipe for good things.</p>
<p>Gurstien also pointed out several solutions to me, which <a href="http://gurstein.wordpress.com/2010/09/09/open-data-2-effective-data-use/">he lists in a follow-up blog post</a>. These solutions would help ensure that what happened in Nova Scotia and Bangalore won&#8217;t happen elsewhere. Among the things he believes governments and other data providers need to take into account are:</p>
<ul>
<li><strong>Advocacy</strong> &#8212; Perhaps the most important of Gurstein&#8217;s guidelines is to ensure that everyone knows the data is available, making sure that a community&#8217;s resources are sufficient for turning the data into some kind of project with local benefits.</li>
<li><strong>Internet access</strong> &#8212; Especially a concern in rural areas, the level of internet access is the cornerstone to open data. Just because data is on the web does not mean everyone can get to it. And if not everyone has access, then your data isn&#8217;t &#8220;open.&#8221;</li>
<li><strong>Content and formatting</strong> &#8212; If the data just a raw GIS database that most people won&#8217;t understand, then even internet access doesn&#8217;t matter because only those with specific skills (or the money to hire them) will be able to do anything with the data.</li>
<li><strong>Computer/software skills</strong> &#8212; Similar to content and formatting issues is having access to GIS tools and other specialty software. As Gurstein says &#8220;techies know how to do the visualization stuff, university and professional types know how to use the analytical software but ordinary community people might not know how to do either.&#8221;</li>
</ul>
<p>It&#8217;s also worth pointing out that Gurstein has several examples of open data being used in constructive ways. He isn&#8217;t arguing that we shouldn&#8217;t put government and other data online, just that we should keep in mind that the data isn&#8217;t necessarily useful to everyone in its most raw forms.</p>
<p>As Tim O&#8217;Reilly <a href="https://twitter.com/timoreilly/status/23179898934">notes</a> in conjunction with Gurstein&#8217;s post, &#8220;we need to think deeply about the future&#8221; &#8212; to consider all the consequences of open data, not just the ones we&#8217;d like to see.</p>
<p><em>Punchcard scan by Steve Collins/<a href="http://www.flickr.com/photos/24876360@N03/4069007704/">Flickr</a>/CC</em></p>
<p><strong>See Also:</strong><br/></p>
<ul>
<li><a href="http://www.webmonkey.com/2010/03/sunlight-labs-offering-5k-for-best-government-data-mashups/">Sunlight Labs Offering $5K for Best Government Data Mashups</a></li>
<li><a href="http://www.webmonkey.com/2008/01/everyblock_launches_hyper-local_news_service_for_big_cities/">EveryBlock Launches Hyper-local News Service for Big Cities</a></li>
</ul>
<div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/09/open-datas-access-problem-and-how-to-solve-it/feed/</wfw:commentRss>
        <slash:comments>2</slash:comments>

        
    </item>
    
    <item>
        <title>Big Data in the Deep Freeze: John Jacobsen of IceCube</title>
        <link>http://www.webmonkey.com/2010/07/big-data-in-the-deep-freeze-john-jacobsen-of-icecube/</link>
        <comments>http://www.webmonkey.com/2010/07/big-data-in-the-deep-freeze-john-jacobsen-of-icecube/#comments</comments>
        <pubDate>Fri, 23 Jul 2010 21:16:51 +0000</pubDate>

                <dc:creator>Michael Calore</dc:creator>

        <guid isPermaLink="false">http://www.webmonkey.com/?p=48144</guid>
        		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Other]]></category>
		<category><![CDATA[IceCube]]></category>
		<category><![CDATA[oscon]]></category>
		<category><![CDATA[OSCON2010]]></category>
		<category><![CDATA[video]]></category>
        <description><![CDATA[<p>John Jacobsen works for the <a href="http://www.icecube.wisc.edu/info/">IceCube telescope project</a>, the world's largest neutrino detector, located at the South Pole. The project's mission is to search for the radioactive sub-atomic particles that have been generated by violent astrophysical events: "exploding stars, gamma ray bursts, and cataclysmic phenomena involving black holes and neutron stars," according to the project website.

<p>Jacobsen is one of the people in charge of handling all the Big Data collected by IceCube. In the video, shot this week at the <a href="http://www.oscon.com/oscon2010">O'Reilly OSCON 2010</a> conference in Portland, Oregon, John explains how they collect a terabyte of raw data per hour, then send everything to IceCube's remote research and backup facilities using a finicky satellite hook-up.

<p>Antarctica is one of the least accomidating places on Earth to perform scientific research with computers. It's the driest place on the planet -- atmospheric humidity hovers around zero -- and bursts of static electricity can cause catastrophic harm to IceCube's data stores. The lack of humidity causes the server clusters' cooling systems to break down. And if something fails, a spare might take six months to arrive.]]></description>

            <content:encoded><![CDATA[<p><!-- wpautop enabled --><object width="580" height="351"><param name="movie" value="http://www.youtube.com/v/v9VUk9xB6co&amp;hl=en_US&amp;fs=1?hd=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/v9VUk9xB6co&amp;hl=en_US&amp;fs=1?hd=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="580" height="351"></embed></object></p>
<p>John Jacobsen works for the <a href="http://www.icecube.wisc.edu/info/">IceCube telescope project</a>, the world&#8217;s largest neutrino detector, located at the South Pole. The project&#8217;s mission is to search for the radioactive sub-atomic particles that have been generated by violent astrophysical events: &#8220;exploding stars, gamma ray bursts, and cataclysmic phenomena involving black holes and neutron stars,&#8221; according to the project website.</p>
<p>Jacobsen is one of the people in charge of handling the massive amounts of data collected by IceCube. In the video, shot this week at the <a href="http://www.oscon.com/oscon2010">O&#8217;Reilly OSCON 2010</a> conference in Portland, Oregon, John explains how they collect a terabyte of raw data per hour, then send everything to IceCube&#8217;s remote research and backup facilities using a finicky satellite hook-up.</p>
<p>Antarctica is one of the least accommodating places on Earth to perform scientific research with computers. It&#8217;s the driest spot on the planet &#8212; atmospheric humidity hovers around zero &#8212; and bursts of static electricity threaten the integrity of IceCube&#8217;s data stores. The lack of humidity causes the server clusters&#8217; cooling systems to break down. And if something fails, a spare might take six months to arrive.</p>
<div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/07/big-data-in-the-deep-freeze-john-jacobsen-of-icecube/feed/</wfw:commentRss>
        <slash:comments>2</slash:comments>

        
    </item>
    
    <item>
        <title>Sunlight Labs Offering $5K for Best Government Data Mashups</title>
        <link>http://www.webmonkey.com/2010/03/sunlight-labs-offering-5k-for-best-government-data-mashups/</link>
        <comments>http://www.webmonkey.com/2010/03/sunlight-labs-offering-5k-for-best-government-data-mashups/#comments</comments>
        <pubDate>Mon, 29 Mar 2010 18:30:30 +0000</pubDate>

                <dc:creator>Scott Gilbertson</dc:creator>

        <guid isPermaLink="false">http://www.webmonkey.com/?p=47046</guid>
        		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Visual Design]]></category>
		<category><![CDATA[contest]]></category>
		<category><![CDATA[goverment]]></category>
		<category><![CDATA[Sunlight Foundation]]></category>
            <enclosure url="http://www.webmonkey.com/wp-content/uploads/2010/03/designforamerica.png" type="image/png" length="48000" />
                    <description><![CDATA[<div class="rss_thumbnail"><img src="http://www.webmonkey.com/wp-content/uploads/2010/03/designforamerica.png" alt="Sunlight Labs Offering $5K for Best Government Data Mashups" /></div>Artists, web developers and data visualization geniuses, here&#8217;s a chance to strut your stuff, serve your country and win some serious money in the process. Sunlight Foundation, a non-profit organization that provides tools to make government data more transparent, has announced a new contest called Design for America. Billed as a &#8220;design and data visualization [...]]]></description>

            <content:encoded><![CDATA[<p><!-- wpautop enabled --><img src="http://www.webmonkey.com/wp-content/uploads/2010/03/designforamerica.png" alt="designforamerica" title="designforamerica" width="560" height="155" class="aligncenter size-full wp-image-47049" /></p>
<p>Artists, web developers and data visualization geniuses, here&#8217;s a chance to strut your stuff, serve your country and win some serious money in the process.</p>
<p>Sunlight Foundation, a non-profit organization that provides tools to make government data more transparent, has announced a new contest called <a href="http://sunlightlabs.com/contests/designforamerica/">Design for America</a>. Billed as a &#8220;design and data visualization extravaganza,&#8221; Sunlight is encouraging the public to create and publish data visualizations that help make complex government data easier for people to digest and interact with.</p>
<p>There are several different categories open for submission, including: visualizations of Recovery.gov data that shows how the stimulus money is being spent, visualizations showing how a bill becomes a law, a redesign of a .gov website, and a redesign of any government form. Top prize in each category is a cool $5,000.</p>
<p>Creations can be in any form &#8212; a website, a game, a poster, a sculpture, whatever &#8212; though we suspect most of the entries will be either posters or interactive Flash graphics.</p>
<p>The contest is being run by Sunlight Labs, the skunkworks wing of the larger Sunlight Foundation. The Sunlight group spends most of its energy collecting government data, organizing it into publicly accessible databases, then creating tools that make it easier for ordinary people to access that data. The non-profit works with organizations like <a href="http://www.opencongress.org/">OpenCongress</a>, <a href="http://maplight.org/">MapLight</a>, <a href="http://www.followthemoney.org/">FollowTheMoney</a> and <a href="http://www.usaspending.gov/">USASpending.gov</a>. Sunlight also maintains a <a href="http://wiki.sunlightlabs.com/Main_Page#Public_APIs_for_government_data">list of APIs</a> developers can use to access the data.</p>
<p>The Design for America contest encourages participants to sift through the vast datasets available from all of these organizations, as well as the datasets maintained by Sunlight Foundation and any raw government data that&#8217;s available. As the Sunlight Labs blog says, the goal of the contest is to &#8220;tell interesting stories&#8221; that go beyond what can be an overwhelming amount of unfiltered data.</p>
<p>Visualizations can be in any medium, not just the web, so if you&#8217;re a video or infographic specialist, you can still enter the contest. The main criteria for judging are the visual quality of the artwork and how well the underlying information is conveyed.</p>
<p><span id="more-47046"></span></p>
<p>Design for America follows in the footsteps of Sunlight&#8217;s <a href="http://www.sunlightlabs.com/contests/appsforamerica/">Apps for America contests</a>, which sought to bring transparency and accountability to government using open web applications to mine government data sites. Apps for America generated a number of useful apps &#8212; like RSS feeds for the House Committee schedule, <a href="http://www.earmarkwatch.org/">GovPulse</a> and the <a href="http://www.earmarkwatch.org/">Earmark Watch</a> tool, among others. With any luck, the Design for America contest will generate some equally useful and enlightening visualizations of government data.</p>
<p>If you&#8217;d like to test your mashup and design chops, head over to Sunlight Labs and have a look at the full contest rules. One important thing for designers to keep in mind &#8212; your entry needs to be licensed under a <a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons By-Attribution</a> or <a href="http://www.opensource.org/licenses/alphabetical">Creative Commons 0</a> license, or an <a href="http://www.opensource.org/licenses/alphabetical">OSI approved license</a> for those submitting code.</p>
<p>The contest judges vary by category, but the list includes some big names in the online design world &#8212; Nicholas Feltron and Nathan Yau are both on the list, as are various members of Sunlight Labs and other design gurus. </p>
<p>Design for America submissions are due by May 17 and the winners will be announced at the <a href="http://www.gov2expo.com/gov2expo2010">Gov 2.0 Expo</a> in Washington, D.C. on May 27. </p>
<p><strong>See Also:</strong><br/></p>
<ul>
<li><a href="http://www.webmonkey.com/2009/05/historical_map_mashups_turn_cities_into_glass_onions_of_time/">Historical Map Mashups Turn Cities Into Glass Onions of Time</a></li>
<li><a href="http://www.webmonkey.com/2010/01/user-contributed_announcements_give_everyblock_a_human_touch/">User-Contributed Announcements Give EveryBlock a Human Touch</a></li>
<li><a href="http://www.webmonkey.com/2009/12/the_twitter_api_is_becoming_far_more_than_just_an_api_for_twitter/">Twitter API Is Becoming Far More than Just an API for Twitter</a></li>
</ul>
<div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/03/sunlight-labs-offering-5k-for-best-government-data-mashups/feed/</wfw:commentRss>
        <slash:comments>4</slash:comments>

        
    </item>
    
    <item>
        <title>PHP and MySQL Tutorial &#8211; Lesson 3</title>
        <link>http://www.webmonkey.com/2010/02/php_and_mysql_tutorial_-_lesson_3/</link>
        <comments>http://www.webmonkey.com/2010/02/php_and_mysql_tutorial_-_lesson_3/#comments</comments>
        <pubDate>Tue, 16 Feb 2010 01:45:47 +0000</pubDate>

                <dc:creator>Webmonkey Staff</dc:creator>

        <guid isPermaLink="false">http://stag.wired.com/primate/?p=737</guid>
        		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[wiki]]></category>
        <description><![CDATA[Welcome to the third and final lesson for this tutorial. If you&#8217;ve gone through Lesson 1 and Lesson 2, you already know the essentials for installing and writing useful scripts with MySQL and PHP. We&#8217;re going to look at some useful PHP functions that should make your life a lot easier. First, let&#8217;s look at [...]]]></description>

            <content:encoded><![CDATA[<!-- wpautop disabled --><p>Welcome to the third and final lesson for this tutorial. If you&#8217;ve gone through <a href="/2010/02/PHP_and_MySQL_Tutorial_-_Lesson_1" title="Tutorial:PHP and MySQL Tutorial - Lesson 1"> Lesson 1</a> and <a href="/2010/02/PHP_and_MySQL_Tutorial_-_Lesson_2" title="Tutorial:PHP and MySQL Tutorial - Lesson 2"> Lesson 2</a>, you already know the essentials for installing and writing useful scripts with MySQL and PHP. We&#8217;re going to look at some useful PHP functions that should make your life a lot easier. First, let&#8217;s look at include files.

</p><p>We all know the basics of includes, right? Contents of an external file are referenced and imported into the main file. It&#8217;s pretty easy:You call a file and it&#8217;s included. When we do this in PHP there are two functions we need to talk about:<tt>include()</tt> and <tt>require()</tt>. The difference between these two functions is subtle but important, so let&#8217;s take a closer look. The <tt>require()</tt> function works in a XSSI-like way; files are included as part of the original document as soon as that file is parsed, regardless of its location in the script. So if you decide to place a <tt>require()</tt> function inside a conditional loop, the external file will be included even if that part of the conditional loop is false.</p>
<br />
<span id="more-737"></span>

<p><b>A Place for Everything</b>
</p><p>The <tt>include()</tt> function imports the referenced file each time it is encountered. If it&#8217;s not encountered, PHP won&#8217;t bother with it. This means that you can use <tt>include</tt> in loops and conditional statements, and they&#8217;ll work exactly as planned.

</p><p>Finally, if you use <tt>require()</tt> and the file you&#8217;re including does not exist, your script will halt and produce an error. If you use <tt>include()</tt>, your script will generate a warning, but carry on. You can test this yourself by trying the following script. Run the script, then replace <tt>include()</tt> with <tt>require()</tt> and compare the results.



</p>

<pre class="brush: js">&lt;html&gt;



&lt;body&gt;

&lt;?php

include("emptyfile.inc");

echo "Hello World";

?&gt;

&lt;/body&gt;

&lt;/html&gt;
</pre>

<p>I like to use the suffix .inc with my include files so I can separate them from normal PHP scripts. If you do this, make sure that you set your Web server configuration file to parse .inc files as PHP files. Otherwise, hackers might be able to guess the name of your include files and display them through the browser as text files. This could be bad if you&#8217;ve got sensitive information &#8211; such as database passwords &#8211; contained in the includes.

</p><p>So what are you going to do with include files? Simple! Place information common to all pages inside them. Things like HTML headers, footers, database connection code, and user-defined functions are all good candidates. Paste this text into a file called header.inc.

</p>

<pre class="brush: js">&lt;?php

$db = mysql_connect("localhost", "root");

mysql_select_db("mydb",$db);

?&gt;

&lt;html&gt;

&lt;head&gt;

&lt;title&gt;

&lt;?php echo $title&nbsp;?&gt;

&lt;/title&gt;

&lt;/head&gt;

&lt;body&gt;

&lt;center&gt;&lt;h2&gt;&lt;?php echo $title&nbsp;?&gt;&lt;/h2&gt;&lt;/center&gt;
</pre>

<p>Then create another file called footer.txt that contains some appropriate closing text and tags.

</p><p>Now let&#8217;s create a third file containing the actual PHP script. Try the following code, making sure that your MySQL server is running.

</p>

<pre class="brush: js">&lt;?php

$title = "Hello World";

include("header.inc");

$result = mysql_query("SELECT * FROM employees",$db);

echo "&lt;table border=1&gt;n";

echo "&lt;tr&gt;&lt;td&gt;Name&lt;/td&gt;&lt;td&gt;Position&lt;/tr&gt;n";

while ($myrow = mysql_fetch_row($result)) {

  printf("&lt;tr&gt;&lt;td&gt;%s&nbsp;%s&lt;/td&gt;&lt;td&gt;%s&lt;/tr&gt;n", $myrow[1], $myrow[2], $myrow[3]);

}

echo "&lt;/table&gt;n";

include("footer.inc");

?&gt;
</pre>

<p>See what happens? The include files are tossed into the main file and then the whole thing is executed by PHP. Notice how the variable <tt>$title</tt> was defined before header.inc is referenced. Its value is made available to the code in header.inc; hence, the title of the page is changed. You can now use header.inc across all your PHP pages, and all you&#8217;ll have to do is change the value of <tt>$title</tt> from page to page.

</p><p>Using a combination of includes, HTML, conditional statements, and loops, you can create complex variations from page to page with an absolute minimum of code. Includes become especially useful when used with functions, as we&#8217;ll see down the road.On to the exciting world of data validation.


<a name="Simple_Validation"></a><h4> <span class="mw-headline">Simple Validation</span></h4>

<p>Imagine for a moment that we&#8217;ve got our database nicely laid out and we&#8217;re now requesting information from users that will be inserted into the database. Further, let&#8217;s imagine that you have a field in your database waiting for some numeric input, such as a price. Finally, imagine your application falling over in a screaming heap because some smart aleck put text in that field. MySQL doesn&#8217;t want to see text in that portion of your SQL statement &#8211; and it complains bitterly.

</p><p>What to do? Time to validate.

</p><p>Validation simply means that we&#8217;ll examine a piece of data, usually from an HTML form, and check to make sure that it fits a certain model. This can range from ensuring that a element is not blank to validating that an element meets certain criteria (for example, that a numeric value is stipulated or that an email address contains an @ for an email address).

</p><p>Validation can be done on the server side or on the client side. PHP is used for server-side validation, while JavaScript or another client-based scripting language can provide client-side validation. This article is about PHP, so we&#8217;re going to concentrate on the server end of things.

</p><p>Let&#8217;s ignore our database for the moment and concentrate on PHP validation. If you wish, you can add additional fields to our employee database quite simply by using the MySQL <a href="http://www.mysql.com/Manual_chapter/manual_Reference.html#ALTER_TABLE" class="external text" title="http://www.mysql.com/Manual_chapter/manual_Reference.html#ALTER_TABLE" rel="nofollow">ALTER statement</a> &#8211; that is, if you want to commit to the values that we&#8217;ll validate.

</p><p>There are several useful PHP functions we can use to validate our data, and they range from simple to highly complex. A simple function we could use might be <tt>strlen()</tt>, which tells us the length of the variable.

</p><p>A more complex function would be <tt>ereg()</tt>, which uses full regular expression handling for complex queries. I won&#8217;t delve into the complexities of regex here, as entire books have been written on the subject, but I will provide some examples on the next page.



</p><p>Let&#8217;s start with a simple example. We&#8217;ll check to see whether a variable does or does not exist.

</p>

<pre class="brush: js"> &lt;html&gt;

 &lt;body&gt;

 &lt;?php

 if ($submit) {

      if (!$first ||&nbsp;!$last) {

 	$error = "Sorry! You didn't fill in all the fields!";

 	} else {

 		// process form

 		echo "Thank You!";
 	}
 }

 if (!$submit || $error) {

      echo $error;

     &nbsp;?&gt;

      &lt;P&gt;

      &lt;form method="post" action="&lt;?php echo $PHP_SELF&nbsp;?&gt;"&gt;

      FIELD 1:&lt;input type="text" name="first" value="&lt;?php echo $first&nbsp;?&gt;"&gt;

      &lt;br&gt;

      FIELD 2:&lt;input type="text" name="last" value="&lt;?php echo $last&nbsp;?&gt;"&gt;

      &lt;br&gt;

      &lt;input type="Submit" name="submit" value="Enter Information"&gt;

      &lt;/form&gt;

      &lt;?php

 } // end if

 ?&gt;

 &lt;/body&gt;

 &lt;/html&gt;

</pre>

<p>The keys to this script are the nested conditional statements. The first checks to see whether the Submit button has been pressed. If it has, it goes on to check that both the variables <tt>$first</tt> and <tt>$last</tt> exist. The || symbol means &#8220;or&#8221; and the&nbsp;! symbol means &#8220;not.&#8221; We could also rewrite the statement to say, &#8220;If $first does not exist or $last does not exist, then set $error to the following.&#8221;

</p><p>Next, let&#8217;s extend things a little by checking to see whether a string is a certain length. This would be ideal for passwords, since you don&#8217;t want some lazy user entering a password of only one or two letters. You&#8217;d rather it be, say, six or more characters.

</p><p>The function for this is, as you already know, <tt>strlen()</tt>. It simply returns a number equal to the number of characters in the variable being tested. Here, I modified the script above to check the length of <tt>$first</tt> and <tt>$last</tt>.

</p>

<pre class="brush: js"> &lt;html&gt;

 &lt;body&gt;

 &lt;?php

 if ($submit) {

      if (strlen($first) &lt; 6 || strlen($last) &lt; 6) {

 	$error = "Sorry! You didn't fill in all the fields!";

 	} else {

 		// process form

 		echo "Thank You!";

 	}

 }

 if (!$submit || $error) {

      echo $error;

     &nbsp;?&gt;

      &lt;P&gt;

      &lt;form method="post" action="&lt;?php echo $PHP_SELF&nbsp;?&gt;"&gt;

      FIELD 1:&lt;input type="text" name="first" value="&lt;?php echo $first&nbsp;?&gt;"&gt;

      &lt;br&gt;

      FIELD 2:&lt;input type="text" name="last" value="&lt;?php echo $last&nbsp;?&gt;"&gt;

      &lt;br&gt;

      &lt;input type="Submit" name="submit" value="Enter Information"&gt;

      &lt;/form&gt;

      &lt;?php

 } // end if

 ?&gt;

 &lt;/body&gt;

 &lt;/html&gt;

</pre>

<p>Run this script and try entering six or fewer letters to see what happens. It&#8217;s simple yet quite effective.

</p>

<a name="Not-So-Simple_Validation"></a><h4> <span class="mw-headline">Not-So-Simple Validation</span></h4>

<p>Let&#8217;s talk a bit about using regular expressions with the <tt>ereg()</tt> and <tt>eregi()</tt> functions. As I said earlier, these can be either quite complex or very simple, depending on what you need.

</p><p>Using regular expressions, you can examine a string and intelligently search for patterns and variations to see whether they match the criteria you set. The most common of these involves checking whether an email address is valid (although, of course, there&#8217;s no fail-safe way of doing this).

</p><p>Rather than delve into the mysteries of regular expressions, I&#8217;ll provide some examples. You can use the same form we created on the previous page &#8211; just paste in the lines below to see how they work.

</p><p>First, let&#8217;s make sure that text only has been entered into a form element. This regular expression tests true if the user has entered one or more lowercase characters, from a to z. No numbers are allowed:

</p>

<pre class="brush: js"> if (!ereg("[a-Z]", $first) ||&nbsp;!ereg("[a-Z]", $last)) { </pre>

<p>Now, let&#8217;s extend this expression to check whether the string is four to six characters in length. Using <tt><a href="/special?title=Alpha:&amp;action=edit" class="new" title="Alpha:">alpha:</a></tt> is an easy way to check for valid alphabetic characters. The numbers in the braces check for the number of occurrences. And note that the ^ and $ indicate the beginning and end of the string.

</p>

<pre class="brush: js"> if (!ereg("^[[:alpha:]]{4,6}$", $first) ||&nbsp;!ereg("^[[:alpha:]]{4,6}$", $last)) { </pre>

<p>Finally, let&#8217;s build a regular expression that will check an email address&#8217; validity. There&#8217;s been plenty of discussion about the effectiveness of checking for email addresses in this way. Nothing&#8217;s completely foolproof, but what I have below works pretty well.

</p><p>I took this gem from the PHP <a href="http://www.progressive-comp.com/Lists/?l=php3-general#php3-general" class="external text" title="http://www.progressive-comp.com/Lists/?l=php3-general#php3-general" rel="nofollow">mailing list</a>. It&#8217;s a great resource &#8211; use it. And yes, this is as scary as it looks.

</p>

<pre class="brush: js">	if (!ereg('^[-!#$%&amp;'*+./0-9=?A-Z^_`a-z{|}~]+'.

'@'.

'[-!#$%&amp;'*+/0-9=?A-Z^_`a-z{|}~]+.'.

'[-!#$%&amp;'*+./0-9=?A-Z^_`a-z{|}~]+$', $last)) {

</pre>

<p>Don&#8217;t spend too much time looking at this. Just move on to the next bit.

</p>

<a name="Functions"></a><h4> <span class="mw-headline">Functions</span></h4>

<p>Enjoy that last regex expression? Fun, wasn&#8217;t it? Wouldn&#8217;t it be even more fun to enter that chunk on a dozen different pages that need to process email addresses?! Think about the joy of finding a typo in that mess &#8211; and doing it a dozen times no less. But of course, there&#8217;s a better way.

</p><p>Remember when we talked about include files earlier in this lesson? They&#8217;ll allow us to create a piece of code like the email checker and include it multiple times across several pages. This way, when we want to change the code, we need edit only one file, not many.

</p><p>But if we want to get this done, we&#8217;ll have to use functions.

</p><p>We&#8217;ve already used functions plenty of times. Every time we query the database or check the length of a string we&#8217;re using functions. These functions are built into PHP. If you&#8217;re a keen coder, you can extend PHP with your own customized functions. But that&#8217;s a bit advanced for this tutorial. Instead we&#8217;ll create functions that will reside within our PHP script.

</p><p>A function is simply a block of code that we pass one or more values to. The function then processes the information and returns a value. The function can be as simple or complex as we like, but as long as we can pass a value in and get one out, we don&#8217;t really care how complex it is. That&#8217;s the beauty of functions.

</p><p>Functions in PHP behave similarly to functions in C. When we define the functions, we must specify what values the function can expect to receive. It&#8217;s tricky to get a handle on at first, but it prevents weird things from happening down the road. This is done because the variables inside a function are known as private variables. That is, they exist only inside the function. You may, for instance, have a variable in your script called <tt>$myname</tt>. If you created a function and expected to use the same <tt>$myname</tt> variable (with the same value), it wouldn&#8217;t work. Alternatively, you could have the variable <tt>$myname</tt> in your script and also create another variable called <tt>$myname</tt> in your function, and the two would co-exist quite happily with separate values. I do not recommend doing this, however! When you come back and edit it six months later, you&#8217;ll be breaking things left and right. There are exceptions to this rule as with all things, but that&#8217;s outside the scope of this article.



</p><p>So let&#8217;s create a function. We&#8217;ll start simply. We need to give the function a name and tell it what variables to expect. We also need to define the function before we call it.

</p>

<pre class="brush: js"> &lt;html&gt;
 &lt;body&gt;

 &lt;?php

 function  addnum($first, $second) {

 	$newnum = $first + $second;

	return $newnum;

 }

 echo addnum(4,5);

 ?&gt;

 &lt;/body&gt;

 &lt;/html&gt;

</pre>

<p>That&#8217;s it! First, we created our function. Notice how we defined two new variables, called <tt>$first</tt> and <tt>$second</tt>. When we call the function, each variable is assigned a value based on the order in which it appears in the list &#8211; 4 goes to <tt>$first</tt>, 5 to <tt>$second</tt>. Then we simply added the two numbers together and returned the result. &#8220;Return&#8221; here simply means to send the result back. At the end of the script we print the number 9.

</p><p>Let&#8217;s create something that&#8217;s more useful to our database application. How about something that gracefully handles errors? Try this:

</p>

<pre class="brush: js"> &lt;html&gt;
 &lt;body&gt;

 &lt;?php

 function  do_error($error) {

 	echo  "Hmm, looks like there was a problem here...&lt;br&gt;";

 	echo "The reported error was $error.n&lt;br&gt;";

 	echo "Best you get hold of the site admin and let her know.";

 	die;
 }

 if (!$db = @mysql_connect("localhost","user", "password")) {

 	$db_error = "Could not connect to MySQL Server";

 	do_error($db_error);

 }

 ?&gt;

 &lt;/body&gt;
 &lt;/html&gt;
</pre>

<p>Before running this, try shutting down MySQL or using a bogus username or password. You&#8217;ll get a nice, useful error message. Observant readers will notice the @ symbol in front of <tt>mysql_connect()</tt>. This suppresses error messages so that you get the information only from the function. You&#8217;ll also see we were able to pass a variable into the function, which was defined elsewhere.

</p><p>Remember that I said functions use their own private variables? That was a little white lie. In fact, you can make variables outside of a function accessible to the function. You might create a function to query a database and display a set of results over several pages. You don&#8217;t want to have to pass the database connection identifier into the function every time. So in this situation, you can make connection code available as a global variable. For example:

</p>

<pre class="brush: js">

 &lt;html&gt;

 &lt;body&gt;

 &lt;?php

 function  db_query($sql) {

 	global $db;

 	$result = mysql_query($sql,$db);

 	return $result;

 }

 $sql = "SELECT * FROM mytable";

 $result = db_query($sql);

 ?&gt;

 &lt;/body&gt;

 &lt;/html&gt;
 </pre>

<p>This is a basic function, but the point is that you don&#8217;t need to send <tt>$db</tt> through when you call the function &#8211; you can make it available using the word global. You can define other variables as global in this statement, just separate the variable names by a comma.

</p><p>Finally, you can look like a real pro by using optional function variables. Here, the key is to define the variable to some default in the function, then when you call the function without specifying a value for the variable, the default will be adopted. But if you do specify a value, it will take precedence.

</p><p>Confused? For example, when you connect to a database, you nearly always connect to the same server and you&#8217;ll likely use the same username and password. But sometimes you&#8217;ll need to connect to a different database. Let&#8217;s take a look.

</p>

 <pre class="brush: js"> &lt;html&gt;
 &lt;body&gt;
 &lt;?php

 function  db_connect($host = "localhost", $user="username", $pass="graeme") {

 	$db = mysql_connect($host, $username, $password);

 	return $db;

 }

 $old_db = db_connect();

 $new_host = "site.com";

 $new_db = db_connect($new_host);

 ?&gt;

 &lt;/body&gt;

 &lt;/html&gt;
 </pre>

<p>Isn&#8217;t that cool? The variables used inside the function were defined when the function was defined. The first time the function is called, the defaults are used. The second time, we connect to a new host, but with the same username and password. Great stuff!

</p><p>Think about where you could use other functions in your code. You could use them for data checking, performing routine tasks, and so on. I use them a lot when processing text for display on a Web page. I can check, parse, and modify the text to add new lines and escape HTML characters in one fell swoop.

</p><p>Now all that&#8217;s left to do is to impart some words of wisdom.

</p>

<a name="Closing_Advice"></a><h4> <span class="mw-headline">Closing Advice</span></h4>

<p>When it comes to databasing, there&#8217;s a lot to learn. If you haven&#8217;t done it already, find a good book about database design and learn to put together a solid database &#8211; on any platform. It&#8217;s an invaluable skill and it will save you plenty of time and headache in the long run. Also, learn about MySQL. It&#8217;s a complex but interesting database with a wealth of useful documentation. Learn about table structure, data types, and SQL. You can actually achieve some pretty impressive stuff if you know enough SQL.

</p><p>Finally, there&#8217;s PHP. The PHP Web site has nearly everything you need, from a comprehensive manual to mailing-list archives to code repositories. An excellent way to learn about PHP is to study the examples used in the manual and to check out the code archives. Many of the posted scripts consist of functions or classes that you can use for free in your own scripts without having to reinvent the wheel. Additionally, the mailing list is an excellent spot to check out if you get stuck. The developers themselves read the list and there are plenty of knowledgeable people there who can help you along the way.

</p><p>Good luck and good coding!

</p>

<ul><li><a href="/2010/02/PHP_and_MySQL_Tutorial" title="Tutorial:PHP and MySQL Tutorial"> PHP and MySQL Tutorial</a>

</li><li><a href="/2010/02/PHP_and_MySQL_Tutorial_-_Lesson_1" title="Tutorial:PHP and MySQL Tutorial - Lesson 1"> PHP and MySQL Tutorial &#8211; Lesson 1</a>

</li><li><a href="/2010/02/PHP_and_MySQL_Tutorial_-_Lesson_2" title="Tutorial:PHP and MySQL Tutorial - Lesson 2"> PHP and MySQL Tutorial &#8211; Lesson 2</a>

</li><li><strong class="selflink"> PHP and MySQL Tutorial &#8211; Lesson 3</strong>

</li></ul>

<p><div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/02/php_and_mysql_tutorial_-_lesson_3/feed/</wfw:commentRss>
        <slash:comments>0</slash:comments>

        
    </item>
    
    <item>
        <title>Cake and Trax for Beginners</title>
        <link>http://www.webmonkey.com/2010/02/cake_and_trax_for_beginners/</link>
        <comments>http://www.webmonkey.com/2010/02/cake_and_trax_for_beginners/#comments</comments>
        <pubDate>Tue, 16 Feb 2010 01:45:47 +0000</pubDate>

                <dc:creator>Webmonkey Staff</dc:creator>

        <guid isPermaLink="false">http://stag.wired.com/primate/?p=767</guid>
        		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[wiki]]></category>
        <description><![CDATA[In my last article, Building With Ajax and Rails I made a faintly disparaging joke about some new web frameworks that have been created in fond imitation of Rails. I got a lot of feedback about that joke. I&#8217;m not allowed to comment here about the pending lawsuits, but I would ask that the drive-by [...]]]></description>

            <content:encoded><![CDATA[<!-- wpautop disabled --><p>In my last article, <a href="/2010/02/Building_With_Ajax_and_Rails" title="Tutorial:Building With Ajax and Rails"> Building With Ajax and Rails</a> I made a faintly disparaging joke about some new web frameworks that have been created in fond imitation of Rails. I got a lot of feedback about that joke. I&#8217;m not allowed to comment here about the pending lawsuits, but I would ask that the drive-by eggings of my house and threats to my family please cease. (They&#8217;ve been relocated to a secret Webmonkey farm anyway.)

</p><p>Today we&#8217;re going to take a look at a couple of those frameworks for PHP:<a href="http://phpontrax.com/" class="external text" title="http://phpontrax.com/" rel="nofollow">Trax</a> and <a href="http://cakephp.com/" class="external text" title="http://cakephp.com/" rel="nofollow">Cake</a>. Both attempt to bring the quick, easy, helpful tools and easily understood, easily maintained structure of Rails to PHP &#8212; a boon to web developers who know PHP and perhaps have some keeper code in that language, but can&#8217;t resist the Rails buzz. Both Trax and Cake use the same model-view-controller pattern and Active Record ways of addressing data that Rails does. Makes one curious, no? I don&#8217;t have time to get deeply into them today, but both stress &#8220;rapid development,&#8221; so let&#8217;s see if I, your average not-too-bright web developer, can get a little app off the ground before the end of this article.

</p><span id="more-767"></span><p><br />

</p>

<table id="toc" class="toc" summary="Contents"><tbody><tr><td><div id="toctitle"><h2>Contents</h2> </div>

<ol>

<li><a href="#Cutting_into_Cake">Cutting into Cake</a></li>

<li><a href="#Makin.27_Trax">Makin&#8217; Trax</a></li>



<li><a href="#Hardly_the_End_of_the_Story">Hardly the End of the Story</a></li>

<li><a href="#Helpful_Links">Helpful Links</span></a></li>

</ol>

</td></tr></tbody></table>



<p><br />

</p><p><br />

</p>

<a name="Cutting_into_Cake"></a><h3> <span class="mw-headline">Cutting into Cake</span></h3>



<p>This is 100 percent true:At lunch yesterday, my fortune cookie said &#8220;A nice cake is waiting for you.&#8221; So, I am going to start with Cake first and try Trax later.

</p><p>I go to the <a href="http://cakephp.org/downloads/index/release" class="external text" title="http://cakephp.org/downloads/index/release" rel="nofollow">Cake site</a> and download the latest stable release (discouragingly called 1.1.19.6305) onto my Debian web server running Apache and PHP 5. Unzipping the tarchive, I immediately see some names that look familiar from Rails:<tt>app</tt>, <tt>config</tt> and something called <tt>dispatcher.php</tt>. The <tt>app</tt> directory looks even friendlier. It contains <tt>views</tt>, <tt>controllers</tt>, <tt>model</tt> &#8211; just like Rails!



</p><p>There&#8217;s also a <tt>webroot</tt> directory, which I assume is going to be the root of my application. Indeed, look at that! If I browse to <tt><a href="http://my.web.server/trax_and_cake_playground/cake/app/webroot" class="external free" title="http://my.web.server/trax_and_cake_playground/cake/app/webroot" rel="nofollow">http://my.web.server/trax_and_cake_playground/cake/app/webroot</a></tt>, I see a friendly boilerplate intro page. Later, if I decide I want to use Cake full time, I&#8217;ll add a line to my Apache configuration to set that directory as the whole server&#8217;s root directory. At the moment, the page is extolling Cake&#8217;s coolness and warning me, &#8220;Your database configuration file is not present.&#8221;

</p><p>Correct, it&#8217;s not. I find a sample database configuration in <tt>app/config/database.php.default</tt>. I&#8217;ll copy that sample to an actual working file, database.php, in the same directory. The file includes an array of settings, which I change to suit my own environment:

</p><p><br />

</p>

 <pre class="brush: js">var $default = array('driver'   =&gt; 'mysql',



                  'connect'  =&gt; 'mysql_pconnect',



                  'host'     =&gt; 'localhost',



                  'login'    =&gt; 'paul',



                  'password' =&gt; 'passw0rd',



                  'database' =&gt; 'bookmarker' );



</pre>

<p><br />

Now, when I reload the intro page, it tells me, &#8220;Your database configuration file is present. Cake is able to connect to the database.&#8221; Yay!

</p><p>Now, I&#8217;ve told it I have a MySQL database called &#8220;bookmarker,&#8221; but that&#8217;s not true yet. I still have to create it. I&#8217;m eager to get rolling, so I&#8217;ll just recycle the code from Webmonkey&#8217;s <a href="/2010/02/Ruby_on_Rails_for_Beginners" title="Tutorial:Ruby on Rails for Beginners"> Ruby on Rails for Beginners</a> article in which I built a bookmarking app. This time I also want to populate the table with a little starter data, to give us something to work with. So I type:

</p>

<pre class="brush: js"> $mysql



 mysql&gt; CREATE DATABASE bookmarker;



 mysql&gt; USE bookmarker;



 mysql&gt; CREATE TABLE bookmarks (



    -&gt;  id SMALLINT (5) NOT NULL auto_increment,



    -&gt;  url VARCHAR (255),



    -&gt;  name VARCHAR (100),



    -&gt;  description VARCHAR (255),



    -&gt;  PRIMARY KEY (id)



    -&gt; );



 mysql&gt; INSERT INTO bookmarks (url, name, description) VALUES



 ('http://webmonkey.com/', 'Webmonkey', 'Not the only monkey that makes



 websites, but the best!');



 mysql&gt; INSERT INTO bookmarks (url, name, description) VALUES



 ('http://ubuntu.com/', 'Ubuntu', 'Linux for human beings (no monkeys



 please!)');



 mysql&gt; exit;



</pre>

<p>At this point in developing a Rails app, I&#8217;d run the built-in scaffold-generating tool. Here in Cakeland, I see a file called <tt>bake.php</tt> in <tt>cake/scripts</tt>, and instantly I pick up on the metaphor &#8211; bake a cake, get it? Turns out that&#8217;s a false start, as <tt>bake.php</tt> doesn&#8217;t seem to work in the pre-beta. It&#8217;s giving me all sorts of fatal errors and files not found. I&#8217;m going to have to create my model, view and controller by hand-editing code.

</p><p>The <tt>app/models</tt> directory contains an empty file called <tt>put_models_here</tt>. So, I do just that, creating a file in that directory called <tt>bookmark.php</tt>:



</p>

<pre class="brush: js"> &lt;?php



 class Bookmark extends AppModel



 {



     var $name = 'Bookmarks';



    function display()



     {



         $this-&gt;set('data',$this-&gt;Bookmark-&gt;findAll());



     }



 }



 ?&gt;

</pre>

<p>That puts the data from the table in <tt>$data</tt>, using the built-in <tt>set</tt> method. You might want to read along in the Cake <a href="http://api.cakephp.org/" class="external text" title="http://api.cakephp.org/" rel="nofollow">API documentation</a> &#8211; I certainly am!



</p><p>Then I create a controller, <tt>app/controllers/bookmarks_controller.php</tt>:

</p>

<pre class="brush: js"> &lt;?php



 class BookmarksController extends AppController



 {



     var $name = 'Bookmarks';



 }



 ?&gt;

</pre>

<p>I will also need to create a view. In the <tt>app/views</tt> directory, I create a subdirectory called <tt>bookmarks</tt> and a file called <tt>index.thtml</tt> inside of the subdirectory. The &#8220;t&#8221; in the file extension is for template, I assume. Note that I have had to scratch around in some slightly opaque documentation to glean all this &#8211; not as polished as Rails, not yet at least! In <tt>index.thtml</tt> I just put together a little <tt>foreach</tt> loop to display my content:



</p>

 <pre class="brush: js">&lt;?php



 echo "&lt;p&gt;&lt;table&gt;";



 foreach ($data as $bookmark):



      echo "&lt;tr&gt;&lt;td&gt;";



      echo $html-&gt;link($bookmark['Bookmark']['name'],



 $bookmark['Bookmark']['url']);



      echo "&lt;/td&gt;&lt;td&gt;&lt;b&gt;";



      echo $bookmark['Bookmark']['description'];



      echo "&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;";



 endforeach;



 echo "&lt;/table&gt;&lt;p&gt;";



 ?&gt;



</pre>

<p><br />

Finally, I need to add routing in order to tell Cake where my little app is and what to do with it. In <tt>app/config/routes.php</tt> I add a line:

</p>

<pre class="brush: js"> $Route-&gt;connect ('/bookmarks/*', array('controller'=&gt;'bookmarks',



 'action'=&gt;'display'));

</pre>

<p>Note that the action, &#8220;display&#8221;, corresponds to the method I defined in my controller.

</p><p>Now all the pieces are in place at last. I browse to <tt><a href="http://my.web.server/trax_and_cake_playground/cake/index.php/" class="external free" title="http://my.web.server/trax_and_cake_playground/cake/index.php/" rel="nofollow">http://my.web.server/trax_and_cake_playground/cake/index.php/</a> bookmarks </tt> (I can clean up that ugly URL later) and lo! The boilerplate page is now displaying the preliminary bookmarks I put in my table! I am up and running. In Rails, at this point, I would have some nice auto-generated methods to add and delete bookmarks. Hopefully Cake&#8217;s auto-bake feature will come together soon.



</p><p>Next, let&#8217;s take a look at Trax.

</p><p><br />

</p>

<a name="Makin.27_Trax"></a><h3> <span class="mw-headline">Makin&#8217; Trax</span></h3>

<p>Quick now, we know the drill. Go to the <a href="http://www.phpontrax.com/downloads/?downloads.html" class="external text" title="http://www.phpontrax.com/downloads/?downloads.html" rel="nofollow">Trax site</a>, download the archive, untar it. Like all of these prima-donna frameworks, Trax wants to be the top level of my web hierarchy, or rather it wants its <tt>public</tt> directory to be, and its <tt>trax</tt> directory to be parallel at the same level, out of sight of prying eyes. If my web server were publicly accessible, I&#8217;d put it up there, or find a way around that limitation. For now I&#8217;ll just unzip it in my playground (so to speak). Whoo!

</p><p>Already now, if I go to <tt><a href="http://my.web.server/trax_and_cake_playground/trax/public/" class="external free" title="http://my.web.server/trax_and_cake_playground/trax/public/" rel="nofollow">http://my.web.server/trax_and_cake_playground/trax/public/</a></tt>, I have a page telling me &#8220;Congratulations, you&#8217;ve put PHP on Trax!&#8221; I feel good.



</p><p>Trax <i>does</i> have a working auto-generate function, which is very nice, because I am getting tired of hand-editing all these files. If I wanted to do that, I&#8217;d be writing Perl or something. Still, there are a few more steps. I need to install the PEAR modules that Trax requires, which I do on the command-line:

</p>

<pre class="brush: js"> pear install Mail_Mime

</pre>

<p>I&#8217;ll use the same database and table I created back at the beginning, so long ago. I need to configure <tt>trax/config/database.ini</tt> to tell the application where they are:

</p>

<pre class="brush: js">    phptype = mysql



    database = bookmarker



    hostspec = localhost



    username = paul



    password = passw0rd



    persistent = 1

</pre>

<p>And then I need to edit <tt>public/.htaccess</tt> to tell the application where in my file system its own configuration is. The start of that file reads:



</p>

<pre class="brush: js"> # php include path for Trax ( Pear &amp; Trax config dir )



 php_value include_path



 .:/usr/local/lib/php:/home/&lt;username&gt;/trax/config

</pre>

<p>I change it to suit my Debian setup:

</p>

<pre class="brush: js"> # php include path for Trax ( Pear &amp; Trax config dir )



 php_value include_path .:/usr/share/php:/var/www/html/trax/trax/config

</pre>

<p>Now I am ready to &#8212; make Trax? Lay down Trax? There doesn&#8217;t seem to be a catchy verb for auto-generating models and controllers and views here. I, um, look both ways and prepare to cross the Trax.

</p><p>The script that does the work is <tt>trax/script/generate.php</tt>. First, I need to edit the first line of that file to point to where my PHP executable actually is. Not <tt>/usr/local/bin/php</tt>, as the default has it. Mine is at <tt>/usr/bin/php</tt>. Also, the script seems to be happiest if I add my path information there as well, so toward the beginning of the file I enter the following:



</p>

<pre class="brush: js"> ini_set("include_path", ".:/usr/share/php:/var/www/html/trax/trax/config"); </pre>

<p>While I&#8217;m at it, I&#8217;ll add the same line to <tt>public/dispatch.php</tt>.

</p><p>Then I need to make <tt>generate.php</tt> executable with a deft <tt>chmod a+x</tt>.

</p><p>Now I&#8217;m ready to run the generate script, which I do from the command line. If your server doesn&#8217;t like PHP scripts to be run from the command line, you&#8217;ll have to open the script in a browser. I type this:

</p>

<pre class="brush: js"> ./trax/script/generate.php model Bookmark </pre>



<p>and Trax replies:

</p>

<pre class="brush: js"> created /var/www/html/trax/trax/app/models/bookmark.php </pre>

<p>Then I type:

</p>

<pre class="brush: js"> ./trax/script/generate.php controller bookmark display add </pre>

<p>and Trax replies:

</p>

 <pre class="brush: js">created /var/www/html/trax/trax/app/controllers/bookmark_controller.php



 created /var/www/html/trax/trax/app/helpers/bookmark_helper.php



 created /var/www/html/trax/trax/app/views/bookmark/display.phtml



 created /var/www/html/trax/trax/app/views/bookmark/add.phtml

</pre>

<p><br />

&#8220;Display&#8221; and &#8220;add&#8221; are the initial views I want. Finally (I hope), I just need to add routing, so I can view my views in a browser. I add the following to <tt>trax/config/routes.php</tt>:



</p>

<pre class="brush: js"> $router-&gt;connect( "", array(":controller" =&gt; "bookmark") ); </pre>

<p>and <i>voila</i>! I can see a page! True, it&#8217;s blank, which means that I need to flesh out my actions and views. But it is a page! Let me just put in a couple of basics.

</p><p>In <tt>trax/app/controllers/bookmark_controller.php</tt>, there&#8217;s an empty definition of the view() method. I&#8217;ll put this in:

</p>

<pre class="brush: js"> function view() {



        $bookmark = new Bookmark();



        $this-&gt;bookmarks = $bookmark-&gt;find_all();



    }



</pre>

<p><br />

and in <tt>app/views/bookmark/display.phtml</tt> I put a PHP table similar to the one I used for Cake, to loop through the bookmarks table and display each one.

</p><p>Whew. Two starter semi-apps built in as many hours. Not too bad.

</p><p><br />

</p>

<a name="Hardly_the_End_of_the_Story"></a><h3> <span class="mw-headline">Hardly the End of the Story</span></h3>

<p>Would I do it again? Are either of the frameworks are 100 percent ready for prime time? Documentation is getting better every day, but neither framework has anything like the whopping user community of Rails.

</p><p>I was able to iron out my own snags &#8212; several had to do with permissions, Apache directory overrides, and stuff like that &#8211; but if I couldn&#8217;t, it would be nice to have more resources to turn to. Conversely, PHP has a considerably larger support community on the Web than Ruby does, although that tide may slowly be turning.

</p><p>Trax and Cake aren&#8217;t the end of the PHP dev framework story:there&#8217;s <a href="http://www.symfony-project.com/" class="external text" title="http://www.symfony-project.com/" rel="nofollow">Symfony</a>; Zend has a <a href="http://www.zend.com/collaboration/framework-overview.php" class="external text" title="http://www.zend.com/collaboration/framework-overview.php" rel="nofollow">framework</a> and a quick trawl of the web turns up things like <a href="http://www.php2go.com.br/" class="external text" title="http://www.php2go.com.br/" rel="nofollow">PHP2Go</a>, <a href="http://qcodo.com/" class="external text" title="http://qcodo.com/" rel="nofollow">Qcodo</a> and doubtless many more.



</p><p>Rails is a pleasure to use, while Trax and Cake combine pleasure with a bit of effort. If you&#8217;re a PHP wiz, though, the fact that they&#8217;re based in a language you know should more than outweigh any difficulties brought on by the frameworks&#8217; immaturity. It&#8217;s easier to debug a stuck app than to learn a whole new language, even one as perspicuous and enjoyable as Ruby.

</p><p>So tune in next time when we cover Brails, the new web programming framework for the visually impaired! That&#8217;s a joke. Don&#8217;t sue.

</p><p><br />

</p>

<a name="Helpful_Links"></a><h3> <span class="mw-headline">Helpful Links</span></h3>

<ul><li> Visit <a href="http://cakephp.org/" class="external text" title="http://cakephp.org/" rel="nofollow">CakePHP.org</a>

</li><li> Visit <a href="http://bakery.cakephp.org/" class="external text" title="http://bakery.cakephp.org/" rel="nofollow">The Bakery</a>

</li><li> Visit the <a href="http://www.nabble.com/CakePHP-f16511.html" class="external text" title="http://www.nabble.com/CakePHP-f16511.html" rel="nofollow">CakePHP forum</a> at Nabble



</li></ul>

<ul><li> Visit the <a href="http://forum.phpontrax.com/" class="external text" title="http://forum.phpontrax.com/" rel="nofollow">Trax forum</a>

</li></ul>

<p><br />

</p><p><br /><div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/02/cake_and_trax_for_beginners/feed/</wfw:commentRss>
        <slash:comments>0</slash:comments>

        
    </item>
    
    <item>
        <title>Manage Transactions in MySQL</title>
        <link>http://www.webmonkey.com/2010/02/manage_transactions_in_mysql/</link>
        <comments>http://www.webmonkey.com/2010/02/manage_transactions_in_mysql/#comments</comments>
        <pubDate>Tue, 16 Feb 2010 01:45:47 +0000</pubDate>

                <dc:creator>Webmonkey Staff</dc:creator>

        <guid isPermaLink="false">http://stag.wired.com/primate/?p=779</guid>
        		<category><![CDATA[Databases]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[wiki]]></category>
        <description><![CDATA[Overview In this tell-all tutorial, Jay Greenspan, author of MySQL Weekend Crash Course and co-author of MySQL/PHP Database Applications, starts with a tour of the basics: He answers the age-old Q: &#8220;What&#8217;s the big deal with Transactions?&#8221;; investigates the four properties that a database must have to be considered transaction-capable; takes a closer look at [...]]]></description>

            <content:encoded><![CDATA[<!-- wpautop disabled --><a name="Overview"></a><h3> <span class="mw-headline">Overview</span></h3>

<p>In this tell-all tutorial, Jay Greenspan, author of <i><a href="http://shop.barnesandnoble.com/booksearch/isbnInquiry.asp?userid=1BY8IS0FQU&amp;mscssid=&amp;isbn=0764536346" class="external text" title="http://shop.barnesandnoble.com/booksearch/isbnInquiry.asp?userid=1BY8IS0FQU&amp;mscssid=&amp;isbn=0764536346" rel="nofollow">MySQL Weekend Crash Course</a></i> and co-author of <i><a href="http://shop.barnesandnoble.com/booksearch/isbnInquiry.asp?userid=0CJ4LF616I&amp;mscssid=7E25DM3JFHGX8P6RQA3H59MMCN4RC12F&amp;isbn=0764535374" class="external text" title="http://shop.barnesandnoble.com/booksearch/isbnInquiry.asp?userid=0CJ4LF616I&amp;mscssid=7E25DM3JFHGX8P6RQA3H59MMCN4RC12F&amp;isbn=0764535374" rel="nofollow">MySQL/PHP Database Applications</a></i>, starts with a tour of the basics: He answers the age-old Q: &#8220;What&#8217;s the big deal with Transactions?&#8221;; investigates the four properties that a database must have to be considered transaction-capable; takes a closer look at locking mechanisms; and finishes up with a look at MyISAM tables, the lesser cousin of fully transaction-capable tables.

</p><p>Once you have a taste of the limitations of MyISAM tables, you&#8217;ll be hungry for the real deal. In Lesson 2, Jay satiates that hunger with a thorough introduction to MySQL&#8217;s different transactional table types: BDB, Gemini, and InnoDB.

</p><p>Get started: <b><a href="/2010/02/Manage_Transactions_in_MySQL_-_Lesson_1" title="Tutorial:Manage Transactions in MySQL - Lesson 1">Lesson 1</a></b><div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/02/manage_transactions_in_mysql/feed/</wfw:commentRss>
        <slash:comments>0</slash:comments>

        
    </item>
    
    <item>
        <title>Manage Transactions in MySQL &#8211; Lesson 1</title>
        <link>http://www.webmonkey.com/2010/02/manage_transactions_in_mysql_-_lesson_1/</link>
        <comments>http://www.webmonkey.com/2010/02/manage_transactions_in_mysql_-_lesson_1/#comments</comments>
        <pubDate>Tue, 16 Feb 2010 01:45:47 +0000</pubDate>

                <dc:creator>Webmonkey Staff</dc:creator>

        <guid isPermaLink="false">http://stag.wired.com/primate/?p=781</guid>
        		<category><![CDATA[Databases]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[wiki]]></category>
        <description><![CDATA[(Note: This article is adapted from Jay&#8217;s new book, MySQL Weekend Crash Course look for it at a store near you. A book store! -Ed.) MySQL has become the database of choice for many Web developers over the last few years and for good reason. It&#8217;s fast, free, easy to use, and has great community [...]]]></description>

            <content:encoded><![CDATA[<!-- wpautop disabled --><p><i>(Note: This article is adapted from Jay&#8217;s new book,</i> <a href="http://shop.barnesandnoble.com/booksearch/isbnInquiry.asp?userid=1BY8IS0FQU&amp;mscssid=&amp;isbn=0764536346" class="external text" title="http://shop.barnesandnoble.com/booksearch/isbnInquiry.asp?userid=1BY8IS0FQU&amp;mscssid=&amp;isbn=0764536346" rel="nofollow">MySQL Weekend Crash Course</a><i> look for it at a store near you. A book store! -Ed.)</i>

</p><p>MySQL has become the database of choice for many Web developers over the last few years and for good reason. It&#8217;s fast, free, easy to use, and has great community support.

</p><p>But many experienced developers refused to touch MySQL because, they complained, the product didn&#8217;t implement features that were absolutely critical in an SQL server. MySQL&#8217;s most egregious omission, according to some, was its lack of transaction support. But thanks to recent developments in MySQL land, that&#8217;s no longer the case.

</p><p>When it first hit the cyber-street, MySQL offered only one table type for data storage, the ISAM table now upgraded to the MyISAM type for all recent versions of MySQL. But MyISAM tables were limited. Very limited.

</p><p>Then the folks from <a href="http://www.sleepycat.com/" class="external text" title="http://www.sleepycat.com/" rel="nofollow">Sleepycat Software</a> came into the picture. Sleepycat creates and sells a database storage engine which is used mostly with embedded devices. The storage engine comes with an API that allows developers to integrate Sleepycat&#8217;s data storage software into their products. And that&#8217;s just what the folks at MySQL did, they integrated the Berkeley DB (or BDB) table from Sleepycat. This was the first transactional table type included available to MySQL users.

</p><p>Berkeley DB tables were followed shortly by two other transactional table types: InnoDB and Gemini. Gemini tables are adopted from another embedded storage mechanism; this one from <a href="http://www.nusphere.com/" class="external text" title="http://www.nusphere.com/" rel="nofollow">NuSphere</a>, a <a href="http://www.progress.com" class="external text" title="http://www.progress.com" rel="nofollow">Progress Software</a> property. <a href="http://www.innodb.com/" class="external text" title="http://www.innodb.com/" rel="nofollow">InnoDB</a> tables were designed specifically for MySQL.

</p><p>But we&#8217;re getting ahead of ourselves here. Before we take a closer look at each of these different options, we need to start at square one: Why you want transaction support in the first place.</p>

<p><span id="more-781"></span>
</p>

<table id="toc" class="toc" summary="Contents"><tbody><tr><td><div id="toctitle"><h2>Contents</h2> </div>
<ol>
<li><a href="#Getting_in_on_the_Transactions">Getting in on the Transactions</a></li>
<li><a href="#Are_You_on_ACID.3F">Are You on ACID?</a></li>
<li><a href="#Lockdown.21">Lockdown!</a></li>
<li><a href="#Using_MyISAM_Tables">Using MyISAM Tables</a></li>
</ol>
</td></tr></tbody></table>


<a name="Getting_in_on_the_Transactions"></a><h3> <span class="mw-headline">Getting in on the Transactions </span></h3>

<p>If you&#8217;re relatively new to databases, or if MySQL has been the database on which you&#8217;ve cut your teeth, you may not even know what a transaction is. Put simply, a transaction is a series of SQL statements that are executed as a single unit; either all the statements are executed completely or none are executed at all.

</p><p>Why are transactions so important? Consider a fairly typical Web application: a shopping cart. In a simple shopping cart application, you&#8217;re likely to have tables that look a little something like this (only less simplified, and with real info instead of the dummy data):

</p>



<pre class="brush: js"> products

 +------------+-------------------+---------------------------+---------------+

 | product_id | product_name      | product_description       | product_price |

 +------------+-------------------+---------------------------+---------------+

 |          1 | Old Pair of Socks | Plenty of holes           |          4.25 |

 |          2 | Old T-shirt       | Ketchup stains everywhere |          6.75 |

 +------------+-------------------+---------------------------+---------------+



 inventory

 +------------+----------+

 | product_id | in_stock |

 +------------+----------+

 |          1 |       25 |

 |          2 |       12 |

 +------------+----------+



 buyers

 +----------+-------+---------+------------+------------+

 | buyer_id | fname | lname   | phone      | fax        |

 +----------+-------+---------+------------+------------+

 |        1 | John  | Doe     | 7185551414 | NULL       |

 |        2 | Jane  | Johnson | 7185551414 | 2126667777 |

 +----------+-------+---------+------------+------------+



 orders

 +----------+----------+-------------+

 | order_id | buyer_id | order_price |

 +----------+----------+-------------+

 |        1 |        1 |       11.00 |

 +----------+----------+-------------+



 order_items

 +----------+------------+---------------+

 | order_id | product_id | product_price |

 +----------+------------+---------------+

 |        1 |          1 |          4.25 |

 |        1 |          2 |          6.75 |

 +----------+------------+---------------+

</pre>

<p>You can see how these tables fit together in this diagram:

</p><p><img src="http://www.wired.com/wired/webmonkey/stuff/schema.jpg" alt="schema.jpg">

</p><p>When it comes time to process an order, you have to run several SQL statements within a script (written in PHP, Perl, Java, or whatever language you prefer). In the script, you want to take a look at what items the buyer wants, see if there&#8217;s adequate inventory to complete the order, and if there is adequate inventory, you want to complete the order. In pseudo-code, the script used to complete the order would look something like this:

</p>

<pre class="brush: js"> get buyer data and shopping cart data from web forms

 insert buyer data into buyer table

 start order by creating row in orders table

 get current order_id

 for each item desired

    check available inventory

    if inventory is available

       write item to order_items table

       decrement inventory

    endif

 end for loop

 get total for items for the order

 update orders table

</pre>

<p>I simplified this listing so that it&#8217;s easier to spot a potential problem. Consider what would happen if the power failed on the machine hosting the database just as it was in the middle of checking the inventory of the first item in the order. You&#8217;d restart your machine to find a row in the <tt>orders</tt> table without any child rows in the <tt>order_items</tt> table. It&#8217;s quite possible you&#8217;d be left with data that was, to a large extent, incomprehensible. You wouldn&#8217;t know what orders had been placed unless your customers sent you email, wondering just when you planned to send them the old pairs of socks they had requested not the best way to run a business.



</p><p>If you had transaction support in place, however, you could treat this group of statements as a single unit. If for any reason the database failed to complete all of the statements in their entirety, the data would revert (or roll back) to the condition it was in prior to the first statement&#8217;s execution.

</p><p>Of course there&#8217;s a bit more to transactions. A transaction-capable database must implement four specific properties. Wanna know what they are? Turn the page.

</p>

<a name="Are_You_on_ACID.3F"></a><h3> <span class="mw-headline">Are You on ACID? </span></h3>

<p>Transaction-capable databases must implement four properties, collectively known by the mnemonic acronym ACID.

</p>

<ul><li> Atomicity: Transactions must be singular operations. Either all statements are executed as a single (atomic) unit or none are executed at all.

</li><li> Consistency: In a transactional database, data will move from one consistent state to another. There will never be a point during a transaction when data is partly processed.

</li><li> Isolation: The dealings of one transaction will not be visible to other clients until the transaction is completed successfully or rolled back. You can be sure that the data available to one transaction is accurate because it is isolated from changes other clients might make.

</li><li> Durability: When a transaction completes successfully, the changes are permanent. Nothing, not even a disk crash or power failure, will erase the changes made by a successfully completed transaction.

</li></ul>



<p>SQL servers that allow transactions make use of several keywords: BEGIN WORK, COMMIT, and ROLLBACK. The phrase BEGIN WORK lets the SQL server know that the SQL statements that follow are part of a transaction. The transaction is not completed until either a COMMIT or ROLLBACK statement is executed. COMMIT writes the changes to the database. Once a transaction has been successfully COMMITed, only another successfully committed SQL statement can alter the data. No crashes or concurrently run SQL statements will effect the data. The ROLLBACK command tells the database that all of the statements within the transaction should be ignored and the database should revert to the point it was in prior to the start of the transactions. In the case of a crash, all transactions that were not expressly committed are automatically rolled back.

</p><p>You can now revisit the pseudo-code first presented on the previous page. I&#8217;ve improved the listing by incorporating a transaction.

</p>

<pre class="brush: js"><tt>

get buyer data and shopping cart data from web forms

insert buyer data into buyer table

BEGIN WORK

start order by creating row in orders table

get current order_id

for each item desired

   check available inventory

   if inventory is available

      write item to order_items table

      decrement inventory

   else

       set error variable to true

   endif

end for loop

if error variable is true

	ROLLBACK

else

	get total for items for the order

	update orders table

	COMMIT

</tt>

</pre>

<p>Notice the ROLLBACK that I&#8217;ve added. This ensures that if inventory isn&#8217;t available to complete even a portion of a user&#8217;s request, the entire order is ignored. No row will be written to the <tt>orders</tt> or <tt>order_items</tt> table. Are you beginning to see how good transactions can be?

</p><p>In a Web environment, you can expect multiple users (database clients or threads) to be accessing the script simultaneously. Therefore, the inventory of a given item will be changing continually. But when using transactions, you don&#8217;t have to worry that a user will complete an order for an item that is actually out of stock. That&#8217;s because of the I (for Isolation) in ACID. In a transactional environment, each transaction is isolated from the other, so one transaction cannot see the working of another transaction until the first one is complete.

</p><p>The last sentence was a bit of a simplification, but it&#8217;s pretty close, and it&#8217;s good enough for now. In order to isolate one transaction from another, database systems must implement some sort of locking scheme. That is, the database needs a way for one client (or thread) to lock out (or isolate itself) from all other clients.

</p><p>Locking is a key element of transactions. I&#8217;ll be talking about this subject extensively throughout this tutorial, starting on the next page.



</p>

<a name="Lockdown.21"></a><h3> <span class="mw-headline">Lockdown! </span></h3>

<p>Locking makes some portion of data the property of a single client. That client says, in effect, &#8220;this data here is mine, and the rest of you can only do what I expressly permit.&#8221; Locks can have one of two effects: A lock may prevent other clients from altering data (with UPDATE or DELETE statements) or a lock may prevent all access to some data preventing UPDATEs, DELETEs, and even SELECTs.

</p><p>To understand locking mechanisms in MySQL, you first need to recognize that MySQL is an unusual product. It isn&#8217;t really a single, unified piece of software. Rather, it uses technology from several different sources, and the way you implement your transactions in MySQL largely depends on the table type you use. Each table-type uses a different method of locking, and the differences in those locking mechanisms will effect how you write your code.

</p><p>MyISAM tables are very fast for SELECTs, but they have some serious drawbacks when it comes to locking. These shortcomings are what prevented MySQL from implementing some key database features, including transactions.

</p><p>Looking at the way MyISAM struggles with locking, you really begin to appreciate the power and value of actual transactions. So before we get into BDB, Gemini, and InnoDB, let&#8217;s first take a look at the limitations of MyISAM&#8217;s table-level locking.

</p>

<a name="Using_MyISAM_Tables"></a><h3> <span class="mw-headline">Using MyISAM Tables </span></h3>

<p>I already mentioned that MyISAM tables (usually MySQL&#8217;s default table type) don&#8217;t support transactions. This is largely because MyISAM tables offer only table-level locking, which means that locks can only be placed on entire tables. So if you want to prevent a single row in a table from being changed, you need to prevent all rows in the table from being changed.

</p><p>Take our inventory table as an example. If one client is buying an item, you&#8217;ll want to check the inventory, and if the item is there in sufficient quantity, you&#8217;ll decrement the number available after the sale. To make sure the quantity doesn&#8217;t change between the time you check the availability and the time your change the inventory, you&#8217;ll want to put a lock on that row. But because MyISAM offers only table-level locking, you&#8217;ll have to cut off access to all other rows in the table.

</p><p>MyISAM offers two types of table-level locks, a read lock and a write lock. When a read lock is initiated by a client, all other clients are prevented both from making changes to the table via INSERTs, DELETEs, or UPDATES.

</p><p>To see how a read-level lock works on a MyISAM table, open up two copies of the MySQL command-line client. Then create a table and insert some data with the statements below

</p>



<pre class="brush: js"> create table inventory (

     product_id int not null  primary key,

     in_stock int not null,

     index index_on_in_stock(in_stock)

 )type=myisam;



 INSERT INTO inventory (product_id, in_stock) VALUES(1,25), (2,12);

</pre>

<p>Now in one client, place a read lock on the <tt>inventory</tt> table with the following command:

</p>

<pre class="brush: js"> LOCK TABLES inventory READ;

</pre>

<p>Now in the second copy of the client run a <tt>SELECT * FROM inventory</tt>. You&#8217;ll see that the command executes just fine. However, if you try to run an UPDATE, it&#8217;s a different story. Try the following command with the lock in place.

</p><p>&lt;/pre&gt;

</p>



<pre class="brush: js">UPDATE inventory set in_stock=24 where product_id=1;

</pre>

<p>&lt;/pre&gt;

</p><p>You&#8217;ll see that this copy of the client does not respond. It&#8217;s locked out and can&#8217;t execute the command. Only the client that placed the lock can change the table. Now go back to the first copy of the command-line client and release the lock with:

</p>

<pre class="brush: js"> UNLOCK TABLES;

</pre>

<p>Once the lock is released the second client will be free to run the UPATE command and change the row.

</p><p>A write lock prevents other clients from even running SELECTs on the locked table. You can place a write lock with the following command:

</p>

<pre class="brush: js"> LOCK TABLES inventory WRITE;



</pre>

<p>Go back and run the previous experiment but this time issue a WRITE lock. You&#8217;ll see that the other client is prevented from doing anything, even reading from the locked table with a SELECT.

</p><p>So now you know all the locks that are possible with MyISAM tables. As I mentioned earlier, the folks at MySQL AB (who run MySQL development) often argue that transactions really aren&#8217;t necessary. They say that by properly applying locks and writing clever SQL, you should be able to avoid the need for transactions. Below I&#8217;ve written some pseudo-code that adds transaction-like abilities to the shopping cart pseudo-code using MyISAM tables.



</p>

<pre class="brush: js"> INSERT query into buyers table.

 run last_insert_id() to get buyer_id

 run INSERT into orders table

 run last_insert_id() to get order_id

 get write lock on inventory table

 for each of the items in the order

     get quantity from the inventory table

     if quantity is &gt; 0

         insert into order_items table

         update inventory table subtracting the ordered item

     elseif quantity = 0

         delete all items from order_items with current order_id

         delete item from orders table with current order_id

         update inventory table to replenish items previously subtracted

         set error variable to true

         break from for loop

 if error variable is not true

     update orders table with the current order_id, adding the order_total

 else

     output error

</pre>

<p>I might be able to clean this up a bit and remove a few of the SQL statements, but I think you see the way you&#8217;d need to go writing transaction-like code with MyISAM tables. While this code might add a degree of isolation (remember the I in ACID) by way of locks, there are other ACID properties missing here. Most notable is the lack of consistency: The data moves through several inconsistent states before the script is done. If the power goes out during one these inconsistent phases, you&#8217;ve got problems.

</p><p>While ISAM locks are better than nothing, they are really no substitute for true ACID transactions. In Lesson 2 of this tutorial, I&#8217;ll discuss locking and transactions in BDB, InnoDB, and Gemini tables.

</p><p>Come on back, ya&#8217;here.

</p><p>Next: <b><a href="/2010/02/Manage_Transactions_in_MySQL_-_Lesson_2" title="Tutorial:Manage Transactions in MySQL - Lesson 2">Lesson2</a></b>

</p><p><div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/02/manage_transactions_in_mysql_-_lesson_1/feed/</wfw:commentRss>
        <slash:comments>0</slash:comments>

        
    </item>
    
    <item>
        <title>Manage Transactions in MySQL &#8211; Lesson 2</title>
        <link>http://www.webmonkey.com/2010/02/manage_transactions_in_mysql_-_lesson_2/</link>
        <comments>http://www.webmonkey.com/2010/02/manage_transactions_in_mysql_-_lesson_2/#comments</comments>
        <pubDate>Tue, 16 Feb 2010 01:45:47 +0000</pubDate>

                <dc:creator>Webmonkey Staff</dc:creator>

        <guid isPermaLink="false">http://stag.wired.com/primate/?p=783</guid>
        		<category><![CDATA[Databases]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[wiki]]></category>
        <description><![CDATA[In Lesson 1 of this tutorial, you leaned how to approximate transaction-like behavior with MyISAM tables. In this lesson, you&#8217;ll see how you can achieve real transactions with each of MySQL&#8217;s three transactional table types: BDB, InnoDB, and Gemini. But before I get to specifics surrounding each table, I need to revisit the notion of [...]]]></description>

            <content:encoded><![CDATA[<!-- wpautop disabled --><p>In Lesson 1 of this tutorial, you leaned how to approximate transaction-like behavior with MyISAM tables. In this lesson, you&#8217;ll see how you can achieve real transactions with each of MySQL&#8217;s three transactional table types: BDB, InnoDB, and Gemini. But before I get to specifics surrounding each table, I need to revisit the notion of locking.

</p><p>Remember that MyISAM supports only table-level locks of two types: read locks and write locks. The transactional tables types offer more granular locking mechanisms: They can place locks on specific subsets of data. You&#8217;ll read more about each table&#8217;s locking mechanisms as I get to them in the following pages.
</p><br />
<span id="more-783"></span>

<table id="toc" class="toc" summary="Contents"><tbody><tr><td><div id="toctitle"><h2>Contents</h2> </div>

<ol>
<li><a href="#Using_BDB_Tables">Using BDB Tables</a></li>
<li><a href="#Working_with_Gemini_Tables">Working with Gemini Tables</a></li>
<li><a href="#Using_InnoDB_Tables">Using InnoDB Tables</a></li>
<li><a href="#The_Right_Choice_for_You">The Right Choice for You</a></li>
</ol>
</td></tr></tbody></table>

<p><a name="Working_with_MySQL.27s_Transactional_Table_Types"></a><h3> <span class="mw-headline">Working with MySQL&#8217;s Transactional Table Types </span></h3>

</p><p>Transactional table types can apply two types of locks. These are known as <i>shared locks</i> and <i>exclusive locks</i>. A shared lock is similar to the MyISAM read lock. When a client places a shared lock on data, other clients cannot alter that data with UPDATE or DELETE statements, but they can read the locked data via SELECTs. When a client gains an exclusive lock, other clients can neither alter the locked data via UPDATEs and DELETEs, nor can they read the data with SELECTs.

</p><p>Before we get to the actual code, there&#8217;s a MySQL setting I need to mention. MySQL contains an environment variable called <code>autocommit</code>. By default, autocommit is set to 1. When autocommit is set to 1, you cannot run transactions with any of the MySQL table types. In this mode, MySQL treats every SQL statement as its own transaction. To use groups of statements as transactions you need to turn autocommit mode off. So in all the code snippets that follow, you&#8217;ll notice that I start each with the line:

</p>



<pre class="brush: js"><code>SET autocommit=0;

</code>

</pre>

<p>OK, now on to the rest of the code, starting with BDB tables.

</p>

<a name="Using_BDB_Tables"></a><h3> <span class="mw-headline">Using BDB Tables </span></h3>

<p>To check if you have BDB tables available, run the following query:

</p>

<pre class="brush: js"> mysql&gt; show variables like '%have%';

 +---------------+-------+

 | Variable_name | Value |

 +---------------+-------+

 | have_bdb      | YES   |

 | have_innodb   | YES   |

 | have_isam     | YES   |

 | have_raid     | NO    |

 | have_symlink  | YES   |

 | have_openssl  | NO    |

 +---------------+-------+

 6 rows in set (0.00 sec)



</pre>

<p>If the first row in the listing says &#8220;no&#8221; you don&#8217;t have BDB installed. If you&#8217;ve got either InnoDB or Gemini, that&#8217;s fine &#8212; you can just use one of those, and I&#8217;ll talk about these tables soon (but please stick around, what you learn here will be useful there). If you decide to work with BDB tables, you can either install a MySQL-Max binary or recompile MySQL from source using the <code>--with-bdb</code> flag. BDB tables are available for most operating systems, including Windows, Linux, and Mac OS X.



</p><p>To create BDB tables, you can include <code>type=bdb</code> at the end of the CREATE statement. For example:

</p>

<pre class="brush: js">

 create table inventory(

     product_id int not null primary key,

     in_stock int not null

 )type=bdb;

</pre>

<p>Or, if you wish to move data from a MyISAM to a BDB table, you can run an ALTER statement, like so:

</p>

<pre class="brush: js"><code>

ALTER table table_name type=bdb;

</code>

</pre>

<p>Note that before you run an ALTER statement like this, you should backup the table. This type of ALTER statement actually dumps the table data, creates a new BDB table, and then loads the dumped data into the table. It&#8217;s an involved process that can fail, and if it does fail you want to be protected. Also be prepared to wait a while. If you&#8217;ve got large table, the dump-and-reload process can take a bit of time.

</p><p>BDB tables offer page-level locking. What&#8217;s a page? It&#8217;s a group of rows. The exact number of rows in a page varies depending on the number of rows in your tables, the operating system in use, and other factors. During a transaction, MySQL will apply a lock to a page worth of data. All other rows are unaffected by locks and ready to process whatever queries you throw at them.



</p><p>Page-level locking is a vast improvement over the table-level locking used by MyISAM tables. If only groups of rows &#8212; small subsets of whole tables &#8212; are locked by a single client, that means many clients can access different portions of the table simultaneously. In fact, it&#8217;s acceptable, even commonplace, to have many clients applying various locks to different portions of a table at the same time. The simultaneous access of data by different clients is usually referred to as <i>concurrency</i>. In database land (where the men have hairless backs and the women shapely legs) the greater the concurrency the better.

</p><p>One of the great things about transactions is that for the most part you don&#8217;t need to worry about manually applying the locks. Just start a transaction, run your SQL statements as you normally would, and the clever MySQL engine will mostly take care of the locking for you. Neat-o!

</p><p>Take a look at a simple transaction in a BDB table working with the following table:

</p>

<pre class="brush: js">mysql&gt; select * from inventory;

 +------------+----------+

 | product_id | in_stock |

 +------------+----------+

 |          1 |       24 |

 |          2 |       47 |

 +------------+----------+

 2 rows in set (0.05 sec)

</pre>

<p>To see the effect of a transaction, open up two copies of the command-line client. In one, start a transaction and run a SELECT on the first row:

</p>

<pre class="brush: js"> mysql&gt; set autocommit=0;

 mysql&gt; begin work;

 mysql&gt; select * from inventory where product_id=1;





</pre>

<p>Now in the second client, start a transaction and try to update the row 1.

</p>

<pre class="brush: js"> mysql&gt; set autocommit=0;

 mysql&gt; begin work;

 mysql&gt; update inventory set in_stock=23 where product_id=1;&lt;/code&gt;

</pre>

<p>You&#8217;ll see that the second client, the one trying to do the UPDATE, doesn&#8217;t respond. That&#8217;s because the first client has a share lock on that row. To release the lock, commit the transaction in the first client:

</p>

<pre class="brush: js"><code>mysql&gt; commit;</code>



</pre>

<p>You&#8217;ll notice that the second client is immediately freed to run the update operation.

</p><p>Take a look at the following improvement to the pseudo-code I used in Lesson 1 of the tutorial. Note the use of the BEGIN WORK-COMMIT/ROLLBACK syntax.

</p>

<pre class="brush: js"> set autocommit=0

 INSERT query into buyers table.

 run last_insert_id() to get user_id

 BEGIN WORK

 run INSERT into orders table

 run last_insert_id() to get order_id

 for each of the items in the order

     get quantity from the inventory table

     if quantity is &gt; 0

         insert into order_items table

         update inventory table subtracting the ordered item

     elseif quantity = 0

         set error variable

 if error variable is not set

     update orders table with the current order_id,

     adding the order_total



     COMMIT

 else

     ROLLBACK

     output error

</pre>

<p>Pretty nice, eh? Much cleaner than the MyISAM transaction-equivalent, I think. Keep in mind that you get all the ACID properties with this code if you&#8217;re using BDB tables. There is only one line of this code that doesn&#8217;t really work well and needs to be improved.

</p><p>Notice that for each item in the order, I first check the quantity from the <code>inventory</code> table. That quantity will come from a SELECT statement, something like <code>SELECT in_stock FROM inventory WHERE product_id=1</code>. But in most cases, the inventory is going to change just after this SELECT is run. If there&#8217;s sufficient quantity in stock, this person is going to buy the item and therefore the quantity listed in the table will decrement by one when the transaction is complete. You&#8217;d hate to see other clients get data that will be inaccurate in a matter of milliseconds.

</p><p>In a case like this, you&#8217;d be much better off putting an exclusive lock on a page containing the row in question until the transaction is complete. Remember, with an exclusive lock, all other clients are forbidden from even reading the locked rows. But unfortunately, BDB tables have no way to execute exclusive locks on pages of data. Only by instituting a table-wide write lock can you safeguard the data in the inventory table.



</p><p>When revised with the table-wide write lock the pseudo-code looks like this:

</p>

<pre class="brush: js"> set autocommit=0

 INSERT query into buyers table.

 run last_insert_id() to get user_id

 BEGIN WORK

 run INSERT into orders table

 run last_insert_id() to get order_id

 LOCK TABLES inventory WRITE

 for each of the items in the order

     get quantity from the inventory table

     if quantity is &gt; 0

         insert into order_items table

         update inventory table subtracting the ordered item

     elseif quantity = 0

         set error variable

 UNLOCK TABLES;

 if error variable is not set

     update orders table with the current order_id,

     adding the order_total



     COMMIT

 else

     ROLLBACK

</pre>

<p>The LOCK TABLES command here is a bit messy. But with the other two MySQL tables you won&#8217;t have to worry about this kind of lock.

</p>

<a name="Working_with_Gemini_Tables"></a><h3> <span class="mw-headline">Working with Gemini Tables </span></h3>

<p>It&#8217;s difficult to talk about Gemini tables without touching on the controversy surrounding the maker of the Gemini table, NuSphere. The NuSphere corporation is currently in a <a href="http://www.theregister.co.uk/content/4/24219.html" class="external text" title="http://www.theregister.co.uk/content/4/24219.html" rel="nofollow">legal dispute</a> with MySQL AB, the folks who code the MySQL core engine. The issues include copyright infringement and abuse of the GNU GPL. You may want to read further about these issues before choosing the Gemini table type.

</p><p>Gemini offers a more granular level of locking than BDB. With Gemini (and InnoDB, which I&#8217;ll discuss momentarily), you get the advantage of row-level locking. With Gemini, you can apply both share and exclusive locks to one row at a time. A row-level locking scheme will generally achieve higher concurrency than page-level locking, and much greater concurrency than table-level locking.



</p><p>You can check if you have Gemini installed by running <code>show variables like '%have%'</code>. And if you don&#8217;t have Gemini, you can get an installer that includes MySQL, PHP, mod_perl and other goodies from the <a href="http://www.nusphere.com/" class="external text" title="http://www.nusphere.com/" rel="nofollow">NuSphere website</a>. Note that the most current release of the Gemini table seems to have some bugs running on Windows 98, so if any of the following experiments crash your NuSphere MySQL installation on Windows 98, don&#8217;t blame me.

</p><p>To create Gemini tables include the <code>type=gemini</code> syntax at the end of the CREATE statement, and to transfer a current table to Gemini, run an ALTER TABLE query. The same caveats I mentioned for BDB apply here. For example:

</p>

<pre class="brush: js">	 create table inventory(

     product_id int not null primary key,

     in_stock int not null

 )type=gemini;





 ALTER table table_name type=gemini;

</pre>

<p>Unlike BDB, Gemini tables implement both shared and exclusive locks. If a thread runs an UPDATE or DELETE statement on a row, Gemini will place an exclusive lock on that row, preventing other threads from either reading or altering the locked row until the transaction is complete. If you think about it, this makes perfect sense. If a row is about to change, other threads should be protected from seeing potentially inaccurate data.

</p><p>If a thread runs a SELECT statement on a row, a shared lock will be placed on that row so other threads can read the row with SELECTs but they won&#8217;t be able to alter the row with UPDATE or DELETE statements.

</p><p>You can do some quick experiments with Gemini tables to see how this locking works. Assume you have the following Gemini table.

</p>



<pre class="brush: js">mysql&gt; select * from inventory;

 +------------+----------+

 | product_id | in_stock |

 +------------+----------+

 |          1 |       24 |

 |          2 |       47 |

 +------------+----------+

 2 rows in set (0.05 sec)

</pre>

<p>Open two copies of the command-line client. In the first start a transaction, then run a SELECT on row 1.

</p>

<pre class="brush: js"> mysql&gt; set autocommit=0;

 mysql&gt; begin work;

 mysql&gt; SELECT * FROM inventory WHERE product_id=1;

</pre>

<p>Now in the second client, start a transaction and try two statements, a SELECT and an UPDATE.

</p>



<pre class="brush: js"> mysql&gt; set autocommit=0;

 mysql&gt; begin work;

 mysql&gt; SELECT * FROM inventory WHERE product_id=1;

 mysql&gt; UPDATE inventory SET in_stock=23 WHERE product_id=1;

</pre>

<p>You&#8217;ll see that the SELECT executes immediately, but the UPDATE doesn&#8217;t execute. The UPDATE won&#8217;t execute until you COMMIT or ROLLBACK the transaction started in the first client, which releases the shared lock.

</p><p>You can re-run this experiment trying an UPDATE in the first client. You&#8217;ll notice that the second client is prevented from reading the locked row with a SELECT. When a client runs an UPDATE statement, it gets an exclusive lock on that row.

</p><p>When I discussed BDB tables, I pointed out that at times when inventory numbers are changing fast, you need a SELECT to obtain an exclusive lock so your users access the most up-to-date information. When you run a SELECT on the <code>inventory</code> table to find out the number of items currently in stock, you&#8217;re better off locking out all other threads from reading that row because that number is likely to change very quickly &#8212; an UPDATE will almost always follow that SELECT.



</p><p>With Gemini tables, you can get a exclusive lock while running a SELECT by using the FOR UPDATE keywords. For example.

</p>

<pre class="brush: js"><code>SELECT * FROM inventory WHERE product_id=1 FOR UPDATE</code>

</pre>

<p>Using this added power, the shopping cart pseudo-code can be re-written like so:

</p>

<pre class="brush: js"> set autocommit=0

 INSERT query into buyers table.

 run last_insert_id() to get user_id

 BEGIN WORK

 run INSERT into orders table

 run last_insert_id() to get order_id

 for each of the items in the order

     get quantity from the inventory

     table with SELECT ... FOR UPDATE



     if quantity is &gt; 0

         insert into order_items table

         update inventory table subtracting the ordered item

     elseif quantity = 0

         set error variable

 if error variable is not set

     update orders table with the current order_id,

     adding the order_total



     COMMIT

 else

     ROLLBACK

</pre>

<p>This is much cleaner, and much safer, than non-transactional code. And you can do something similar with InnoDB tables.

</p><p><br />

</p>

<a name="Using_InnoDB_Tables"></a><h3> <span class="mw-headline">Using InnoDB Tables </span></h3>



<p>InnoDB offers row-level locking and works on a wide variety of operating systems, including most UNIX variants, MacOS X, and Windows. This table type is now included by default in most MySQL installations, so if you get current binary from <a href="http://www.mysql.com/" class="external text" title="http://www.mysql.com/" rel="nofollow">mysql.com</a>, you&#8217;ll have InnoDB tables. You can check if you have InnoDB installed by running <code>SHOW VARIABLES LIKE '%have%';</code>.

</p><p>You can create InnoDB tables by using <code>type=innodb</code> in the CREATE statement or by running an ALTER TABLE command. For example:

</p>

<pre class="brush: js"> create table inventory(

     product_id int not null primary key,

     in_stock int not null

 )type=innodb;





 ALTER table table_name type=innodb;

</pre>

<p>The InnoDB transaction model is not quite as straightforward as the Gemini model. If you don&#8217;t understand how InnoDB implements transactions, you could end up with some serious problems with your data.

</p><p>InnoDB uses what&#8217;s called a <i>multi-versioning concurrency</i> model. Essentially, this means that each transaction is locked to a view of the data at a specific point in time. When a thread initiates a transaction, InnoDB gets a snapshot of the data based on the exact moment the transaction started. To understand how this works, take a look at the following example. You have a simple InnoDB table:



</p>

<pre class="brush: js"> mysql&gt; select * from inventory;

 +------------+----------+

 | product_id | in_stock |

 +------------+----------+

 |          1 |       24 |

 |          2 |       47 |

 +------------+----------+

</pre>

<p>In one copy of the command line client, you start a transaction:

</p>

<pre class="brush: js"> mysql&gt; set AUTOCOMMIT=0;

 mysql&gt; begin work;

</pre>

<p>This thread now has a snapshot of the table seen above. If you were to then open another copy of the client and start another transaction, that second client would have the same snapshot of the same table. At this point, the first client runs an UPDATE statement and commits the transaction.

</p>



<pre class="brush: js"><code>mysql&gt; UPDATE inventory set in_stock=23 WHERE product_id=1

mysql&gt; commit;</code>

</pre>

<p>Even after this COMMIT, the second client will not see the results of the UPDATE. The second client receives a snapshot of the data at the moment its transaction began. Until the second client finishes its transaction (with a COMMIT or ROLLBACK), it will not be able to view the changes implemented by other threads that took place while the transaction was active.

</p><p>Things get really sticky if the second client was also running an UPDATE on the same row. If the first and second clients start their transactions at the same time, they would get the same snapshots of data. The first client would run an update, <code>WHERE order_id=3</code>, but the second client would be unaware of the change. The second client could then run its own update, <code>UPDATE WHERE order_id=3</code>. After both of these clients commit their transactions, only one of the values can survive. As it turns out, the last one to COMMIT wins.

</p><p>As you can see, this is potentially a dangerous situation. If you&#8217;re not careful, some of your threads could see out-of-date information.

</p><p>But there are steps you can take to make sure the rows obtained by your transactions are up to date. It may not surprise you that staying current involves locking. With InnoDB, threads can apply the same types of locks that were available in Gemini.

</p><p>In Gemini tables, when you run a SELECT within a transaction, a share lock is placed on the rows read by the SELECT. However, by default, InnoDB does not place any locks on rows during a SELECT. But you can let InnoDB know that you want to obtain a share lock by the adding the clause LOCK IN SHARE MODE at the end of a SELECT.

</p><p>When a thread issues a SELECT with a LOCK IN SHARE MODE clause, InnoDB goes beyond the snapshot of data taken at the start of the transaction and looks for the latest committed data. If another thread is operating on that data (via an UPDATE, DELETE, or another LOCK IN SHARE MODE), the first thread won&#8217;t be able to obtain the share lock and will wait until the other thread finishes its transaction and releases its locks. By attempting to obtain the share lock and receiving the latest committed data, the LOCK IN SHARE MODE clause ensures that the data read by a SELECT will be accurate and up to date.



</p><p>If you&#8217;d like to see how this works, try the following, using the same table shown above. In one client, start a transaction and then run an UPDATE statement:

</p>

<pre class="brush: js"> mysql&gt; set autocommit=0;

 mysql&gt; begin work;

 mysql&gt; update inventory set in_stock=22 where product_id=1;

</pre>

<p>Now in the second client, run two different SELECTs. The first you will run without the LOCK IN SHARE MODE clause. Try <code>SELECT * FROM inventory</code>. This will execute immediately, but the data is potentially inaccurate because there&#8217;s no telling if the first client will COMMIT or ROLLBACK the transaction. If you alter that SELECT statement to include the LOCK IN SHARE MODE clause, the client will not respond until the first client issues a COMMIT or ROLLBACK.

</p><p>Threads can obtain exclusive locks in SELECT statements by using the same FOR UPDATE clause that is used with Gemini.

</p><p>The pseudo-code shown for Gemini will also work for InnoDB tables. But be very careful when writing your SELECT statements for InnoDB. You want to make sure you&#8217;re getting the latest, most accurate data.

</p>



<a name="The_Right_Choice_for_You"></a><h3> <span class="mw-headline">The Right Choice for You </span></h3>

<p>At this point, InnoDB is the most logical choice for most. It offers row-level locking, is available on most every operating system, and is getting a lot of support from MySQL AB. InnoDB is also the first table type to enforce foreign key constraints. But if you&#8217;re working with an installation that has support of one of the other transactional tables, both of those will work just fine.

</p><p>When you decide on the table type you wish to work with, you&#8217;ll have more technical matters to consider. You should read everything the MySQL manual has to say on the table type you end up using.

</p><p>Pay especially careful attention to your logs. The transactional tables use logs to help recover from crashes. If a hard-disk failure causes a crash on your system, you could be in trouble if your logs are on the same hard disk as your MySQL data.

</p><p>If you&#8217;re unhappy with the types of locks initiated by specific statements, you can adjust the locking behavior of Gemini and BDB table with the <a href="http://www.mysql.com/doc/S/E/SET_TRANSACTION.html" class="external text" title="http://www.mysql.com/doc/S/E/SET_TRANSACTION.html" rel="nofollow">SET TRANSACTION command</a>. I won&#8217;t cover it in detail here because the defaults discussed in this tutorial are usually preferable. Note that InnoDB tables are unaffected by SET TRANSACTION command.

</p><p>Transactions are a great improvement to the MySQL database. If you&#8217;re not using them now, consider using them in the future. Because when that backhoe works it way through your power cord, you&#8217;ll be awfully glad you did.

</p><div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/02/manage_transactions_in_mysql_-_lesson_2/feed/</wfw:commentRss>
        <slash:comments>0</slash:comments>

        
    </item>
    </channel>
</rss>
