<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hack MySQL</title><link>https://hackmysql.com/</link><description>Recent content on Hack MySQL</description><generator>Hugo</generator><language>en-us</language><copyright>2024 Daniel Nichter</copyright><lastBuildDate>Fri, 12 Dec 2025 16:39:00 -0500</lastBuildDate><atom:link href="https://hackmysql.com/index.xml" rel="self" type="application/rss+xml"/><item><title>Query Response Time</title><link>https://hackmysql.com/learn/query-response-time/</link><pubDate>Thu, 15 May 2025 06:47:00 -0700</pubDate><guid>https://hackmysql.com/learn/query-response-time/</guid><description>&lt;h2 id="context">Context&lt;/h2>
&lt;p>This is why you need to learn MySQL query response time:&lt;/p>
&lt;div class="intro">
Performance is query response time.
&lt;p>This book explores that idea from various angles with a single intent: to help you achieve remarkable MySQL performance.
&lt;i>Efficient&lt;/i> MySQL performance means focusing on the best practices and techniques that directly affect MySQL performance—no superfluous details or deep internals required by DBAs and experts.
I presume that you’re a busy professional who is using MySQL, not managing it, and that you need the most results for the least effort.
That’s not laziness, that’s efficiency.
To that end, this book is direct and to the point.
And by the end, you will be able to achieve remarkable MySQL performance.&lt;/p></description></item><item><title>Indexes and Indexing</title><link>https://hackmysql.com/learn/indexes-and-indexing/</link><pubDate>Thu, 15 May 2025 06:47:00 -0700</pubDate><guid>https://hackmysql.com/learn/indexes-and-indexing/</guid><description>&lt;h2 id="context">Context&lt;/h2>
&lt;p>This is why you need to learn MySQL indexes and indexing:&lt;/p>
&lt;div class="intro">
Many factors determine MySQL performance, but indexes are special because performance cannot be achieved without them.
You can remove other factors—queries, schemas, data, and so on—and still achieve performance, but removing indexes limits performance to brute force: relying on the speed and capacity of hardware.
If this book were titled &lt;i>Brute Force MySQL Performance&lt;/i>, the contents would be as long as the title: "Buy better, faster hardware."
You laugh but just a few days ago I met with a team of developers who had been improving performance in the cloud by purchasing faster hardware until stratospheric costs compelled them to ask, "How else can we improve performance?"
&lt;p>MySQL leverages hardware, optimizations, and indexes to achieve performance when accessing data.
Hardware is an obvious leverage because MySQL runs on hardware: the faster the hardware, the better the performance.
Less obvious and perhaps more surprising is that hardware provides the &lt;em>least&lt;/em> leverage.
I explain why in a moment.
&lt;em>Optimizations&lt;/em> refer to the numerous techniques, algorithms, and data structures that enable MySQL to utilize hardware efficiently.
Optimizations bring the power of hardware into focus.
And focus is the difference between a light bulb and a laser.
Consequently, optimizations provide more leverage than hardware.
If databases were small, hardware and optimizations would be sufficient.
But increasing data size &lt;em>deleverages&lt;/em> the benefits of hardware and optimizations.
Without indexes, performance is severely limited.&lt;/p></description></item><item><title>Data and Access Patterns</title><link>https://hackmysql.com/learn/data-and-access-patterns/</link><pubDate>Thu, 15 May 2025 06:47:00 -0700</pubDate><guid>https://hackmysql.com/learn/data-and-access-patterns/</guid><description>&lt;h2 id="context">Context&lt;/h2>
&lt;p>This is why you need to learn about MySQL data storage and access patterns:&lt;/p>
&lt;div class="intro">
Even when you master indexes and indexing, you will encounter queries that are simple and properly indexed but still slow.
That’s when you begin to optimize &lt;i>around&lt;/i> the query, starting with the data that it accesses.
To understand why, let’s think about rocks.
&lt;p>Imagine that your job is to move rocks, and you have three piles of different sized rocks.
The first pile contains pebbles: very light, no larger than your thumbnail.
The second pile contains cobbles: heavy but light enough to pick up, no larger than your head.
The third pile contains boulders: too large and heavy to pick up; you need leverage or a machine to move them.
Your job is to move one pile from the bottom of a hill to the top.
Which pile do you choose?&lt;/p></description></item><item><title>Sharding</title><link>https://hackmysql.com/learn/sharding/</link><pubDate>Thu, 15 May 2025 06:47:00 -0700</pubDate><guid>https://hackmysql.com/learn/sharding/</guid><description>&lt;h2 id="context">Context&lt;/h2>
&lt;p>This is why you need to learn about sharding MySQL:&lt;/p>
&lt;div class="intro">
On a single instance of MySQL, performance depends on queries, data, access patterns, and hardware.
When direct and indirect query optimization—assiduously applied—no longer deliver acceptable performance, you have reached the relative limit of single-instance MySQL performance for the application workload.
To surpass that relative limit, you must divide the application workload across multiple instances of MySQL to achieve MySQL at scale.
&lt;p>&lt;em>Sharding&lt;/em> a database is the common and widely used technique of &lt;em>scaling out&lt;/em> (or, &lt;em>horizontal scaling&lt;/em>): increasing performance by distributing the workload across multiple databases.
(By contrast, &lt;em>scaling up&lt;/em>, or &lt;em>vertical scaling&lt;/em>, increases performance by increasing hardware capacity.)
Sharding divides one database into many databases.
Each database is a shard, and each shard is typically stored on a separate MySQL instance running on separate hardware.
Shards are physically separate but logically the same (very large) database.&lt;/p></description></item><item><title>Server Metrics and InnoDB</title><link>https://hackmysql.com/learn/server-metrics-and-innodb/</link><pubDate>Thu, 15 May 2025 06:47:00 -0700</pubDate><guid>https://hackmysql.com/learn/server-metrics-and-innodb/</guid><description>&lt;h2 id="context">Context&lt;/h2>
&lt;p>This is why you need to learn about MySQL server metrics, especially InnoDB metrics:&lt;/p>
&lt;div class="intro">
MySQL metrics are closely related to MySQL performance—that’s obvious.
After all, the purpose of metrics in any system is to measure and report how the system is operating.
What’s not obvious is how they are related.
It’s not unreasonable if you currently see MySQL metrics as a black box with metrics inside that, in some way, indicate something about MySQL.
&lt;p>That view is not unreasonable (or uncommon) because MySQL metrics are often discussed but never taught.
Even in my career with MySQL, I have never read or heard an exposition of MySQL metrics—and I have worked with people who created them.
The lack of pedagogy for MySQL metrics is due to a false presumption that metrics do not require understanding or interpretation because their meaning is self-evident.
That presumption has a semblance of truth when considering a single metric in isolation, like &lt;code>Threads_running&lt;/code>: the number of threads running—what more is there to know?
But isolation is the fallacy: MySQL performance is revealed through a spectrum of MySQL metrics.&lt;/p></description></item><item><title>Replication</title><link>https://hackmysql.com/learn/replication/</link><pubDate>Thu, 15 May 2025 06:47:00 -0700</pubDate><guid>https://hackmysql.com/learn/replication/</guid><description>&lt;h2 id="context">Context&lt;/h2>
&lt;p>This is why you need to learn the basics of MySQL replication, especially the cause of replication lag:&lt;/p>
&lt;div class="intro">
&lt;i>Replication lag&lt;/i> is the delay between the time when a write occurs on a source MySQL instance and the time when that write is applied on a replica MySQL instance.
Replication lag is inherent to all database servers because replication across a network incurs network latency.
&lt;p>Replication lag is data loss.
Seriously.
Do not dismiss replication lag.&lt;/p></description></item><item><title>Transactions and Data Locks</title><link>https://hackmysql.com/learn/transactions-and-data-locks/</link><pubDate>Thu, 15 May 2025 06:47:00 -0700</pubDate><guid>https://hackmysql.com/learn/transactions-and-data-locks/</guid><description>&lt;h2 id="context">Context&lt;/h2>
&lt;p>This is why you need to learn about MySQL transactions and data locks, which are closely related:&lt;/p>
&lt;div class="intro">
MySQL has non-transactional storage engines, but InnoDB is the default and the presumptive norm.
Therefore, practically speaking, every MySQL query executes in a transaction by default, even a single &lt;code>SELECT&lt;/code> statement.
&lt;p>From our point of view as programmers, transactions appear conceptual: &lt;code>BEGIN&lt;/code>, execute queries, and &lt;code>COMMIT&lt;/code>.
Then we trust MySQL (and InnoDB) to uphold the ACID properties: atomicity, consistency, isolation, and durability.
When the application workload—queries, indexes, data, and access patterns—is well optimized, transactions are a nonissue with respect to performance.
(Most database topics are a nonissue when the workload is well optimized.)
But behind the scenes, transactions invoke a whole new world of considerations because upholding ACID properties while maintaining performance is not an easy feat.
Fortunately, MySQL shines at executing transactions.&lt;/p></description></item><item><title>Common Challenges</title><link>https://hackmysql.com/learn/common-challenges/</link><pubDate>Thu, 15 May 2025 06:47:00 -0700</pubDate><guid>https://hackmysql.com/learn/common-challenges/</guid><description>&lt;h2 id="context">Context&lt;/h2>
&lt;p>This is why you need to learn about common challenges when using MySQL:&lt;/p>
&lt;div class="intro">
This chapter is a short but important laundry list of common MySQL challenges and how to mitigate them.
These challenges don’t fit into other chapters because most are not directly related to performance.
But don’t underestimate them: the first two challenges, for example, can ruin a database.
More importantly, these challenges are not special cases that only happen when the stars align and The Fates conspire to ruin your day.
These are common challenges.
Take them seriously, and expect to face them.
&lt;div class="src">Excerpt from &lt;i>&lt;a href="https://oreil.ly/efficient-mysql-performance">Efficient MySQL Performance&lt;/a>&lt;/i>, Chapter 9&lt;br>Copyright 2021 Daniel Nichter&lt;br>No reproduction of this excerpt without permission&lt;/div>

&lt;/div>
&lt;h2 id="key-points">Key Points&lt;/h2>
&lt;ul>
&lt;li>Split-brain occurs when two or more MySQL instances in the same replication topology are written to&lt;/li>
&lt;li>Split-brain is a detriment to data integrity—the data can no longer be trusted&lt;/li>
&lt;li>Data drift occurs when a replica becomes out of sync with the source&lt;/li>
&lt;li>Data drift is real but the origin of the drift is virtually impossible to pinpoint&lt;/li>
&lt;li>Data drift can be detected with pt-table-checksum&lt;/li>
&lt;li>ORMs can generate very poor queries and overall performance&lt;/li>
&lt;li>Schemas always change, so an online schema change (OSC) tool is must-have&lt;/li>
&lt;li>There are three popular OSC tools: pt-online-schema-change, gh-ost, and Spirit&lt;/li>
&lt;li>MySQL has non-standard SQL statements, options, and clauses&lt;/li>
&lt;li>Applications do not fail gracefully by default; it takes effort to fail gracefully&lt;/li>
&lt;li>High performance MySQL is difficult&lt;/li>
&lt;/ul>
&lt;h2 id="pitfalls">Pitfalls&lt;/h2>
&lt;ul>
&lt;li>Not taking into account the key points above&lt;/li>
&lt;/ul>
&lt;h2 id="hack-mysql-articles">Hack MySQL Articles&lt;/h2>
&lt;ul>



&lt;li>&lt;a href="https://hackmysql.com/future-of-mysql-schema-change-spirit/">The Future of MySQL Schema Change: Spirit&lt;/a>&lt;/li>

&lt;li>&lt;a href="https://hackmysql.com/book-9/">How Not to Use MySQL&lt;/a>&lt;/li>

&lt;li>&lt;a href="https://hackmysql.com/when-mysql-goes-away/">When MySQL Goes Away&lt;/a>&lt;/li>

&lt;/ul>

&lt;h2 id="additional-resources">Additional Resources&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Resource&lt;/th>
 &lt;th>Type&lt;/th>
 &lt;th>About&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://dev.mysql.com/doc/refman/en/innodb-online-ddl.html">InnoDB and Online DDL&lt;/a>&lt;/td>
 &lt;td>MySQL manual&lt;/td>
 &lt;td>Since schema changes are routine for developers, it&amp;rsquo;s important to understand how MySQL (and InnoDB) handle them because there are many edge cases depending on the specific type of change.&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://github.com/block/spirit">Spirit&lt;/a>&lt;/td>
 &lt;td>Open source tool&lt;/td>
 &lt;td>The fastest, most advanced online schema change (OSC) change tool available.&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://github.com/github/gh-ost">gh-ost&lt;/a>&lt;/td>
 &lt;td>Open source tool&lt;/td>
 &lt;td>The predecessor of Spirit. Both are solid tools, but use Spirit if possible.&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://docs.percona.com/percona-toolkit/pt-table-checksum.html">pt-table-checksum&lt;/a>&lt;/td>
 &lt;td>Open source tool&lt;/td>
 &lt;td>Still the only tool that can detection data drift on replicas&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;div class="note">
&lt;b>pt-online-schema-change&lt;/b>&lt;br>
Before gh-ost and Spirit, pt-online-schema-change (pt-osc) was the de facto standard tool.
It's still widely used and referenced today, but as the author of pt-osc I strongly advise that you use Spirit instead.
The only reason to use pt-osc is for rare (and risky) edge cases that Spirit (and usually gh-ost) do not support for good reason.
&lt;/div></description></item><item><title>Cloud Performance</title><link>https://hackmysql.com/learn/cloud-performance/</link><pubDate>Thu, 15 May 2025 06:47:00 -0700</pubDate><guid>https://hackmysql.com/learn/cloud-performance/</guid><description>&lt;h2 id="context">Context&lt;/h2>
&lt;p>This is why you need to learn about the reality of using MySQL in the cloud:&lt;/p>
&lt;div class="intro">
MySQL in the cloud is fundamentally the same MySQL that you know and love (or know and tolerate).
In the cloud, best practices and techniques are not only true but &lt;i>eminently&lt;/i> true because cloud providers charge for every byte and millisecond of work.
Performance is money in the cloud.
&lt;p>I wish it were as simple as &amp;ldquo;optimize the workload and you’re done&amp;rdquo;, but MySQL in the cloud raises unique considerations.
The goal is to know and mitigate these cloud considerations so that you can focus on MySQL, not the cloud.
After all, the cloud is nothing special: behind the proverbial curtain, it’s physical servers in a data center running programs like MySQL.&lt;/p></description></item><item><title>mlrd: DynamoDB-Compatible API on MySQL</title><link>https://hackmysql.com/mlrd-dynamodb-compatible-api-on-mysql/</link><pubDate>Fri, 12 Dec 2025 16:39:00 -0500</pubDate><guid>https://hackmysql.com/mlrd-dynamodb-compatible-api-on-mysql/</guid><description>&lt;p>Introducing &lt;a href="https://mlrd.tech/">&lt;code>mlrd&lt;/code>&lt;/a> (&amp;ldquo;mallard&amp;rdquo;) to the world: a DynamoDB-compatible API on MySQL.
Crazy, but it works really well and I&amp;rsquo;m confident it will help a lot of businesses save a lot of money.
Here&amp;rsquo;s why.&lt;/p></description></item><item><title>Learn MySQL Performance</title><link>https://hackmysql.com/learn-mysql-performance/</link><pubDate>Thu, 15 May 2025 06:47:00 -0700</pubDate><guid>https://hackmysql.com/learn-mysql-performance/</guid><description>&lt;p>Every year new cohorts of programmers, DBAs, managers, and more learn MySQL.
After &lt;a href="https://www.mysql.com/news-and-events/events/mysql-summit-2025.html">MySQL and HeatWave Summit 2025&lt;/a> a few weeks ago, I realized what &lt;a href="https://medium.com/mbreads/competing-against-luck-379fe4b9268a">job needs to be done&lt;/a> for these people and how I could help them make progress: revamping this website to focus on &amp;ldquo;the path&amp;rdquo;.&lt;/p></description></item><item><title>An Efficient Path to Learn MySQL Performance</title><link>https://hackmysql.com/path/</link><pubDate>Mon, 21 Apr 2025 00:00:00 +0000</pubDate><guid>https://hackmysql.com/path/</guid><description>&lt;h2 id="conference-presentations">Conference Presentations&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Video&lt;/th>
 &lt;th>Slides&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://youtu.be/NjmLTxlFG4w?si=Qm3GO4APReEjZXnL">MySQL Performance for Application Developers @ MySQL and HeatWave Summit 2025&lt;/a>&lt;/td>
 &lt;td>&lt;a href="https://hackmysql.com/mysql-summit-2025.pdf">mysql-summit-2025.pdf&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>MySQL Performance for Developers @ Percona Live 2023&lt;sup>†&lt;/sup>&lt;/td>
 &lt;td>&lt;a href="https://hackmysql.com/PL23.pdf">PL23.pdf&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://www.youtube.com/watch?v=1C6thrnoGU0">Efficient MySQL Performance @ Percona Live 2022&lt;/a>&lt;/td>
 &lt;td>&lt;a href="https://hackmysql.com/PL22.pdf">PL22.pdf&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://archive.fosdem.org/2022/schedule/event/efficient_mysql/">Efficient MySQL Performance @ FOSDEM 2022&lt;/a>&lt;/td>
 &lt;td>-&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&amp;dagger; Video recording not available&lt;/p>
&lt;h2 id="what-is-the-path">What Is the Path?&lt;/h2>
&lt;p>The path is an ordered sequence of MySQL topics to learn in order to understand and improve MySQL performance.
It&amp;rsquo;s shown to the left (or below on small screens): start by learning topic 1 (query response time), then proceed topic by topic until the end, topic 9 (cloud performance).&lt;/p></description></item><item><title>Career Advice</title><link>https://hackmysql.com/eng/career-advice/</link><pubDate>Mon, 20 Jan 2025 00:00:00 +0000</pubDate><guid>https://hackmysql.com/eng/career-advice/</guid><description>&amp;lsquo;Career Advice&amp;rsquo; lists advice to help ambitious software engineers become the best in their field.</description></item><item><title>Monitoring Multi-threaded Replication Lag With Performance Schema</title><link>https://hackmysql.com/monitoring-replication-lag-with-performance-schema/</link><pubDate>Sat, 28 Dec 2024 20:07:00 -0500</pubDate><guid>https://hackmysql.com/monitoring-replication-lag-with-performance-schema/</guid><description>&lt;p>Used to be that replication lag was as simple as &lt;code>Seconds_Behind_Master&lt;/code> (renamed to &lt;code>Seconds_Behind_Source&lt;/code>).
But with multi-threaded replication (MTR) this is no longer the case.
It&amp;rsquo;s time to relearn replication lag monitoring using Performance Schema tables.&lt;/p></description></item><item><title>Replica Preserve Commit Order and Measuring Lag</title><link>https://hackmysql.com/replica-preserve-commit-order/</link><pubDate>Thu, 21 Nov 2024 19:01:00 -0500</pubDate><guid>https://hackmysql.com/replica-preserve-commit-order/</guid><description>&lt;p>With multi-threaded replication (MTR), a replica can commit transactions in the same order as the source, or not.
This is determined by sysvar &lt;a href="https://dev.mysql.com/doc/refman/en/replication-options-replica.html#sysvar_replica_preserve_commit_order">&lt;code>replica_preserve_commit_order&lt;/code>&lt;/a> (RPCO).
As of MySQL v8.0.27 (released October 2021) it&amp;rsquo;s ON by default, but it was OFF by default for several years prior.
In either case, it&amp;rsquo;s relatively new compared to 20+ years of single-threaded replication for which commit order was not an issue or option.
But with MTR, it&amp;rsquo;s important to understand the affects of RPCO, especially with respect to the focus of this three-part series: replication lag.&lt;/p></description></item><item><title>Efficient MySQL Performance In 10 Sentences</title><link>https://hackmysql.com/book/</link><pubDate>Sat, 09 Nov 2024 14:27:00 -0500</pubDate><guid>https://hackmysql.com/book/</guid><description>&lt;p>Don&amp;rsquo;t have time to read &lt;a href="https://oreil.ly/efficient-mysql-performance">&lt;em>Efficient MySQL Performance&lt;/em>&lt;/a>?
Here&amp;rsquo;s the book (10 chapters) in one-liners.&lt;/p>
&lt;ol>
&lt;li>Performance is query response time.&lt;/li>
&lt;li>Proper left-most indexing is required for performance.&lt;/li>
&lt;li>The less data, the better.&lt;/li>
&lt;li>Access patterns (part of the workload) help or hinder performance.&lt;/li>
&lt;li>Sharding is how to scale writes when single-node performance is truly reached.&lt;/li>
&lt;li>Server metrics reflect how the app workload causes MySQL to work.&lt;/li>
&lt;li>Replication lag is data loss.&lt;/li>
&lt;li>Locks are held until a transaction commits, so commit quickly.&lt;/li>
&lt;li>There are many other challenges that you might need to address—sorry.&lt;/li>
&lt;li>MySQL in the cloud is slower &lt;em>and&lt;/em> more expensive, so performance is more important than ever.&lt;/li>
&lt;/ol></description></item><item><title>Group Commit and Transaction Dependency Tracking</title><link>https://hackmysql.com/group-commit-and-trx-dependency-tracking/</link><pubDate>Sun, 20 Oct 2024 22:35:00 -0400</pubDate><guid>https://hackmysql.com/group-commit-and-trx-dependency-tracking/</guid><description>&lt;p>MySQL 8.0 and newer change and improve how we measure and monitor replication lag.
Even though multi-threaded replication (MTR) has been on by default for the last three years (since &lt;a href="https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-27.html">v8.0.27&lt;/a> released October 2021), the industry has been steeped in single-threaded replication for nearly &lt;em>30&lt;/em> years.
As a result, replication lag with MTR is a complicated topic because it depends on version, configuration, and more.
This three-part series provides a detailed understanding, starting from what was originally an unrelated feature: binary log group commit.&lt;/p></description></item><item><title>Lessons From 20 Years Hacking MySQL (Part 1)</title><link>https://hackmysql.com/lessons-from-20-years-hacking-mysql-part-1/</link><pubDate>Thu, 20 Jun 2024 10:01:00 -0400</pubDate><guid>https://hackmysql.com/lessons-from-20-years-hacking-mysql-part-1/</guid><description>&lt;p>I vividly remember 2004 when I decided to specialize in MySQL because the year before I was homeless and living in my car.
It&amp;rsquo;s been a long road and an amazing journey ever since.&lt;/p></description></item><item><title>Lessons From 20 Years Hacking MySQL (Part 2)</title><link>https://hackmysql.com/lessons-from-20-years-hacking-mysql-part-2/</link><pubDate>Thu, 20 Jun 2024 10:00:00 -0400</pubDate><guid>https://hackmysql.com/lessons-from-20-years-hacking-mysql-part-2/</guid><description>&lt;p>A relational database is more than a data bank, it&amp;rsquo;s a profound philosophical expression.
This is the second and final part of &amp;ldquo;Lessons From 20 Years Hacking MySQL&amp;rdquo;.&lt;/p></description></item><item><title>Why MySQL Replication Is Fast</title><link>https://hackmysql.com/why-mysql-replication-is-fast/</link><pubDate>Fri, 31 May 2024 11:31:00 -0400</pubDate><guid>https://hackmysql.com/why-mysql-replication-is-fast/</guid><description>&lt;p>Replication being slow—replication lag—is a common complaint, but MySQL replication is actually really fast.
Let&amp;rsquo;s run a controlled experiment and peek inside the Performance Schema and binary logs to see why.&lt;/p></description></item><item><title>When COMMIT Is the Slowest Query</title><link>https://hackmysql.com/when-commit-is-the-slowest-query/</link><pubDate>Wed, 17 Apr 2024 16:06:00 -0400</pubDate><guid>https://hackmysql.com/when-commit-is-the-slowest-query/</guid><description>&lt;p>When &lt;code>COMMIT&lt;/code> is the slowest query, it means your storage is slow.
Let&amp;rsquo;s look at an example.&lt;/p></description></item><item><title>The Fallacy of Small Functions</title><link>https://hackmysql.com/design/fallacy-of-small-functions/</link><pubDate>Sun, 24 Mar 2024 17:00:00 -0400</pubDate><guid>https://hackmysql.com/design/fallacy-of-small-functions/</guid><description>&lt;p>Decades of computer programming advice, best practices, and books have taught that small functions are good.
That&amp;rsquo;s misleading at best and counterproductive at worst: increasing complexity rather than reducing it.&lt;/p>
&lt;p>For brevity, I&amp;rsquo;m going to say things are false or wrong without explaining because you already have a &lt;em>fantastic&lt;/em> explanation: &lt;a href="https://web.stanford.edu/~ouster/cgi-bin/book.php">&lt;em>A Philosophy of Software Design&lt;/em>&lt;/a> by John Ousterhout.
Everything I&amp;rsquo;m arguing here is explained in that book.&lt;/p>
&lt;p>Here&amp;rsquo;s an example of bad design:&lt;/p></description></item><item><title>The Infamous ORDER BY LIMIT Query Optimizer Bug</title><link>https://hackmysql.com/infamous-order-by-limit-query-optimizer-bug/</link><pubDate>Tue, 28 Nov 2023 17:39:00 -0500</pubDate><guid>https://hackmysql.com/infamous-order-by-limit-query-optimizer-bug/</guid><description>&lt;p>Which is faster: &lt;code>LIMIT 1&lt;/code> or &lt;code>LIMIT 20&lt;/code>?
Presumably, fetching less rows is faster than fetching more rows.
But for 16 years (&lt;a href="https://github.com/mysql/mysql-server/commit/cf3942929584#diff-f3db433ca1b69c2c77575643263bf78d">since 2007&lt;/a>) the MySQL query optimizer has had a &amp;ldquo;bug&amp;rdquo;† that not only makes &lt;code>LIMIT 1&lt;/code> &lt;em>slower&lt;/em> than &lt;code>LIMIT 20&lt;/code> but can also make the former a table scan, which tends to cause problems.
This happened last week where I work, and although MySQL DBAs are familiar with this bug, I&amp;rsquo;m writing this blog post for developers to more clearly illustrate and explain what&amp;rsquo;s going on and why because it&amp;rsquo;s really counterintuitive.&lt;/p></description></item><item><title>The Future of MySQL Schema Change: Spirit</title><link>https://hackmysql.com/future-of-mysql-schema-change-spirit/</link><pubDate>Mon, 06 Nov 2023 09:00:00 -0500</pubDate><guid>https://hackmysql.com/future-of-mysql-schema-change-spirit/</guid><description>&lt;p>Using pt-online-schema or gh-ost?
Of course you are; everyone in the MySQL industry does.
But now there&amp;rsquo;s a new online schema change tool that will obsolete these two: &lt;a href="https://github.com/cashapp/spirit">Spirit&lt;/a> by renowned MySQL expert Morgan Tocker.&lt;/p></description></item><item><title>Deferred Join: A Deep Dive</title><link>https://hackmysql.com/deferred-join-deep-dive/</link><pubDate>Wed, 09 Aug 2023 13:27:00 -0400</pubDate><guid>https://hackmysql.com/deferred-join-deep-dive/</guid><description>&lt;p>Deferred join is powerful.
Deferred join is simple.
Deferred join is misunderstood.&lt;/p></description></item><item><title>Announcing Finch: A New MySQL Benchmarking Tool</title><link>https://hackmysql.com/announcing-finch-mysql-benchmarking/</link><pubDate>Tue, 01 Aug 2023 13:41:00 -0400</pubDate><guid>https://hackmysql.com/announcing-finch-mysql-benchmarking/</guid><description>&lt;p>I&amp;rsquo;m happy to announce &lt;a href="https://github.com/square/finch">Finch&lt;/a>: a new MySQL benchmarking tool for experts, developers, and modern infrastructure.
TL;DR: &lt;a href="https://square.github.io/finch/">https://square.github.io/finch/&lt;/a>&lt;/p></description></item><item><title>Benchmarking</title><link>https://hackmysql.com/eng/benchmarking/</link><pubDate>Sun, 28 May 2023 00:00:00 +0000</pubDate><guid>https://hackmysql.com/eng/benchmarking/</guid><description>A primer on the fundamentals of database benchmarking: results, workload, benchmark types, cheats, challenges, and reporting</description></item><item><title>Are Aurora Performance Claims True?</title><link>https://hackmysql.com/are-aurora-performance-claims-true/</link><pubDate>Fri, 12 May 2023 09:38:00 -0400</pubDate><guid>https://hackmysql.com/are-aurora-performance-claims-true/</guid><description>&lt;p>Amazon claims that Aurora has &amp;ldquo;Up to 5X the throughput of MySQL&amp;rdquo;.
Is it true?
It wasn&amp;rsquo;t easy to find the truth, but I kept digging until I found it.
This is a long read; let&amp;rsquo;s chase the rabbit all the way down the hole.&lt;/p></description></item><item><title>Announcing Blip: A New MySQL Monitor</title><link>https://hackmysql.com/announcing-blip-mysql-monitor/</link><pubDate>Tue, 28 Mar 2023 13:40:00 -0400</pubDate><guid>https://hackmysql.com/announcing-blip-mysql-monitor/</guid><description>&lt;p>&lt;a href="https://github.com/cashapp/blip" target="_blank">Blip&lt;/a> is a new MySQL monitor that collects and reports server metrics.
But wasn&amp;rsquo;t this problem solved long ago?
Not really&amp;hellip;&lt;/p></description></item><item><title>The First Design</title><link>https://hackmysql.com/design/the-first-design/</link><pubDate>Fri, 03 Feb 2023 16:30:00 -0500</pubDate><guid>https://hackmysql.com/design/the-first-design/</guid><description>&lt;p>When I review the code for a new program, I often provide the original authors &lt;em>a lot&lt;/em> of feedback.
And just as often, those authors are a little annoyed by me, the feedback, or both.
But I keep doing it for two reasons.&lt;/p></description></item><item><title>Level Up</title><link>https://hackmysql.com/eng/level-up/</link><pubDate>Thu, 19 Jan 2023 00:00:00 +0000</pubDate><guid>https://hackmysql.com/eng/level-up/</guid><description>&amp;lsquo;Level Up&amp;rsquo; explains how software engineers can become the best in their field and produce more output than most.</description></item><item><title>COMMIT Latency: Aurora vs. RDS MySQL 8.0</title><link>https://hackmysql.com/commit-latency-aurora-vs-rds-mysql-8.0/</link><pubDate>Mon, 02 Jan 2023 20:18:00 -0500</pubDate><guid>https://hackmysql.com/commit-latency-aurora-vs-rds-mysql-8.0/</guid><description>&lt;p>Let&amp;rsquo;s examine &lt;code>COMMIT&lt;/code> latency on Aurora v2 (MySQL 5.7) vs. Aurora v3 (MySQL 8.0) vs. RDS MySQL 8.0 2-AZ vs. RDS MySQL 8.0 3-AZ &amp;ldquo;cluster&amp;rdquo;.&lt;/p></description></item><item><title>Blip: A New Open Source MySQL Metrics Collector</title><link>https://hackmysql.com/blip-v1.0.0-released/</link><pubDate>Thu, 22 Dec 2022 12:55:00 -0500</pubDate><guid>https://hackmysql.com/blip-v1.0.0-released/</guid><description>&lt;p>&lt;a href="https://github.com/cashapp/blip">Blip&lt;/a> is a new open source MySQL metrics collector, or &amp;ldquo;MySQL monitor&amp;rdquo; for short.
But isn&amp;rsquo;t collecting MySQL metrics easy?
And don&amp;rsquo;t we already have some open source MySQL monitors?
Let&amp;rsquo;s take a trip down &lt;a href="https://www.merriam-webster.com/dictionary/memory%20lane">memory lane&lt;/a>&amp;hellip;&lt;/p></description></item><item><title>How to Write Well</title><link>https://hackmysql.com/eng/write/</link><pubDate>Sun, 18 Dec 2022 00:00:00 +0000</pubDate><guid>https://hackmysql.com/eng/write/</guid><description>&amp;lsquo;How to Write Well&amp;rsquo; is a short guide for software engineers on how to write well.</description></item><item><title>MySQL IOPS for Reads and Surprsies</title><link>https://hackmysql.com/mysql-iops-for-reads-and-surprsies/</link><pubDate>Sun, 20 Nov 2022 13:00:00 -0500</pubDate><guid>https://hackmysql.com/mysql-iops-for-reads-and-surprsies/</guid><description>&lt;p>When you think about IOPS, you probably think about writes because MySQL write I/O has a long tradition of optimization, benchmarking, new algorithms, new storage engines, and so forth.
There&amp;rsquo;s no shortage of material on MySQL write I/O; just two examples from Percona are &lt;a href="https://www.percona.com/blog/2018/08/29/scaling-io-bound-workloads-mysql-cloud/">Scaling IO-Bound Workloads for MySQL in the Cloud&lt;/a> and &lt;a href="https://www.percona.com/blog/2020/05/14/tuning-mysql-innodb-flushing-for-a-write-intensive-workload/">Tuning MySQL/InnoDB Flushing for a Write-Intensive Workload&lt;/a>.
But in this short blog post I highlight two other, less common aspects of MySQL I/O: reads and surprises.&lt;/p></description></item><item><title>Is MySQL in the Cloud the End of the DBA?</title><link>https://hackmysql.com/book-10/</link><pubDate>Sat, 15 Oct 2022 16:31:00 -0400</pubDate><guid>https://hackmysql.com/book-10/</guid><description>&lt;p>No, I don&amp;rsquo;t think so.
But it is does change our profession and have important implications for software engineers using (not managing) MySQL.&lt;/p></description></item><item><title>How Not to Use MySQL</title><link>https://hackmysql.com/book-9/</link><pubDate>Fri, 16 Sep 2022 16:01:00 -0400</pubDate><guid>https://hackmysql.com/book-9/</guid><description>&lt;p>Chapter 9 of &lt;a href="https://oreil.ly/efficient-mysql-performance">&lt;em>Efficient MySQL Performance&lt;/em>&lt;/a> changed in development. Originally, it was a chapter titled &amp;ldquo;Not MySQL&amp;rdquo;, as in &amp;ldquo;how not to use MySQL.&amp;rdquo; But we (O&amp;rsquo;Reilly and I) pulled the chapter, and the current chapter 9 in print is &amp;ldquo;Other Challenges&amp;rdquo;: an important laundry list of other challenges engineers using MySQL must be aware of and address. This blog post is a sketch of the unwritten chapter 9: how not to use MySQL.&lt;/p></description></item><item><title>Mining the MySQL Performance Schema for Transactions</title><link>https://hackmysql.com/book-8/</link><pubDate>Sun, 28 Aug 2022 13:29:00 -0400</pubDate><guid>https://hackmysql.com/book-8/</guid><description>&lt;p>The MySQL &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/performance-schema.html">Performance Schema&lt;/a> is a gold mine of valuable data.
Among the many nuggets you can extract from it is an historical report of transactions: how long a transaction took to execute, what queries were executed in it (with query metrics), and idle time between queries.
Mining this information is not trivial, but it&amp;rsquo;s fun and this blog post shows how to start.&lt;/p></description></item><item><title>MySQL Transaction Reporting</title><link>https://hackmysql.com/mysql-transaction-reporting/</link><pubDate>Sun, 28 Aug 2022 13:28:00 -0400</pubDate><guid>https://hackmysql.com/mysql-transaction-reporting/</guid><description>How to inspect and report MySQL transactions using the Performance Schema</description></item><item><title>Better Replication Heartbeats</title><link>https://hackmysql.com/book-7/</link><pubDate>Thu, 28 Jul 2022 13:57:00 -0400</pubDate><guid>https://hackmysql.com/book-7/</guid><description>&lt;p>We&amp;rsquo;ve been measuring MySQL replication lag with heartbeats for more than a decade.
It works, but can we do better?
Let&amp;rsquo;s see.&lt;/p></description></item><item><title>InnoDB Page Flushing Diagram</title><link>https://hackmysql.com/book-6/</link><pubDate>Sat, 18 Jun 2022 19:09:00 -0400</pubDate><guid>https://hackmysql.com/book-6/</guid><description>&lt;p>Who dares diagram a system and process as complex as InnoDB page flushing?
I do.&lt;/p></description></item><item><title>NewDB: Fate of an Open Source Database</title><link>https://hackmysql.com/rand/newdb/</link><pubDate>Sat, 21 May 2022 15:10:00 -0400</pubDate><guid>https://hackmysql.com/rand/newdb/</guid><description>&lt;p>Recently, I&amp;rsquo;ve had several discussions with engineers, industry experts, and business people of various titles and functions (from sales to CEO) about the fate of a new open source database.
It&amp;rsquo;s not MySQL, and I won&amp;rsquo;t name the real database because it doesn&amp;rsquo;t matter for the purpose of this post.
But to make writing and communication more clear, let&amp;rsquo;s call the database &amp;ldquo;NewDB&amp;rdquo; and the business &amp;ldquo;New Corp.&amp;rdquo;&lt;/p>
&lt;p>This blog post is a think piece on how New Corp. can win the market with NewDB by remaining true to its open source origins &lt;em>and&lt;/em> build a profitable business.&lt;/p></description></item><item><title>I Don't Want to Shard (MySQL)</title><link>https://hackmysql.com/book-5/</link><pubDate>Fri, 20 May 2022 19:00:00 -0400</pubDate><guid>https://hackmysql.com/book-5/</guid><description>&lt;p>Chapter 5 of &lt;a href="https://oreil.ly/efficient-mysql-performance">&lt;em>Efficient MySQL Performance&lt;/em>&lt;/a> addresses sharding, and it was difficult to write but not for technical reasons.
Let me say a little more on the matter.&lt;/p></description></item><item><title>Access Patterns for MySQL</title><link>https://hackmysql.com/book-4/</link><pubDate>Sun, 17 Apr 2022 13:50:00 -0400</pubDate><guid>https://hackmysql.com/book-4/</guid><description>&lt;p>Access patterns intrigue me because it seems that everyone knows what they are and talks about them, but there&amp;rsquo;s also very little written about them—in MySQL literature, at least.
That&amp;rsquo;s why I set out to enumerate a list of access patterns (specific to MySQL).
Since there&amp;rsquo;s no apparent standard for access patterns, I cannot say how my list measures up, but after spending most my career with MySQL, I know this: it is necessary to consider these access patterns when evaluating and improving MySQL performance.
Simply put: you cannot ignore &lt;em>how&lt;/em> the application accesses MySQL.&lt;/p></description></item><item><title>Go Single-character Names</title><link>https://hackmysql.com/golang/go-single-character-names/</link><pubDate>Fri, 25 Mar 2022 16:55:00 -0400</pubDate><guid>https://hackmysql.com/golang/go-single-character-names/</guid><description>&amp;lsquo;Go Single-character Names&amp;rsquo; details the proper, idoimatic usage of single character symbols in Go.</description></item><item><title>Performance Is Less</title><link>https://hackmysql.com/book-3/</link><pubDate>Sat, 19 Mar 2022 16:04:00 -0400</pubDate><guid>https://hackmysql.com/book-3/</guid><description>&lt;p>Is MySQL performance about &amp;ldquo;more&amp;rdquo; or &amp;ldquo;less&amp;rdquo;? From the title, you can tell that I&amp;rsquo;m going to argue that it&amp;rsquo;s about &amp;ldquo;less&amp;rdquo;. Here&amp;rsquo;s the punchline: zero is maximum performance. Let&amp;rsquo;s see where this philosophical blog post leads us.&lt;/p></description></item><item><title>MySQL EXPLAIN ANALYZE</title><link>https://hackmysql.com/book-2/</link><pubDate>Sun, 27 Feb 2022 14:28:00 -0500</pubDate><guid>https://hackmysql.com/book-2/</guid><description>&lt;p>As of MySQL 8.0.18, &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/explain.html#explain-analyze">&lt;code>EXPLAIN ANALYZE&lt;/code>&lt;/a> is an indispensable tool for understanding query execution because it breaks down the query execution stage of response time by measuring each step of the query execution plan.
The information is illuminating, but the output is not intuitive: it requires practice and some understanding of how MySQL executes queries beyond the table join order shown by traditional &lt;code>EXPLAIN&lt;/code> output.
This blog post closely examines three different examples of &lt;code>EXPLAIN ANALYZE&lt;/code> output.&lt;/p></description></item><item><title>Configuring MySQL Query Metrics</title><link>https://hackmysql.com/book-1/</link><pubDate>Sun, 16 Jan 2022 15:40:00 -0500</pubDate><guid>https://hackmysql.com/book-1/</guid><description>&lt;p>Editors and technical reviewers suggested that I cover how to configure MySQL query metrics in chapter 1 of &lt;a href="https://oreil.ly/efficient-mysql-performance">&lt;em>Efficient MySQL Performance&lt;/em>&lt;/a>, but I deferred because it was out of scope for the book, which focuses on engineers &lt;em>using&lt;/em> MySQL, not DBAs.
As such, there&amp;rsquo;s only a note in chapter 1 that says: &amp;ldquo;Ask your DBA or read the MySQL manual.&amp;rdquo;
But I&amp;rsquo;ll cover the topic here because that&amp;rsquo;s what this blog post series is for: behind the book.&lt;/p></description></item><item><title>Efficient MySQL Performance</title><link>https://hackmysql.com/book-0/</link><pubDate>Mon, 27 Dec 2021 09:30:00 -0500</pubDate><guid>https://hackmysql.com/book-0/</guid><description>&lt;p>After 17 years with MySQL, I wrote a book: &lt;a href="https://oreil.ly/efficient-mysql-performance">&lt;em>Efficient MySQL Performance&lt;/em>&lt;/a>.&lt;/p>
&lt;p>I&amp;rsquo;ll make a bold claim: a MySQL book like this has never been written—not even close.
The preface explains why this book is unique:&lt;/p></description></item><item><title>Database Operations Manual</title><link>https://hackmysql.com/eng/database-operations-manual/</link><pubDate>Sat, 16 Oct 2021 00:00:00 +0000</pubDate><guid>https://hackmysql.com/eng/database-operations-manual/</guid><description>&amp;lsquo;Database Operations Manual&amp;rsquo; outlines requirements for operating a database server in production.</description></item><item><title>MySQL LRU Flushing and I/O Capacity</title><link>https://hackmysql.com/mysql-lru-flushing-io-capacity/</link><pubDate>Thu, 02 Sep 2021 18:11:00 -0400</pubDate><guid>https://hackmysql.com/mysql-lru-flushing-io-capacity/</guid><description>&lt;p>InnoDB background LRU list flushing is &lt;em>not&lt;/em> limited by &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_io_capacity">&lt;code>innodb_io_capcity&lt;/code>&lt;/a> or &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_io_capacity_max">&lt;code>innodb_io_capacity_max&lt;/code>&lt;/a>.
I&amp;rsquo;ll prove it in this blog post, but since MySQL experts disagree (or don&amp;rsquo;t know for sure), I&amp;rsquo;d like you to prove me wrong.
This is not an intro; you&amp;rsquo;ll need to know all the InnoDB details wrt page flushing.&lt;/p></description></item><item><title>MySQL Data Locks: Mapping 8.0 to 5.7</title><link>https://hackmysql.com/mysql-data-locks-mapping-80-to-57/</link><pubDate>Mon, 26 Jul 2021 15:40:00 -0400</pubDate><guid>https://hackmysql.com/mysql-data-locks-mapping-80-to-57/</guid><description>&lt;p>As of MySQL 8.0, &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/performance-schema-data-locks-table.html">&lt;code>performance_schema.data_locks&lt;/code>&lt;/a> shows InnoDB data locks.
Before MySQL 8.0, you must &lt;code>SET GLOBAL innodb_status_output_locks=ON&lt;/code> and ruminate on the output of &lt;code>SHOW ENGINE INNODB STATUS&lt;/code>.
The image below (click to see full size) shows how the former maps to the latter for three record locks and one table lock on table &lt;code>t&lt;/code>.&lt;/p>
&lt;a href="https://hackmysql.com/img/mysql-data-locks-mapped-to-innodb-engine-status-locks.png">
&lt;img src="https://hackmysql.com/img/mysql-data-locks-mapped-to-innodb-engine-status-locks.png">
&lt;/a>
&lt;p>Information Schema tables &lt;code>INNODB_LOCKS&lt;/code> and &lt;code>INNODB_LOCK_WAITS&lt;/code> are deprecated as of MySQL 5.7 and removed as of MySQL 8.0.
They are better than nothing, but &lt;a href="https://dev.mysql.com/doc/refman/5.7/en/innodb-information-schema-internal-data.html">&amp;ldquo;Persistence and Consistency of InnoDB Transaction and Locking Information&amp;rdquo;&lt;/a> cautions their usage.
Moreover, &lt;code>INNODB_LOCKS&lt;/code> only shows locks blocking other transactions, which makes it unsuitable to examine InnoDB row locking without a blocking transaction.&lt;/p></description></item><item><title>MySQL Password Rotation with AWS Secrets Manager and Lambda</title><link>https://hackmysql.com/mysql-password-rotation-lambda/</link><pubDate>Mon, 28 Dec 2020 09:56:00 -0500</pubDate><guid>https://hackmysql.com/mysql-password-rotation-lambda/</guid><description>How to set up MySQL password rotation with AWS Secrets Manager, AWS Lambda, and Terraform</description></item><item><title>Query Metrics Requirements for MySQL</title><link>https://hackmysql.com/query-metrics-requirements-for-mysql/</link><pubDate>Sun, 01 Nov 2020 20:25:00 -0500</pubDate><guid>https://hackmysql.com/query-metrics-requirements-for-mysql/</guid><description>&lt;p>Let&amp;rsquo;s answer a question which, to my knowledge, has never been systematically addressed: &lt;em>What are the requirements for a production-ready query metrics app at scale?&lt;/em> I am uniquely qualified to answer that because I have written four query metrics apps, two of which are the open-source standard for MySQL: &lt;a href="https://www.percona.com/doc/percona-toolkit/LATEST/pt-query-digest.html">pt-query-digest&lt;/a> and the original (v1) code behind the query metrics/analysis part of &lt;a href="https://www.percona.com/software/database-tools/percona-monitoring-and-management">Percona Monitoring and Management&lt;/a>. I&amp;rsquo;ve also published a couple of packages related to query metrics: &lt;a href="https://github.com/go-mysql/slowlog">go-mysql/slowlog&lt;/a> and &lt;a href="https://github.com/go-mysql/query">go-mysql/query&lt;/a>.&lt;/p></description></item><item><title>What the Flush?</title><link>https://hackmysql.com/what-the-flush-mysql-dirty-pages/</link><pubDate>Sun, 05 Jul 2020 18:50:00 -0300</pubDate><guid>https://hackmysql.com/what-the-flush-mysql-dirty-pages/</guid><description>&lt;p>Yves Trudeau and Francisco Bordenave, MySQL experts at Percona, recently published a three-part post:
(1) &lt;a href="https://www.percona.com/blog/2019/12/18/give-love-to-your-ssds-reduce-innodb_io_capacity_max/">Give Love to Your SSDs – Reduce innodb_io_capacity_max!&lt;/a>;
(2) &lt;a href="https://www.percona.com/blog/2020/01/22/innodb-flushing-in-action-for-percona-server-for-mysql/">InnoDB Flushing in Action for Percona Server for MySQL&lt;/a>;
(3) &lt;a href="https://www.percona.com/blog/2020/05/14/tuning-mysql-innodb-flushing-for-a-write-intensive-workload/">Tuning MySQL/InnoDB Flushing for a Write-Intensive Workload&lt;/a>. It&amp;rsquo;s a fantastic read from start to finish, and it made me realize: dirty pages sound bad, but they are good. I suspect the opposite (&amp;ldquo;dirty pages are &lt;em>not&lt;/em> good&amp;rdquo;) is a misconception due to an incomplete picture. Let&amp;rsquo;s complete the picture.&lt;/p></description></item><item><title>21 Parameter Group Values to Change in Amazon RDS for MySQL</title><link>https://hackmysql.com/21-parameter-group-values-to-change-in-amazon-rds-for-mysql/</link><pubDate>Mon, 29 Jun 2020 11:15:00 -0300</pubDate><guid>https://hackmysql.com/21-parameter-group-values-to-change-in-amazon-rds-for-mysql/</guid><description>&lt;p>&lt;a href="https://aws.amazon.com/rds/mysql/">Amazon RDS for MySQL&lt;/a> uses many default values for system variables, but it also sets a few &amp;ldquo;sys vars&amp;rdquo; with different values. As with any database, neither product (MySQL) nor provider (AWS) defaults can best suite all use cases. It&amp;rsquo;s our responsibility to carefully review and set every important system variable. This is tedious and difficult, but I&amp;rsquo;ve done it for you.&lt;/p>
&lt;p>Below are are 21 MySQL 5.7 system variables that I recommend changing by creating a new &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithParamGroups.html">parameter group&lt;/a>. This presumes new RDS instances; some of these sys vars cannot be changed easily after provisioning MySQL. This only applies to RDS for MySQL, &lt;em>not&lt;/em> Amazon Aurora.&lt;/p></description></item><item><title>Missing Writes with MySQL GTID</title><link>https://hackmysql.com/mysql-gtid-missing-writes/</link><pubDate>Sun, 31 May 2020 00:00:00 +0000</pubDate><guid>https://hackmysql.com/mysql-gtid-missing-writes/</guid><description>&lt;p>&lt;a href="https://dev.mysql.com/doc/refman/8.0/en/replication-gtids.html">GTID-based replication&lt;/a> makes managing replication topology easy: just &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/change-master-to.html">CHANGE MASTER&lt;/a> to any node and voilà. It &lt;a href="https://hackmysql.com/fixing-ghosted-gtids/">doesn&amp;rsquo;t always work&lt;/a>, but for the most part it does. That&amp;rsquo;s great, but it can hide a serious problem: missing writes. Even when MySQL GTID-based replication says, &amp;ldquo;OK, sure!&amp;rdquo;, which is most of the time, you should double check it.&lt;/p></description></item><item><title>MySQL Threads Running</title><link>https://hackmysql.com/mysql-threads-running-how-hard-is-mysql-working/</link><pubDate>Sat, 25 Apr 2020 16:18:00 -0300</pubDate><guid>https://hackmysql.com/mysql-threads-running-how-hard-is-mysql-working/</guid><description>&lt;p>Queries per second (QPS) measures database throughput, but it does not reflect how hard MySQL is working. The latter is measured by &lt;em>&lt;a href="https://dev.mysql.com/doc/refman/8.0/en/server-status-variables.html#statvar_Threads_running">Threads_running&lt;/a>&lt;/em>, expressed as a gauge (whereas QPS is a rate). Before discussing &lt;em>Threads_running&lt;/em>, let&amp;rsquo;s consider an analogy:&lt;/p></description></item><item><title>Queries Effect Performance</title><link>https://hackmysql.com/queries-effect-performance/</link><pubDate>Sun, 12 Jan 2020 00:00:00 +0000</pubDate><guid>https://hackmysql.com/queries-effect-performance/</guid><description>&lt;p>Queries &lt;em>effect&lt;/em> database performance. That&amp;rsquo;s not a typo: &amp;ldquo;effect&amp;rdquo; not &amp;ldquo;affect&amp;rdquo;. The difference is not a word game but an important way to think about database performance.&lt;/p>
&lt;p>Many things can affect performance. For example, if the system runs out of memory then starts swapping which causes high disk IO latency, that will negatively affect performance. But external factors like that notwithstanding (i.e. when hardware and MySQL are normal and stable), it&amp;rsquo;s important to understand that queries effect performance.&lt;/p></description></item><item><title>Fixing Ghosted GTIDs</title><link>https://hackmysql.com/fixing-ghosted-gtids/</link><pubDate>Sun, 15 Dec 2019 00:00:00 +0000</pubDate><guid>https://hackmysql.com/fixing-ghosted-gtids/</guid><description>&lt;p>&lt;a href="https://dev.mysql.com/doc/refman/8.0/en/replication-gtids-auto-positioning.html">MySQL auto-positioning&lt;/a> is an integral part of replication with GTID, but it&amp;rsquo;s neither required nor guaranteed to work. It&amp;rsquo;s possible to enable GTIDs but disable auto-positioning, and it&amp;rsquo;s possible that one MySQL instance cannot auto-position on another even when GTIDs are used. The former (GTID on but auto-pos off) is an issue for another time. The latter is the topic of this post: when MySQL GTID auto-positioning fails—and how to fix it.&lt;/p></description></item><item><title>Response Time SLO</title><link>https://hackmysql.com/rand/response-time-slo/</link><pubDate>Sat, 29 Jun 2019 19:00:00 -0300</pubDate><guid>https://hackmysql.com/rand/response-time-slo/</guid><description>&lt;p>Response time &lt;a href="https://hackmysql.com/eng/percentiles/">percentiles&lt;/a> are a ubiquitous measure of system performance.
The P999 (99.9th percentile) is a high bar, so it&amp;rsquo;s a good metric to determine a service level objective (SLO).
For example, my team runs a system with a P999 ≤ 800 millisecond SLO.
The system meets the SLO, but here&amp;rsquo;s its P999 graph:&lt;/p>
&lt;p>&lt;img src="https://hackmysql.com/img/query-sla-p999-chart.png" alt="Query SLO P999 Chart">&lt;/p>
&lt;p>Looks bad, but the system &lt;em>is&lt;/em> meeting the SLO. To understand why, let&amp;rsquo;s look at how percentiles are calculated. The &lt;a href="https://hackmysql.com/eng/percentiles/">Percentiles&lt;/a> page on this site is a longer, more technical read about the subject, but for our purposes here the TL;DR is: &lt;mark>a percentile is a high water mark.&lt;/mark> Consider a literal high water mark:&lt;/p></description></item><item><title>Path and Dimension Metrics</title><link>https://hackmysql.com/rand/path-and-dimension-metrics/</link><pubDate>Fri, 12 Apr 2019 09:00:00 -0400</pubDate><guid>https://hackmysql.com/rand/path-and-dimension-metrics/</guid><description>&lt;p>The two most common strategies for identifying and organizing data points that comprise metric time series are &lt;em>path&lt;/em> and &lt;em>dimension&lt;/em>. This post is geared towards engineers who have never been introduced to the subject. Implementing metrics from the ground up, or adding new metrics to an existing system, can be overwhelming in nontrivial systems. Understanding these two strategies simplifies one&amp;rsquo;s efforts.&lt;/p>
&lt;h2 id="path-based-metrics">Path-based Metrics&lt;/h2>
&lt;p>Path-based metrics are the historical norm:&lt;/p>
&lt;pre tabindex="0">&lt;code class="language-none" data-lang="none">host.prod1.disk-free.sda
host.prod1.disk-free.sdc
host.prod2.disk-free.sda
host.prod2.disk-free.sdc
&lt;/code>&lt;/pre>&lt;p>Data points are identified by a path like the fully qualified path name of a file: &lt;code>/home/brian/success.log&lt;/code>. Also like a file, the data point name has a separator character, usually &lt;code>.&lt;/code> or &lt;code>/&lt;/code>. So the examples above have four parts: &lt;code>host&lt;/code> (fixed), a hostname (variable), &lt;code>disk-free&lt;/code> (fixed), a drive (variable). Data points, like files, are uniquely identified by their &lt;em>full&lt;/em> path. For example, file &amp;ldquo;success.log&amp;rdquo; is not unique because it can exist in any directory. Likewise, &amp;ldquo;disk-free.sda&amp;rdquo; is not unique because it can apply to any host.&lt;/p></description></item><item><title>Go Error Types</title><link>https://hackmysql.com/golang/go-error-types/</link><pubDate>Mon, 25 Mar 2019 11:00:00 -0400</pubDate><guid>https://hackmysql.com/golang/go-error-types/</guid><description>&lt;p>This is not a post about Go error handling, it&amp;rsquo;s a post about Go error &amp;ldquo;types&amp;rdquo;: three different ways to construct and use the built-in &lt;a href="https://pkg.go.dev/builtin#error">error interface type&lt;/a>. &lt;code>error&lt;/code> is deceptively simple. When used in the ways described here, it allows us to design meaningful errors and error handling in large Go programs. Errors should be first-class citizens because when things break (and they always do), errors are the first—and often only—information we have. So make them great.&lt;/p></description></item><item><title>Percentiles</title><link>https://hackmysql.com/eng/percentiles/</link><pubDate>Sun, 10 Feb 2019 00:00:00 +0000</pubDate><guid>https://hackmysql.com/eng/percentiles/</guid><description>&amp;lsquo;Percentiles&amp;rsquo; is a deep dive into how percentiles are calculated using nearest rank and linear interpolation.</description></item><item><title>Go Channel Red Flags</title><link>https://hackmysql.com/golang/go-channel-red-flags/</link><pubDate>Sun, 16 Dec 2018 13:00:00 -0300</pubDate><guid>https://hackmysql.com/golang/go-channel-red-flags/</guid><description>&lt;h2 id="more-than-one-close">More Than One close()&lt;/h2>
&lt;p>When reviewing code that uses channels, first thing I do is search for &lt;code>close()&lt;/code> on every channel. More than one &lt;code>close()&lt;/code> is red flag because, unless all uses of the channel are carefully written and tested, it can lead to a panic on close of closed channel. It can also lead to strange behavior or subtle bugs because the code that didn&amp;rsquo;t close the channel isn&amp;rsquo;t aware the channel is closed, so send and receive on the closed channel don&amp;rsquo;t have the intended effect.&lt;/p></description></item><item><title>Component-based Software Design</title><link>https://hackmysql.com/design/component-based-software-design/</link><pubDate>Sun, 02 Dec 2018 00:00:00 +0000</pubDate><guid>https://hackmysql.com/design/component-based-software-design/</guid><description>&lt;p>Software systems are difficult to design because code does not delineate and organize itself. Even experienced engineers can struggle to design a system because there are many solutions but it&amp;rsquo;s not clear which is the best. Compounding the difficulty: engineers know that code can work fine even if, internally, it&amp;rsquo;s an unorganized highly-entangled mess. We want code to be well-organized, but we don&amp;rsquo;t know how to make it so. &lt;a href="https://en.wikipedia.org/wiki/Component-based_software_engineering">Component-based design&lt;/a> is the solution.&lt;/p></description></item><item><title>When MySQL Goes Away</title><link>https://hackmysql.com/when-mysql-goes-away/</link><pubDate>Sun, 22 Jul 2018 18:00:00 -0300</pubDate><guid>https://hackmysql.com/when-mysql-goes-away/</guid><description>&lt;p>Handling MySQL errors in Go is not easy. There are &lt;em>a lot&lt;/em> of &lt;a href="https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html">MySQL server error codes&lt;/a>, and the &lt;a href="https://github.com/go-sql-driver/mysql">Go MySQL driver&lt;/a> as its own errors, and Go &lt;a href="https://golang.org/pkg/database/sql/">database/sql&lt;/a> has its own errors, and errors can bubble up from other packages, like &lt;a href="https://golang.org/pkg/net/#OpError">net.OpError&lt;/a>. Consequently, Go programs tend not to handle errors. Instead, they simply report errors:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="nx">err&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="nx">db&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">Query&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">...&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="nf">Scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="nx">v&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="nx">err&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="kc">nil&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nx">err&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then the error is logged or reported somewhere. This is as poor as it common, and it&amp;rsquo;s extremely common. A robust program handles the error: retry the query if possible; or report a more specific error; else, report the unhandled error. But robust MySQL error handling in Go requires very specific knowledge and experience that is beyond the reasonable purview of app developers.&lt;/p></description></item><item><title>Thinking in Go</title><link>https://hackmysql.com/design/thinking-in-go/</link><pubDate>Sun, 13 May 2018 09:00:00 -0700</pubDate><guid>https://hackmysql.com/design/thinking-in-go/</guid><description>&lt;p>After learning Go, it is necessary to think in Go in order to design and implement well-written, idiomatic Go. This blog post outlines aspects that I think are important for thinking in Go. A full exploration of these aspects could fill a book, but this only an orientation for experienced programmers new to Go.&lt;/p>
&lt;p>Programming languages have aspects which affect how we think, design, and implement software with the language: syntax, documentation, features/capabilities, language type (object-oriented, functional, compiled, etc.), etc. Consider &lt;a href="https://perldoc.perl.org/Time/HiRes.html">Perl Time::HiRes module&lt;/a> vs. &lt;a href="https://ruby-doc.org/core-2.2.0/Time.html">Ruby Time class&lt;/a> vs. &lt;a href="https://pkg.go.dev/time">Go Time package&lt;/a>. Even subtle differences like &amp;ldquo;module&amp;rdquo; vs. &amp;ldquo;class&amp;rdquo; vs. &amp;ldquo;package&amp;rdquo; reflect thinking in the language. Effective language use requires correct language thinking. Applying Java thinking to Go results in non-idiomatic Go code, which is to say: Go code that does not &amp;ldquo;speak to&amp;rdquo; other Go programmers. This is not a superficial concern: from open-source to proprietary enterprise software, a codebase must be familiar and intuitive to other programmers with respect to the language so that the language itself does not impede the already difficult task of ongoing software maintenance by people who did not write the original code.&lt;/p></description></item><item><title>Bootloader Design Pattern</title><link>https://hackmysql.com/design/bootloader-design-pattern/</link><pubDate>Sun, 04 Feb 2018 19:30:00 -0700</pubDate><guid>https://hackmysql.com/design/bootloader-design-pattern/</guid><description>&lt;p>&lt;a href="https://en.wikipedia.org/wiki/Extensibility">Extensibility&lt;/a> is a lofty goal for software design, and difficult to achieve. The Wikipedia article notes:&lt;/p>
&lt;blockquote>
&lt;p>Extensible design in software engineering is to accept that not everything can be designed in advance.&lt;/p>&lt;/blockquote>
&lt;p>That&amp;rsquo;s a paradox because it entails that extensible design does not accept that extensibility can be designed in advance! Fortunately, there&amp;rsquo;s at least one solution that can be intentionally designed and implemented in advance. I call it the &amp;ldquo;Bootloader&amp;rdquo; design pattern. Its intention is twofold: boot the program &lt;em>and&lt;/em> make it extensible to the caller. Of course, every program is booted (started) somehow, usually a &lt;code>main()&lt;/code> function that does a lot and isn&amp;rsquo;t well tested. But before we dive into Bootloader, let&amp;rsquo;s consider Keurig.&lt;/p></description></item><item><title>Database Scalability: Contention and Crosstalk</title><link>https://hackmysql.com/database-scalability-contention-and-crosstalk/</link><pubDate>Sun, 28 Jan 2018 11:20:00 -0700</pubDate><guid>https://hackmysql.com/database-scalability-contention-and-crosstalk/</guid><description>&lt;p>New engineers might not know and experienced engineers might not believe that database systems do not and cannot scale gracefully to 100% system capacity but, rather and counterintutively, exhibit &lt;em>retrograde&lt;/em> performance at some point less than 100% system capacity. The reasonable presumption is:&lt;/p>
&lt;p>&lt;img src="https://hackmysql.com/img/db-scalability-myth.svg" alt="Database Scalability Myth">&lt;/p>
&lt;p>We presume that a database can scale to almost 100% of system capacity, and max performance is a small fraction at the very top (right, orange slice) because, after all, the system itself needs some resources to run itself. But the reality of database scalability is far less optimistic:&lt;/p></description></item><item><title>Crash-safe MySQL Replication</title><link>https://hackmysql.com/crash-safe-mysql-replication-a-visual-guide/</link><pubDate>Tue, 23 Jan 2018 18:40:00 -0700</pubDate><guid>https://hackmysql.com/crash-safe-mysql-replication-a-visual-guide/</guid><description>&lt;p>MySQL crash-safe replication is an old feature (~4 years as of MySQL 5.6), but it&amp;rsquo;s not consistently understood or applied. The MySQL manual on the topic, &lt;a href="https://dev.mysql.com/doc/refman/5.7/en/replication-solutions-unexpected-slave-halt.html">16.3.2 Handling an Unexpected Halt of a Replication Slave&lt;/a>, is correct and authoritative, but unless you grok MySQL replication that page doesn&amp;rsquo;t make it obvious &lt;em>why&lt;/em> crash-safe replication works. Other blog posts explain why, but sometimes add other considerations, making it unclear which settings are necessary and sufficient. The aim of this blog post is total enlightenment, a full crash-safe-spiritual awakening. Light the censers and let us begin at the beginning&amp;hellip;&lt;/p></description></item><item><title>Tech Workers Are Good People</title><link>https://hackmysql.com/rand/tech-workers-are-good-people/</link><pubDate>Sun, 31 Dec 2017 09:50:00 -0700</pubDate><guid>https://hackmysql.com/rand/tech-workers-are-good-people/</guid><description>&lt;p>&lt;a href="https://www.wired.com/story/the-other-tech-bubble/">The Other Tech Bubble&lt;/a> is a provocative and interesting read. The author clearly has a lot of experience with Silicon Valley and has done their homework. There are many good insights, like &amp;ldquo;They&amp;rsquo;re still asking if it&amp;rsquo;s possible to do something, and not whether they should.&amp;rdquo; But there are two claims and one ambiguity that need to be addressed.&lt;/p>
&lt;h2 id="villains">Villains&lt;/h2>
&lt;p>The first claim is:&lt;/p>
&lt;blockquote>
&lt;p>In 2008, it was Wall Street bankers. In 2017, tech workers are the world&amp;rsquo;s villain.&lt;/p></description></item><item><title>Approaching a New Software Project</title><link>https://hackmysql.com/design/approaching-a-new-software-project/</link><pubDate>Sun, 10 Dec 2017 00:00:00 +0000</pubDate><guid>https://hackmysql.com/design/approaching-a-new-software-project/</guid><description>&lt;p>Approaching a new software project is difficult for two reasons. First, there&amp;rsquo;s no &amp;ldquo;guiding star&amp;rdquo;, no objective starting point. The developer can begin from and proceed in many directions, which makes choosing difficult. They want to proceed in a good direction from the start, not wasting time or effort, but how can they make a good choice without a guide or the benefit of experience? Being forced to choose and move ahead, the choice is often made randomly rather than methodically. If lucky, the choice is good, but as Ryan says: &amp;ldquo;Luck is not a strategy.&amp;rdquo; Second, this is not something commonly taught. It&amp;rsquo;s common for developers to learn by being thrown into water and they either sink or swim. Becoming good at moving from idea to design to implementation to the long tail of software development/maintenance is a skill that requires practice, learning from mistakes, and learning from other resources (books, blogs, people, etc.).&lt;/p></description></item><item><title>Ideas, Leaders, and Engineers</title><link>https://hackmysql.com/rand/ideas-leaders-and-engineers/</link><pubDate>Sun, 12 Nov 2017 00:00:00 +0000</pubDate><guid>https://hackmysql.com/rand/ideas-leaders-and-engineers/</guid><description>&lt;p>&lt;a href="http://silverwraith.com/blog/2017/10/the-senior-engineers-guide-to-helping-others-make-decisions/">The Senior Engineer&amp;rsquo;s Guide to Helping Others Make Decisions&lt;/a> is a good read and good advice. I would summarize the advice as:&lt;/p>
&lt;ol>
&lt;li>&amp;ldquo;Seek first to understand, then to be understood&amp;rdquo; (&lt;a href="https://www.stephencovey.com/7habits/7habits-habit5.php">Dr. Stephen Covey&lt;/a>)&lt;/li>
&lt;li>Lead and guide, don&amp;rsquo;t micromanage&lt;/li>
&lt;li>Embrace change, which entails embracing other people&amp;rsquo;s thinking and way of doing things&lt;/li>
&lt;/ol>
&lt;p>In the first dialog, the senior engineer fails those three points.&lt;/p>
&lt;p>Av&amp;rsquo;s blog post made me think&amp;hellip;&lt;/p>
&lt;h2 id="good-ideas">Good Ideas&lt;/h2>
&lt;p>Let me jump right to the punch line: &lt;em>levels of seniority should not apply to ideas&lt;/em>. Many years ago I realized the following, one of my personal maxims:&lt;/p></description></item><item><title>Five-Point Checklist for Excellent Software</title><link>https://hackmysql.com/design/five-point-checklist-for-excellent-software/</link><pubDate>Sun, 17 Sep 2017 00:00:00 +0000</pubDate><guid>https://hackmysql.com/design/five-point-checklist-for-excellent-software/</guid><description>&lt;p>I&amp;rsquo;ve never met a developer who hasn&amp;rsquo;t read or reviewed &lt;em>a lot&lt;/em> of code written by other developers. If there&amp;rsquo;s one truism in the field of software of engineering it&amp;rsquo;s that the process is collaborative. Unless you write and never release software, other people will read the code, and they&amp;rsquo;re most likely reading it not for a fun bedtime story but because they need to understand and probably fix or modify it.&lt;/p></description></item><item><title>Designing Tools for Integration</title><link>https://hackmysql.com/design/designing-tools-for-integration/</link><pubDate>Tue, 05 Sep 2017 00:00:00 +0000</pubDate><guid>https://hackmysql.com/design/designing-tools-for-integration/</guid><description>&lt;p>When we write a new tool to do X, it&amp;rsquo;s common to program the tool to do X in one way. When X is trivial or very narrow in scope, this makes sense, and programming any more would fall prey to over-engineering. However, when the tool does many things (all logically related, else it falls prey to bloat and/or feature-creep), there quickly becomes many ways to accomplish those many things. No problem, we program all those things, too, but during my tool-making career I&amp;rsquo;ve learned two things:&lt;/p></description></item><item><title>How To Test the Database</title><link>https://hackmysql.com/design/how-to-test-the-database/</link><pubDate>Sun, 20 Aug 2017 11:20:00 -0700</pubDate><guid>https://hackmysql.com/design/how-to-test-the-database/</guid><description>&lt;p>&amp;ldquo;How do I test the database?&amp;rdquo; is a question I&amp;rsquo;ve been asked by colleagues many times. There&amp;rsquo;s a good, clean solution, but let&amp;rsquo;s first step back from what seems to be the problem to unpack why &amp;ldquo;testing the database&amp;rdquo; is not special (but nonetheless important). In other words: colleagues don&amp;rsquo;t ask, &amp;ldquo;How do I test such-and-such package?&amp;rdquo;, because that&amp;rsquo;s common and well understood. The question about testing the database implies that the database is a special beast that, if not treated properly, will devour the developer in their sleep.&lt;/p></description></item><item><title>Design Before Implementation</title><link>https://hackmysql.com/design/design-before-implementation/</link><pubDate>Tue, 01 Aug 2017 00:00:00 +0000</pubDate><guid>https://hackmysql.com/design/design-before-implementation/</guid><description>&lt;p>Like most software engineers, I review my colleagues&amp;rsquo; code. I rarely provide feedback on implementation details because developers rarely choose obviously bad implementations. I focus my attention on design rather than implementation for one simple reason: implementation details are easy to change when software is well designed. Or, from the business perspective, design is the most costly aspect of software to change, so I review for great and therefore cost-effective design.&lt;/p></description></item><item><title>Reading os/exec.Cmd Output Without Race Conditions</title><link>https://hackmysql.com/rand/reading-os-exec-cmd-output-without-race-conditions/</link><pubDate>Sat, 17 Jun 2017 00:00:00 +0000</pubDate><guid>https://hackmysql.com/rand/reading-os-exec-cmd-output-without-race-conditions/</guid><description>&lt;p>&lt;a href="https://golangweekly.com/issues/164">Golang Weekly issue 164&lt;/a> features a nice article, &lt;a href="https://blog.kowalczyk.info/article/wOYk/advanced-command-execution-in-go-with-osexec.html">Advanced command execution in Go with os/exec&lt;/a>, which details several ways of working with &lt;a href="https://golang.org/pkg/os/exec/">os/exec&lt;/a>, especially how to read STDOUT and STDERR while the command is running. This common task is commonly done wrong, where &amp;ldquo;wrong&amp;rdquo; means &amp;ldquo;the code has a race condition&amp;rdquo;. This blog post shows how to read STDOUT and STDERR from an &lt;code>os/exec.Cmd&lt;/code> while it&amp;rsquo;s running and &lt;em>without&lt;/em> race conditions.&lt;/p>
&lt;h2 id="problem">Problem&lt;/h2>
&lt;p>The Internet is rife solutions like Krzysztof provides (but afaik no one has provided them in one place and so thoroughly, so his post is a good read nonetheless), but let&amp;rsquo;s test one:&lt;/p></description></item><item><title>Custom MongoDB Replica Set Write Concern</title><link>https://hackmysql.com/rand/custom-mongodb-replica-set-write-concern/</link><pubDate>Sun, 11 Jun 2017 00:00:00 +0000</pubDate><guid>https://hackmysql.com/rand/custom-mongodb-replica-set-write-concern/</guid><description>&lt;p>One of the great things about MongoDB is &lt;a href="https://docs.mongodb.com/manual/reference/write-concern/">write concern&lt;/a>:&lt;/p>
&lt;blockquote>
&lt;p>Write concern describes the level of acknowledgement requested from MongoDB for write operations to a standalone mongod or to replica sets or to sharded clusters.&lt;/p>&lt;/blockquote>
&lt;p>Awesome! I want 1 write ack from any secondary in the primary DC so when the primary crashes we&amp;rsquo;re guaranteed to have an up-to-date secondary in the primary DC ready to be elected primary. Here&amp;rsquo;s my production MongoDB replica set:&lt;/p></description></item><item><title>Go Antipatterns</title><link>https://hackmysql.com/golang/go-antipatterns/</link><pubDate>Sat, 03 Jun 2017 18:51:14 -0700</pubDate><guid>https://hackmysql.com/golang/go-antipatterns/</guid><description>&amp;lsquo;Go Antipatterns&amp;rsquo; describes bad Go code and how to make it better.</description></item><item><title>Idiomatic Go</title><link>https://hackmysql.com/golang/idiomatic-go/</link><pubDate>Sat, 03 Jun 2017 00:00:00 +0000</pubDate><guid>https://hackmysql.com/golang/idiomatic-go/</guid><description>&amp;lsquo;Idiomatic Go&amp;rsquo; is a list of resources for learning about idomatic Go.</description></item><item><title>MySQL Select and Sort Status Variables</title><link>https://hackmysql.com/mysql-select-and-sort/</link><pubDate>Fri, 23 Dec 2005 00:00:00 -0500</pubDate><guid>https://hackmysql.com/mysql-select-and-sort/</guid><description>A deep dive into the MySQL select and sort status variables</description></item><item><title>About</title><link>https://hackmysql.com/about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://hackmysql.com/about/</guid><description>Hack MySQL is the personal website of Daniel Nichter, author of the book Efficient MySQL Performance published by O&amp;rsquo;Reilly. His webiste explores MySQL, Go, and software design.</description></item><item><title>Archive</title><link>https://hackmysql.com/archive/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://hackmysql.com/archive/</guid><description>The HackMySQL archives</description></item></channel></rss>