<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Roman Agabekov</title>
    <description>The latest articles on DEV Community by Roman Agabekov (@drupaladmin).</description>
    <link>https://dev.to/drupaladmin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F559015%2Fc01d3fd5-e37a-4aff-b8ef-be60aedee397.jpeg</url>
      <title>DEV Community: Roman Agabekov</title>
      <link>https://dev.to/drupaladmin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/drupaladmin"/>
    <language>en</language>
    <item>
      <title>Laravel Deadlocks: Causes and Fixes</title>
      <dc:creator>Roman Agabekov</dc:creator>
      <pubDate>Wed, 05 Aug 2026 14:54:44 +0000</pubDate>
      <link>https://dev.to/drupaladmin/laravel-deadlocks-causes-and-fixes-3ni7</link>
      <guid>https://dev.to/drupaladmin/laravel-deadlocks-causes-and-fixes-3ni7</guid>
      <description>&lt;p&gt;Deadlocks show up once an app has enough traffic for queries to overlap. They rarely appear in development, which makes them frustrating to understand the first time you see one. Plus, deadlocks are hard to reproduce locally and even harder to diagnose after the fact.&lt;/p&gt;

&lt;p&gt;Laravel adds its own twist here. The framework makes parallel work easy with queues, Horizon, scheduled tasks, and event dispatching, but that also means multiple processes start touching the same rows at the same time. A local setup with a single queue worker won’t reveal any of this. Production with 10 Horizon workers running jobs in parallel will. &lt;/p&gt;

&lt;p&gt;This guide explains what a deadlock is, why it happens in Laravel workloads, and how to debug and reduce it without turning your codebase upside down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is a deadlock?&lt;/li&gt;
&lt;li&gt;Common deadlock patterns in MySQL&lt;/li&gt;
&lt;li&gt;What do developers see in Laravel?&lt;/li&gt;
&lt;li&gt;6 Reasons why deadlocks happen in Laravel apps&lt;/li&gt;
&lt;li&gt;Why deadlocks feel random in production&lt;/li&gt;
&lt;li&gt;How to debug deadlocks in production&lt;/li&gt;
&lt;li&gt;How to reduce and prevent deadlocks in Laravel&lt;/li&gt;
&lt;li&gt;Tools that help monitor and understand deadlocks&lt;/li&gt;
&lt;li&gt;Where this leaves you&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is a deadlock?
&lt;/h2&gt;

&lt;p&gt;A deadlock happens when two transactions hold locks that the other needs. Both stop and wait. Neither can progress, so MySQL cancels one to break the stall and keep the server moving. The canceled query receives a deadlock error, and the other continues normally. &lt;/p&gt;

&lt;p&gt;A basic example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Transaction A updates row 1, then waits on row 2.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transaction B updates row 2, then waits on row 1.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They are stuck. The fix is not manual unlocking. MySQL automatically ends the cheaper transaction and logs the cycle. Deadlocks are normal, not a sign that the database is breaking down. They’re a side effect of concurrency and the way InnoDB enforces isolation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common deadlock patterns in MySQL
&lt;/h2&gt;

&lt;p&gt;MySQL tends to reveal a handful of recurring deadlock shapes or types. Each comes from the way workers, queues, and HTTP requests interact with the same tables under load.&lt;/p&gt;

&lt;p&gt;Here are the &lt;a href="https://releem.com/blog/mysql-deadlock-detection" rel="noopener noreferrer"&gt;deadlock types&lt;/a&gt; you’ll see most often:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;Update-Update&lt;/strong&gt;: two transactions update related rows in opposite order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Select-for-Update conflicts&lt;/strong&gt;: one worker locks rows for processing while another tries to modify them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-increment inserts&lt;/strong&gt;: concurrent inserts collide with follow-up updates or related-table writes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gap-lock collisions&lt;/strong&gt;: range queries or non-selective indexes lock more rows than expected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Insert intent conflicts&lt;/strong&gt;: multiple workers inserting into the same index gap at once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Same-PK inserts&lt;/strong&gt;: two writers try to insert the same PRIMARY KEY at the same time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Foreign-key interactions&lt;/strong&gt;: parent/child updates and deletes taken in different order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long transactions&lt;/strong&gt;: broad locking footprints collide with fast writes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What do developers see in Laravel?
&lt;/h2&gt;

&lt;p&gt;When a deadlock occurs, Laravel doesn’t show the lock cycle or the conflicting query. It only reports the error returned by MySQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SQLSTATE[40001]: Deadlock found when trying to get lock; try restarting transaction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the message teams see in Laravel application logs, Horizon failed jobs, queue worker output, Sentry, Bugsnag, or other APM tools. It confirms that one transaction was rolled back, but it doesn’t tell you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which transaction it conflicted with&lt;/li&gt;
&lt;li&gt;Which table or index was involved&lt;/li&gt;
&lt;li&gt;Which rows MySQL locked**&lt;/li&gt;
&lt;li&gt;Why the lock order diverged&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most Laravel deadlocks come from two recurring patterns:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Queries lock more rows than expected&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This often happens when a query scans more of the table than intended. Maybe because an index is missing or not selective enough or because Eloquent issues an implicit SELECT before the update, or because REPEATABLE READ expands the locked range.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Queries touch tables in a different order&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If two workers update the same models but reach the underlying tables in different sequences, MySQL ends up with a mismatched lock order and cancels one of them.&lt;/p&gt;

&lt;p&gt;The next section shows how these patterns appear in real Laravel code and the adjustments you can make to reduce them.&lt;/p&gt;

&lt;h2&gt;
  
  
  6 Reasons why deadlocks happen in Laravel apps
&lt;/h2&gt;

&lt;p&gt;Laravel code doesn’t cause deadlocks by itself. The framework generates straightforward SQL. The problems start when the same table or row is touched by several workers at the same time. Small differences in timing create new lock sequences.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Jobs or requests update the same rows
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If two workers touch the same row in a different order, a deadlock can form.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Worker A&lt;/span&gt;
&lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'status'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'processing'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// Worker B (same row, different path)&lt;/span&gt;
&lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'last_checked_at'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Cause&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tables like orders, invoices, carts, and inventory often receive overlapping updates from web requests, queue workers, and scheduled tasks. Laravel makes these updates simple to express with Eloquent, but each update may include hidden reads or joins that widen the lock scope. &lt;/p&gt;

&lt;p&gt;When two execution paths update the same record but reach it in different sequences, MySQL ends up with a mismatched lock order. If you’re also loading related models (&lt;strong&gt;-&amp;gt;with(...)&lt;/strong&gt;), the initial &lt;strong&gt;SELECT&lt;/strong&gt; may lock more rows than expected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use consistent update paths&lt;/strong&gt; for high-traffic tables.&lt;/li&gt;
&lt;li&gt;Add the &lt;strong&gt;exact index&lt;/strong&gt; your lookup uses (&lt;strong&gt;id, id,status,&lt;/strong&gt; etc.) to keep row locks narrow.&lt;/li&gt;
&lt;li&gt;Consider &lt;strong&gt;SELECT . . . FOR UPDATE&lt;/strong&gt; if you truly need exclusive access.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Long transactions with multiple queries
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Deadlocks occur inside DB::transaction() even though each query seems harmless on its own.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$inventory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'status'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'paid'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nv"&gt;$inventory&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;decrement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'count'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// touches a second table&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another worker might execute the same two statements but in the opposite order.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cause&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;DB::transaction()&lt;/strong&gt; block is convenient and usually correct, but it also groups several operations under the same lock footprint. If one worker updates &lt;strong&gt;orders&lt;/strong&gt; then &lt;strong&gt;inventory&lt;/strong&gt;, while another updates &lt;strong&gt;inventory&lt;/strong&gt; then &lt;strong&gt;order&lt;/strong&gt;, the locking order diverges and a deadlock becomes possible.&lt;/p&gt;

&lt;p&gt;The more steps there are inside a transaction, the more places this can happen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep transactions &lt;strong&gt;short and narrow&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Always touch tables in the &lt;strong&gt;same order&lt;/strong&gt; throughout the app.&lt;/li&gt;
&lt;li&gt;Move slow operations (API calls, heavy queries) &lt;strong&gt;outside&lt;/strong&gt; the transaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Hidden locking from Eloquent
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A simple model update deadlocks, even though you’re updating by primary key.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'last_login_at'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first query may scan more rows than expected if the column isn’t indexed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cause&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Eloquent often performs a &lt;strong&gt;SELECT&lt;/strong&gt; before it performs an &lt;strong&gt;UPDATE&lt;/strong&gt;. If the &lt;strong&gt;SELECT&lt;/strong&gt; touches more rows than you expect (because an index is missing or not selective enough), the transaction holds locks longer and on more rows. Range locks give deadlocks room to form.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the &lt;strong&gt;missing index&lt;/strong&gt; (in this example, an index on &lt;strong&gt;email&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;Avoid &lt;strong&gt;first()&lt;/strong&gt; + &lt;strong&gt;update()&lt;/strong&gt; patterns on non-indexed columns. &lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;whereKey()&lt;/strong&gt; or direct &lt;strong&gt;update()&lt;/strong&gt; calls when possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. High concurrency on a busy queue or Horizon setup
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Deadlocks appear only when Horizon or queue workers are scaled up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'views'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;LogView&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the same job running in parallel, each worker may hit &lt;strong&gt;products&lt;/strong&gt; and &lt;strong&gt;log_views&lt;/strong&gt; in different sequences depending on load, caching, or conditional code branches. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cause&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Queue workers running the same job type at the same time take different execution paths. The code is the same, but the order of queries is not guaranteed. High concurrency exposes lock order issues that do not show up locally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;dedicated queues&lt;/strong&gt; for heavy write operations so they run serially. &lt;/li&gt;
&lt;li&gt;Audit your jobs for &lt;strong&gt;conditional branching&lt;/strong&gt; that changes query order.&lt;/li&gt;
&lt;li&gt;If writes are frequent, consider moving them into &lt;strong&gt;batched updates&lt;/strong&gt; or a single “writer” service.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Schema shape that increases lock ranges
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Deadlocks point to unexpected rows or ranges in the lock graph, even though the code only touches one model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'category_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'updated_at'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Searching on a non-selective column forces a range scan. In this case, if &lt;strong&gt;category_id&lt;/strong&gt; isn’t indexed or is low-cardinality, MySQL may lock a much broader range.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cause&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes the deadlock has nothing to do with code structure. Missing or incomplete indexes may force MySQL to choose a less efficient path. Under &lt;strong&gt;REPEATABLE READ&lt;/strong&gt; that can mean gap locks, next-key locks, or broad range locks that collide with other updates – even unrelated ones. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the &lt;strong&gt;right composite indexes&lt;/strong&gt; for your most common lookup patterns.&lt;/li&gt;
&lt;li&gt;Avoid large &lt;strong&gt;range updates&lt;/strong&gt;. Break them into smaller batches if possible.&lt;/li&gt;
&lt;li&gt;Review slow queries to confirm the optimizer has a narrow path.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Model events, mutators, and touches() adding hidden queries
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An update() call deadlocks even though the row being updated is indexed and the query looks simple.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Comment&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$touches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'post'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$comment&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'body'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$newBody&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This single update silently triggers another update on the related &lt;strong&gt;posts&lt;/strong&gt; row.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cause&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Eloquent model events (&lt;strong&gt;saving, saved, updating,&lt;/strong&gt; etc.), attribute mutators, and &lt;strong&gt;touches()&lt;/strong&gt; relationships all introduce extra queries behind the scenes. If two workers update different comments attached to the same post, you now have multiple hidden writes targeting &lt;strong&gt;posts.id&lt;/strong&gt;. Those extra writes widen the lock footprint and create new lock-order paths that weren't obvious from the code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Disable &lt;strong&gt;touches()&lt;/strong&gt; for high-write tables.&lt;/li&gt;
&lt;li&gt;Audit model events for extra queries and move heavy logic into jobs.&lt;/li&gt;
&lt;li&gt;Use inline &lt;strong&gt;DB::table()-&amp;gt;update()&lt;/strong&gt; where you need a truly minimal write.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why deadlocks feel random in production
&lt;/h2&gt;

&lt;p&gt;Developers often report that deadlocks “come out of nowhere.” The behavior feels random because the timing is influenced by factors you don’t see during local testing. The lock sequence changes slightly with each request, which makes the incidents look unrelated even when they come from the same pattern.&lt;/p&gt;

&lt;p&gt;Situations that create this “random” behavior include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request traffic arriving in a slightly different order&lt;/li&gt;
&lt;li&gt;Queue workers finishing tasks at different speeds&lt;/li&gt;
&lt;li&gt;Query plans shifting when MySQL adjusts cost estimates&lt;/li&gt;
&lt;li&gt;Background jobs overlapping with normal writes&lt;/li&gt;
&lt;li&gt;Large reads that occasionally scan more rows than expected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These changes reorder the locks taken inside MySQL. You may never see the same pattern twice, but the underlying cause is usually stable. It only appears chaotic because the lock collisions depend on micro timing that varies under load.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to debug deadlocks in production
&lt;/h2&gt;

&lt;p&gt;Laravel’s exception messages help you detect a deadlock, but the real source of truth is the MySQL deadlock report. MySQL logs the full lock cycle so you can see what happened. The more you read these traces, the faster you can spot the problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Pull the deadlock details from MySQL
&lt;/h3&gt;

&lt;p&gt;Use one of these methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SHOW ENGINE INNODB STATUS&lt;/strong&gt; – returns the most recent deadlock&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Performance Schema&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;events_transactions_history_long&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;data_locks&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;data_lock_waits&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MySQL error logs&lt;/strong&gt; if deadlock logging is enabled&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Read the lock information
&lt;/h3&gt;

&lt;p&gt;Look closely for three parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The victim query&lt;/li&gt;
&lt;li&gt;The conflicting query&lt;/li&gt;
&lt;li&gt;The locked index and row ranges&lt;/li&gt;
&lt;li&gt;The order in which each transaction acquired locks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A real deadlock report looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;------------------------&lt;/span&gt;
&lt;span class="n"&gt;LATEST&lt;/span&gt; &lt;span class="n"&gt;DETECTED&lt;/span&gt; &lt;span class="n"&gt;DEADLOCK&lt;/span&gt;
&lt;span class="c1"&gt;------------------------&lt;/span&gt;
&lt;span class="o"&gt;***&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;TRANSACTION&lt;/span&gt; &lt;span class="mi"&gt;123456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ACTIVE&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;sec&lt;/span&gt; &lt;span class="n"&gt;starting&lt;/span&gt; &lt;span class="k"&gt;index&lt;/span&gt; &lt;span class="k"&gt;read&lt;/span&gt;
&lt;span class="n"&gt;mysql&lt;/span&gt; &lt;span class="n"&gt;tables&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;locked&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;LOCK&lt;/span&gt; &lt;span class="n"&gt;WAIT&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="k"&gt;lock&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;MySQL&lt;/span&gt; &lt;span class="n"&gt;thread&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="mi"&gt;98&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OS&lt;/span&gt; &lt;span class="n"&gt;thread&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="mi"&gt;140294&lt;/span&gt;
&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="mi"&gt;5542&lt;/span&gt; &lt;span class="k"&gt;Update&lt;/span&gt; &lt;span class="n"&gt;order_items&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="n"&gt;quantity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;

&lt;span class="o"&gt;***&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;WAITING&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="n"&gt;THIS&lt;/span&gt; &lt;span class="k"&gt;LOCK&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;BE&lt;/span&gt; &lt;span class="k"&gt;GRANTED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;RECORD&lt;/span&gt; &lt;span class="n"&gt;LOCKS&lt;/span&gt; &lt;span class="k"&gt;space&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="k"&gt;no&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt; &lt;span class="mi"&gt;72&lt;/span&gt;
&lt;span class="k"&gt;index&lt;/span&gt; &lt;span class="nv"&gt;`PRIMARY`&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="nv"&gt;`order_items`&lt;/span&gt; &lt;span class="n"&gt;trx&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="mi"&gt;123456&lt;/span&gt; &lt;span class="k"&gt;lock&lt;/span&gt; &lt;span class="k"&gt;mode&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="n"&gt;locks&lt;/span&gt; &lt;span class="n"&gt;rec&lt;/span&gt; &lt;span class="n"&gt;but&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="n"&gt;gap&lt;/span&gt;
&lt;span class="n"&gt;Record&lt;/span&gt; &lt;span class="k"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;heap&lt;/span&gt; &lt;span class="k"&gt;no&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="n"&gt;PHYSICAL&lt;/span&gt; &lt;span class="n"&gt;RECORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;n_fields&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;(...)&lt;/span&gt;

&lt;span class="o"&gt;***&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;TRANSACTION&lt;/span&gt; &lt;span class="mi"&gt;123457&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ACTIVE&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;sec&lt;/span&gt; &lt;span class="n"&gt;starting&lt;/span&gt; &lt;span class="k"&gt;index&lt;/span&gt; &lt;span class="k"&gt;read&lt;/span&gt;
&lt;span class="n"&gt;mysql&lt;/span&gt; &lt;span class="n"&gt;tables&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;locked&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="k"&gt;lock&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;MySQL&lt;/span&gt; &lt;span class="n"&gt;thread&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OS&lt;/span&gt; &lt;span class="n"&gt;thread&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="mi"&gt;140310&lt;/span&gt;
&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="mi"&gt;5543&lt;/span&gt; &lt;span class="k"&gt;Update&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'paid'&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;

&lt;span class="o"&gt;***&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;HOLDS&lt;/span&gt; &lt;span class="n"&gt;THE&lt;/span&gt; &lt;span class="k"&gt;LOCK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="n"&gt;RECORD&lt;/span&gt; &lt;span class="n"&gt;LOCKS&lt;/span&gt; &lt;span class="k"&gt;space&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="k"&gt;no&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt; &lt;span class="mi"&gt;72&lt;/span&gt;
&lt;span class="k"&gt;index&lt;/span&gt; &lt;span class="nv"&gt;`PRIMARY`&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="nv"&gt;`order_items`&lt;/span&gt; &lt;span class="n"&gt;trx&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="mi"&gt;123457&lt;/span&gt; &lt;span class="k"&gt;lock&lt;/span&gt; &lt;span class="k"&gt;mode&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;

&lt;span class="o"&gt;***&lt;/span&gt; &lt;span class="n"&gt;WE&lt;/span&gt; &lt;span class="n"&gt;ROLL&lt;/span&gt; &lt;span class="n"&gt;BACK&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Transaction 1 was rolled back, so it’s the victim query. Transaction 2 continued on, so it was the conflicting (and winning) query. The query id tells you exactly which statements were involved in the locking.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Deadlocks are often caused by the database needing to lock more rows than expected. If you see a large range on a table that should be handled by a narrow index, that is a hint.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Check the order of operations
&lt;/h3&gt;

&lt;p&gt;Compare the order of queries between the transactions. If they touch rows in a different sequence, that’s often the direct cause. &lt;/p&gt;

&lt;p&gt;For example, if one part of the code updates a parent model before its related child, and another updates the child before the parent, the lock order shifts. &lt;/p&gt;

&lt;h3&gt;
  
  
  4. Try to reproduce locally
&lt;/h3&gt;

&lt;p&gt;A small script with parallel workers often reveals the inconsistent locking order. Even if you don’t hit the deadlock, the mismatched query order becomes visible. &lt;/p&gt;

&lt;p&gt;If you want to go deeper into how MySQL records deadlocks internally and how to interpret these reports in more detail, take a look at a separate guide on &lt;a href="https://releem.com/blog/mysql-deadlock-detection" rel="noopener noreferrer"&gt;MySQL deadlock detection&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to reduce and prevent deadlocks in Laravel
&lt;/h2&gt;

&lt;p&gt;You cannot remove deadlocks completely, but you can reduce how often they happen and how long they take to debug. Most fixes come from tightening transaction scopes and improving lock predictability.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Keep transactions short
&lt;/h3&gt;

&lt;p&gt;Wrap only the queries that truly need to happen together. Every extra query widens the lock footprint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'confirmed'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Avoid loading relationships or running expensive SELECTs inside the transaction when possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Update rows in a consistent order
&lt;/h3&gt;

&lt;p&gt;If two parts of your app modify related rows, standardize the order. For example, always update the parent before the child or always update by primary key in ascending order. When updates always lock rows in the same sequence, deadlocks drop sharply.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Use row-level locks where needed
&lt;/h3&gt;

&lt;p&gt;Laravel’s query builder supports row-level locking with &lt;strong&gt;lockForUpdate()&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Inventory&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'sku'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$sku&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;lockForUpdate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;decrement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'quantity'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: This requires a unique index on 'sku' to lock a single row. Without it, MySQL may lock a range of rows, increasing deadlock risk.&lt;/p&gt;

&lt;p&gt;This helps when concurrent workers modify the same inventory, balance, or counter rows. It narrows the lock to the exact row instead of a larger range.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Add the right indexes
&lt;/h3&gt;

&lt;p&gt;Deadlocks often come from queries that lock many rows. Missing or weak indexes enlarge those ranges. Look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Queries scanning a full table to find a single record&lt;/li&gt;
&lt;li&gt;Updates that use a non-selective index&lt;/li&gt;
&lt;li&gt;JOINs that lock broader ranges than expected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Better indexing means fewer rows touched, which means fewer collisions.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Avoid unnecessary reads inside writes
&lt;/h3&gt;

&lt;p&gt;If a write operation requires a read, try to move the read outside the transaction or rely on known primary keys instead of scanning.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Implement retry logic for deadlock-prone operations
&lt;/h3&gt;

&lt;p&gt;Deadlocks are transient errors—the rolled-back transaction can usually succeed if retried immediately. Laravel supports automatic retries in transactions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Laravel 8+&lt;/span&gt;
&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'status'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'paid'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;inventory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;decrement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'count'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;For&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;control&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="n"&gt;manual&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt; &lt;span class="n"&gt;logic&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\QueryException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;retry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// your logic here&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;sleepMilliseconds&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$exception&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$exception&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;QueryException&lt;/span&gt; 
        &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;str_contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$exception&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;'Deadlock found'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach is especially useful for queue jobs that process high-contention rows like inventory counts or user balances.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools that help monitor and understand deadlocks
&lt;/h2&gt;

&lt;p&gt;To debug deadlocks properly, you need visibility into both sides of the conflict:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which queries were running&lt;/li&gt;
&lt;li&gt;Which tables and indexes were locked&lt;/li&gt;
&lt;li&gt;How MySQL’s lock order diverged&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many teams rely on logs, APM tools, or exception trackers to spot deadlocks. APM systems like Sentry are great for surfacing the exception, but they don’t record the conflicting transaction, the locked index, or the range of rows involved. &lt;strong&gt;It’s incomplete information&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Database monitoring platforms add a bit more depth:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Percona Monitoring and Management (PMM)&lt;/strong&gt; collects MySQL deadlock events and shows the raw InnoDB report&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Navicat Monitor&lt;/strong&gt; displays captured deadlock graphs in a UI and makes single-event lock cycles readable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MONyog&lt;/strong&gt; pulls MySQL deadlock details and provides alerts, but focuses on event detection rather than suggesting fixes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://releem.com/blog/mysql-deadlock-detection" rel="noopener noreferrer"&gt;Releem&lt;/a&gt;&lt;/strong&gt; captures every deadlock, stores the full history, groups recurring incidents, classifies the deadlock type, and provides guidance on how to resolve the underlying lock pattern.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpfl7fhfz1ge6vc80nxnp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpfl7fhfz1ge6vc80nxnp.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this leaves you
&lt;/h2&gt;

&lt;p&gt;Your first Laravel deadlock can be a bit of a surprise. It typically appears when your application scales with Horizon workers, queued jobs, and scheduled tasks all touching the same rows. It feels unpredictable until you learn to read MySQL's lock report, but even then you only see one incident at a time.&lt;/p&gt;

&lt;p&gt;To actually prevent these patterns, you need ongoing visibility into how transactions overlap and what queries keep causing pressure. &lt;/p&gt;

&lt;p&gt;Some teams use tools like &lt;a href="https://releem.com" rel="noopener noreferrer"&gt;Releem&lt;/a&gt; to keep this visibility continuously, so deadlock patterns are easier to spot before they turn into recurring incidents.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>mysql</category>
      <category>database</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Safe automation for MySQL index recommendations | What’s New At Releem</title>
      <dc:creator>Roman Agabekov</dc:creator>
      <pubDate>Mon, 03 Aug 2026 07:40:00 +0000</pubDate>
      <link>https://dev.to/drupaladmin/safe-automation-for-mysql-index-recommendations-whats-new-at-releem-3j73</link>
      <guid>https://dev.to/drupaladmin/safe-automation-for-mysql-index-recommendations-whats-new-at-releem-3j73</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiu71l9pled89wbw0dnac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiu71l9pled89wbw0dnac.png" alt=" " width="760" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Over the past few months, we’ve been expanding Releem into more database environments while making recommendations easier to understand and act on. June continues that work with updates designed to shorten the path from identifying an issue to resolving it safely.&lt;/p&gt;

&lt;p&gt;This release introduces a more guided &lt;strong&gt;Installation Wizard&lt;/strong&gt;, broader &lt;strong&gt;PostgreSQL configuration coverage&lt;/strong&gt;, improvements to reporting and reliability, and a new workflow for safely &lt;strong&gt;applying index recommendations&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Together, these updates bring Releem closer to our vision of a single workflow for database performance, resource usage, security, and availability.🎯&lt;/p&gt;

&lt;h2&gt;
  
  
  Community Contributions
&lt;/h2&gt;

&lt;p&gt;We're always collecting issues and feature requests on &lt;a href="https://github.com/Releem/releem-agent" rel="noopener noreferrer"&gt;our GitHub&lt;/a&gt;. Here's where you can contribute:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Issues&lt;/strong&gt; – If you encounter any problems or bugs, report them &lt;a href="https://github.com/Releem/releem-agent/issues" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature Requests&lt;/strong&gt; – Have an idea to make Releem even better? Share your suggestions &lt;a href="https://github.com/Releem/releem-agent/discussions" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Product Updates
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Safe automation for index recommendations
&lt;/h3&gt;

&lt;p&gt;Releem can now safely apply index recommendations. Every change goes through a guarded workflow designed to protect availability and preserve a recovery path:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Before a schema change is sent to the Agent, Releem validates whether the affected data can be recovered and whether the operation can run online in that environment.&lt;/li&gt;
&lt;li&gt;The workflow accounts for the database distribution, version, storage engine, and table structure when selecting an eligible execution method. If the database cannot support an online backup, point-in-time recovery is unavailable, or the change would require a blocking operation, Releem stops before execution.&lt;/li&gt;
&lt;li&gt;The Agent then checks available space in the backup and database filesystems and confirms that the required backup tools are installed. It creates a backup and runs a schema-change dry run before applying the index.
Any failed prerequisite, backup, or dry run aborts the change. This gives teams a controlled path from identifying a missing index to applying it safely.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Pd-DUK0so9Y"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Added multi-step Installation Wizard
&lt;/h3&gt;

&lt;p&gt;The new Installation Wizard guides users through three setup decisions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Which database they want to connect&lt;/li&gt;
&lt;li&gt;Where the database is running&lt;/li&gt;
&lt;li&gt;How Releem should be installed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The wizard supports MySQL, MariaDB, and PostgreSQL. For self-managed environments, users can choose Linux, Windows, WHM/cPanel, Docker, or Kubernetes. Managed cloud options include AWS, Google Cloud, and Azure.&lt;/p&gt;

&lt;p&gt;For Linux and Windows installations, the database password is no longer entered in the web interface. The generated script requests it locally during installation, keeping the credential out of the browser-based setup flow for added security.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F46uy2byncjgbb7hnezpo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F46uy2byncjgbb7hnezpo.png" alt=" " width="741" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Expanded PostgreSQL configuration recommendations
&lt;/h3&gt;

&lt;p&gt;Releem now provides recommendations for a broader range of PostgreSQL settings, giving users more control over autovacuum behavior, memory allocation, storage use, parallel query execution, and idle transactions.&lt;/p&gt;

&lt;p&gt;The expanded recommendation set includes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;– autovacuum_max_workers&lt;br&gt;– autovacuum_vacuum_cost_limit&lt;br&gt;– autovacuum_vacuum_cost_delay&lt;br&gt;– autovacuum_naptime&lt;br&gt;– autovacuum_vacuum_scale_factor&lt;br&gt;– autovacuum_vacuum_threshold&lt;/td&gt;
&lt;td&gt;– autovacuum_analyze_scale_factor&lt;br&gt;– autovacuum_analyze_threshold&lt;br&gt;– idle_in_transaction_session_timeout&lt;br&gt;– hash_mem_multiplier&lt;br&gt;– max_parallel_workers_per_gather&lt;br&gt;– work_mem_recommended&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;These additions allow Releem to make more specific recommendations based on how each PostgreSQL database is operating.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Show just the recommended configuration changes
&lt;/h3&gt;

&lt;p&gt;Recommended Configuration now includes a Show just changes view, allowing users to focus on the settings that differ from their current database configuration instead of reviewing every available value.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkxr9sifh8e3og2i0c7fy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkxr9sifh8e3og2i0c7fy.png" alt=" " width="799" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Reports for invited users on shared servers
&lt;/h3&gt;

&lt;p&gt;Invited users can now receive reports for servers shared with them. This keeps collaborators informed about the databases they work on without requiring the server owner to forward updates manually.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7ksxa1sos0y92be1x1uh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7ksxa1sos0y92be1x1uh.png" alt=" " width="800" height="875"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Removed an irrelevant security check for cloud-managed MySQL and MariaDB
&lt;/h3&gt;

&lt;p&gt;Releem previously displayed a symlink security check for managed cloud MySQL and MariaDB instances, even though users cannot change the related setting or access the underlying host.&lt;br&gt;
The check is now skipped for cloud-managed instances, removing a warning and advice that users could not act on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixed deadlock analysis for names with special characters
&lt;/h3&gt;

&lt;p&gt;Deadlock analysis can now parse quoted database and table names that contain special characters. We update the parser’s regular expressions after finding cases where these names prevented Releem from reading the deadlock output correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixed an error when adding servers simultaneously
&lt;/h3&gt;

&lt;p&gt;We fixed an error that could occur when two servers were added at the same time. Parallel server onboarding can now complete without one addition interfering with the other (&lt;a href="https://github.com/Releem/releem-agent/issues/created_by/515" rel="noopener noreferrer"&gt;Closes #515&lt;/a&gt;).&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>database</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Releem Now Supports PostgreSQL, Azure MySQL, and Better Windows Automation</title>
      <dc:creator>Roman Agabekov</dc:creator>
      <pubDate>Mon, 22 Jun 2026 06:27:10 +0000</pubDate>
      <link>https://dev.to/drupaladmin/releem-now-supports-postgresql-azure-mysql-and-better-windows-automation-4a3</link>
      <guid>https://dev.to/drupaladmin/releem-now-supports-postgresql-azure-mysql-and-better-windows-automation-4a3</guid>
      <description>&lt;p&gt;Releem now supports more database environments, helping teams monitor database health, review recommendations, and improve security, performance, and reliability from one workflow.&lt;/p&gt;

&lt;p&gt;In April and May, we added PostgreSQL support, Azure Database for MySQL support, Windows installation improvements, automated configuration changes for Windows, and several Query Analytics updates to make recommendations faster to understand. 🎉&lt;/p&gt;

&lt;p&gt;We’ve also been sharing more of our database research with the community. This month, Gabriel presented a deep technical session at Percona Live titled &lt;em&gt;The Hidden Lives of Temp Tables: Unraveling MySQL Internal Management&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Community Contributions
&lt;/h2&gt;

&lt;p&gt;We're always collecting issues and feature requests on &lt;a href="https://github.com/Releem/mysqlconfigurer" rel="noopener noreferrer"&gt;our GitHub&lt;/a&gt;. Here's where you can contribute:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Issues&lt;/strong&gt; – If you encounter any problems or bugs, report them &lt;a href="https://github.com/Releem/mysqlconfigurer/issues" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;strong&gt;Feature Requests&lt;/strong&gt; – Have an idea to make Releem even better? Share your suggestions &lt;a href="https://github.com/Releem/mysqlconfigurer/discussions" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Product Updates
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;- Expanded database support to PostgreSQL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Releem now supports PostgreSQL, giving teams a more consistent way to monitor database health, receive recommendations, and manage performance across MySQL, MariaDB, and PostgreSQL environments. Health checks, security checks, query analytics, activity monitoring, and configuration tuning are currently in place.&lt;br&gt;
&lt;strong&gt;&lt;a href="https://docs.releem.com/releem-agent/installation-guides/postgresql-manual-linux" rel="noopener noreferrer"&gt;Read the PostgreSQL installation docs&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbhm0tpa4oup508higzd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbhm0tpa4oup508higzd.png" alt=" " width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Expanded database support to Azure Database for MySQL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Releem now supports Azure database for MySQL, making it easier to connect managed MySQL environments on Azure and bring them into the same database management workflow as other supported databases (&lt;a href="https://github.com/Releem/mysqlconfigurer/discussions/265" rel="noopener noreferrer"&gt;Closes #265&lt;/a&gt;).&lt;br&gt;
&lt;strong&gt;&lt;a href="https://docs.releem.com/releem-agent/installation-guides/cloud-managed-azure-mysql-automatic-installation" rel="noopener noreferrer"&gt;Read the installation docs&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Improved Windows installation and automation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We added a Windows installer and helper scripts to simplify installation, updates, apply, and rollback workflows on Windows. This reduces manual setup and makes it easier to keep Releem Agent installed and up to date in Windows environments (&lt;a href="https://github.com/Releem/mysqlconfigurer/issues/436" rel="noopener noreferrer"&gt;Closes #436&lt;/a&gt;).&lt;br&gt;
&lt;strong&gt;&lt;a href="https://docs.releem.com/releem-agent/installation-guides/self-managed-servers-manual-installation-windows" rel="noopener noreferrer"&gt;Read the Windows installation docs&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Safe configuration changes on Windows&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Releem can now safely apply approved configuration changes on Windows. Teams can review recommendations in the dashboard, approve them with a click, and let Releem apply the selected changes automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Query recommendations now shown in Query Analytics&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Query Analytics now shows query recommendations directly inside the analytics tab. Instead of clicking a button to request results, you can see available recommendations immediately and move from identifying expensive queries to reviewing what can be improved.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj6nn0jm6sg3nxuvjt1rc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj6nn0jm6sg3nxuvjt1rc.png" alt=" " width="649" height="887"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Last analysis details added to Query Analytics&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Query Analytics now shows when each SQL query was last analyzed with a timestamp displayed in this format: &lt;strong&gt;Analyzed at: 2026.5.29 20.01.&lt;/strong&gt; This helps teams understand whether recommendations reflect recent workload activity, which is especially useful after deployments, traffic changes, or configuration updates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0j2wnfcyy7j9bkfpnvjs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0j2wnfcyy7j9bkfpnvjs.png" alt=" " width="653" height="794"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Configurable Security Checks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Releem now allows you to disable Security Checks that are not relevant to your environment. This gives teams more control over security monitoring and helps reduce noise from checks that do not apply to a specific system configuration. A special thanks to our early user Jeff for suggesting this improvement 🙌 (&lt;a href="https://github.com/Releem/mysqlconfigurer/discussions/472" rel="noopener noreferrer"&gt;Closes #472&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxm3jdev9el146wq01plf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxm3jdev9el146wq01plf.gif" alt=" " width="600" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Demo server added for new users&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;New users now get access to a demo server. This makes it easier to explore the Releem dashboard, review the recommendation workflow, and understand the product before connecting to a production database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Notifications for invited users&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Invited users now receive weekly reports, recommendations and other notifications, so partners and teams can bring additional users into the workflow more easily.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Agent security fixes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We shipped security fixes for Releem Agent as part of our ongoing work to keep the Agent safer and more reliable in production environments.&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>devops</category>
      <category>webdev</category>
      <category>postgres</category>
    </item>
    <item>
      <title>What's New At Releem  -  WHM/cPanel integration is available</title>
      <dc:creator>Roman Agabekov</dc:creator>
      <pubDate>Thu, 30 Apr 2026 22:00:13 +0000</pubDate>
      <link>https://dev.to/drupaladmin/whats-new-at-releem-whmcpanel-integration-is-available-1fid</link>
      <guid>https://dev.to/drupaladmin/whats-new-at-releem-whmcpanel-integration-is-available-1fid</guid>
      <description>&lt;p&gt;We spent March focused on expanding query optimization, building out partner integrations, continuing PostgreSQL testing, and improve the overall experience for hosting providers and teams using Releem.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tbody&gt;&lt;tr&gt;
    &lt;td&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fprk0iaripgm9veey4ydb.png" alt="Screenshot 1" width="600" height="600"&gt;
    &lt;/td&gt;
    &lt;td&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1nteb3r99uey5aijs3a0.png" alt="Screenshot 2" width="400" height="399"&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We also had the chance to connect with the hosting community at CloudFest. There, we met with hosting providers interested in partnering with Releem to offer Database Advisor to their customers. I gave a talk on Database Advisor for teams running databases without a DBA.&lt;/p&gt;

&lt;p&gt;Gabriel presented a deep technical session at Scale23X titled &lt;em&gt;&lt;a href="https://www.socallinuxexpo.org/scale/23x/presentations/hidden-lives-temp-tables-unraveling-mysql-internal-management" rel="noopener noreferrer"&gt;The Hidden Lives of Temp Tables: Unraveling MySQL Internal Management.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Community Contributions
&lt;/h2&gt;

&lt;p&gt;We're always collecting issues and feature requests on &lt;a href="https://github.com/Releem/mysqlconfigurer" rel="noopener noreferrer"&gt;our GitHub&lt;/a&gt;. Here's where you can contribute:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Issues&lt;/strong&gt; – If you encounter any problems or bugs, report them &lt;a href="https://github.com/Releem/mysqlconfigurer/issues" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feature Requests&lt;/strong&gt; – Have an idea to make Releem even better? Share your suggestions &lt;a href="https://github.com/Releem/mysqlconfigurer/discussions" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Product Updates
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Batch SQL query analysis and recommendations
&lt;/h3&gt;

&lt;p&gt;You can now see recommendations for all queries directly in &lt;strong&gt;Query Analytics&lt;/strong&gt; without any additional clicks, and save them to the &lt;strong&gt;Query Optimization&lt;/strong&gt; tab for further review and optimization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgs6ca3ivio6sktxae1qu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgs6ca3ivio6sktxae1qu.png" alt=" " width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If no issues are found, the result shows that the query was analyzed along with the timestamp of the latest check, so you can clearly see what was reviewed and when.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fovpirnj0glmq9o7zkhnm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fovpirnj0glmq9o7zkhnm.png" alt=" " width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Releem continues to automatically identify the most impactful queries based on workload and adds them as discovered opportunities in the Query Optimization tab.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom SQL query optimization
&lt;/h3&gt;

&lt;p&gt;You can now analyze and get recommendations for your own SQL queries, not just the ones Releem detects automatically. Developers can review and optimize queries before they reach production. In &lt;strong&gt;Queries &amp;amp; Schema&lt;/strong&gt; plate go to &lt;strong&gt;&lt;u&gt;Query Optimization&lt;u&gt;&lt;/u&gt;&lt;/u&gt;&lt;/strong&gt; tab and press + Add Custom Query&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbi6ub0g1x7x76ylrszkr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbi6ub0g1x7x76ylrszkr.png" alt=" " width="800" height="607"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  WHM/cPanel integration
&lt;/h3&gt;

&lt;p&gt;Releem also integrates with WHM/cPanel, simplifying the installation process and providing access to the Releem dashboard directly from WHM. During installation, Releem disables cPanel auto-tuning rules to ensure compatibility.&lt;/p&gt;

&lt;p&gt;Learn more in the &lt;a href="https://docs.releem.com/releem-agent/installation-guides/whm-cpanel" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4caymg4gvd5bz2ay02d6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4caymg4gvd5bz2ay02d6.png" alt=" " width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  API and WHMCS integration for hosting partners
&lt;/h3&gt;

&lt;p&gt;We released an API for hosting partners, enabling programmatic integration of Releem into hosting platforms and making it possible to offer Database Advisor to VPS, dedicated, and cloud server customers.&lt;/p&gt;

&lt;p&gt;Releem also integrates with &lt;strong&gt;WHMCS&lt;/strong&gt;, allowing providers to sell and manage Database Advisor as an add-on through their existing billing workflows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://releem.com/get-releem-partner-deck" rel="noopener noreferrer"&gt;Get the partner deck&lt;/a&gt; to learn more about integration and partnership options.&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS Aurora Serverless support
&lt;/h3&gt;

&lt;p&gt;We added support for AWS Aurora Serverless, bringing Releem’s performance analysis and recommendations to these environments (&lt;a href="https://github.com/Releem/mysqlconfigurer/discussions/477" rel="noopener noreferrer"&gt;Feature request #477&lt;/a&gt;).&lt;br&gt;
The installation process is the same as for AWS RDS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deadlock export to CSV
&lt;/h3&gt;

&lt;p&gt;Detected deadlocks can now be exported to CSV for external analysis and reporting (&lt;a href="https://github.com/Releem/mysqlconfigurer/discussions/503" rel="noopener noreferrer"&gt;Feature request #503&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuap4u7oqf4k50h1gie60.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuap4u7oqf4k50h1gie60.png" alt=" " width="800" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Improved data collection performance
&lt;/h3&gt;

&lt;p&gt;We fixed an issue in how Releem queried table_io_waits_summary_by_index_usage reducing unnecessary full table scans on servers with many databases (&lt;a href="https://github.com/Releem/mysqlconfigurer/issues/500" rel="noopener noreferrer"&gt;Issue #500&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Uninstallation dependency fix
&lt;/h3&gt;

&lt;p&gt;The agent no longer downloads unnecessary dependencies during uninstallation (&lt;a href="https://github.com/Releem/mysqlconfigurer/issues/466" rel="noopener noreferrer"&gt;Issue #466&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Duplicate index detection improvement
&lt;/h3&gt;

&lt;p&gt;We improved duplicate index analysis to account for foreign key-backed indexes, helping prevent unsafe recommendations during index optimization (&lt;a href="https://github.com/Releem/mysqlconfigurer/issues/478" rel="noopener noreferrer"&gt;Issue #478&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Expanded query parser support
&lt;/h3&gt;

&lt;p&gt;Releem now supports optimization for queries that start with '(' instead of 'SELECT' (&lt;a href="https://github.com/Releem/mysqlconfigurer/issues/427" rel="noopener noreferrer"&gt;Issue #427&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Offline agent apply-task fix
&lt;/h3&gt;

&lt;p&gt;We fixed an issue that allowed configuration apply tasks to be scheduled while the agent was offline (&lt;a href="https://github.com/Releem/mysqlconfigurer/issues/311" rel="noopener noreferrer"&gt;Issue #311&lt;/a&gt;).&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>devops</category>
      <category>database</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What’s New At Releem - January 2026</title>
      <dc:creator>Roman Agabekov</dc:creator>
      <pubDate>Thu, 05 Mar 2026 17:01:47 +0000</pubDate>
      <link>https://dev.to/drupaladmin/whats-new-at-releem-january-2026-36dd</link>
      <guid>https://dev.to/drupaladmin/whats-new-at-releem-january-2026-36dd</guid>
      <description>&lt;p&gt;In the first month of the new year, we focused on practical improvements for the Dashboard, Platform, and Agent, while continuing development on a set of larger integrations that are nearing release. We’ll be sharing details soon.&lt;/p&gt;

&lt;p&gt;In March, we’ll be at &lt;a href="https://www.cloudfest.com/event" rel="noopener noreferrer"&gt;CloudFest in Germany (23–26 March)&lt;/a&gt;, and you can find us in &lt;strong&gt;Startup Alley&lt;/strong&gt;. If you’re planning to attend, let us know so we can connect in person and discuss database performance, automation, and partnership opportunities.&lt;/p&gt;

&lt;p&gt;For Releem Community members, we have &lt;strong&gt;free tickets available&lt;/strong&gt;.&lt;br&gt;
To claim your free ticket and save &lt;strong&gt;€499&lt;/strong&gt;, just send us request.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd091phw8gtdhiutjhvvj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd091phw8gtdhiutjhvvj.png" alt=" " width="800" height="135"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also shipped &lt;strong&gt;Dashboard Sharing&lt;/strong&gt; 💪 This was something we initially treated as a lower-priority request, but it kept coming up. Eventually it became clear it was blocking teams from using Releem together, so we moved it up and shipped it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Community Contributions
&lt;/h2&gt;

&lt;p&gt;We're always collecting issues and feature requests on &lt;a href="https://github.com/Releem/mysqlconfigurer" rel="noopener noreferrer"&gt;our GitHub&lt;/a&gt;. Here's where you can contribute:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Issues&lt;/strong&gt; – If you encounter any problems or bugs, report them &lt;a href="https://github.com/Releem/mysqlconfigurer/issues" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature Requests&lt;/strong&gt; – Have an idea to make Releem even better? Share your suggestions &lt;a href="https://github.com/Releem/mysqlconfigurer/discussions" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Updates to Releem Dashboard
&lt;/h2&gt;

&lt;p&gt;This month’s dashboard updates concentrate on making Query Analytics easier to work with and streamlining how you handle optimization recommendations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Filtering control statements&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can now filter out control statements such as &lt;strong&gt;COMMIT, USE&lt;/strong&gt;, and similar commands inside Query Analytics. This helps isolate performance-relevant queries without noise from session or transaction control statements (&lt;a href="https://github.com/Releem/mysqlconfigurer/discussions/457" rel="noopener noreferrer"&gt;Closes #457&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6g9q1s9o9xzhhqxd3hkw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6g9q1s9o9xzhhqxd3hkw.png" alt=" " width="800" height="86"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Improved query optimization workflow&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can now delete optimization recommendations directly from the interface, with a confirmation step to prevent accidental removal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tfh344hvv9wuned95z6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tfh344hvv9wuned95z6.png" alt=" " width="800" height="104"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Filter queries by status&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Easily filter optimization recommendations by status to focus only on discovered, custom or optimized items.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0z4gjbdpyn3m6ees1cir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0z4gjbdpyn3m6ees1cir.png" alt=" " width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Optional schema checks&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can now disable schema checks when they’re not relevant to your database environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F119nlaquseygen13tb1u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F119nlaquseygen13tb1u.png" alt=" " width="800" height="131"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Google authentication&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Google Sign-In is now available during new account registration, making it faster to get started with Releem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updates to Releem Platform
&lt;/h2&gt;

&lt;p&gt;We pushed out several fixes this month to improve reliability and compatibility:&lt;/p&gt;

&lt;p&gt;Fixed duplicate entry errors during multiple team member invitations (&lt;a href="https://github.com/Releem/mysqlconfigurer/issues/489" rel="noopener noreferrer"&gt;Closes #489&lt;/a&gt;).&lt;br&gt;
Fixed InnoDB index key size detection logic (&lt;a href="https://github.com/Releem/mysqlconfigurer/issues/487" rel="noopener noreferrer"&gt;Closes #487&lt;/a&gt;).&lt;br&gt;
Fixed configuration application issues for RDS MariaDB instances (&lt;a href="https://github.com/Releem/mysqlconfigurer/issues/484" rel="noopener noreferrer"&gt;Closes #484&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Updates to Releem Agent
&lt;/h2&gt;

&lt;p&gt;We simplified Releem Agent installation for WHM/cPanel environments.&lt;/p&gt;

&lt;p&gt;The agent received security and performance improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Updated Go and dependencies&lt;/strong&gt; to the latest versions, resolving critical and high-severity CVEs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Removed envsubst&lt;/strong&gt; from the Agent image to eliminate unnecessary vulnerability exposure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fixed an issue that triggered full table scans&lt;/strong&gt; during constraint metadata collection, reducing impact on database servers (&lt;a href="https://github.com/Releem/mysqlconfigurer/issues/493" rel="noopener noreferrer"&gt;Closes #493&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Events
&lt;/h2&gt;

&lt;p&gt;We spoke at AI DBA Conf and MariaDB Day in Brussels during FOSDEM, connecting with DBAs and engineers focused on automation and database performance.&lt;/p&gt;

&lt;p&gt;If you missed these sessions, you can watch them here: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?si=spwZxIEJtA7s5bS3&amp;amp;v=CXTJLkv9ZIk&amp;amp;feature=youtu.be" rel="noopener noreferrer"&gt;From Manual DBA Work to Safe Automation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/NJue5xXyFkQ?si=1YZLokD5rfz5GbZH" rel="noopener noreferrer"&gt;SQL Query Optimization Without Query Ownership&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>mysql</category>
      <category>database</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
    <item>
      <title>When “MySQL” isn’t actually MySQL</title>
      <dc:creator>Roman Agabekov</dc:creator>
      <pubDate>Tue, 17 Feb 2026 14:23:57 +0000</pubDate>
      <link>https://dev.to/drupaladmin/when-mysql-isnt-actually-mysql-4o4f</link>
      <guid>https://dev.to/drupaladmin/when-mysql-isnt-actually-mysql-4o4f</guid>
      <description>&lt;p&gt;I was recently looking at engine distribution across a few thousand production database instances.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fluaw5g5c2imueb8l3wpd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fluaw5g5c2imueb8l3wpd.png" alt="Database servers statistics by Releem" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What stood out is that some teams believed they were running MySQL, but were actually on MariaDB.&lt;/p&gt;

&lt;p&gt;In most cases this isn’t confusion. It’s environment defaults.&lt;/p&gt;

&lt;p&gt;Many Linux distributions replaced MySQL with MariaDB years ago. Hosting panels and cloud images often install MariaDB by default. The mysql client works the same. ORMs abstract most differences. From the application layer, everything looks like “MySQL.”&lt;/p&gt;

&lt;p&gt;Is your database engine an intentional architectural choice, or something inherited from your base image or hosting stack?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>mysql</category>
      <category>devops</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Releem 2025 Recap: Building a Database Advisor for Developer Teams</title>
      <dc:creator>Roman Agabekov</dc:creator>
      <pubDate>Thu, 22 Jan 2026 15:20:10 +0000</pubDate>
      <link>https://dev.to/drupaladmin/releem-2025-recap-building-a-database-advisor-for-developer-teams-5fi1</link>
      <guid>https://dev.to/drupaladmin/releem-2025-recap-building-a-database-advisor-for-developer-teams-5fi1</guid>
      <description>&lt;p&gt;Hello friends 👋&lt;/p&gt;

&lt;p&gt;2025 was the year we finally had the team we needed.&lt;/p&gt;

&lt;p&gt;For most of Releem's existence, I was the bottleneck. Features sat in backlogs. Support tickets aged. Every decision waited on me. &lt;/p&gt;

&lt;p&gt;Getting &lt;a href="https://www.linkedin.com/in/victor-podkopaev/" rel="noopener noreferrer"&gt;Victor&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/dmitrii-kochetov-563a36354/" rel="noopener noreferrer"&gt;Dmitrii&lt;/a&gt; full-time changed that overnight. Features moved from idea to production faster, and more time went into tickets, feedback, and edge cases.&lt;/p&gt;

&lt;p&gt;We also welcomed the &lt;a href="https://releem.com/blog/tuningwizard-joins-releem" rel="noopener noreferrer"&gt;TuningWizard team and their founder Gabriel&lt;/a&gt; to Releem. Their hands-on SQL optimization experience directly shaped how we analyze queries today and pushed us to raise the bar on accuracy and safety.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8ikt1m17zadyqhl9eki.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8ikt1m17zadyqhl9eki.jpg" alt=" " width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The scale still surprises me. We reached milestones that honestly felt far away when we started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;348 billion SQL queries collected&lt;/li&gt;
&lt;li&gt;808 million API requests&lt;/li&gt;
&lt;li&gt;714,000 schema recommendations&lt;/li&gt;
&lt;li&gt;6 million query recommendations&lt;/li&gt;
&lt;li&gt;571,000 deadlocks detected and analyzed&lt;/li&gt;
&lt;li&gt;53,000 config tuning suggestions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Around 1,000 new users joined along the way 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  What we shipped
&lt;/h2&gt;

&lt;p&gt;On the product side we spent most of the year improving visibility into problems that usually surface too late, and adding automation that is safe to trust in live systems. This included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time deadlock detection with root cause analysis&lt;/li&gt;
&lt;li&gt;Live visibility into blocking and long-running queries&lt;/li&gt;
&lt;li&gt;Schema checks for missing, unused, and redundant indexes&lt;/li&gt;
&lt;li&gt;Full configuration history with before-and-after performance metrics&lt;/li&gt;
&lt;li&gt;Full support for GCP Cloud SQL&lt;/li&gt;
&lt;li&gt;Per-server access control and user roles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Oh, and Dark Mode🌙. Users &lt;em&gt;really&lt;/em&gt; wanted dark mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thank you
&lt;/h2&gt;

&lt;p&gt;Behind the scenes, the team ran more than &lt;strong&gt;100 live demos&lt;/strong&gt;, answered over &lt;strong&gt;1,400 support questions&lt;/strong&gt;, shipped &lt;strong&gt;1,292 commits&lt;/strong&gt;, and &lt;strong&gt;deployed the platform roughly 200 times&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;None of this would be possible without everyone who was willing to try something new, report issues, ask hard questions, and push us to do better. Thank you to our early adopters, our customers, and the broader database community for the trust and feedback throughout the year ❤️&lt;/p&gt;

&lt;p&gt;We are proud of what we built in 2025 and excited to keep going in 2026.&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>database</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What's New At Releem - November 2025</title>
      <dc:creator>Roman Agabekov</dc:creator>
      <pubDate>Wed, 24 Dec 2025 22:18:39 +0000</pubDate>
      <link>https://dev.to/drupaladmin/whats-new-at-releem-november-2025-2lk2</link>
      <guid>https://dev.to/drupaladmin/whats-new-at-releem-november-2025-2lk2</guid>
      <description>&lt;p&gt;Another month wrapped up at Releem, and this month we focused on removing friction in everyday workflows.&lt;/p&gt;

&lt;p&gt;We finally brought &lt;strong&gt;Dark Mode&lt;/strong&gt; to Releem Dashboard 🎉 It took longer than expected, with small UI details needing clean up before it was ready to ship. We quietly rolled the feature out, but a few dozen users enabled it right away!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flr0iij8uru1x0tnw9qfc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flr0iij8uru1x0tnw9qfc.png" alt=" " width="800" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also shipped &lt;strong&gt;Dashboard Sharing&lt;/strong&gt; 💪 This was something we initially treated as a lower-priority request, but it kept coming up. Eventually it became clear it was blocking teams from using Releem together, so we moved it up and shipped it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Community Contributions
&lt;/h2&gt;

&lt;p&gt;We're always collecting issues and feature requests on &lt;a href="https://github.com/Releem/mysqlconfigurer" rel="noopener noreferrer"&gt;our GitHub&lt;/a&gt;. Here's where you can contribute:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Issues&lt;/strong&gt; – If you encounter any problems or bugs, report them &lt;a href="https://github.com/Releem/mysqlconfigurer/issues" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Feature Requests&lt;/strong&gt; – Have an idea to make Releem even better? Share your suggestions &lt;a href="https://github.com/Releem/mysqlconfigurer/discussions" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Updates to Releem Dashboard
&lt;/h2&gt;

&lt;p&gt;We’ve shipped a set of dashboard improvements focused on usability, collaboration, and the workflows you use everyday:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dashboard Sharing &amp;amp; User Roles&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can now invite users to shared dashboards per server through server Settings and assign roles (&lt;a href="https://github.com/Releem/mysqlconfigurer/discussions/279" rel="noopener noreferrer"&gt;Issue #279&lt;/a&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Viewer – Read-only access to dashboard and insights&lt;/li&gt;
&lt;li&gt;Editor – Can change settings and apply recommendations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmy37ywu8fw3625ebkq3u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmy37ywu8fw3625ebkq3u.png" alt=" " width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dark Mode&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can now apply a dark theme to the dashboard. Dark Mode has always had a dedicated group of users who overwhelmingly prefer it to light mode. We’re glad to finally make it available.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5nmhpe5lewwvht8mrb1j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5nmhpe5lewwvht8mrb1j.png" alt=" " width="800" height="891"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Export Process List to CSV&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can now export the process list directly to CSV, making it easier to analyze queries, share snapshots, and include data in reports and incident reviews (&lt;a href="https://github.com/Releem/mysqlconfigurer/discussions/437" rel="noopener noreferrer"&gt;Issue #437&lt;/a&gt;).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Improved Apply Workflow&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To reduce confusion during configuration changes, the &lt;strong&gt;Apply&lt;/strong&gt; button has been moved directly into the &lt;strong&gt;Recommended Configuration&lt;/strong&gt; popup. This keeps review and action in one place.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqh9m94nvq8multc9zvr2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqh9m94nvq8multc9zvr2.png" alt=" " width="800" height="789"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Updates to Releem Platform
&lt;/h2&gt;

&lt;p&gt;Several fixes this month focused on recommendation accuracy and schema analysis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Smarter Buffer Pool Recommendations&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Releem now takes overall system memory pressure into account when generating &lt;strong&gt;innodb_buffer_pool_size&lt;/strong&gt; recommendations. When RAM usage is already high, recommended values are scaled down instead of being calculated solely from total available memory. This prevents over-allocation in constrained environments and reduces the risk of memory pressure (&lt;a href="https://github.com/Releem/mysqlconfigurer/issues/481" rel="noopener noreferrer"&gt;Issue #481&lt;/a&gt;).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Primary Key Detection Fix&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Resolved an issue where tables could be flagged as missing a primary key where the Agent has limited schema permissions. Previously, missing column-level metadata could lead to false “no primary key” warnings. The updated logic now handles these cases correctly (&lt;a href="https://github.com/Releem/mysqlconfigurer/issues/475" rel="noopener noreferrer"&gt;Issue #475&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Updates to Releem Agent
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Expanded Initial Configuration Options&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We added support for generating an initial MySQL configuration directly from the Releem Agent. With a single command, the agent analyzes server hardware and creates a sensible baseline config for new or default MySQL installations, before workload-based tuning kicks in. You can find full details in the &lt;a href="https://docs.releem.com/configuration-tuning/initial-mysql-configuration" rel="noopener noreferrer"&gt;updated documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>mysql</category>
      <category>devops</category>
      <category>saas</category>
    </item>
    <item>
      <title>What’s New At Releem - October 2025</title>
      <dc:creator>Roman Agabekov</dc:creator>
      <pubDate>Wed, 12 Nov 2025 14:39:26 +0000</pubDate>
      <link>https://dev.to/drupaladmin/whats-new-at-releem-october-2025-4ei0</link>
      <guid>https://dev.to/drupaladmin/whats-new-at-releem-october-2025-4ei0</guid>
      <description>&lt;p&gt;Another month in the books – and it’s been a great one. Highlights include support for GCP Cloud SQL, enhanced servers overview for multi-server management, and a round of Agent improvements focused on stability and lighter performance impact.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fks74152p8ze87k3v91gk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fks74152p8ze87k3v91gk.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kicking things off, we’re excited to share that the &lt;strong&gt;TuningWizard&lt;/strong&gt; team has officially joined Releem, bringing their expertise in database optimization and performance analytics directly into what we’re building together.&lt;/p&gt;

&lt;p&gt;Led by &lt;strong&gt;Gabriel Ciciliani&lt;/strong&gt;, TuningWizard has spent the past four years perfecting SQL Query Optimization, helping users identify costly queries and improve performance with precision. This partnership traces back to an introduction by &lt;strong&gt;Peter Zaitsev&lt;/strong&gt;, founder of Percona, which sparked a collaboration that’s been growing ever since. You can read more about how the teams are merging efforts in our &lt;a href="https://releem.com/blog/tuningwizard-joins-releem" rel="noopener noreferrer"&gt;official announcement&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Community Contributions
&lt;/h2&gt;

&lt;p&gt;We're always collecting issues and feature requests on &lt;a href="https://github.com/Releem/mysqlconfigurer" rel="noopener noreferrer"&gt;our GitHub&lt;/a&gt;. Here's where you can contribute:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Issues&lt;/strong&gt; – If you encounter any problems or bugs, report them &lt;a href="https://github.com/Releem/mysqlconfigurer/issues" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Feature Requests&lt;/strong&gt; – Have an idea to make Releem even better? Share your suggestions &lt;a href="https://github.com/Releem/mysqlconfigurer/discussions" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Updates to Releem Dashboard
&lt;/h2&gt;

&lt;p&gt;We’ve added new controls to simplify &lt;strong&gt;multi-server management&lt;/strong&gt; and speed up configuration workflows across all your databases:&lt;/p&gt;

&lt;h3&gt;
  
  
  Servers Overview Bar
&lt;/h3&gt;

&lt;p&gt;Provides a quick summary of total servers and pending configurations directly on the &lt;strong&gt;Servers&lt;/strong&gt; page, improving visibility and navigation for teams managing multiple instances.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67s8un47qvg24ch5cws4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67s8un47qvg24ch5cws4.png" alt=" " width="800" height="37"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  One-Click Apply Across Servers
&lt;/h3&gt;

&lt;p&gt;You can now apply configuration recommendations to all servers simultaneously. This reduces repetitive work and saves you even more time (&lt;a href="https://github.com/Releem/mysqlconfigurer/discussions/452" rel="noopener noreferrer"&gt;Feature request #452&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvw52t7hq5bdj7wepimqb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvw52t7hq5bdj7wepimqb.png" alt=" " width="781" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Status Indicators
&lt;/h3&gt;

&lt;p&gt;Adds clear visual markers for &lt;strong&gt;Error&lt;/strong&gt; and &lt;strong&gt;Unapplied&lt;/strong&gt; configurations, helping you see what needs attention at a glance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automatic Restart Option
&lt;/h3&gt;

&lt;p&gt;A new “Restart if needed” checkbox allows Releem to safely handle restarts during configuration updates without your intervention.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updates to Releem Platform
&lt;/h2&gt;

&lt;p&gt;We’ve expanded Releem’s platform with smarter indexing and broader cloud coverage. This update helps optimize complex queries and brings full support for Google Cloud SQL alongside AWS RDS:&lt;/p&gt;

&lt;h3&gt;
  
  
  GCP Cloud SQL Support
&lt;/h3&gt;

&lt;p&gt;Adds full integration for Google Cloud’s managed MySQL and PostgreSQL databases, joining existing AWS RDS and Azure Database compatibility (&lt;a href="https://github.com/Releem/mysqlconfigurer/discussions/259" rel="noopener noreferrer"&gt;Feature request #259&lt;/a&gt;). Enterprise customers can now enjoy complete cloud provider coverage with Releem.&lt;/p&gt;

&lt;h3&gt;
  
  
  GROUP BY / ORDER BY Index Detection
&lt;/h3&gt;

&lt;p&gt;Now identifies missing indexes in queries that aggregate or sort large result sets, cutting down on processing time for reporting and analytics (&lt;a href="https://github.com/Releem/mysqlconfigurer/issues/441" rel="noopener noreferrer"&gt;Issue #441&lt;/a&gt;).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Looks at real query history to pinpoint where indexes will make the biggest difference and suggest practical fixes.&lt;/li&gt;
&lt;li&gt;In testing, these improvements have delivered 30-50% faster query performance for affected queries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Index Identification Accuracy
&lt;/h3&gt;

&lt;p&gt;Fixed an issue where optimization recommendations remained marked as “Discovered” even after indexes were created. The platform now correctly tracks index changes across multiple databases and updates the status to “Evaluating” once the fix is applied (&lt;a href="https://github.com/Releem/mysqlconfigurer/issues/474" rel="noopener noreferrer"&gt;Issue #474&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Updates to Releem Agent
&lt;/h2&gt;

&lt;p&gt;We’ve improved Releem Agent to make it more accurate, responsive, and efficient. It now handles version changes and server reporting more smoothly while using fewer resources overall.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database Upgrade Detection
&lt;/h3&gt;

&lt;p&gt;The Agent now recognizes the exact MySQL / MariaDB / Percona version when the database is upgraded and updates recommendations to match. This prevents outdated or irrelevant suggestions when variables are added, changed, or deprecated in newer releases (&lt;a href="https://github.com/Releem/mysqlconfigurer/issues/408" rel="noopener noreferrer"&gt;Issue #408&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Server Visibility Fix
&lt;/h3&gt;

&lt;p&gt;Now registers servers in the Releem Dashboard immediately after startup. Previously, some servers remained invisible for hours if the Agent existed during early metric collection (&lt;a href="https://github.com/Releem/mysqlconfigurer/issues/411" rel="noopener noreferrer"&gt;Issue #411&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimized Data Collection
&lt;/h3&gt;

&lt;p&gt;Streamlined how query examples and process data are gathered. This has lowered Agent resource consumption by 25% and sped up metric collection. Monitoring now runs with less impact on production workloads.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>mysql</category>
      <category>database</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What's New At Releem - September 2025</title>
      <dc:creator>Roman Agabekov</dc:creator>
      <pubDate>Tue, 28 Oct 2025 09:49:24 +0000</pubDate>
      <link>https://dev.to/drupaladmin/whats-new-at-releem-september-2025-1dmj</link>
      <guid>https://dev.to/drupaladmin/whats-new-at-releem-september-2025-1dmj</guid>
      <description>&lt;p&gt;September was a month of momentum. We focused on problems that frustrate every DBA: deadlocks, incomplete visibility, and cloud deployment quirks. We’ve shipped real-time deadlock monitoring, expanded the weekly reports, and fixed key issues with Releem Agent for RDS.&lt;/p&gt;

&lt;p&gt;Beyond the product, our company flag reached &lt;a href="https://www.linkedin.com/feed/update/urn:li:activity:7371856454883966976/" rel="noopener noreferrer"&gt;Kazbek Mountain&lt;/a&gt; (5,047m and one of the highest peaks in the Caucasus). It’s a small but symbolic reminder of how far we’ve come as a team and community. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyp6d30z861ugh63vtumw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyp6d30z861ugh63vtumw.png" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And while one part of the team was climbing mountains, &lt;a href="https://www.linkedin.com/posts/roman-agabekov_proud-of-the-team-my-co-founders-dmytrii-activity-7368326799723864066-Act3/" rel="noopener noreferrer"&gt;our co-founders Dmytrii Kochetov and Victor Podkopaev&lt;/a&gt; represented at Percona University Yerevan 2025. They shared insights into how LLMs can help with database performance tuning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Community Contributions
&lt;/h2&gt;

&lt;p&gt;We're always collecting issues and feature requests on &lt;a href="https://github.com/Releem/mysqlconfigurer" rel="noopener noreferrer"&gt;our GitHub&lt;/a&gt;. Here's where you can contribute:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Issues&lt;/strong&gt; – If you encounter any problems or bugs, report them &lt;a href="https://github.com/Releem/mysqlconfigurer/issues" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature Requests&lt;/strong&gt; – Have an idea to make Releem even better? Share your suggestions &lt;a href="https://github.com/Releem/mysqlconfigurer/discussions" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Updates to Releem Dashboard
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Deadlock Monitoring
&lt;/h3&gt;

&lt;p&gt;After many requests, real-time MySQL and MariaDB deadlock detection has landed (&lt;a href="https://github.com/Releem/mysqlconfigurer/discussions/293" rel="noopener noreferrer"&gt;Issue #293&lt;/a&gt;). No more hunting through logs. You’ll now see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instant alerts when a deadlock occurs&lt;/li&gt;
&lt;li&gt;A detailed breakdown of conflicting transactions&lt;/li&gt;
&lt;li&gt;Actionable recommendations to prevent recurrence&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://releem.com/blog/mysql-deadlock-detection" rel="noopener noreferrer"&gt;Read our full deep-dive on deadlock detection to learn more.&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsgcauz2hcm3skmo6p5zv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsgcauz2hcm3skmo6p5zv.png" alt=" " width="800" height="713"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0fs6hiofk7sml4a8dz59.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0fs6hiofk7sml4a8dz59.png" alt=" " width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  New Weekly Reports
&lt;/h3&gt;

&lt;p&gt;Weekly reports now give a richer snapshot of your server health including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expanded Health Checks – System, MyISAM/InnoDB, Memory, Queries/Logs&lt;/li&gt;
&lt;li&gt;A new Security Check summary with severity levels&lt;/li&gt;
&lt;li&gt;Cleaner formatting for quick scanning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F874chcumfjv0y5mp7uif.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F874chcumfjv0y5mp7uif.png" alt=" " width="800" height="807"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Updates to Releem Agent
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Resolved AWS Security Hub Alerts
&lt;/h3&gt;

&lt;p&gt;Releem Agent was previously being flagged by AWS Security Hub. The new update corrects those triggers (&lt;a href="https://github.com/releem/mysqlconfigurer/issues/415" rel="noopener noreferrer"&gt;Issue #415&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Improved EC2 Deployment Documentation
&lt;/h3&gt;

&lt;p&gt;We’ve added guidance for monitoring multiple RDS instances from one EC2 instance. This reduces setup overhead and cuts Fargate resource costs. Read the documentation &lt;a href="https://docs.releem.com/releem-agent/installation-guides/cloud-managed-aws-rds-automatic-installation" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stabilized Setup Process
&lt;/h3&gt;

&lt;p&gt;Fixed an issue that caused the Agent to restart MySQL/MariaDB unnecessarily during initial installation. It was annoying everyone and we’re glad it’s no longer a problem (&lt;a href="https://github.com/releem/mysqlconfigurer/issues/413" rel="noopener noreferrer"&gt;Issue #413&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  News You Might Have Missed
&lt;/h2&gt;

&lt;p&gt;Laravel News recently covered a Releem study on how MySQL’s default settings can drag down performance for Laravel apps. It’s a great read if you want to learn more about what’s hiding behind “out-of-the-box” configurations. &lt;a href="https://laravel-news.com/the-hidden-cost-of-mysql-defaults-in-laravel-apps" rel="noopener noreferrer"&gt;The Hidden Cost of MySQL Defaults in Laravel Apps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0c3uug1fllfjno7fc6nj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0c3uug1fllfjno7fc6nj.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>mysql</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
    <item>
      <title>MySQL Deadlock Detection: How to Find and Fix Transaction Conflicts</title>
      <dc:creator>Roman Agabekov</dc:creator>
      <pubDate>Mon, 13 Oct 2025 15:34:17 +0000</pubDate>
      <link>https://dev.to/drupaladmin/mysql-deadlock-detection-how-to-find-and-fix-transaction-conflicts-5159</link>
      <guid>https://dev.to/drupaladmin/mysql-deadlock-detection-how-to-find-and-fix-transaction-conflicts-5159</guid>
      <description>&lt;p&gt;Understand, detect, and resolve deadlocks in your database with Releem’s automated monitoring and alerting.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a deadlock?
&lt;/h2&gt;

&lt;p&gt;A deadlock is a situation where two or more transactions are each waiting for the other to release a lock. Because neither transaction can proceed, they become stuck. MySQL has a built-in mechanism to detect deadlocks when the &lt;strong&gt;innodb_deadlock_detect&lt;/strong&gt; setting is enabled, which is the default in most setups. When MySQL detects a deadlock, it automatically rolls back one of the transactions to break the loop.&lt;/p&gt;

&lt;p&gt;Deadlocks are not always a sign of a bug. They can occur in any system with high concurrency or complex workflows involving multiple statements. However, when deadlocks happen repeatedly or appear in the same workflow, they often signal a deeper issue in how transactions are structured, how indexes are applied, or how application logic interacts with the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to monitor deadlocks manually
&lt;/h2&gt;

&lt;p&gt;If you want to manually check for a deadlock on your MySQL server, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SHOW ENGINE INNODB STATUS\G
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for the section labeled &lt;strong&gt;LATEST DETECTED DEADLOCK&lt;/strong&gt;. Examine the output for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;------------------------
LATEST DETECTED DEADLOCK
------------------------
2025-09-19 21:42:10 0x7f2cd67fa700
*** (1) TRANSACTION:
TRANSACTION 24692, ACTIVE 3 sec starting index read
mysql tables in use 2, locked 2
LOCK WAIT 5 lock struct(s), heap size 1128, 3 row lock(s)
MySQL thread id 127, OS thread handle 139832472479488, query id 44118 localhost appuser updating
UPDATE order_items 
  SET qty = qty + 1 
  WHERE order_id = 500 AND id = 1001
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 121 page no 145 n bits 72 index `PRIMARY` of table `shop`.`orders` trx id 24692 
lock_mode X locks rec but not gap waiting
Record lock, heap no 7 PHYSICAL RECORD: n_fields 6; compact format; info bits 0
 0: len 4; id=500
 1: ... (hidden/internal fields omitted)

*** (2) TRANSACTION:
TRANSACTION 24691, ACTIVE 4 sec updating or deleting
4 lock struct(s), heap size 1136, 4 row lock(s)
MySQL thread id 123, OS thread handle 139832488126208, query id 44116 localhost appuser updating
UPDATE orders 
  SET status = 'processed' 
  WHERE id = 500
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 121 page no 145 n bits 72 index `PRIMARY` of table `shop`.`orders` trx id 24691 
lock_mode X locks rec but not gap
Record lock, heap no 7 PHYSICAL RECORD: n_fields 6; compact format; info bits 0
 0: len 4; id=500
 1: ... (hidden/internal fields omitted)
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 122 page no 88 n bits 80 index `fk_order_items_order_id` of table `shop`.`order_items` trx id 24691 
lock_mode X locks rec but not gap waiting
Record lock, heap no 12 PHYSICAL RECORD: n_fields 6; compact format; info bits 0
 0: len 4; order_id=500
 1: ... (hidden/internal fields omitted)

*** WE ROLL BACK TRANSACTION (1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Transaction IDs and SQL queries&lt;/li&gt;
&lt;li&gt;Lock types and what each transaction was waiting for&lt;/li&gt;
&lt;li&gt;Table names and indexes involved&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This manual approach works, but it’s reactive, time-consuming, and only shows the latest deadlock. You also won’t get historical data unless you’re already logging it elsewhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deadlock types and how to fix them
&lt;/h2&gt;

&lt;p&gt;Deadlocks can be grouped by the type of operation or lock pattern that caused them. Different deadlocks require different fixes. Recognizing the type helps you identify the underlying cause and choose the right fix. Here are the most common categories:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Update-Update deadlock
&lt;/h3&gt;

&lt;p&gt;Occurs when two transactions update the same rows but in a different order. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transaction A updates &lt;strong&gt;orders&lt;/strong&gt;, then &lt;strong&gt;order_items&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Transaction B updates &lt;strong&gt;order_items&lt;/strong&gt;, then &lt;strong&gt;orders&lt;/strong&gt;.
Since both are waiting on each other’s locks, the transactions are stuck.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  How to fix:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Access and update rows in the same order in every transaction.&lt;/li&gt;
&lt;li&gt;Standardize your transaction logic across your application.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  2. Select-for-Update deadlock
&lt;/h3&gt;

&lt;p&gt;This happens when one transaction uses &lt;strong&gt;SELECT ... FOR UPDATE&lt;/strong&gt; to lock rows that another transaction is trying to update or delete. This often occurs in job queues or task schedulers that select rows for processing while other workers modify or remove the same data.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to fix:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Only use &lt;strong&gt;FOR UPDATE&lt;/strong&gt; when necessary.&lt;/li&gt;
&lt;li&gt;Consider &lt;strong&gt;LOCK IN SHARE MODE&lt;/strong&gt; if full write-locks aren’t needed.&lt;/li&gt;
&lt;li&gt;Separate row selection and modification into different steps when possible.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  3. Insert Auto Increment deadlock
&lt;/h3&gt;

&lt;p&gt;InnoDB places a special lock (called the auto-inc lock) on the end of the index when inserting into a table with an &lt;strong&gt;AUTO_INCREMENT&lt;/strong&gt; column. If multiple transactions insert rows and then touch related tables, they can block each other in unpredictable ways.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to fix:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Move insert operations to the end of your transaction.&lt;/li&gt;
&lt;li&gt;Use bulk inserts to reduce contention.&lt;/li&gt;
&lt;li&gt;Avoid mixing inserts with updates on related tables in the same transaction.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  4. Gap lock deadlock
&lt;/h3&gt;

&lt;p&gt;InnoDB uses gap locks to lock ranges of index values for &lt;strong&gt;SELECT ... FOR UPDATE&lt;/strong&gt;, &lt;strong&gt;DELETE&lt;/strong&gt;, or &lt;strong&gt;UPDATE&lt;/strong&gt; queries that use inequality or range filters. These range locks can block other inserts or updates that try to work within the same range. This is common with pagination, uniqueness checks, or complex filters.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to fix:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Use equality comparisons instead of ranges if possible.&lt;/li&gt;
&lt;li&gt;Reduce the locked range by adding filters or more specific indexes.&lt;/li&gt;
&lt;li&gt;Consider &lt;strong&gt;READ COMMITTED&lt;/strong&gt; isolation level to reduce the range lock scope.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  5. Insert Intention deadlock
&lt;/h3&gt;

&lt;p&gt;An insert intention lock is a type of gap lock set by &lt;strong&gt;INSERT&lt;/strong&gt; operations prior to row insertion. This lock signals the intent to insert in such a way that multiple transactions inserting into the same index gap need not wait for each other if they are not inserting at the same position within the gap.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to fix:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Use &lt;strong&gt;INSERT IGNORE&lt;/strong&gt;, &lt;strong&gt;REPLACE&lt;/strong&gt;, or &lt;strong&gt;INSERT ... ON DUPLICATE KEY UPDATE&lt;/strong&gt; if the inserted row may already exist.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;SELECT ... FOR UPDATE&lt;/strong&gt; beforehand to lock the row and avoid conflicts.&lt;/li&gt;
&lt;li&gt;Reduce the locked range by adding filters or more specific indexes.&lt;/li&gt;
&lt;li&gt;Consider &lt;strong&gt;READ COMMITTED&lt;/strong&gt; isolation level to reduce the range lock scope.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  6. Insert same PK deadlock
&lt;/h3&gt;

&lt;p&gt;Plain &lt;code&gt;INSERT&lt;/code&gt; is not idempotent when multiple workers try to write the same key at once . Two writers collide on the same PRIMARY key and deadlock.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to fix:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Change the statement to one of these patterns so the second writer doesn’t need to “win” a brand-new insert: &lt;strong&gt;INSERT IGNORE&lt;/strong&gt;, &lt;strong&gt;REPLACE&lt;/strong&gt;, or &lt;strong&gt;INSERT ... ON DUPLICATE KEY UPDATE&lt;/strong&gt; if the inserted row may already exist. &lt;/li&gt;
&lt;li&gt;Reduce the locked range by adding filters or more specific indexes.&lt;/li&gt;
&lt;li&gt;Consider &lt;strong&gt;READ COMMITTED&lt;/strong&gt; isolation level to reduce the range lock scope.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  7. Foreign key deadlock
&lt;/h3&gt;

&lt;p&gt;This affects operations where one transaction deletes or updates a parent row, and another interacts with the child table. If referential integrity checks are triggered mid-transaction, InnoDB may require shared or exclusive locks on multiple tables, resulting in a deadlock.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to fix:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Always delete or update related rows in a consistent parent-first or child-first order.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;ON DELETE CASCADE&lt;/strong&gt; or &lt;strong&gt;ON UPDATE CASCADE&lt;/strong&gt; appropriately.&lt;/li&gt;
&lt;li&gt;Minimize transactional overlap on dependent tables.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  8. Long transaction deadlock
&lt;/h3&gt;

&lt;p&gt;A transaction that touches many rows or tables and holds locks for a long time can easily deadlock with smaller, faster transactions. This isn’t necessarily a logic bug, but sometimes it simply happens due to bad timing under high load.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to fix:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Break large transactions into smaller chunks.&lt;/li&gt;
&lt;li&gt;Commit frequently when possible.&lt;/li&gt;
&lt;li&gt;Avoid idle sessions within a transaction.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  9. Lock escalation deadlock
&lt;/h3&gt;

&lt;p&gt;Though relatively rare in MySQL, some workloads cause escalation-like behavior when multiple row-level locks start conflicting across transactions in unexpected patterns. These usually surface in high-concurrency systems with heavy writes and insufficient indexing.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to fix:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Add indexes to reduce full scans and write lock contention.&lt;/li&gt;
&lt;li&gt;Analyze patterns in locking and restructure queries to reduce overlap.&lt;/li&gt;
&lt;li&gt;Consider queuing or scheduling batch operations to run sequentially.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How Releem helps with deadlock monitoring
&lt;/h2&gt;

&lt;p&gt;Releem's Deadlock Monitoring Service continuously checks for deadlocks by analyzing MySQL's internal reports. It captures complete information about every detected deadlock and makes that information accessible and actionable.&lt;/p&gt;

&lt;p&gt;Here’s what Releem’s deadlock monitoring does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatically detects all deadlocks in real time using &lt;strong&gt;SHOW ENGINE INNODB STATUS&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Captures all relevant information, including SQL statements, table names, lock types, and indexes&lt;/li&gt;
&lt;li&gt;Sends notifications through your preferred channels&lt;/li&gt;
&lt;li&gt;Stores the full history of deadlocks, accessible through the Releem web interface.&lt;/li&gt;
&lt;li&gt;Provides practical guidance to help you understand the lock type and fix the root cause&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What you’ll see in a deadlock alert
&lt;/h3&gt;

&lt;p&gt;When Releem detects a deadlock, it sends an alert that includes everything you need to start investigating. This includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The exact time the deadlock occurred&lt;/li&gt;
&lt;li&gt;The full SQL statement for the transaction that was rolled back&lt;/li&gt;
&lt;li&gt;The SQL statement that blocked it&lt;/li&gt;
&lt;li&gt;The table names involved&lt;/li&gt;
&lt;li&gt;The type of locks that were in conflict&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fra0gmcdctz4t08dh2t0n.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fra0gmcdctz4t08dh2t0n.jpg" alt=" " width="800" height="713"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to respond to a Releem deadlock notification
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Review the alert
&lt;/h3&gt;

&lt;p&gt;Start by examining the SQL statements in the alert. Look at the tables involved and the type of lock that caused the block. This gives you an immediate view of what was happening in the database at the time of the deadlock.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Find the code
&lt;/h3&gt;

&lt;p&gt;Use the query text and table names to trace the transaction back to the relevant part of your codebase. If the query comes from an ORM, enable SQL logging to get the original code. Most ORMs provide a way to log generated SQL, such as enabling echo=True in SQLAlchemy or enabling query logs in Laravel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Apply Fix
&lt;/h3&gt;

&lt;p&gt;Once you’ve identified the query and type of deadlock, apply the corresponding fix based on the lock pattern involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to prevent deadlocks in the future
&lt;/h2&gt;

&lt;p&gt;Deadlocks aren’t always avoidable, especially in high-concurrency environments. But you can reduce how often they occur and how disruptive they are by structuring your transactions and queries more deliberately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access tables and rows in a consistent order&lt;/strong&gt;: Inconsistent ordering is one of the most common causes of deadlocks. Always access tables and rows in the &lt;strong&gt;same order&lt;/strong&gt; across all parts of your application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use proper indexes on frequently updated or filtered columns&lt;/strong&gt;: When queries scan too many rows due to missing indexes, they hold locks longer than necessary. This increases the likelihood of conflicting transactions. Add indexes to support any columns used in joins, updates, deletes, and &lt;strong&gt;SELECT ... FOR UPDATE&lt;/strong&gt; queries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Keep transactions short and commit as early as possible&lt;/strong&gt;: Long-running transactions hold locks open and increase contention. Avoid starting a transaction and then performing multiple slow operations or leaving the session idle. If changes are unrelated, split them into separate transactions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid combining SELECT FOR UPDATE and INSERT statements in the same transaction when possible&lt;/strong&gt;: Locking existing rows and writing new ones can create complex lock dependencies, especially in tables with AUTO_INCREMENT values or triggers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consider adjusting your isolation level&lt;/strong&gt;: The default isolation level in MySQL, &lt;strong&gt;REPEATABLE READ&lt;/strong&gt;, holds more locks than &lt;strong&gt;READ COMMITTED&lt;/strong&gt;. If you don’t need consistent snapshots for the duration of a transaction, switching to &lt;strong&gt;READ COMMITTED&lt;/strong&gt; can help reduce lock contention.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;As a last resort, serialize critical sections with explicit table locking&lt;/strong&gt;: If nothing else helps, you can use &lt;strong&gt;LOCK TABLES&lt;/strong&gt; to manually control access to entire tables. This approach guarantees exclusive access, but it comes with tradeoffs. You must start with &lt;strong&gt;SET autocommit = 0&lt;/strong&gt;, lock the tables, perform the operations, then commit and release the locks. It should only be used in tightly scoped, low-volume parts of the application where deadlocks are unavoidable through normal means.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Releem makes deadlocks easier to deal with
&lt;/h2&gt;

&lt;p&gt;Deadlocks are a natural part of working with transactional databases, but that doesn’t mean you have to treat them as a black box. With Releem’s Deadlock Detection, you get automated early warnings, full context, and clear next steps. It reduces the time you spend diagnosing blocking issues and gives you visibility into the health of your transaction patterns.&lt;/p&gt;

&lt;p&gt;If you're ready to stop chasing deadlocks after the fact, turn on Deadlock Detection in your Releem dashboard. It takes care of the tracking so you can focus on fixing the real issues.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>database</category>
      <category>webdev</category>
      <category>mysql</category>
    </item>
    <item>
      <title>ChatGPT Alternative for SQL Query Optimization</title>
      <dc:creator>Roman Agabekov</dc:creator>
      <pubDate>Mon, 13 Oct 2025 10:53:47 +0000</pubDate>
      <link>https://dev.to/drupaladmin/chatgpt-alternative-for-sql-query-optimization-2mbi</link>
      <guid>https://dev.to/drupaladmin/chatgpt-alternative-for-sql-query-optimization-2mbi</guid>
      <description>&lt;p&gt;Working with SQL query optimizers powered by LLMs has its ups and downs. I’ve noticed that even with tools like ChatGPT or Claude, the process can feel awkward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Write a prompt → Paste the query → Wait → Refine prompt → Repeat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This cycle is fine once or twice, but quickly becomes tedious — especially for long or complex queries.&lt;/p&gt;

&lt;p&gt;So I built a tool that removes prompt engineering from the equation and focuses purely on helping you analyze and optimize SQL queries.&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Paste your SQL query
2. Select your database (PostgreSQL, MySQL, SQL Server, etc.)
3. Click “Analyze”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The screenshot:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7qn0etf2c8822wi5fn0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7qn0etf2c8822wi5fn0.png" alt="SQLito Paste Query" width="800" height="699"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  You’ll Get
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- ✅ A list of suggestions with brief reasoning
- 🔄 A rewritten (optimized) version of your query
- 🎯 A confidence tag for each recommendation (High / Medium / Low)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The screenshot:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9wf0mk78f3i58m85m0qq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9wf0mk78f3i58m85m0qq.png" alt="SQLito Analysis Results" width="800" height="888"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Want deeper insights?
&lt;/h3&gt;

&lt;p&gt;You can optionally add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EXPLAIN plans&lt;/li&gt;
&lt;li&gt;Schema&lt;/li&gt;
&lt;li&gt;Indexes&lt;/li&gt;
&lt;li&gt;Table stats&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tool will use this additional context to refine its suggestions and increase recommendation confidence.&lt;/p&gt;

&lt;p&gt;The screenshot of this step:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsj4n50z8cvln7k8d205l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsj4n50z8cvln7k8d205l.png" alt="SQLito Enhanced Analysis" width="800" height="965"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Deeper Technical Rationale
&lt;/h3&gt;

&lt;p&gt;The tool supports two levels of analysis:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Standard Analysis (available to all users)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you paste a SQL query and click “Analyze”, the system runs a one-step evaluation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parses the query syntax and structure.&lt;/li&gt;
&lt;li&gt;Identifies common inefficiencies.&lt;/li&gt;
&lt;li&gt;Generates a list of suggestions based on known performance patterns and best practices.&lt;/li&gt;
&lt;li&gt;Provides an optimized version of the query.&lt;/li&gt;
&lt;li&gt;Assigns confidence tags based on available context.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This mode is fast and lightweight, ideal for quick feedback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Deep Analysis (available to registered users)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Deep Analysis follows a multi-stage reasoning process using an internal AI agent:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Hypothesis Generation&lt;br&gt;
The model builds multiple performance-related hypotheses based on the SQL query and any provided context — including schema, EXPLAIN plans, table/index stats, constraints, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validation and Filtering&lt;br&gt;
It then self-evaluates each recommendation. Weak or irrelevant suggestions are filtered out. This step prevents common LLM hallucinations or overly generic advice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optimized Query Generation&lt;br&gt;
A refined, rewritten query is generated — informed by the validated insights and context.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach improves both precision and reliability of recommendations, especially for complex queries involving joins, CTEs, subqueries, or large tables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Who is this for?
&lt;/h3&gt;

&lt;p&gt;This tool isn’t trying to replace profilers or DB-specific advisors. It’s designed for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developers who want quick feedback on queries&lt;/li&gt;
&lt;li&gt;Teams who want to share and discuss queries&lt;/li&gt;
&lt;li&gt;People learning SQL who want to understand improvements&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Give It a Shot
&lt;/h3&gt;

&lt;p&gt;You can try the tool here: &lt;a href="https://sqli.to" rel="noopener noreferrer"&gt;https://sqli.to&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’d love to hear your thoughts❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>sql</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
