<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Databases on traviscj/blog</title>
    <link>https://traviscj.com/blog/tags/databases/</link>
    <description>Recent content in Databases on traviscj/blog</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Tue, 24 Jun 2025 19:47:52 -0500</lastBuildDate>
    <atom:link href="https://traviscj.com/blog/tags/databases/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Evolution of a Get Endpoint</title>
      <link>https://traviscj.com/blog/post/2025-06-24-evolution-of-a-get-endpoint/</link>
      <pubDate>Tue, 24 Jun 2025 19:47:52 -0500</pubDate>
      <guid>https://traviscj.com/blog/post/2025-06-24-evolution-of-a-get-endpoint/</guid>
      <description>&lt;p&gt;My work project started pretty simple: there was a simple &lt;code&gt;GetXyz&lt;/code&gt; endpoint that just looked up the &lt;code&gt;xyz&lt;/code&gt; record in the database by a unique key &amp;amp; returned it.&#xA;How complicated could it be?&lt;/p&gt;&#xA;&lt;p&gt;It was a straightforward generalization of an old &lt;code&gt;GetAbc&lt;/code&gt; functionality, it was really only used by oncall engineers through an admin console, it shouldn&amp;rsquo;t have been too big of a deal.&lt;/p&gt;&#xA;&lt;p&gt;Ok, but then it outgrew its original datastore, so a separate service had to be created.&#xA;We thought about migrating clients, but at the time it seemed faster to just implement once on our side &amp;amp; have clients continue calling us; essentially encapsulating the separate service as an implementation detail.&#xA;But as part of the traffic swing, we figured it should support either the &lt;code&gt;local&lt;/code&gt; or the &lt;code&gt;remote&lt;/code&gt; read path.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Transacter and Intent/Result</title>
      <link>https://traviscj.com/blog/post/2022-06-15-transacter-and-intent-result/</link>
      <pubDate>Wed, 15 Jun 2022 08:07:47 -0500</pubDate>
      <guid>https://traviscj.com/blog/post/2022-06-15-transacter-and-intent-result/</guid>
      <description>&lt;p&gt;At SQ, we had a family of &lt;code&gt;Transacter&lt;/code&gt; interfaces:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Transacter&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;transaction&lt;/span&gt;(Function&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Session, Void&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; session);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Session&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    DSLContext &lt;span style=&#34;color:#a6e22e&#34;&gt;dsl&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;where &lt;code&gt;DSLContext&lt;/code&gt; is a &lt;a href=&#34;https://www.jooq.org/javadoc/latest/org.jooq/org/jooq/DSLContext.html&#34;&gt;jOOQ concept&lt;/a&gt; &amp;amp; is the handle for doing work against the database.&#xA;Then this would be used in some class like&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;KvDao&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;@Inject&lt;/span&gt; Transacter transacter;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;put&lt;/span&gt;(String ns, String k, String v) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    transacter.&lt;span style=&#34;color:#a6e22e&#34;&gt;transaction&lt;/span&gt;(session &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        KvRecord record &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; KvRecord(ns, k, v);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        session.&lt;span style=&#34;color:#a6e22e&#34;&gt;dsl&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;insertInto&lt;/span&gt;(KV).&lt;span style=&#34;color:#a6e22e&#34;&gt;set&lt;/span&gt;(record).&lt;span style=&#34;color:#a6e22e&#34;&gt;execute&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The parameters &lt;code&gt;ns&lt;/code&gt;, &lt;code&gt;k&lt;/code&gt;, and &lt;code&gt;v&lt;/code&gt; are shorthand for &lt;code&gt;namespace&lt;/code&gt;, &lt;code&gt;key&lt;/code&gt;, and &lt;code&gt;value&lt;/code&gt;, respectively.&#xA;We&amp;rsquo;ll show how these might be used together shortly!&lt;/p&gt;</description>
    </item>
    <item>
      <title>feeds justification</title>
      <link>https://traviscj.com/blog/post/2019-06-11-feeds_justification/</link>
      <pubDate>Tue, 11 Jun 2019 00:00:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2019-06-11-feeds_justification/</guid>
      <description>&lt;p&gt;I realized I&amp;rsquo;ve left out a major part from my &lt;a href=&#34;https://traviscj.com/blog/post/2019-01-08-feed_sequences/&#34;&gt;sequence&lt;/a&gt; of &lt;a href=&#34;https://traviscj.com/blog/post/2018-10-03-feeds_as_cache_invalidation_mechanism/&#34;&gt;previous&lt;/a&gt; &lt;a href=&#34;https://traviscj.com/blog/post/2018-06-29-mysql_feeds/&#34;&gt;feed&lt;/a&gt;-&lt;a href=&#34;https://traviscj.com/blog/post/2018-07-10-cross-dc-sync-with-feed-published_kv/&#34;&gt;related&lt;/a&gt; &lt;a href=&#34;https://traviscj.com/blog/post/2018-10-29-sharded_feeds/&#34;&gt;posts&lt;/a&gt;: a justification for why we should bother with a separate &lt;code&gt;feed_sync_id&lt;/code&gt;.&#xA;So let&amp;rsquo;s give it a shot!&#xA;The fundamental problem is:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;code&gt;AUTO_INCREMENT&lt;/code&gt; ids are &lt;em&gt;assigned&lt;/em&gt; in &lt;strong&gt;insertion&lt;/strong&gt; order, but become visible to other threads in &lt;strong&gt;commit&lt;/strong&gt; order.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;To see how this causes a problem, consider the interactions and visibilities between three transactions to the same database:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;t0: TRX0: BEGIN; INSERT INTO kv (ns, k, v) VALUES (&amp;quot;-&amp;quot;, &amp;quot;k0&amp;quot;, &amp;quot;v0&amp;quot;); COMMIT;&#xA;t1: TRX1: BEGIN; INSERT INTO kv (ns, k, v) VALUES (&amp;quot;-&amp;quot;, &amp;quot;k1&amp;quot;, &amp;quot;v1&amp;quot;);&#xA;t2: TRX2: BEGIN; INSERT INTO kv (ns, k, v) VALUES (&amp;quot;-&amp;quot;, &amp;quot;k2&amp;quot;, &amp;quot;v2&amp;quot;);&#xA;t3: TRX0: SELECT MAX(id) FROM kv;&#xA;t4: TRX2: COMMIT;&#xA;t5: TRX0: SELECT MAX(id) FROM kv;&#xA;t6: TRX1: COMMIT;&#xA;t7: TRX0: SELECT MAX(id) FROM kv;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Here, we have two transactions that both insert a new &lt;code&gt;kv&lt;/code&gt; record.&#xA;The database &lt;em&gt;has&lt;/em&gt; to assign an &lt;code&gt;id&lt;/code&gt; value to each of those records, because we might be creating other associations to those records in our application code.&#xA;But other threads &amp;ndash; &lt;code&gt;TRX0&lt;/code&gt; in this case &amp;ndash; shouldn&amp;rsquo;t be able to see those records until we &lt;code&gt;COMMIT&lt;/code&gt;, and so indeed the &lt;code&gt;SELECT&lt;/code&gt; at &lt;code&gt;t=t3&lt;/code&gt; might return &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>absolutely minimal OLTP to OLAP pipeline</title>
      <link>https://traviscj.com/blog/post/2019-04-25-oltp_to_olap/</link>
      <pubDate>Thu, 25 Apr 2019 00:00:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2019-04-25-oltp_to_olap/</guid>
      <description>&lt;p&gt;Suppose we have some data in a production OLTP database, and we need to send it to some OLAP database.&#xA;This post describes one of the simplest approaches, and how to make it productional enough to rely on.&lt;/p&gt;&#xA;&lt;p&gt;For every table &lt;code&gt;t&lt;/code&gt;, we need to:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;introduce a new field, &lt;code&gt;updated_at&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;introduce a new index on that field, so we can get the records that changed after a certain &lt;code&gt;updated_at&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;For example,&lt;/p&gt;</description>
    </item>
    <item>
      <title>feed sequences</title>
      <link>https://traviscj.com/blog/post/2019-01-08-feed_sequences/</link>
      <pubDate>Tue, 08 Jan 2019 00:00:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2019-01-08-feed_sequences/</guid>
      <description>&lt;p&gt;In the &lt;a href=&#34;https://traviscj.com/blog/post/2018-06-29-mysql_feeds/&#34;&gt;mysql feeds&lt;/a&gt; post, I mentioned that the publisher could do&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;MAX&lt;/span&gt;(feed_sync_id)&lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; kv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;to find the next &lt;code&gt;feed_sync_id&lt;/code&gt; during the publishing process, but&#xA;&lt;strong&gt;this is actually a really bad idea.&lt;/strong&gt;&#xA;(And I knew it at the time, so forgive me for selling lies&amp;hellip;)&lt;/p&gt;&#xA;&lt;h2 id=&#34;republishing&#34;&gt;Republishing&lt;/h2&gt;&#xA;&lt;p&gt;Before we jump into the problematic scenario, I&amp;rsquo;d like to motivate it with a tiny bit of background.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;em&gt;republish&lt;/em&gt; operation is extremely useful when consumers need to receive updates.&#xA;It is also extremely simple!&#xA;A query like&lt;/p&gt;</description>
    </item>
    <item>
      <title>watching progress in mysql</title>
      <link>https://traviscj.com/blog/post/2019-01-04-watching_progress_in_mysql/</link>
      <pubDate>Fri, 04 Jan 2019 00:00:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2019-01-04-watching_progress_in_mysql/</guid>
      <description>&lt;p&gt;Pretty frequently at work, I end up &lt;a href=&#34;https://traviscj.com/blog/post/2014-10-15-dont_poll/&#34;&gt;polling&lt;/a&gt; a database with some command like&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;MAX&lt;/span&gt;(id) &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; my_tbl;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;MAX&lt;/span&gt;(id) &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; my_tbl;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;MAX&lt;/span&gt;(id) &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; my_tbl;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;MAX&lt;/span&gt;(id) &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; my_tbl;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- .... ad nauseam ....&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ve eventually noticed a few patterns I use pretty consistently:&lt;/p&gt;&#xA;&lt;h3 id=&#34;estimate-eta-by-including-nowunix_timestamp&#34;&gt;estimate ETA by including &lt;code&gt;NOW()&lt;/code&gt;/&lt;code&gt;UNIX_TIMESTAMP()&lt;/code&gt;&lt;/h3&gt;&#xA;&lt;p&gt;Generally, the point of hovering over the table is to get an estimate of when it will finish/catch up/whatever.&#xA;For that, you generally want to include a timestamp in the query output, so when you come back a while later, you can know exactly how much time has elapsed.&#xA;I might transform the above query into&lt;/p&gt;</description>
    </item>
    <item>
      <title>sharded feeds</title>
      <link>https://traviscj.com/blog/post/2018-10-29-sharded_feeds/</link>
      <pubDate>Mon, 29 Oct 2018 18:30:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2018-10-29-sharded_feeds/</guid>
      <description>&lt;p&gt;Suppose that:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;our humble &lt;a href=&#34;https://traviscj.com/blog/post/2018-06-29-mysql_feeds/&#34;&gt;KV feed&lt;/a&gt; sees &lt;em&gt;a lot&lt;/em&gt; of traffic.&lt;/li&gt;&#xA;&lt;li&gt;someone needs to consume our &lt;a href=&#34;https://traviscj.com/blog/post/2018-06-29-mysql_feeds/&#34;&gt;KV feed&lt;/a&gt; with multiple threads.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;data&#34;&gt;data&lt;/h3&gt;&#xA;&lt;p&gt;The first step is to introduce a notion of &amp;ldquo;shards&amp;rdquo; into our data model:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ALTER&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;TABLE&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;kv&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;ADD&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;COLUMN&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;shard&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; INT(&lt;span style=&#34;color:#ae81ff&#34;&gt;11&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;DEFAULT&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;ADD&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;INDEX&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;k_fsi_s&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;feed_sync_id&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;shard&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;publishing&#34;&gt;publishing&lt;/h3&gt;&#xA;&lt;p&gt;We don&amp;rsquo;t need to alter the publishing until the publishing &lt;em&gt;itself&lt;/em&gt; is too slow to work with a single thread, but this introduces a &lt;em&gt;lot&lt;/em&gt; of complications, so let&amp;rsquo;s just hold off for now.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Feeds as cache invalidation mechanism</title>
      <link>https://traviscj.com/blog/post/2018-10-03-feeds_as_cache_invalidation_mechanism/</link>
      <pubDate>Wed, 03 Oct 2018 02:31:43 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2018-10-03-feeds_as_cache_invalidation_mechanism/</guid>
      <description>&lt;p&gt;One really cool use of &lt;a href=&#34;https://traviscj.com/blog/post/2018-06-29-mysql_feeds/&#34;&gt;feeds&lt;/a&gt; we&amp;rsquo;ve realized is that it gives a very efficient mechanism for application code to load the most recent versions of a table into memory.&#xA;The basic idea is:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Set it up as a usual feed published table with an appropriate index on &lt;code&gt;feed_sync_id&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Either alongside or within the cache, represent the latest loaded &lt;code&gt;feed_sync_id&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Set up a cronjob/etc that reads the latest &lt;code&gt;feed_sync_id&lt;/code&gt; and compares it to the cache&amp;rsquo;s &lt;code&gt;feed_sync_id&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;If they differ, reload the cache.&lt;/li&gt;&#xA;&lt;li&gt;Ensure that all changes set &lt;code&gt;feed_sync_id&lt;/code&gt; to null!&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;This works really well because the &lt;code&gt;feed_sync_id&lt;/code&gt; in the database only gets updated on changes, so the reload cronjob mostly is a no-op.&#xA;This means we can reload very frequently!&lt;/p&gt;</description>
    </item>
    <item>
      <title>cross-dc sync with feed published KV</title>
      <link>https://traviscj.com/blog/post/2018-07-10-cross-dc-sync-with-feed-published_kv/</link>
      <pubDate>Tue, 10 Jul 2018 11:34:39 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2018-07-10-cross-dc-sync-with-feed-published_kv/</guid>
      <description>&lt;p&gt;It&amp;rsquo;s been fun describing the &lt;a href=&#34;https://traviscj.com/blog/post/2018-06-29-mysql_feeds/&#34;&gt;feeds&lt;/a&gt; framework we use at Square.&#xA;Today we&amp;rsquo;ll dive into a concrete problem:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;We&amp;rsquo;ll stick with the feed-published &lt;code&gt;kv&lt;/code&gt; table again.&lt;/li&gt;&#xA;&lt;li&gt;We want two instances of some application code to bidirectionally synchronize the writes that happened on their instance to the other.&lt;/li&gt;&#xA;&lt;li&gt;Eventually consistent is ok.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;First, a bit of justification, though:&#xA;I use this KV table to remember things I might have to look up without usual context, like my motorcycle&amp;rsquo;s license plate number, or that one weird python snippet I can never remember.&#xA;I also have a whole slew of them at work &amp;ndash; a bunch of random representative IDs for a bunch of things in our systems that I use from time to time.&#xA;I &lt;em&gt;also&lt;/em&gt; use a bunch of these as todo items at work, but that happens to work differently and is a topic for a future blog post :-)&lt;/p&gt;</description>
    </item>
    <item>
      <title>history preserving data models</title>
      <link>https://traviscj.com/blog/post/2018-07-02-history-preserving-data-models/</link>
      <pubDate>Mon, 02 Jul 2018 11:34:39 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2018-07-02-history-preserving-data-models/</guid>
      <description>&lt;p&gt;Start with a super simple data model:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;CREATE TABLE kv (&#xA;  id BIGINT(22) NOT NULL AUTO_INCREMENT,&#xA;  k VARCHAR(255) NOT NULL,&#xA;  v LONGBLOB NOT NULL,&#xA;  PRIMARY KEY (`id`),&#xA;  UNIQUE KEY u_k (`k`)&#xA;) Engine=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Suppose we want to audit &amp;ldquo;changes&amp;rdquo; to this data model.&lt;/p&gt;&#xA;&lt;h2 id=&#34;approach-1-kv_log&#34;&gt;Approach 1: &lt;code&gt;kv_log&lt;/code&gt;&lt;/h2&gt;&#xA;&lt;p&gt;add data model like&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;CREATE TABLE `kv_log` (&#xA;  id BIGINT(22) NOT NULL AUTO_INCREMENT,&#xA;  changed_at TIMESTAMP NOT NULL,&#xA;  k VARCHAR(255) NOT NULL,&#xA;  old_v LONGBLOB NOT NULL,&#xA;  new_v LONGBLOB NOT NULL,&#xA;  &#xA;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;current value query: unchanged&lt;/p&gt;</description>
    </item>
    <item>
      <title>mysql feeds</title>
      <link>https://traviscj.com/blog/post/2018-06-29-mysql_feeds/</link>
      <pubDate>Fri, 29 Jun 2018 00:00:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2018-06-29-mysql_feeds/</guid>
      <description>&lt;p&gt;At work, we use a pattern called &lt;em&gt;feeds&lt;/em&gt; that gets an incredible amount of work done.&#xA;I&amp;rsquo;ve been wanting to describe it here for quite a while, and now seems as good of time as any.&lt;/p&gt;&#xA;&lt;p&gt;The basic premise is: You have a service A with some data that other &amp;ldquo;consuming&amp;rdquo; services B, C, and D want to find out about.&#xA;Maybe the data is payments, maybe it&amp;rsquo;s support cases, maybe it&amp;rsquo;s password changes&amp;hellip; whatever.&#xA;The other services might include your data warehouse, some event listeners, whatever.&lt;/p&gt;</description>
    </item>
    <item>
      <title>constraint violations in tests</title>
      <link>https://traviscj.com/blog/post/2018-05-31-constraint_violations_in_tests/</link>
      <pubDate>Thu, 31 May 2018 00:00:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2018-05-31-constraint_violations_in_tests/</guid>
      <description>&lt;p&gt;I had some test code that looked something like&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;@Test public void a() {&#xA;  db.insert(0, &amp;quot;a&amp;quot;);&#xA;  assertThat(db.query(1).getKey()).isEqualTo(&amp;quot;a&amp;quot;);&#xA;}&#xA;&#xA;@Test public void b() {&#xA;  db.insert(0, &amp;quot;a&amp;quot;);&#xA;  db.insert(1, &amp;quot;b&amp;quot;);&#xA;  assertThat(db.query(2).getKey()).isEqualTo(&amp;quot;b&amp;quot;);&#xA;}&#xA;&#xA;@Test public void c() {&#xA;  assertThat(db.query(3)).isNull();&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;There&amp;rsquo;s some stuff to like about this:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;pretty straightforward which test is touching which records&lt;/li&gt;&#xA;&lt;li&gt;pretty clear what you expect to see in the database.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;There&amp;rsquo;s a bunch of coincidences here that make this work, though:&lt;/p&gt;</description>
    </item>
    <item>
      <title>osquery</title>
      <link>https://traviscj.com/blog/post/2018-01-12-osquery/</link>
      <pubDate>Fri, 12 Jan 2018 08:43:17 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2018-01-12-osquery/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve known about [osquery][] for a while, but recently spent some time digging around in it.&#xA;[osquery]: &lt;a href=&#34;https://osquery.io&#34;&gt;https://osquery.io&lt;/a&gt;&#xA;The basic idea is to provide a consistent SQL interface to a bunch of system data, instead of learning idiosyncrasies of individual commands (which themselves vary across operating systems).&#xA;My hacker buddy Sharvil has worked on osquery a fair bit and explained to me a couple years ago that it actually uses [sqlite][]&amp;rsquo;s [virtual table functionality][vtab] to provide the interface &amp;ndash; it&amp;rsquo;s a fascinating and brilliant project!&#xA;[sqlite]: &lt;a href=&#34;https://sqlite.org/&#34;&gt;https://sqlite.org/&lt;/a&gt;&#xA;[vtab]: &lt;a href=&#34;https://sqlite.org/vtab.html&#34;&gt;https://sqlite.org/vtab.html&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>python attrs</title>
      <link>https://traviscj.com/blog/post/2017-08-31-python-attrs/</link>
      <pubDate>Thu, 31 Aug 2017 08:42:43 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2017-08-31-python-attrs/</guid>
      <description>&lt;p&gt;I came across a very interesting library in a &lt;a href=&#34;https://news.ycombinator.com/item?id=15131981&#34;&gt;HN thread&lt;/a&gt;: the python &lt;a href=&#34;http://www.attrs.org/en/stable/examples.html&#34;&gt;attrs&lt;/a&gt; library.&lt;/p&gt;&#xA;&lt;p&gt;In particular, this seems like a great way to do the &amp;ldquo;dumb data objects&amp;rdquo; they talk about in &lt;a href=&#34;https://www.youtube.com/watch?v=3MNVP9-hglc&#34;&gt;the end of object inheritance&lt;/a&gt;, and also related to (but maybe lighter weight than) &lt;a href=&#34;https://zopeinterface.readthedocs.io/en/latest/README.html&#34;&gt;zope.interface&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;This also seems very similar to what I use &lt;a href=&#34;https://github.com/google/auto&#34;&gt;autovalue&lt;/a&gt; for at work.&lt;/p&gt;&#xA;&lt;p&gt;One particularly interesting application is a &amp;ldquo;code database&amp;rdquo; &amp;ndash; using static, checked-in-to-version-control definitions of some data model as a sort of very-fast-to-read, very-slow-to-update &amp;ldquo;Data Model&amp;rdquo;.&#xA;I find this fascinating:&#xA;Code shares a lot of properties with great data stores: ability to rollback (&lt;code&gt;git revert&lt;/code&gt;) and accountability/auditability (&lt;code&gt;git blame&lt;/code&gt;).&#xA;It also makes a lot of fairly hard problems much simpler: you don&amp;rsquo;t need to poll the database for changes.&#xA;You don&amp;rsquo;t need to invalidate any caches.&#xA;You don&amp;rsquo;t need to consider a &amp;ldquo;split brain&amp;rdquo; environment where half of the in-memory caches have updated but the other half haven&amp;rsquo;t.&#xA;You don&amp;rsquo;t need to consider failure cases of how long the in-memory cache is allowed to be invalid: you just fail to boot up on deploy.&#xA;(Admittedly, there&amp;rsquo;s still an opportunity window for split brain behavior for the duration of the deploy, but this is a lot easier to reason about than an essentially arbitrary.)&lt;/p&gt;</description>
    </item>
    <item>
      <title>relational java explorations with sqlite3 vtab</title>
      <link>https://traviscj.com/blog/post/2017-05-05-relational-java-explorations-with-sqlite3-vtab/</link>
      <pubDate>Fri, 05 May 2017 20:10:28 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2017-05-05-relational-java-explorations-with-sqlite3-vtab/</guid>
      <description>&lt;p&gt;One idea i have been mulling over lately is exposing a java codebase relationally, with queries like:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; classes &lt;span style=&#34;color:#66d9ef&#34;&gt;c&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;JOIN&lt;/span&gt; annotations a&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;ON&lt;/span&gt; a.class_id &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;c&lt;/span&gt;.id&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; a.name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;MyAnnotationClass&amp;#39;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;The idea here is that you could search a codebase by pretending that you had tables for a whole bunch of things like:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;classes&lt;/li&gt;&#xA;&lt;li&gt;annotations&lt;/li&gt;&#xA;&lt;li&gt;variables&lt;/li&gt;&#xA;&lt;li&gt;literals&lt;/li&gt;&#xA;&lt;li&gt;methods&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;This would be a useful thing because instead of relying on an IDE like IntelliJ to do &amp;ldquo;find usages&amp;rdquo; operations, you could actually script those interactions.&#xA;Admittedly, of course, Java has some pretty sophisticated reflection APIs to find this sort of stuff too, but it seems like exploring the structure could be much easier writing Java code to traverse those trees.&lt;/p&gt;</description>
    </item>
    <item>
      <title>toy/life data models</title>
      <link>https://traviscj.com/blog/post/2017-04-19-toy_life_data_models/</link>
      <pubDate>Wed, 19 Apr 2017 00:00:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2017-04-19-toy_life_data_models/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been experimenting a lot with some kinda &amp;ldquo;toy&amp;rdquo; data models based on random things that I wish there was a database to query, but isn&amp;rsquo;t.&#xA;For example:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What was my average arrival time this week?&lt;/li&gt;&#xA;&lt;li&gt;How much of my equity has vested before a certain date?&lt;/li&gt;&#xA;&lt;li&gt;When was the last time we had spaghetti for dinner?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve been doing this with flat JSON files.&#xA;This is a bit of an odd choice for me; I actually love schematizing data models in protobuf and MySQL and designing proper indices for the data models I work on during work hours.&lt;/p&gt;</description>
    </item>
    <item>
      <title>filter vs spec (draft)</title>
      <link>https://traviscj.com/blog/post/2017-01-18-filter_vs_spec/</link>
      <pubDate>Wed, 18 Jan 2017 00:00:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2017-01-18-filter_vs_spec/</guid>
      <description>&lt;p&gt;Consider a silly data model to store data about cities like&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;message City {&#xA;  optional string city_name = 1;&#xA;  optional string state = 2;&#xA;  optional int32 population = 3;&#xA;  optional int32 year_founded = 4;&#xA;  // ... presumably others :-)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;and some sample data like:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;[&#xA;  {&amp;quot;city_name&amp;quot;: &amp;quot;Portland&amp;quot;, &amp;quot;state&amp;quot;: &amp;quot;OR&amp;quot;, &amp;quot;population&amp;quot;: ...},&#xA;  {&amp;quot;city_name&amp;quot;: &amp;quot;Portland&amp;quot;, &amp;quot;state&amp;quot;: &amp;quot;ME&amp;quot;, &amp;quot;population&amp;quot;: ...},&#xA;  {&amp;quot;city_name&amp;quot;: &amp;quot;Springfield&amp;quot;, &amp;quot;state&amp;quot;: &amp;quot;FL&amp;quot;, &amp;quot;population&amp;quot;: ...},&#xA;  {&amp;quot;city_name&amp;quot;: &amp;quot;Springfield&amp;quot;, &amp;quot;state&amp;quot;: &amp;quot;IL&amp;quot;, &amp;quot;population&amp;quot;: ...},&#xA;  {&amp;quot;city_name&amp;quot;: &amp;quot;Springfield&amp;quot;, &amp;quot;state&amp;quot;: &amp;quot;CO&amp;quot;, &amp;quot;population&amp;quot;: ...}&#xA;]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;There are some useful entities we can define: (DRAFT NB: don&amp;rsquo;t read too much into the matcher vs filter lingo.)&lt;/p&gt;</description>
    </item>
    <item>
      <title>MySQLdb module in Python on Ubuntu</title>
      <link>https://traviscj.com/blog/post/2009-05-30-mysqldb_module_in_python_on_ubuntu/</link>
      <pubDate>Sat, 30 May 2009 00:00:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2009-05-30-mysqldb_module_in_python_on_ubuntu/</guid>
      <description>&lt;p&gt;To install the mysqldb module in python on Ubuntu:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;sudo apt-get install python-mysqldb&#xA;&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    <item>
      <title>A Quick MySQL Reference</title>
      <link>https://traviscj.com/blog/post/2009-05-27-a_quick_mysql_reference/</link>
      <pubDate>Wed, 27 May 2009 00:00:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2009-05-27-a_quick_mysql_reference/</guid>
      <description>&lt;p&gt;I got frustrated with not being able to write MySQL because I don&amp;rsquo;t do it often enough to be seeing it in my nightmares like MATLAB. But recently my datasets got annoyingly huge and it seemed like SQL might be a boon to me. So I set out to write a quick little program, and ended up writing this little reference along the way.&lt;/p&gt;&#xA;&lt;p&gt;Also, Sharvil Shah contributed some comments to it, so thanks to him for that!&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
