<?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>Karl Katzke &#187; mysql</title>
	<atom:link href="http://www.karlkatzke.com/categories/mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.karlkatzke.com</link>
	<description>Geek of the Week</description>
	<lastBuildDate>Thu, 22 Jul 2010 16:14:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Detecting and Resolving LAMP Stack Problems &#8211; Scheduled Downtime</title>
		<link>http://www.karlkatzke.com/detecting-and-resolving-lamp-stack-problems-scheduled-downtime/</link>
		<comments>http://www.karlkatzke.com/detecting-and-resolving-lamp-stack-problems-scheduled-downtime/#comments</comments>
		<pubDate>Thu, 15 Oct 2009 04:51:15 +0000</pubDate>
		<dc:creator>karlkatzke</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[apc]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[innodb]]></category>
		<category><![CDATA[myisam]]></category>
		<category><![CDATA[xcache]]></category>

		<guid isPermaLink="false">http://www.karlkatzke.com/?p=536</guid>
		<description><![CDATA[In the last issue of my current consulting saga, Detecting and Resolving LAMP Stack Performance Problems, we talked about a Drupal site that was being brought offline every few hours due to poor tuning of the LAMP stack. With the default settings, a site isn&#8217;t going to take much before it just falls flat on [...]]]></description>
			<content:encoded><![CDATA[<p>In the last issue of my current consulting saga, <a href="http://www.karlkatzke.com/detecting-and-resolving-lamp-stack-performance-problems/">Detecting and Resolving LAMP Stack Performance Problems</a>, we talked about a Drupal site that was being brought offline every few hours due to poor tuning of the LAMP stack. With the default settings, a site isn&#8217;t going to take much before it just falls flat on it&#8217;s face. </p>
<p>After triaging and addressing the main issues based on the logs, we were left with two more issues. The first was the inability of Drupal to perform well in an environment where it had to rebuild every page from source for every page view. This is well documented in the drupal community; there are many pages inn the documentation area of Drupal that deal with caching and performance optimization. The second issue was MySQL performance and the long table lock/scan times we were seeing on some queries that could not be further optimized. </p>
<p>We scheduled a 2 hour downtime with the customer to install some tools. Our checklist was installing <a href="http://www.danga.com/memcached/">memcached</a> and <a href="http://pecl.php.net/package/APC">PHP-APC</a>. I also wanted to take the time to back up the MySQL database and run a good check_table on each of the MyISAM tables. (Yes, I know. MyISAM. More on that later.) </p>
<p><small>Side note: I would typically prefer <a href="http://xcache.lighttpd.net/">xcache</a>, which in my mind is superior to APC because I have an easier time working with it and prefer it&#8217;s management interface and tuning parameters. However, APC was available as a binary package for the platform we were on, and xcache was not. To make things faster and easier, we chose APC. Despite the endless debate about which is superior, both are usable and work. I have not run into problems using APC on an 8-core system, despite oft-reported-but-never-proven flock() issues.</small> </p>
<p>APC was fast to install and required minimal tuning. It produced a noticeable performance improvement. However, the number of deadlocked apache threads (and total number of apache threads) went up, and the other Apache errors that dealt with clients timing out did not cease. </p>
<p>We installed <a href="http://drupal.org/project/memcache">the Drupal Memcache implementation</a> along with the appropriate PECL module. We configured two pools, both using up to 1 GB of RAM (which we had to spare on the web server.) The &#8216;hot&#8217; pool would mostly handle cached pages for non-logged-in users, and the other one would handle some higher volume caching for users that are logged in, as well as some internal/custom functionality to go along with specialized RSS feed parsing. (Side note: We found that the <a href="http://drupal.org/project/cache">Cache</a> and <a href="http://drupal.org/project/cacherouter">Cacherouter</a> plugins did not work as expected. Rather than waste downtime troubleshooting them, we used what worked.)</p>
<p>Again, we saw a huge performance boost. We needed to do some tuning (changing certain cache settings and analyzing performance, but that was essentially everything that we could find to do from a single-server web server side of things. </p>
<p>While we&#8217;re on the topic of drupal: Don&#8217;t forget that Drupal has a &#8216;cron&#8217; program that should be getting called remotely. It&#8217;s sort of a <a href="http://drupal.org/cron">poor man&#8217;s cron solution</a>, but it works. It was causing our load to spike every 20 minutes. We occasionally disabled it during testing to be sure we understood it&#8217;s effects. </p>
<p>The next beast to tackle was the database. As previously mentioned, it was on MyISAM tables. Obviously, this isn&#8217;t ideal. We found that node lookups, statistics lookups, and searches were taking up a disproportionate amount of server time because they were both  The weirdest part was that we were seeing some full table scans in the slow query log (i.e. 3 million rows scanned) but a later &#8216;explain&#8217; statement couldn&#8217;t replicate the performance recorded in the slow query log. </p>
<p>We batted around adding indexes. The issue was that Drupal&#8217;s search and nodes tables are frequently altered, which means the indexes become scrambled quickly. And really, what was taking time was the size of the table we were dealing with &#8212; the table wouldn&#8217;t fit in memory, so it was copying it to a disk temporary table and then doing a filesort. </p>
<p>Running check_table did the trick to re-sort the indexes and &#8216;defrag&#8217; the files, but the benefits only lasted so long. </p>
<p>What we ended up doing was taking the database down, dumping everything out to a SQL file, and re-importing everything to InnoDB. Make sure that innodb_files_per_table is enabled, or you might end up with some unexpectedly big files &#8212; this depends on your architecture and filesystem. Remember that InnoDB files can not currently shrink. (Also: You <b>can</b> do the table changes online, but it&#8217;s really not recommended. It takes a long time, especially when some of your tables are larger than 1gb.) Don&#8217;t forget to switch to <a href="http://www.mysqlperformanceblog.com/2007/11/03/choosing-innodb_buffer_pool_size/">set innodb_buffer_pool_size</a> appropriately.</p>
<p>The change to InnoDB, the implementation of both PHP engine-level opcode and actual built pages, and the careful tuning of Apache and MySQL parameters led to stability for this client. </p>
<p>There were some further problems, but they were with an unrelated product that causes a nightly load spike on the database machine. Tomorrow night I&#8217;ll covering the cleanup work: NFS iops vs. local disk, binary logging and the lack of backups in the original configuration, and building some redundancy into the system so that it can tolerate faults more smoothly.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.karlkatzke.com/detecting-and-resolving-lamp-stack-problems-scheduled-downtime/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Detecting and Resolving LAMP Stack Performance Problems</title>
		<link>http://www.karlkatzke.com/detecting-and-resolving-lamp-stack-performance-problems/</link>
		<comments>http://www.karlkatzke.com/detecting-and-resolving-lamp-stack-performance-problems/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 03:45:34 +0000</pubDate>
		<dc:creator>karlkatzke</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[deadlock]]></category>
		<category><![CDATA[lamp]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[problems]]></category>
		<category><![CDATA[syslog]]></category>
		<category><![CDATA[troubleshooting]]></category>

		<guid isPermaLink="false">http://www.karlkatzke.com/?p=534</guid>
		<description><![CDATA[As a sysadmin, we sometimes run into performance problems with multiple angles and portions. It&#8217;s sometimes not particularly obvious where the actual performance problem is, and resolving one problem that you can see might bring another couple of problems to the surface. The below comes from a consulting gig that I&#8217;ve been working on recently. [...]]]></description>
			<content:encoded><![CDATA[<p>As a sysadmin, we sometimes run into performance problems with multiple angles and portions. It&#8217;s sometimes not particularly obvious where the actual performance problem is, and resolving one problem that you <i>can</i> see might bring another couple of problems to the surface. </p>
<p>The below comes from a consulting gig that I&#8217;ve been working on recently. The parties will remain nameless. I&#8217;m going to break this into several parts, since it took over three weeks to resolve all of the immediate <i>problems</i> with the site, and we&#8217;re still not all the way done with the task list. </p>
<p>Going in, I knew that we were dealing with a heavily loaded Drupal site that shared a mysql database with a wiki and a forum. The site would go down at random times &#8212; sometimes multiple times per hour. Upon logging into the server the first time, it seemed slow &#8212; so I immediately called &#8216;uptime&#8217; and the answer came back with all three time period load averages over 90 on an 8-core server. There were 125 Apache processes running, but most of them were in Deadlocked state. The very second command I ran on the server was <code>killall -9 httpd</code>, which is never the way you want to start out a consulting gig&#8230; </p>
<p>While that was busy killing off processes, I checked the Apache configuration. Sure enough, it was still at the stock settings. I immediately cranked up the requests per process to 20,000 and upped the server limit to 300. (Remember, we&#8217;re dealing with prefork here.) I restarted Apache and watched it churn. It handled the load far more gracefully with some room to move around, and I quickly saw the number of Apache processes spike, and then sink down to about 80 and stay there. </p>
<p>The next step was looking through the logs. A quick aside about logs: I like my logs to be clean. I don&#8217;t like debug messages, I don&#8217;t like status messages, and I don&#8217;t want to see either of them. If I have a lot of a certain type of status message that I *do* want to trap, I make sure that syslog puts it into it&#8217;s own file or I handle the problem that&#8217;s causing it. In this case, <code>/var/log/messages</code> had a bunch of SNMP messages logging each get, and some messages about martian packets. The martian packets issue could be (and was) resolved with a quick firewall tweak to reject packets from an illegal source. The snmp issue was resolved by editing snmpd&#8217;s startup configuration to log to local1 instead of the default (check your man file for snmpd to make sure you get the right flags, it&#8217;s changed&#8230;), and then editing syslog&#8217;s configuration to log everything on local1 to /var/log/snmpd &#8212; and don&#8217;t forget to add it to logrotate! </p>
<p>Now we were down to two classes of errors. The first was obvious and sort of easy to troubleshoot: &#8220;MySQL server has gone away.&#8221; Log into the MySQL server. See if there&#8217;s slow-running queries. Nope? Well, double check the timeout that&#8217;s set in <code>/etc/my.cnf</code> &#8212; on this server, slow-query-time was set to twenty seconds, but timeout was set to ten seconds. Well, that&#8217;s not very useful. Also, check your caches and table types. In this case, everything was MyISAM. More on that later &#8212; for now, just make sure we&#8217;re using the right kind of caching strategy for your table type and system specs, which in this case is MyISAM key cache (and lots of it!). Try to fit all of your most-used tables in memory. </p>
<p>On this gig, we got the site back on it&#8217;s feet with these things. Downtime went from multiple events an hour down to one or two events per six hour period. Unfortunately, we were also out of easy things to change. Next time I post, we&#8217;ll start to get into fixes that will <i>cause</i> downtime. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.karlkatzke.com/detecting-and-resolving-lamp-stack-performance-problems/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Sun/MySQL Reducing or Eliminating Support for Other OSes?</title>
		<link>http://www.karlkatzke.com/sunmysql-reducing-or-eliminating-support-for-other-oses/</link>
		<comments>http://www.karlkatzke.com/sunmysql-reducing-or-eliminating-support-for-other-oses/#comments</comments>
		<pubDate>Thu, 09 Apr 2009 13:48:19 +0000</pubDate>
		<dc:creator>karlkatzke</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[mysql tools]]></category>
		<category><![CDATA[mysql workbench]]></category>

		<guid isPermaLink="false">http://www.karlkatzke.com/?p=429</guid>
		<description><![CDATA[Two years ago, I reported a bug in MySQL Query Browser that caused it to crash on OS X and Linux. For those not in the know, MySQL Workbench is an attempt to get a GUI tool comparable to Microsoft&#8217;s SQL Explorer off the ground. Today, the bug was updated and changed to &#8220;unsupported&#8221; status. [...]]]></description>
			<content:encoded><![CDATA[<p>Two years ago, I reported a bug in MySQL Query Browser that caused it to crash on OS X and Linux. For those not in the know, MySQL Workbench is an attempt to get a GUI tool comparable to Microsoft&#8217;s SQL Explorer off the ground. </p>
<p>Today, the <a href="http://bugs.mysql.com/bug.php?id=32688">bug was updated and changed to &#8220;unsupported&#8221; status.</a> According to the MySQL website, the <a href="http://www.mysql.com/support/supportedplatforms/tools.html">only supported platform for MySQL Workbench is Windows</a>. This is quote odd, because it seems that <a href="http://dev.mysql.com/workbench/?p=205">MySQL has been working hard to release a cross-platform version</a> of it&#8217;s workbench as recently as one week ago. </p>
<p>I suppose this is why Drizzle is getting such a huge groundswell of support behind it: MySQL&#8217;s development efforts have been fractured and mismanaged so badly at this point that nothing can save the company or it&#8217;s products.</p>
<p><b>Update:</b> Apparently they&#8217;re phasing out Query Browser and the other GUI tools in favor of making workbench cross-browser. I got confused because I filed a bunch of bugs at the same time, most of them dealing with Workbench crashes. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.karlkatzke.com/sunmysql-reducing-or-eliminating-support-for-other-oses/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The coolest mysql function I didn&#8217;t know existed&#8230;</title>
		<link>http://www.karlkatzke.com/the-coolest-mysql-function-i-didnt-know-existed/</link>
		<comments>http://www.karlkatzke.com/the-coolest-mysql-function-i-didnt-know-existed/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 17:07:51 +0000</pubDate>
		<dc:creator>karlkatzke</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[group]]></category>
		<category><![CDATA[group_concat]]></category>

		<guid isPermaLink="false">http://www.karlkatzke.com/?p=375</guid>
		<description><![CDATA[Apparently I&#8217;ve been living under a rock for the past three years. group_concat. To use it is to know it, and to know it is to love it.]]></description>
			<content:encoded><![CDATA[<p>Apparently I&#8217;ve been living under a rock for the past three years. </p>
<p><a href="http://www.mysqlperformanceblog.com/2006/09/04/group_concat-useful-group-by-extension/">group_concat</a>. To use it is to know it, and to know it is to love it. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.karlkatzke.com/the-coolest-mysql-function-i-didnt-know-existed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Little Love for Lua</title>
		<link>http://www.karlkatzke.com/a-little-love-for-lua/</link>
		<comments>http://www.karlkatzke.com/a-little-love-for-lua/#comments</comments>
		<pubDate>Fri, 30 Jan 2009 21:36:20 +0000</pubDate>
		<dc:creator>karlkatzke</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[LÖVE]]></category>
		<category><![CDATA[Lua]]></category>
		<category><![CDATA[mysql proxy]]></category>
		<category><![CDATA[pygame]]></category>

		<guid isPermaLink="false">http://www.karlkatzke.com/?p=364</guid>
		<description><![CDATA[Version 0.5 of LÖVE &#8211; a 2d game engine for Lua &#8211; has dropped. Lua is a lightweight open-source scripting language that&#8217;s embeddable in other products and devices. I first encountered Lua using the MySQL Proxy. LÖVE looks interesting, kind of like a relatively polished PyGame without the annoying Python.]]></description>
			<content:encoded><![CDATA[<p>Version 0.5 of <a href="http://love2d.org/">LÖVE &#8211; a 2d game engine for Lua</a> &#8211; has dropped. <a href="http://www.lua.org/">Lua</a> is a lightweight open-source scripting language that&#8217;s embeddable in other products and devices. I first encountered Lua using the <a href="http://forge.mysql.com/wiki/MySQL_Proxy">MySQL Proxy</a>. </p>
<p>LÖVE looks interesting, kind of like a relatively polished PyGame without the annoying Python. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.karlkatzke.com/a-little-love-for-lua/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MySQL Temporal Handling</title>
		<link>http://www.karlkatzke.com/mysql-temporal-handling/</link>
		<comments>http://www.karlkatzke.com/mysql-temporal-handling/#comments</comments>
		<pubDate>Mon, 12 Jan 2009 06:10:53 +0000</pubDate>
		<dc:creator>karlkatzke</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[date]]></category>
		<category><![CDATA[datetime]]></category>
		<category><![CDATA[time]]></category>

		<guid isPermaLink="false">http://www.karlkatzke.com/?p=350</guid>
		<description><![CDATA[Wow, this post by Jay Pipes on how MySQL handles time/date-related issues couldn&#8217;t come at a better time&#8230; more on that in another week or two. Update: Jay posted his sample code.]]></description>
			<content:encoded><![CDATA[<p>Wow, <a href="http://jpipes.com/index.php?/archives/280-So,-What-Is-a-Day-Number.html">this post by Jay Pipes on how MySQL handles time/date-related issues couldn&#8217;t come at a better time</a>&#8230; more on that in another week or two.</p>
<p><b>Update</b>: <a href="http://jpipes.com/index.php?/archives/281-More-on-Day-Numbers-The-Actual-Code.html">Jay posted his sample code.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.karlkatzke.com/mysql-temporal-handling/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>If you can&#8217;t say something nice&#8230;</title>
		<link>http://www.karlkatzke.com/if-you-cant-say-something-nice/</link>
		<comments>http://www.karlkatzke.com/if-you-cant-say-something-nice/#comments</comments>
		<pubDate>Fri, 19 Dec 2008 17:24:00 +0000</pubDate>
		<dc:creator>karlkatzke</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[ha]]></category>
		<category><![CDATA[replication]]></category>

		<guid isPermaLink="false">http://www.karlkatzke.com/?p=333</guid>
		<description><![CDATA[Good article by Sheeri Cabral: Why you Want to Switch to MySQL 5.1. The 5.1 branch has gotten a bad rap, but there&#8217;s a few things in there like the table change locking that will help us with our replication environment.]]></description>
			<content:encoded><![CDATA[<p>Good article by Sheeri Cabral: <a href="http://www.pythian.com/blogs/1168/why-you-want-to-switch-to-mysql-51">Why you Want to Switch to MySQL 5.1</a>. The 5.1 branch has gotten a bad rap, but there&#8217;s a few things in there like the table change locking that will help us with our replication environment.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.karlkatzke.com/if-you-cant-say-something-nice/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL Fulltext Index Stopwords</title>
		<link>http://www.karlkatzke.com/mysql-fulltext-index-stopwords/</link>
		<comments>http://www.karlkatzke.com/mysql-fulltext-index-stopwords/#comments</comments>
		<pubDate>Fri, 31 Oct 2008 13:53:22 +0000</pubDate>
		<dc:creator>karlkatzke</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[fulltext]]></category>
		<category><![CDATA[index]]></category>

		<guid isPermaLink="false">http://www.karlkatzke.com/?p=299</guid>
		<description><![CDATA[The list of stopwords is essential if you&#8217;re thinking of using MySQL&#8217;s FULLTEXT index type, and it hasn&#8217;t been mentioned in other places I&#8217;ve seen the fulltext index discussed.]]></description>
			<content:encoded><![CDATA[<p>The list of <a href="http://dev.mysql.com/doc/refman/5.0/en/fulltext-stopwords.html">stopwords</a> is essential if you&#8217;re thinking of using MySQL&#8217;s FULLTEXT index type, and it hasn&#8217;t been mentioned in other places I&#8217;ve seen the fulltext index discussed. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.karlkatzke.com/mysql-fulltext-index-stopwords/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The Unwritten Manual: Ajax &amp; Flash Multi File Uploader</title>
		<link>http://www.karlkatzke.com/the-unwritten-manual-ajax-flash-multi-file-uploader/</link>
		<comments>http://www.karlkatzke.com/the-unwritten-manual-ajax-flash-multi-file-uploader/#comments</comments>
		<pubDate>Tue, 28 Oct 2008 21:52:34 +0000</pubDate>
		<dc:creator>karlkatzke</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[webdev]]></category>
		<category><![CDATA[zend framework]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[mootools]]></category>

		<guid isPermaLink="false">http://www.karlkatzke.com/?p=294</guid>
		<description><![CDATA[I think my pet peeve of the day today is going to be developers who think that no documentation or setup instructions should be necessary for their little chunk of code&#8230; especially when it mashes up as many things as Harald Kirschner&#8217;s Fancy Uploader does. (Then again, I should know better than to work off [...]]]></description>
			<content:encoded><![CDATA[<p>I think my pet peeve of the day today is going to be developers who think that no documentation or setup instructions should be necessary for their little chunk of code&#8230; especially when it mashes up as many things as <a href="http://digitarald.de/project/fancyupload/">Harald Kirschner&#8217;s Fancy Uploader</a> does. </p>
<p><small>(Then again, I should know better than to work off of someone&#8217;s code when they term themselves a &#8220;Web Craftsman&#8221; and have personal philosophies as headlining elements of their &#8220;about me&#8221; page.) See also: <a href="http://www.youtube.com/watch?v=zSP8xm_gaK4">New Media Douchebags Explained</a>.)</small></p>
<p>If you&#8217;re banging your head against this like I have been for the past four hours, you&#8217;ve probably figured out a few things. First, the library files that are required to make the javascript work need to be called in a particular order. That order is:</p>
<ol>
<li>The MooTools 1.2 &#8211;FULL&#8211; compressed library. Yes, I know he says you only need a few components. Yes, he lied. Selecting the components he specified will give you an error along the lines of &#8220;window.scroll is not a function at Swiff.Uploader.js (line 62)&#8221; &#8230; so save yourself the time and just pull down the full compressed/mangled MooTools.</li>
<li>Fx.ProgressBar.js</li>
<li>Swiff.Uploader.js</li>
<li>FancyUpload2.js</li>
<li>script.js</li>
</ol>
<p>Stray from that order, and you develop problems. Also, I found that instead of using
<pre>window.addEvent('load',function ...</pre>
<p> as the first line of script.js, it was better to use
<pre>window.addEvent('domready',function ...</pre>
<p>. </p>
<p>Second, let&#8217;s take a look at the sample file that&#8217;s supposed to magically save what we spit out. Specifically, script.php &#8212; which receives the ajax update based on a session variable that&#8217;s set, and then saves the information with an indexed .ini file. First off, it&#8217;s hard to debug. Let&#8217;s use PHP&#8217;s output buffering functions to help that. You can use this snippet of code to write a log of what&#8217;s going on:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"> <span style="color: #cc66cc;">13</span>  <span style="color: #000088;">$logfile</span> <span style="color: #339933;">=</span> <span style="color: #990000;">fopen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$folder</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'logfile'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'a'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #cc66cc;">14</span>  <span style="color: #990000;">ob_start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #cc66cc;">15</span>  <span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_FILES</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #cc66cc;">16</span>  <span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #cc66cc;">17</span>  <span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #cc66cc;">18</span>  <span style="color: #990000;">fwrite</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$logfile</span><span style="color: #339933;">,</span><span style="color: #990000;">ob_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #cc66cc;">19</span>  <span style="color: #990000;">ob_end_clean</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>What you&#8217;ll notice is that, with the default code that comes with the script, you&#8217;ll have the same session ID and since the session ID is created in the javascript and each session ID is incremented in the PHP script, you&#8217;ll overwrite your file if you&#8217;re uploading multiple files &#8212; which was the whole purpose of using flash and AJAX in the first place! This is what we call a brillant(sic) programming decision&#8230; or really, one where the developer just didn&#8217;t really THINK before he wrote it. I&#8217;ve rewritten my function to simply create a directory in the &#8216;uploads&#8217; folder with a batch name that I enter on the main form. After all files have uploaded successfully  (or not), I have a &#8216;continue&#8217; button that does a bunch of database work and sucks the text of the files into the database.</p>
<p>Now, I&#8217;m working with a Zend Framework application here &#8212; this means that I need to make a few changes. First, the script depends on not having any authentication ahead of the request. While the browser will still maintain the session, the ajax requests won&#8217;t have the browser&#8217;s cookies and therefore will bounce off of any preDispatch authentication. To get around this but still stay secure, I generate a (hidden) temporary session ID, store it in the database, and clear the table on a regular basis. </p>
<p>I&#8217;m on a crunched deadline and still don&#8217;t quite have things working yet, but in the next day or two I&#8217;ll post the fruits of my labor. Too bad this uses MooTools and not Dojo&#8230; as far as I know, Dojo still doesn&#8217;t have a flash-compatible uploader that will allow multiple selection. </p>
<p>But back to where I started: <a href="http://digitarald.de/">Harald</a>, dude, you ain&#8217;t no web &#8220;craftsman&#8221; if someone needs to spend 8 hours learning your code and writing workarounds before they can implement it. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.karlkatzke.com/the-unwritten-manual-ajax-flash-multi-file-uploader/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>MySQL Cache Optimization</title>
		<link>http://www.karlkatzke.com/mysql-cache-optimization/</link>
		<comments>http://www.karlkatzke.com/mysql-cache-optimization/#comments</comments>
		<pubDate>Thu, 11 Sep 2008 02:25:56 +0000</pubDate>
		<dc:creator>karlkatzke</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[table_cache]]></category>

		<guid isPermaLink="false">http://www.karlkatzke.com/?p=230</guid>
		<description><![CDATA[Freshbooks ran into an interesting bit about selecting a MySQL Table Cache size: The problem was caused by our new configuration of MySQL. The usual approach to setting MySQL’s table cache size is to make it large enough that it can hold all of your tables open, but we have too many tables for that [...]]]></description>
			<content:encoded><![CDATA[<p>Freshbooks ran into an <a href="http://www.freshbooks.com/blog/2008/09/09/now-were-flying/">interesting bit about selecting a MySQL Table Cache size</a>: </p>
<blockquote><p>The problem was caused by our new configuration of MySQL.  The usual approach to setting MySQL’s table cache size is to make it large enough that it can hold all of your tables open, but we have too many tables for that to be practical. Instead, we decided to make it big, to improve the odds that tables we need were already in the cache. And since we had new, bigger hardware with more RAM and faster disks, we decided to cache even more tables.</p>
<p>Unfortunately, while opening tables is fast in MySQL, the speed at which it can close tables gets slower and slower as the table cache grows. Linearly, in fact. And since the cache will always end up full, the speed that MySQL can close tables becomes the speed that MySQL can open tables. And to exacerbate the problem, opening and closing tables in MySQL uses a global lock, so only one thread can be opening or closing tables at a time, regardless of how many threads are executing in parallel.</p>
<p>Once we understood this, we realized that if the cache is going to be full, it needs to be kept as small as possible. We reduced it to the minimum we could get away with without having to reopen tables in the middle of one session interacting with FreshBooks. And now that closing tables is faster, everything’s faster.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.karlkatzke.com/mysql-cache-optimization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
