{"id":705,"date":"2006-05-31T01:25:58","date_gmt":"2006-05-30T15:25:58","guid":{"rendered":"http:\/\/www.flamingspork.com\/blog\/2006\/05\/31\/ha_file\/"},"modified":"2006-05-31T01:25:58","modified_gmt":"2006-05-30T15:25:58","slug":"ha_file","status":"publish","type":"post","link":"https:\/\/www.flamingspork.com\/blog\/2006\/05\/31\/ha_file\/","title":{"rendered":"ha_file"},"content":{"rendered":"<p>In what I laughingly call &#8220;spare time&#8221; I started hacking on ha_file.cc, otherwise known as the FILE storage engine. My idea is relatively simple, I want to be able to store and access my photos from MySQL. I also want the storage to be relatively efficient and have the raw image files on disk, not tied up too much in any different format (my file system is pretty good at storing multi-megabyte files thank you very much) &#8211; it also doesn&#8217;t require any fancy things to re-use space when I delete things. I should also be able to (efficiently) directly serve the images out of a web server (satisfying the efficiency itch). You could also use something like DMF to migrate old rows off to tape.<br \/>\nSo, I started some hacking and some designing and have a working design and a nearly basically working read\/write implementation. I&#8217;ll share the code when it does, in fact, actually work (by &#8220;work&#8221; i mean reads and writes basic rows).<br \/>\nI&#8217;ve decided to go for the approach of storing columns in extended attributes. Why columns? &#8217;cause then you can access them either from the command line or programmatically through another interface. It also adds an extra layer of evil. With XFS and sufficiently large inodes, these should all fit in the inode anyway. ext3 also has some nice optimisations that should help with performance too.<\/p>\n<p>For blob data, I plan to just store that in the file. In my table for photos example, you could then just run a image browser (e.g. gthumb) on the data directory for the table and see your images. It also means that recovery programs (see my jpeg_recover.c) will work as well.<\/p>\n<p>Knowing the primary key of the row (which I plan to use as the file name for the row) then allows us to generate URLs that could be directly served by a lightweight http server, avoiding all that database code when you&#8217;re just serving up an image to a client.<br \/>\nSymbolic links can be used to have indexes.<\/p>\n<p>We can write new rows to a temp directory, sync them, then move them into place. Zero time crash recovery. Index consistency can be handled at runtime with a small extra check.<\/p>\n<p>At some point I should write down how I plan to do isolation levels too. but that&#8217;s for another day.<\/p>\n<p>I at least hope that the resulting code may be a useful example for people wanting to implement a storage engine.<\/p>\n<p>A simple implementation should be fairly fast too (with a slightly tuned file system).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In what I laughingly call &#8220;spare time&#8221; I started hacking on ha_file.cc, otherwise known as the FILE storage engine. My idea is relatively simple, I want to be able to store and access my photos from MySQL. I also want &hellip; <a href=\"https:\/\/www.flamingspork.com\/blog\/2006\/05\/31\/ha_file\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[14],"tags":[],"class_list":["post-705","post","type-post","status-publish","format-standard","hentry","category-mysql"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/s5a6n8-ha_file","jetpack-related-posts":[{"id":2118,"url":"https:\/\/www.flamingspork.com\/blog\/2010\/08\/18\/storage-engine-independent-test-suite\/","url_meta":{"origin":705,"position":0},"title":"Storage Engine independent test suite","author":"Stewart Smith","date":"2010-08-18","format":false,"excerpt":"This is something that has never existed in the MySQL world. Nothing to help you start developing your engine. Sure, you could start running the whole test suite against your engine.... but where it wasn't specifically MyISAM, you'd certainly hit things that were.. well... as simple as having to change\u2026","rel":"","context":"In &quot;drizzle&quot;","block_context":{"text":"drizzle","link":"https:\/\/www.flamingspork.com\/blog\/category\/work-et-al\/drizzle-work-et-al\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1229,"url":"https:\/\/www.flamingspork.com\/blog\/2008\/10\/14\/mysql-cluster-ndb-on-win32-progress\/","url_meta":{"origin":705,"position":1},"title":"MySQL Cluster (NDB) on Win32 progress","author":"Stewart Smith","date":"2008-10-14","format":false,"excerpt":"Many things have been happenning in the land of NDB on Win32 as of late. I've fixed about 700 compiler warnings (some of which were real bugs) leaving about 161 to go on Win32 (VS2003). We're getting a few more warnings on Win64 (some of which look merely semantic, while\u2026","rel":"","context":"In &quot;General&quot;","block_context":{"text":"General","link":"https:\/\/www.flamingspork.com\/blog\/category\/general\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1745,"url":"https:\/\/www.flamingspork.com\/blog\/2009\/12\/09\/drizzle-frm-replacement-the-table-proto\/","url_meta":{"origin":705,"position":2},"title":"Drizzle FRM replacement: the table proto","author":"Stewart Smith","date":"2009-12-09","format":false,"excerpt":"Drizzle originally inherited the FRM file from MySQL (which inherited it from UNIREG). The FRM file stores metadata about a table; what columns it has, what type those columns are, what indexes, any default values, comments etc are all stored in the FRM. In the days of MyISAM, this worked\u2026","rel":"","context":"In &quot;drizzle&quot;","block_context":{"text":"drizzle","link":"https:\/\/www.flamingspork.com\/blog\/category\/work-et-al\/drizzle-work-et-al\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":3705,"url":"https:\/\/www.flamingspork.com\/blog\/2014\/03\/17\/ghosts-of-mysql-past-part-11-why-are-you-happy-about-this\/","url_meta":{"origin":705,"position":3},"title":"Ghosts of MySQL Past, part 11: Why are you happy about this?","author":"Stewart Smith","date":"2014-03-17","format":false,"excerpt":"This is part 11 in what's shaping up to be the best part of a 6 week series (Part 1, 2, 3, 4, 5, 6, 7, 7.1, 8, 8.1, 9 and 10) on various history bits of MySQL, somewhat following my LCA2014 talk (video here). One of my favorite MySQL\u2026","rel":"","context":"In &quot;mysql&quot;","block_context":{"text":"mysql","link":"https:\/\/www.flamingspork.com\/blog\/category\/work-et-al\/mysql\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":745,"url":"https:\/\/www.flamingspork.com\/blog\/2006\/10\/19\/rusty-on-lca-talks-and-other-stuff\/","url_meta":{"origin":705,"position":4},"title":"Rusty on LCA talks and other stuff&#8230;","author":"Stewart Smith","date":"2006-10-19","format":false,"excerpt":"As email is *sooo* non-\"Web 2.0\", i reply in blog form.... Rusty's Bleeding Edge Page talks about a \"Writing an x86 hypervisor: all the cool kids are doing it!\" session that sounds really cool (better not be on at the same time as my talk... :) I don't (currently) intend\u2026","rel":"","context":"In &quot;General&quot;","block_context":{"text":"General","link":"https:\/\/www.flamingspork.com\/blog\/category\/general\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1650,"url":"https:\/\/www.flamingspork.com\/blog\/2009\/05\/27\/pluggable-metadata-stores-or-the-revenge-of-table-discovery\/","url_meta":{"origin":705,"position":5},"title":"Pluggable Metadata stores (or&#8230; the revenge of table discovery)","author":"Stewart Smith","date":"2009-05-27","format":false,"excerpt":"Users of the ARCHIVE or NDB storage engines in MySQL may be aware of a MySQL feature known as \"table discovery\". For ARCHIVE, you can copy the archive data file around between servers and it magically works (you don't need to copy the FRM). For MySQL Cluster (NDB) it works\u2026","rel":"","context":"In &quot;drizzle&quot;","block_context":{"text":"drizzle","link":"https:\/\/www.flamingspork.com\/blog\/category\/work-et-al\/drizzle-work-et-al\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/posts\/705","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/comments?post=705"}],"version-history":[{"count":0,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/posts\/705\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/media?parent=705"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/categories?post=705"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/tags?post=705"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}