<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:content="http://purl.org/rss/1.0/modules/content/">

<channel>
  <title>Planet MySQL</title>
  <link>https://planet.mysql.com</link>
  <pubDate>Tue, 26 May 2026 06:41:18 +0000</pubDate>
  <language>en</language>
  <description>Planet MySQL - https://planet.mysql.com</description>

  <item>
    <title>MySQL HeatWave Database Housekeeping Best Practices</title>
    <guid isPermaLink="false">1118efb225c4b1898595283883ca0873</guid>
    <link>https://blogs.oracle.com/mysql/mysql-heatwave-database-housekeeping-best-practices</link>
    <description>As MySQL HeatWave environments continue to grow, many organizations prioritize scaling compute and storage resources while overlooking a critical area: database housekeeping. Inadequate maintenance practices can result in excessive storage consumption, longer backup and recovery times, replication lag, degraded query performance, and increased operational costs. This blog highlights key database hygiene and optimization strategies for […]</description>
    <pubDate>Sat, 23 May 2026 06:21:00 +0000</pubDate>
    <dc:creator>Oracle MySQL Group</dc:creator>
    <category>MySQL Basics/How-To</category>
    <category>MySQL HeatWave</category>
  </item>

  <item>
    <title>MySQL 9.7.0 PGO Benchmark Analysis</title>
    <guid isPermaLink="false">https://www.percona.com/?p=47781</guid>
    <link>https://www.percona.com/blog/mysql-9-7-0-pgo-benchmark-analysis/</link>
    <description>Overview
Servers Tested:

MySQL 9.7.0 (PGO-enabled build released by Oracle)
MySQL 9.7.0 Non-PGO (built without Profile-Guided Optimization — see BUILD.md)

Tier Configurations:

Tier 2G: 2GB InnoDB buffer pool
Tier 12G: 12GB InnoDB buffer pool
Tier 32G: 32GB InnoDB buffer pool

 
View Results
 Interactive Reports
The benchmark reports are available as interactive HTML pages at:
https://percona-lab-results.github.io/2026-pgo/index.html
Performance Graphs
Tier 2G (2GB Buffer Pool):

Tier 12G (12GB Buffer Pool):
 
Tier 32G (32GB Buffer Pool):
 
 
 
Key Findings

Performance Impact of PGO
MySQL 9.7.0 with Profile-Guided Optimization (PGO) demonstrates measurable performance improvements over the non-PGO build:

Overall Performance Summary:

Average improvement: 6.5% across all configurations
Peak improvement: 14.3% (Tier 32G, 1 thread), gradually tapering to 10.3% at 512 threads as concurrency increases
Performance gains range from 0.5% to 14.3% in most scenarios
Minor regression (-3.1% at Tier 12G, 128 threads)


Performance by Buffer Pool Size:

Tier 2G (2GB buffer pool): Average improvement of 3.0%

– Best gains at 4 threads (5.5% improvement)
– Gains range from 0.5% to 5.5% across all thread counts
– Modest improvements with no regressions

Tier 12G (12GB buffer pool): Average improvement of 4.1%

– Best gains at 4 threads (8.6% improvement)
– Strong gains at low concurrency (1-4 threads: 7.3%-8.6%)
– Minor regression at 128 threads (-3.1%), neutral at 512 threads (-0.0%)

Tier 32G (32GB buffer pool): Average improvement of 12.2%

– Consistently strong gains across all thread counts (10.3% to 14.3%)
– Peak performance at lowest concurrency (1 thread: 14.3%)
– Maintains 11-12% improvement even at highest concurrency (128-512 threads)

Key Observations:

PGO provides the most significant benefits with larger buffer pools (32GB tier shows 12.2% average improvement)
Largest buffer pool configuration benefits from PGO across all concurrency levels with no regressions
Low to moderate concurrency (1-32 threads) shows best PGO gains across all tiers
Smaller buffer pools (2GB, 12GB) show more modest improvements and occasional regressions at very high thread counts
The performance improvements demonstrate PGO’s effectiveness in optimizing hot code paths, particularly when memory resources are abundant


InnoDB Metrics Analysis
Deep analysis of InnoDB metrics reveals the source of PGO’s performance improvements:

Root Cause: CPU-Level Optimizations

PGO improvements are NOT from I/O optimization, caching, or lock reduction
Buffer pool hit ratios remain virtually identical between PGO and non-PGO builds
Lock contention is minimal in both builds
All I/O metrics scale proportionally with increased throughput


What PGO Actually Optimizes:

✓ Better instruction cache utilization
✓ Improved branch prediction in hot code paths
✓ Optimized function inlining
✓ More efficient CPU instruction ordering

The metrics confirm that PGO’s 6.5% average improvement comes entirely from making the CPU more efficient at executing MySQL’s hot code paths, allowing it to process more transactions per second with the same hardware resources.
 
What is PGO?
Profile-Guided Optimization (PGO) is a compiler optimization technique that uses runtime profiling data to guide code optimization. The compiler first instruments the code, collects execution profiles during typical workload runs, and then recompiles the code with optimizations targeted at the most frequently executed code paths.

Benefits of PGO:

Improved branch prediction
Better instruction cache utilization
Optimized function inlining
Reduced code bloat
Better register allocation

 
Benchmark Methodology

Workload

Tool: Sysbench OLTP Read/Write benchmark
Tables: 20 tables
Table Size: 5,000,000 rows per table
Thread Counts: 1, 4, 16, 32, 64, 128, 256, 512


Configuration

Warmup:

– Read-only: 180 seconds
– Read-write: 600 seconds

Measurement Duration: 900 seconds (15 minutes) per thread count
Runs: Single run per configuration


System Metrics Collected

InnoDB storage engine metrics
MySQL status variables
MySQL system variables
System I/O statistics (iostat)
Virtual memory statistics (vmstat)
CPU statistics (mpstat)
System statistics (dstat)

 
Appendix
For Repository structure, Build steps and Technical details go to https://github.com/Percona-Lab-results/2026-pgo/blob/main/README.md#report-categories
 
The post MySQL 9.7.0 PGO Benchmark Analysis appeared first on Percona.</description>
    <content:encoded><![CDATA[<h2><b>Overview</b></h2>
<p><b>Servers Tested:</b></p>
<ul>
<li aria-level="1"><b>MySQL 9.7.0</b><span> (PGO-enabled build released by Oracle)</span></li>
<li aria-level="1"><b>MySQL 9.7.0 Non-PGO</b><span> (built without Profile-Guided Optimization — see </span><a href="https://github.com/Percona-Lab-results/2026-pgo/blob/main/BUILD.md"><span>BUILD.md</span></a><span>)</span></li>
</ul>
<p><b>Tier Configurations:</b></p>
<ul>
<li aria-level="1"><span>Tier 2G: 2GB InnoDB buffer pool</span></li>
<li aria-level="1"><span>Tier 12G: 12GB InnoDB buffer pool</span></li>
<li aria-level="1"><span>Tier 32G: 32GB InnoDB buffer pool</span></li>
</ul>
<p> </p>
<h2><b>View Results</b></h2>
<p><span><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4ca.png" alt="📊" class="wp-smiley"> </span><a href="https://percona-lab-results.github.io/2026-pgo/index.html"><b>Interactive Reports</b></a></p>
<p><span>The benchmark reports are available as interactive HTML pages at:</span></p>
<p><a href="https://percona-lab-results.github.io/2026-pgo/index.html" target="_blank" rel="noopener"><span>https://percona-lab-results.github.io/2026-pgo/index.html</span></a></p>
<h3><b>Performance Graphs</b></h3>
<p><b>Tier 2G (2GB Buffer Pool):</b></p>
<p><b><a href="https://percona-lab-results.github.io/2026-pgo/sysbench_ps_mysql_average.html"><img fetchpriority="high" decoding="async" class="alignnone wp-image-47783 size-large" src="https://www.percona.com/wp-content/uploads/2026/05/pgo_2G-1024x495.png" alt="" width="1024" height="495" srcset="https://www.percona.com/wp-content/uploads/2026/05/pgo_2G-1024x495.png 1024w, https://www.percona.com/wp-content/uploads/2026/05/pgo_2G-300x145.png 300w, https://www.percona.com/wp-content/uploads/2026/05/pgo_2G-768x371.png 768w, https://www.percona.com/wp-content/uploads/2026/05/pgo_2G.png 1296w" sizes="(max-width: 1024px) 100vw, 1024px"></a></b></p>
<p><b>Tier 12G (12GB Buffer Pool):</b></p>
<p><b> <a href="https://percona-lab-results.github.io/2026-pgo/sysbench_ps_mysql_average.html"><img decoding="async" class="alignnone wp-image-47784 size-large" src="https://www.percona.com/wp-content/uploads/2026/05/pgo_12G-1024x494.png" alt="" width="1024" height="494" srcset="https://www.percona.com/wp-content/uploads/2026/05/pgo_12G-1024x494.png 1024w, https://www.percona.com/wp-content/uploads/2026/05/pgo_12G-300x145.png 300w, https://www.percona.com/wp-content/uploads/2026/05/pgo_12G-768x371.png 768w, https://www.percona.com/wp-content/uploads/2026/05/pgo_12G.png 1297w" sizes="(max-width: 1024px) 100vw, 1024px"></a></b></p>
<p><b>Tier 32G (32GB Buffer Pool):</b></p>
<p> </p>
<p><b> <a href="https://percona-lab-results.github.io/2026-pgo/sysbench_ps_mysql_average.html"><img decoding="async" class="alignnone wp-image-47785 size-large" src="https://www.percona.com/wp-content/uploads/2026/05/pgo_32G-1024x494.png" alt="" width="1024" height="494" srcset="https://www.percona.com/wp-content/uploads/2026/05/pgo_32G-1024x494.png 1024w, https://www.percona.com/wp-content/uploads/2026/05/pgo_32G-300x145.png 300w, https://www.percona.com/wp-content/uploads/2026/05/pgo_32G-768x370.png 768w, https://www.percona.com/wp-content/uploads/2026/05/pgo_32G.png 1296w" sizes="(max-width: 1024px) 100vw, 1024px"></a></b></p>
<p> </p>
<h2><b>Key Findings</b></h2>
<h3><b><br>
Performance Impact of PGO</b></h3>
<p><span>MySQL 9.7.0 with Profile-Guided Optimization (PGO) demonstrates measurable performance improvements over the non-PGO build:</span></p>
<p><b><br>
Overall Performance Summary:</b></p>
<ul>
<li aria-level="1"><b>Average improvement: 6.5%</b><span> across all configurations</span></li>
<li aria-level="1"><b>Peak improvement: 14.3%</b><span> (Tier 32G, 1 thread), gradually tapering to 10.3% at 512 threads as concurrency increases</span></li>
<li aria-level="1"><span>Performance gains range from 0.5% to 14.3% in most scenarios</span></li>
<li aria-level="1"><span>Minor regression (-3.1% at Tier 12G, 128 threads)</span></li>
</ul>
<p><b><br>
Performance by Buffer Pool Size:</b></p>
<ul>
<li aria-level="1"><b>Tier 2G</b><span> (2GB buffer pool): Average improvement of </span><b>3.0%</b></li>
</ul>
<p><span>– Best gains at 4 threads (5.5% improvement)</span></p>
<p><span>– Gains range from 0.5% to 5.5% across all thread counts</span></p>
<p><span>– Modest improvements with no regressions</span></p>
<ul>
<li aria-level="1"><b>Tier 12G</b><span> (12GB buffer pool): Average improvement of </span><b>4.1%</b></li>
</ul>
<p><span>– Best gains at 4 threads (8.6% improvement)</span></p>
<p><span>– Strong gains at low concurrency (1-4 threads: 7.3%-8.6%)</span></p>
<p><span>– Minor regression at 128 threads (-3.1%), neutral at 512 threads (-0.0%)</span></p>
<ul>
<li aria-level="1"><b>Tier 32G</b><span> (32GB buffer pool): Average improvement of </span><b>12.2%</b></li>
</ul>
<p><span>– Consistently strong gains across all thread counts (10.3% to 14.3%)</span></p>
<p><span>– Peak performance at lowest concurrency (1 thread: 14.3%)</span></p>
<p><span>– Maintains 11-12% improvement even at highest concurrency (128-512 threads)</span></p>
<p><b><br>
Key Observations:</b></p>
<ul>
<li aria-level="1"><span>PGO provides the most significant benefits with larger buffer pools (32GB tier shows 12.2% average improvement)</span></li>
<li aria-level="1"><span>Largest buffer pool configuration benefits from PGO across all concurrency levels with no regressions</span></li>
<li aria-level="1"><span>Low to moderate concurrency (1-32 threads) shows best PGO gains across all tiers</span></li>
<li aria-level="1"><span>Smaller buffer pools (2GB, 12GB) show more modest improvements and occasional regressions at very high thread counts</span></li>
<li aria-level="1"><span>The performance improvements demonstrate PGO’s effectiveness in optimizing hot code paths, particularly when memory resources are abundant</span></li>
</ul>
<h3><b><br>
InnoDB Metrics Analysis</b></h3>
<p><span>Deep analysis of InnoDB metrics reveals the source of PGO’s performance improvements:</span></p>
<p><b><br>
Root Cause: CPU-Level Optimizations</b></p>
<ul>
<li aria-level="1"><span>PGO improvements are </span><b>NOT</b><span> from I/O optimization, caching, or lock reduction</span></li>
<li aria-level="1"><span>Buffer pool hit ratios remain virtually identical between PGO and non-PGO builds</span></li>
<li aria-level="1"><span>Lock contention is minimal in both builds</span></li>
<li aria-level="1"><span>All I/O metrics scale proportionally with increased throughput</span></li>
</ul>
<p><b><br>
What PGO Actually Optimizes:</b></p>
<ul>
<li aria-level="1"><span>✓ Better instruction cache utilization</span></li>
<li aria-level="1"><span>✓ Improved branch prediction in hot code paths</span></li>
<li aria-level="1"><span>✓ Optimized function inlining</span></li>
<li aria-level="1"><span>✓ More efficient CPU instruction ordering</span></li>
</ul>
<p><span>The metrics confirm that PGO’s 6.5% average improvement comes entirely from making the CPU more efficient at executing MySQL’s hot code paths, allowing it to process more transactions per second with the same hardware resources.</span></p>
<p> </p>
<h2><b>What is PGO?</b></h2>
<p><span>Profile-Guided Optimization (PGO) is a compiler optimization technique that uses runtime profiling data to guide code optimization. The compiler first instruments the code, collects execution profiles during typical workload runs, and then recompiles the code with optimizations targeted at the most frequently executed code paths.</span></p>
<p><b><br>
Benefits of PGO:</b></p>
<ul>
<li aria-level="1"><span>Improved branch prediction</span></li>
<li aria-level="1"><span>Better instruction cache utilization</span></li>
<li aria-level="1"><span>Optimized function inlining</span></li>
<li aria-level="1"><span>Reduced code bloat</span></li>
<li aria-level="1"><span>Better register allocation</span></li>
</ul>
<p> </p>
<h2><b>Benchmark Methodology</b></h2>
<h3><b><br>
Workload</b></h3>
<ul>
<li aria-level="1"><b>Tool</b><span>: Sysbench OLTP Read/Write benchmark</span></li>
<li aria-level="1"><b>Tables</b><span>: 20 tables</span></li>
<li aria-level="1"><b>Table Size</b><span>: 5,000,000 rows per table</span></li>
<li aria-level="1"><b>Thread Counts</b><span>: 1, 4, 16, 32, 64, 128, 256, 512</span></li>
</ul>
<h3><b><br>
Configuration</b></h3>
<ul>
<li aria-level="1"><b>Warmup</b><span>:</span></li>
</ul>
<p><span>– Read-only: 180 seconds</span></p>
<p><span>– Read-write: 600 seconds</span></p>
<ul>
<li aria-level="1"><b>Measurement Duration</b><span>: 900 seconds (15 minutes) per thread count</span></li>
<li aria-level="1"><b>Runs</b><span>: Single run per configuration</span></li>
</ul>
<h3><b><br>
System Metrics Collected</b></h3>
<ul>
<li aria-level="1"><span>InnoDB storage engine metrics</span></li>
<li aria-level="1"><span>MySQL status variables</span></li>
<li aria-level="1"><span>MySQL system variables</span></li>
<li aria-level="1"><span>System I/O statistics (iostat)</span></li>
<li aria-level="1"><span>Virtual memory statistics (vmstat)</span></li>
<li aria-level="1"><span>CPU statistics (mpstat)</span></li>
<li aria-level="1"><span>System statistics (dstat)</span></li>
</ul>
<p> </p>
<h2><b>Appendix</b></h2>
<p><span>For Repository structure, Build steps and Technical details go to </span><a href="https://github.com/Percona-Lab-results/2026-pgo/blob/main/README.md#report-categories"><span>https://github.com/Percona-Lab-results/2026-pgo/blob/main/README.md#report-categories</span></a></p>
<p> </p>
<p>The post <a href="https://www.percona.com/blog/mysql-9-7-0-pgo-benchmark-analysis/">MySQL 9.7.0 PGO Benchmark Analysis</a> appeared first on <a href="https://www.percona.com/">Percona</a>.</p>]]></content:encoded>
    <pubDate>Fri, 22 May 2026 07:33:49 +0000</pubDate>
    <dc:creator>MySQL Performance Blog</dc:creator>
    <category>MySQL</category>
    <category>Optimization</category>
    <category>Performance</category>
    <category>PGO</category>
  </item>

  <item>
    <title>Best Practices for MySQL HeatWave Adoption for OLTP and OLAP Workloads</title>
    <guid isPermaLink="false">54e711df59ae447bef5bd6d32239741a</guid>
    <link>https://blogs.oracle.com/mysql/best-practices-for-mysql-heatwave-adoption-for-oltp-and-olap-workloads</link>
    <description>Organizations modernizing transactional database environments are increasingly adopting MySQL HeatWave to simplify operations, improve scalability, increase availability, enhance security and enable real-time analytics without separating OLTP and OLAP systems. However, successful adoption requires more than simply provisioning a new database instance. This blog explores practical best practices for provisioning and migrating OLTP and OLAP workloads […]</description>
    <pubDate>Fri, 22 May 2026 05:30:19 +0000</pubDate>
    <dc:creator>Oracle MySQL Group</dc:creator>
    <category>MySQL</category>
    <category>MySQL Basics/How-To</category>
    <category>MySQL HeatWave</category>
    <category>migration</category>
    <category>mysql</category>
  </item>

  <item>
    <title>A Practical Guide for MySQL HeatWave Capacity Planning</title>
    <guid isPermaLink="false">805266964395b70a47886b8bd8a4d872</guid>
    <link>https://blogs.oracle.com/mysql/a-practical-guide-for-mysql-heatwave-capacity-planning</link>
    <description>As organizations modernize their data platforms, MySQL HeatWave has emerged as a powerful solution for running online transactional processing (OLTP) and real-time online analytics processing (OLAP) together without ETL complexity. However, achieving optimal performance and cost efficiency requires thoughtful capacity planning. This blog explains how to monitor and estimate MySQL HeatWave capacity using SQL queries, […]</description>
    <pubDate>Thu, 21 May 2026 08:00:39 +0000</pubDate>
    <dc:creator>Oracle MySQL Group</dc:creator>
    <category>MySQL</category>
    <category>MySQL Basics/How-To</category>
    <category>MySQL HeatWave</category>
    <category>Capacity Planning</category>
  </item>

  <item>
    <title>Designing Resilient APIs with MySQL HeatWave High Availability and Read Replicas</title>
    <guid isPermaLink="false">fc25524cf9ca46476bfd60eb0e304a1c</guid>
    <link>https://blogs.oracle.com/mysql/designing-resilient-apis-with-mysql-heatwave-high-availability-and-read-replicas</link>
    <description>Modern cloud applications are expected to remain available even during infrastructure interruptions, replication failovers, maintenance events, and transient network failures. In distributed database environments, it requires applications to treat transient failures as a normal part of production operations. This blog discusses practical API reliability designs for applications using MySQL HeatWave High Availability and Read Replicas, […]</description>
    <pubDate>Thu, 21 May 2026 01:57:46 +0000</pubDate>
    <dc:creator>Oracle MySQL Group</dc:creator>
    <category>MySQL Basics/How-To</category>
    <category>MySQL HeatWave</category>
    <category>high availability</category>
    <category>OCI</category>
    <category>Read Replicas</category>
  </item>

  <item>
    <title>How ProxySQL 3.0.8 improves MySQL session-variable tracking</title>
    <guid isPermaLink="false">https://proxysql.com/blog/proxysql-3-0-8-session-track-variables/</guid>
    <link>https://proxysql.com/blog/proxysql-3-0-8-session-track-variables/</link>
    <description>ProxySQL 3.0.8 extends session-variable tracking beyond parsed SET statements by consuming MySQL session-state notifications from backend OK packets.</description>
    <pubDate>Sun, 17 May 2026 00:00:00 +0000</pubDate>
    <dc:creator>ProxySQL</dc:creator>
  </item>

  <item>
    <title>Building an AI Vision Search Engine with MySQL HeatWave GenAI</title>
    <guid isPermaLink="false">https://dasini.net/blog/?p=8533</guid>
    <link>https://dasini.net/blog/2026/05/14/building-an-ai-vision-search-engine-with-mysql-heatwave-genai/</link>
    <description>Modern AI systems increasingly rely on multimodal data: text, images, documents, audio, and video. Among these modalities, image understanding has become one of the most important capabilities for AI-powered applications.
Traditionally, implementing these capabilities required specialized computer vision infrastructure, external vector databases, custom ML pipelines, and multiple frameworks.
With MySQL HeatWave GenAI, many of these capabilities can now be implemented directly inside SQL workflows using built-in AI routines.
In this article, we will build the foundations of a Vision Model Evaluation Assistant using MySQL HeatWave GenAI. The objective is not to create another image classifier, but rather a semantic image understanding platform.
The post Building an AI Vision Search Engine with MySQL HeatWave GenAI first appeared on dasini.net - Diary of a MySQL expert.</description>
    <content:encoded><![CDATA[<p>Modern AI systems increasingly rely on multimodal data: text, images, documents, audio, and video. Among these modalities, image understanding has become one of the most important capabilities for AI-powered applications.<br>
Traditionally, implementing these capabilities required specialized computer vision infrastructure, external vector databases, custom ML pipelines, and multiple frameworks.<br>
With MySQL HeatWave GenAI, many of these capabilities can now be implemented directly inside SQL workflows using built-in AI routines.<br>
In this article, we will build the foundations of a Vision Model Evaluation Assistant using MySQL HeatWave GenAI. The objective is not to create another image classifier, but rather a semantic image understanding platform.</p>
The post <a href="https://dasini.net/blog/2026/05/14/building-an-ai-vision-search-engine-with-mysql-heatwave-genai/">Building an AI Vision Search Engine with MySQL HeatWave GenAI</a> first appeared on <a href="https://dasini.net/blog">dasini.net - Diary of a MySQL expert</a>.]]></content:encoded>
    <pubDate>Thu, 14 May 2026 16:54:52 +0000</pubDate>
    <dc:creator>Olivier Dasini</dc:creator>
    <category>AI</category>
    <category>Artificial Intelligence</category>
    <category>Cloud</category>
    <category>HeatWave</category>
    <category>Howto</category>
    <category>MDS</category>
    <category>MySQL</category>
    <category>Tuto</category>
    <category>GenAI</category>
    <category>Image</category>
    <category>tuto</category>
  </item>

  <item>
    <title>MySQL Community Update: Public Discussion #4, Design Proposals, and Contributor Summit</title>
    <guid isPermaLink="false">34db9b3cc46c77836ade0ab2348457fd</guid>
    <link>https://blogs.oracle.com/mysql/mysql-community-update-public-discussion-4-design-proposals-and-contributor-summit</link>
    <description>Following the strong engagement across the first three editions of our Public MySQL Community Discussion series, we’re pleased to invite you to Edition #4. We will focus on the upcoming contribution process changes and our Contributor Summit later in May. This ongoing series is part of our commitment to increase transparency, strengthen collaboration, and provide […]</description>
    <pubDate>Tue, 12 May 2026 15:20:34 +0000</pubDate>
    <dc:creator>Oracle MySQL Group</dc:creator>
    <category>MySQL</category>
    <category>MySQL Community</category>
  </item>

  <item>
    <title>MyVector v1.26.5: Component Architecture Arrives</title>
    <guid isPermaLink="false">http://askdba.net/?p=2949</guid>
    <link>https://askdba.net/2026/05/09/myvector-v1-26-5-component-architecture-arrives/</link>
    <description>MySQL 9.7 LTS Support Lands Released May 8, 2026 · GitHub Release



v1.26.5 introduces a MySQL Component build for MySQL 8.4 LTS and 9.7 LTS, a unified logging abstraction, and a set of plugin stability fixes. The plugin path for MySQL 8.0, 8.4, and 9.0 is unchanged.



Why the Component architecture matters



MySQL has been deprecating the legacy plugin API in favor of the Component architecture since 8.0. Components install via INSTALL COMPONENT, integrate through typed service interfaces, and are better isolated from server internals — meaning fewer breakages across MySQL minor versions and a supported path forward as the plugin API winds down. For MyVector, this move isn’t optional in the long run: the component model is where MySQL’s extension ecosystem is heading, and building on it now means users on 8.4 LTS and 9.7 LTS get a stable, upgrade-resilient foundation rather than a deprecated one.



What’s New



MySQL Component build. MyVector can now be installed via INSTALL COMPONENT on MySQL 8.4 and 9.7. The component ships UDF registration, binlog-driven index synchronization, and a query rewrite service hook — all backed by the same core vector index engine as the plugin. A new myvector_log.h abstraction unifies logging across both build modes, replacing scattered #ifdef blocks.



MySQL 9.7 LTS. The 9.x CI, release, and Docker targets move from 9.6 to 9.7 LTS. A new Docker image tag ghcr.io/askdba/myvector:mysql9.7 is now available. If you’re on :mysql9.6, switch to :mysql9.7.



Plugin stability fixes. gmtime() and asctime() replaced with their thread-safe _r variants; concurrency fixes in plugin init/deinit; null-guard added to myvector_ann_set row function. Also: config file permission hardening, a binary_log namespace conflict fix on 8.4/9.7, and a Quick Start wget URL correction (issue #89).



How to Install



Component — pre-built binaries (Linux amd64) are attached to this release:



bash



	
		
			

tar -xzf myvector-component-mysql8.4.8-linux-amd64.tar.gzcp libmyvector_component.so $(mysql_config --plugindir)/mysql -u root -p -e &quot;INSTALL COMPONENT 'file://libmyvector_component';&quot;
		
	



Also available: myvector-component-mysql9.7.0-linux-amd64.tar.gz and checksums.txt. To build from source, use scripts/build-component-8.4-docker.sh or scripts/build-component-9.7-docker.sh.



Plugin — Docker or build from source. Pre-built plugin .so files are not on the release page. Use Docker (multi-arch, amd64 + arm64):



bash



	
		
			

docker pull ghcr.io/askdba/myvector:mysql8.4   # or :mysql8.0, :mysql9.7
		
	



Or build from source with scripts/build-release.sh (requires MySQL dev headers).



Upgrade Notes




No schema or index migration required.



Docker tag change: :mysql9.6 → :mysql9.7.



The component path is the forward path for MySQL 8.4+. The plugin remains supported for 8.0/8.4/9.0 through their EOL dates.



Windows is not supported — use Linux container images.




See docs/BUILD_MODES.md and docs/COMPONENT_MIGRATION_PLAN.md for migration guidance. Bugs and feedback welcome on GitHub Issues.



</description>
    <content:encoded><![CDATA[<p class="wp-block-paragraph">MySQL 9.7 LTS Support Lands Released May 8, 2026 · <a href="https://github.com/askdba/myvector/releases/tag/v1.26.5">GitHub Release</a></p>



<p class="wp-block-paragraph">v1.26.5 introduces a MySQL <strong>Component</strong> build for MySQL 8.4 LTS and 9.7 LTS, a unified logging abstraction, and a set of plugin stability fixes. The plugin path for MySQL 8.0, 8.4, and 9.0 is unchanged.</p>



<h2 class="wp-block-heading">Why the Component architecture matters</h2>



<p class="wp-block-paragraph">MySQL has been deprecating the legacy plugin API in favor of the Component architecture since 8.0. Components install via <code>INSTALL COMPONENT</code>, integrate through typed service interfaces, and are better isolated from server internals — meaning fewer breakages across MySQL minor versions and a supported path forward as the plugin API winds down. For MyVector, this move isn’t optional in the long run: the component model is where MySQL’s extension ecosystem is heading, and building on it now means users on 8.4 LTS and 9.7 LTS get a stable, upgrade-resilient foundation rather than a deprecated one.</p>



<h2 class="wp-block-heading">What’s New</h2>



<p class="wp-block-paragraph"><strong>MySQL Component build.</strong> MyVector can now be installed via <code>INSTALL COMPONENT</code> on MySQL 8.4 and 9.7. The component ships UDF registration, binlog-driven index synchronization, and a query rewrite service hook — all backed by the same core vector index engine as the plugin. A new <code>myvector_log.h</code> abstraction unifies logging across both build modes, replacing scattered <code>#ifdef</code> blocks.</p>



<p class="wp-block-paragraph"><strong>MySQL 9.7 LTS.</strong> The 9.x CI, release, and Docker targets move from 9.6 to 9.7 LTS. A new Docker image tag <code>ghcr.io/askdba/myvector:mysql9.7</code> is now available. If you’re on <code>:mysql9.6</code>, switch to <code>:mysql9.7</code>.</p>



<p class="wp-block-paragraph"><strong>Plugin stability fixes.</strong> <code>gmtime()</code> and <code>asctime()</code> replaced with their thread-safe <code>_r</code> variants; concurrency fixes in plugin init/deinit; null-guard added to <code>myvector_ann_set</code> row function. Also: config file permission hardening, a <code>binary_log</code> namespace conflict fix on 8.4/9.7, and a Quick Start <code>wget</code> URL correction (issue #89).</p>



<h2 class="wp-block-heading">How to Install</h2>



<p class="wp-block-paragraph"><strong>Component — pre-built binaries (Linux amd64)</strong> are attached to this release:</p>



<p class="wp-block-paragraph">bash</p>


<div class="wp-block-code">
	<div class="cm-editor">
		<div class="cm-scroller">
			
<pre>
<code><div class="cm-line">tar -xzf myvector-component-mysql8.4.8-linux-amd64.tar.gz</div><div class="cm-line">cp libmyvector_component.so $(mysql_config --plugindir)/</div><div class="cm-line">mysql -u root -p -e "INSTALL COMPONENT 'file://libmyvector_component';"</div></code></pre>
		</div>
	</div>
</div>


<p class="wp-block-paragraph">Also available: <code>myvector-component-mysql9.7.0-linux-amd64.tar.gz</code> and <code>checksums.txt</code>. To build from source, use <code>scripts/build-component-8.4-docker.sh</code> or <code>scripts/build-component-9.7-docker.sh</code>.</p>



<p class="wp-block-paragraph"><strong>Plugin — Docker or build from source.</strong> Pre-built plugin <code>.so</code> files are not on the release page. Use Docker (multi-arch, amd64 + arm64):</p>



<p class="wp-block-paragraph">bash</p>


<div class="wp-block-code">
	<div class="cm-editor">
		<div class="cm-scroller">
			
<pre>
<code><div class="cm-line">docker pull ghcr.io/askdba/myvector:mysql8.4   # or :mysql8.0, :mysql9.7</div></code></pre>
		</div>
	</div>
</div>


<p class="wp-block-paragraph">Or build from source with <code>scripts/build-release.sh</code> (requires MySQL dev headers).</p>



<h2 class="wp-block-heading">Upgrade Notes</h2>



<ul class="wp-block-list">
<li>No schema or index migration required.</li>



<li>Docker tag change: <code>:mysql9.6</code> → <code>:mysql9.7</code>.</li>



<li>The component path is the forward path for MySQL 8.4+. The plugin remains supported for 8.0/8.4/9.0 through their EOL dates.</li>



<li>Windows is not supported — use Linux container images.</li>
</ul>



<p class="wp-block-paragraph">See <a href="https://github.com/askdba/myvector/blob/main/docs/BUILD_MODES.md"><code>docs/BUILD_MODES.md</code></a> and <a href="https://github.com/askdba/myvector/blob/main/docs/COMPONENT_MIGRATION_PLAN.md"><code>docs/COMPONENT_MIGRATION_PLAN.md</code></a> for migration guidance. Bugs and feedback welcome on <a href="https://github.com/askdba/myvector/issues">GitHub Issues</a>.</p>



<p class="wp-block-paragraph"></p>]]></content:encoded>
    <pubDate>Sat, 09 May 2026 08:08:19 +0000</pubDate>
    <dc:creator>Alkin Tezuysal</dc:creator>
    <category>mysql</category>
    <category>Technical</category>
    <category>ai</category>
    <category>artificial-intelligence</category>
    <category>coding</category>
    <category>llm</category>
    <category>technology</category>
  </item>

  <item>
    <title>A New Era of MySQL Monitoring: OpenTelemetry Metrics with Prometheus</title>
    <guid isPermaLink="false">7ff6317b92d59f67500cb49da31f962f</guid>
    <link>https://blogs.oracle.com/mysql/a-new-era-of-mysql-monitoring-opentelemetry-metrics-with-prometheus</link>
    <description>In modern application development, observability is no longer optional. It is a core requirement for stable operations, faster troubleshooting, and better understanding of system behavior. Databases are especially important because they often sit at the center of application performance. When a database becomes slow, overloaded, or unavailable, the impact is usually felt across the entire […]</description>
    <pubDate>Thu, 07 May 2026 01:58:47 +0000</pubDate>
    <dc:creator>Oracle MySQL Group</dc:creator>
    <category>Monitoring</category>
    <category>MySQL</category>
    <category>MySQL Community</category>
    <category>mysql</category>
    <category>mysqlcommunity</category>
  </item>

  <item>
    <title>MySQL 9.7 is out and the community wins </title>
    <guid isPermaLink="false">http://askdba.net/?p=2917</guid>
    <link>https://askdba.net/2026/05/06/mysql-9-7-is-out-and-the-community-wins/</link>
    <description>May 2026 · 5 min read. Alkin Tezuysal



Cross blog from Oracle https://blogs.oracle.com/mysql/mysql-9-7-is-out-and-the-community-wins



MySQL 9.7 came out on April 21 and I’ve been going through the release notes so you don’t have to. The short version: Oracle has made several previously Enterprise-only features available in the Community Edition; the Hypergraph Optimizer is now free for everyone; and if you’re still on MySQL 8.0, it has reached End-of-Life. Like right now. We’ll get to that.



Let’s go through what matters most.



First: MySQL 8.0 has reached End-of-Life



MySQL 8.0.46 shipped alongside 9.7, and it is the last 8.0 release. As of April 2026, 8.0 is officially End-of-Life. No more security patches. No more bug fixes. Oracle’s release notes now encourage users to upgrade to MySQL 8.4 LTS or 9.7.



If you’re on 8.0 in production, you’ve got two paths. MySQL 8.4 LTS is the safest, most conservative upgrade with a well-trodden migration path from 8.0. MySQL 9.7 is if you want all the new stuff, including everything in this post. Either way, the clock has run out on 8.0. It is strongly recommended to plan your upgrade soon.



Some Enterprise features available in the Community Edition



This is the headline. Oracle has moved five components from Enterprise Edition into Community Edition with this release. For self-hosted MySQL users, this is genuinely good news.



Four of them are replication components that now ship in Community Edition.



Replication Applier Metrics gives you real visibility into how your replica is processing events. Lag monitoring, throughput, the works. This was always the kind of thing you had to implement separately or access the Enterprise Edition.



Group Replication Flow Control Statistics now provides visibility into why your GR cluster is throttling. If you’ve ever stared at a slow cluster and had no idea what was happening under the hood, this one’s for you.



Group Replication Resource Manager lets you control how resources get allocated so replication stops starving your app workloads.



Group Replication Primary Election gives better observability into failover behavior during primary elections, which is exactly when you most need to know what’s going on.



And then there’s the Telemetry component, which is big if you’re running MySQL in a cloud-native setup. Metrics and traces can now flow to Prometheus, OpenTelemetry, and whatever else your observability stack includes. This was Enterprise-only until today.



The Hypergraph Optimizer is in Community Edition now



This is the one that stands out as particularly impactful.



Quick background: MySQL’s traditional query optimizer uses a left-deep tree approach to figure out join order. Works fine for simple queries, but with complex multi-table joins it can miss a lot of better execution plans. The Hypergraph Optimizer takes a completely different approach. It models the whole query as a hypergraph and uses dynamic programming to search a much bigger space of possible plans.



If you’ve got complex reporting queries or anything with a lot of joins, it’s worth turning on and seeing what happens.



To try it:



SET optimizer_switch=’hypergraph_optimizer=on’;



You can set it at session scope (great for testing), globally, persistently across restarts, or hint it on a per-query basis. Start with session scope on your actual slow queries before you go global. The optimizer is solid, but you don’t want surprises in production.



JSON Duality Views are now fully supported in Community



Previously, in Community Edition, you could define JSON Duality Views, but couldn’t do INSERTs, UPDATEs, or DELETEs through them. That was an Enterprise thing. This capability is now available in Community Edition. Full DML is now in Community.



They also added auto-increment support for duality view inserts, which means you can stop manually wiring up primary keys:



INSERT INTO orders_view



VALUES (‘{“customer_id”: 42, “product_id”: 7, “quantity”: 3}’);



The order_id gets generated automatically. Small change, but it removes a real friction point if you’ve been experimenting with duality views.



A few other things worth knowing



Password hashing got stronger.caching_sha2_password now supports PBKDF2 with SHA-512 storage format. Your existing clients don’t need to change anything since this is server-side only, but it makes stored hashes significantly harder to brute-force. Worth noting if you’re in a compliance-heavy environment like PCI-DSS or HIPAA.



Rolling upgrades just got easier. There’s a new variable called replica_allow_higher_version_source that lets a lower-version replica connect to a higher-version primary. Practically, this means you can upgrade your primary first, verify everything looks good, and then roll through your replicas at your own pace instead of taking the whole fleet down at once.



Container users, this one’s for you. MySQL now correctly reads cpuset cgroup limits to figure out how many CPUs are actually available to it. If you’d constrained MySQL to 4 CPUs in Kubernetes, it might have been sizing its thread pools against all 32 host CPUs anyway. That’s fixed.



OpenSSL got bumped to 3.5.5. Not exciting, but good hygiene.



What about Vector search?



A lot of people are asking about this, and the current status is that it is not yet generally available. Oracle is clearly building toward native vector search across the 9.x innovation releases, and you can see pieces of the foundation being put in place. But 9.7 isn’t the release where it lands as something you can use. It’s on the roadmap, it’s coming, the team is looking for feedback, and it is expected in future releases.  As some of you know, I’m especially interested in vector features as a maintainer of the MyVector project. We’ve had a couple of calls with the engineering team to collaborate on this subject. This might be an area for community contributions. Please stay tuned. 



So, should you upgrade?



Your situationWhat to doStill on MySQL 8.0Upgrade. It’s EOL. Pick 8.4 LTS or 9.7.On 8.4 LTS, happy where you areNothing urgent. Track 9.7 for the LTS landing.Running Group ReplicationTry the new components.Complex JOIN-heavy queriesBenchmark the Hypergraph Optimizer.Running MySQL in KubernetesThe cgroup CPU fix alone might be worth it.Excited about vector searchNot yet. Watch this space.



MySQL 9.7 is available at dev.mysql.com/downloads. If you end up benchmarking the Hypergraph Optimizer or trying the new replication components, share your results. The community learns from real-world numbers a lot more than from release notes. Drop them in the MySQL Community Forums or tag #MySQL97.</description>
    <content:encoded><![CDATA[<p class="wp-block-paragraph"><em>May 2026 · 5 min read. Alkin Tezuysal</em></p>



<p class="wp-block-paragraph">Cross blog from Oracle <a href="https://blogs.oracle.com/mysql/mysql-9-7-is-out-and-the-community-wins">https://blogs.oracle.com/mysql/mysql-9-7-is-out-and-the-community-wins</a></p>



<p class="wp-block-paragraph">MySQL 9.7 came out on April 21 and I’ve been going through the release notes so you don’t have to. The short version: Oracle has made several<strong> </strong>previously Enterprise-only features<strong> available</strong> in the Community Edition; the Hypergraph Optimizer is now free for everyone; and if you’re still on MySQL 8.0, it has reached End-of-Life. Like right now. We’ll get to that.</p>



<p class="wp-block-paragraph">Let’s go through what matters most.</p>



<p class="wp-block-paragraph"><strong>First: MySQL 8.0 has reached End-of-Life</strong></p>



<p class="wp-block-paragraph">MySQL 8.0.46 shipped alongside 9.7, and it is the last 8.0 release. As of April 2026, 8.0 is officially End-of-Life. No more security patches. No more bug fixes. Oracle’s release notes now encourage users to upgrade to MySQL 8.4 LTS or 9.7.</p>



<p class="wp-block-paragraph">If you’re on 8.0 in production, you’ve got two paths. MySQL 8.4 LTS is the safest, most conservative upgrade with a well-trodden migration path from 8.0. MySQL 9.7 is if you want all the new stuff, including everything in this post. Either way, the clock has run out on 8.0. It is strongly recommended to plan your upgrade soon.</p>



<p class="wp-block-paragraph"><strong>Some Enterprise features available in the Community Edition</strong></p>



<p class="wp-block-paragraph">This is the headline. Oracle has moved five components from Enterprise Edition into Community Edition with this release. For self-hosted MySQL users, this is genuinely good news.</p>



<p class="wp-block-paragraph">Four of them are replication components that now ship in Community Edition.</p>



<p class="wp-block-paragraph"><strong>Replication Applier Metrics</strong> gives you real visibility into how your replica is processing events. Lag monitoring, throughput, the works. This was always the kind of thing you had to implement separately or access the Enterprise Edition.</p>



<p class="wp-block-paragraph"><strong>Group Replication Flow Control Statistics</strong> now provides visibility into why your GR cluster is throttling<s>.</s> If you’ve ever stared at a slow cluster and had no idea what was happening under the hood, this one’s for you.</p>



<p class="wp-block-paragraph"><strong>Group Replication Resource Manager</strong> lets you control how resources get allocated so replication stops starving your app workloads.</p>



<p class="wp-block-paragraph"><strong>Group Replication Primary Election</strong> gives better observability into failover behavior during primary elections, which is exactly when you most need to know what’s going on.</p>



<p class="wp-block-paragraph">And then there’s the <strong>Telemetry component</strong>, which is big if you’re running MySQL in a cloud-native setup. Metrics and traces can now flow to Prometheus, OpenTelemetry, and whatever else your observability stack includes. This was Enterprise-only until today.</p>



<p class="wp-block-paragraph"><strong>The Hypergraph Optimizer is in Community Edition now</strong></p>



<p class="wp-block-paragraph">This is the one that stands out as particularly impactful.</p>



<p class="wp-block-paragraph">Quick background: MySQL’s traditional query optimizer uses a left-deep tree approach to figure out join order. Works fine for simple queries, but with complex multi-table joins it can miss a lot of better execution plans. The Hypergraph Optimizer takes a completely different approach. It models the whole query as a hypergraph and uses dynamic programming to search a much bigger space of possible plans.</p>



<p class="wp-block-paragraph">If you’ve got complex reporting queries or anything with a lot of joins, it’s worth turning on and seeing what happens.</p>



<p class="wp-block-paragraph">To try it:</p>



<p class="wp-block-paragraph">SET optimizer_switch=’hypergraph_optimizer=on’;</p>



<p class="wp-block-paragraph">You can set it at session scope (great for testing), globally, persistently across restarts, or hint it on a per-query basis. Start with session scope on your actual slow queries before you go global. The optimizer is solid, but you don’t want surprises in production.</p>



<p class="wp-block-paragraph"><strong>JSON Duality Views are now fully supported in Community</strong></p>



<p class="wp-block-paragraph">Previously, in Community Edition, you could <em>define</em> JSON Duality Views, but couldn’t do INSERTs, UPDATEs, or DELETEs through them. That was an Enterprise thing. This capability is now available in Community Edition.<strong> </strong>Full DML is now in Community.</p>



<p class="wp-block-paragraph">They also added auto-increment support for duality view inserts, which means you can stop manually wiring up primary keys:</p>



<p class="wp-block-paragraph">INSERT INTO orders_view</p>



<p class="wp-block-paragraph">VALUES (‘{“customer_id”: 42, “product_id”: 7, “quantity”: 3}’);</p>



<p class="wp-block-paragraph">The order_id gets generated automatically. Small change, but it removes a real friction point if you’ve been experimenting with duality views.</p>



<p class="wp-block-paragraph"><strong>A few other things worth knowing</strong></p>



<p class="wp-block-paragraph"><strong>Password hashing got stronger.</strong>caching_sha2_password now supports PBKDF2 with SHA-512 storage format. Your existing clients don’t need to change anything since this is server-side only, but it makes stored hashes significantly harder to brute-force. Worth noting if you’re in a compliance-heavy environment like PCI-DSS or HIPAA.</p>



<p class="wp-block-paragraph"><strong>Rolling upgrades just got easier.</strong> There’s a new variable called replica_allow_higher_version_source that lets a lower-version replica connect to a higher-version primary. Practically, this means you can upgrade your primary first, verify everything looks good, and then roll through your replicas at your own pace instead of taking the whole fleet down at once.</p>



<p class="wp-block-paragraph"><strong>Container users, this one’s for you.</strong> MySQL now correctly reads cpuset cgroup limits to figure out how many CPUs are actually available to it. If you’d constrained MySQL to 4 CPUs in Kubernetes, it might have been sizing its thread pools against all 32 host CPUs anyway. That’s fixed.</p>



<p class="wp-block-paragraph"><strong>OpenSSL got bumped to 3.5.5.</strong> Not exciting, but good hygiene.</p>



<p class="wp-block-paragraph"><strong>What about Vector search?</strong></p>



<p class="wp-block-paragraph">A lot of people are asking about this, and the current status is that it is not yet generally available. Oracle is clearly building toward native vector search across the 9.x innovation releases, and you can see pieces of the foundation being put in place. But 9.7 isn’t the release where it lands as something you can use. It’s on the roadmap, it’s coming, the team is looking for feedback, and it is expected in future releases.<strong> </strong> As some of you know, I’m especially interested in vector features as a maintainer of the <a href="https://github.com/askdba/myvector">MyVector</a> project. We’ve had a couple of calls with the engineering team to collaborate on this subject. This might be an area for community contributions. Please stay tuned. </p>



<p class="wp-block-paragraph"><strong>So, should you upgrade?</strong></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td><strong>Your situation</strong></td><td><strong>What to do</strong></td></tr><tr><td>Still on MySQL 8.0</td><td>Upgrade. It’s EOL. Pick 8.4 LTS or 9.7.</td></tr><tr><td>On 8.4 LTS, happy where you are</td><td>Nothing urgent. Track 9.7 for the LTS landing.</td></tr><tr><td>Running Group Replication</td><td>Try the new components.</td></tr><tr><td>Complex JOIN-heavy queries</td><td>Benchmark the Hypergraph Optimizer.</td></tr><tr><td>Running MySQL in Kubernetes</td><td>The cgroup CPU fix alone might be worth it.</td></tr><tr><td>Excited about vector search</td><td>Not yet. Watch this space.</td></tr></tbody></table></figure>



<p class="wp-block-paragraph"><br>MySQL 9.7 is available at<a href="https://dev.mysql.com/downloads/mysql/"> dev.mysql.com/downloads</a>. If you end up benchmarking the Hypergraph Optimizer or trying the new replication components, share your results. The community learns from real-world numbers a lot more than from release notes. Drop them in the MySQL Community Forums or tag <strong>#MySQL97</strong>.</p>]]></content:encoded>
    <pubDate>Wed, 06 May 2026 11:37:26 +0000</pubDate>
    <dc:creator>Alkin Tezuysal</dc:creator>
    <category>mysql</category>
    <category>Technical</category>
    <category>ai</category>
    <category>artificial-intelligence</category>
    <category>cloud</category>
    <category>myvector</category>
    <category>sql</category>
    <category>technology</category>
    <category>vector</category>
  </item>

  <item>
    <title>MySQL 9.7 Is Out and the Community Wins</title>
    <guid isPermaLink="false">57fb0c3fd8250b5113adfd0d65398ab0</guid>
    <link>https://blogs.oracle.com/mysql/mysql-9-7-is-out-and-the-community-wins</link>
    <description>Alkin Tezuysal Director of Services at Altinity Inc. MySQL 9.7 came out on April 21 and I’ve been going through the release notes so you don’t have to. The short version: Oracle has made several previously Enterprise-only features available in the Community Edition, the Hypergraph Optimizer is now free for everyone, and if you’re still on MySQL 8.0, it […]</description>
    <pubDate>Wed, 06 May 2026 10:39:07 +0000</pubDate>
    <dc:creator>Oracle MySQL Group</dc:creator>
    <category>MySQL</category>
    <category>MySQL Community</category>
    <category>mysql</category>
    <category>mysqlcommunity</category>
  </item>

  <item>
    <title>Why Your Application Should Not Use One MySQL User for Everything</title>
    <guid isPermaLink="false">f06d124462bf3d337b6f880ee3f75be8</guid>
    <link>https://blogs.oracle.com/mysql/why-your-application-should-not-use-one-mysql-user-for-everything</link>
    <description>Many applications start with a simple database setup: create one MySQL user, give it access to the application schema, put the credentials in the app config, and move on. That may work at first, but it is not a good long-term security model. A better approach is to use separate MySQL users for separate application […]</description>
    <pubDate>Mon, 04 May 2026 20:48:06 +0000</pubDate>
    <dc:creator>Oracle MySQL Group</dc:creator>
    <category>HeatWave AI</category>
    <category>MySQL</category>
    <category>MySQL Basics/How-To</category>
    <category>MySQL Community</category>
    <category>MySQL Enterprise</category>
    <category>MySQL HeatWave</category>
  </item>

  <item>
    <title>Curious case of PXC node that refused to start due to SSL</title>
    <guid isPermaLink="false">https://www.percona.com/?p=43312</guid>
    <link>https://www.percona.com/blog/curious-case-of-pxc-node-that-refused-to-start-due-to-ssl/</link>
    <description>In this blog, I am going to share a real-world debugging case study where a routine Percona XtraDB Cluster node restart led to an unexpected failure. I will walk through what we observed, what we checked, and how we ultimately identified the root cause.
Let’s see how the maintenance goes. It was supposed to be a simple restart. The kind you’ve done a hundred times. You SSH in, run the maintenance, bring the node back up, and go grab a coffee. Except this time, the coffee went cold on the desk… because MySQL refused to start.
The Problem
The error log of Percona XtraDB Cluster (8.0) had the following information:2025-11-05T05:26:10.982984Z 0 [ERROR] [MY-000059]   [Server] SSL error: Unable to get certificate from '/var/lib/mysql/server-cert.pem'.
2025-11-05T05:26:10.983030Z 0 [Warning] [MY-013595] [Server] Failed to initialize TLS for channel: mysql_main. See below for the description of exact issue.
2025-11-05T05:26:10.983045Z 0 [Warning] [MY-010069] [Server] Failed to set up SSL because of the following SSL library error: Unable to get certificate
2025-11-05T05:26:10.983052Z 0 [Note] [MY-000000] [WSREP] New joining cluster node configured to use specified SSL artifacts
2025-11-05T05:26:10.983083Z 0 [Note] [MY-000000] [Galera] Loading provider /usr/lib64/galera4/libgalera_smm.so initial position: 07c67757-0d18-11ef-b5a9-ee5d87b39aa8:4147053897
2025-11-05T05:26:10.983098Z 0 [Note] [MY-000000] [Galera] wsrep_load(): loading provider library '/usr/lib64/galera4/libgalera_smm.so'
2025-11-05T05:26:10.983742Z 0 [Note] [MY-000000] [Galera] wsrep_load(): Galera 4.22(f6c0465) by Codership Oy &amp;lt;info@codership.com&amp;gt; (modified by Percona &amp;lt;https://percona.com/&amp;gt;) loaded successfully.
2025-11-05T05:26:10.983771Z 0 [Note] [MY-000000] [Galera] Resolved symbol 'wsrep_node_isolation_mode_set_v1'
2025-11-05T05:26:10.983784Z 0 [Note] [MY-000000] [Galera] Resolved symbol 'wsrep_certify_v1'
2025-11-05T05:26:10.983807Z 0 [Note] [MY-000000] [Galera] CRC-32C: using 64-bit x86 acceleration.
2025-11-05T05:26:10.983995Z 0 [Note] [MY-000000] [Galera] not using SSL compression
2025-11-05T05:26:10.984341Z 0 [ERROR] [MY-000000] [Galera] Bad value '/var/lib/mysql/server-cert.pem' for SSL parameter 'socket.ssl_cert': 336245135: 'error:140AB18F:SSL routines:SSL_CTX_use_certificate:ee key too small'
         at /mnt/jenkins/workspace/pxc80-autobuild-RELEASE/test/rpmbuild/BUILD/Percona-XtraDB-Cluster-8.0.42/percona-xtradb-cluster-galera/galerautils/src/gu_asio.cpp:ssl_prepare_context():471
2025-11-05T05:26:10.984401Z 0 [ERROR] [MY-000000] [Galera] Failed to create a new provider '/usr/lib64/galera4/libgalera_smm.so' with options 'gcache.size=1G;gcache.recover=yes;socket.ssl=yes;socket.ssl_ca=/data00/mysqldata/ca.pem;socket.ssl_cert=/data00/mysqldata/server-cert.pem;socket.ssl_key=/data00/mysqldata/server-key.pem;socket.ssl_key=/var/lib/mysql/server-key.pem;socket.ssl_ca=/var/lib/mysql/ca.pem;socket.ssl_cert=/var/lib/mysql/server-cert.pem': Failed to initialize wsrep provider
2025-11-05T05:26:10.984434Z 0 [ERROR] [MY-000000] [WSREP] Failed to load provider
2025-11-05T05:26:10.984448Z 0 [ERROR] [MY-010119] [Server] Aborting
2025-11-05T05:26:10.984602Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.42-33.1)  Percona XtraDB Cluster (GPL), Release rel33, Revision 6673f8e, WSREP version 26.1.4.3.
2025-11-05T05:26:10.985473Z 0 [ERROR] [MY-010065] [Server] Failed to shutdown components infrastructure. 
MySQL was down, and the maintenance clock was running. The certificate file sitting at /var/lib/mysql/server-cert.pem was the same file that had been working perfectly fine before the restart!!
From past history, it was known that the following commands were executed correctly on the same cluster nodeSET GLOBAL ssl_ca = '/var/lib/mysql/ca.pem';
  SET GLOBAL ssl_cert = '/var/lib/mysql/server-cert.pem';
  SET GLOBAL ssl_key = '/var/lib/mysql/server-key.pem';
  ALTER INSTANCE RELOAD TLS;Clients connected over TLS. Galera nodes communicated securely. There were zero complaints from the error log.
In other words, the SSL reload at runtime inherited the process environment that existed when MySQL originally booted. Everything was smooth, but after a restart? MySQL complains and declines to start. So what has changed?
Checking Usual Suspects
File permissions
We checked the PEM files. 
Ownership: mysql:mysql.
Permissions: 644 for the cert, 600 for the key. 
We compared them against the other Galera nodes, and they were identical. This didn’t look like a permissions problem.
Is SELinux to blame here?
SELinux has ruined enough DBA time that it is one of the top spots on such checklists – but it was permissive.$ getenforce
PermissiveThat means it was logging any security issues, but not blocking. And there were no AVC denials related to MySQL or the PEM files in /var/log/audit/audit.log or dmesg!
File corruption
Did the files get corrupted/replaced during or before the MySQL restart?$ openssl x509 -in /var/lib/mysql/server-cert.pem -noout -text
# Output looked perfectly valid when compared to the output from other nodes

$ openssl rsa -in /var/lib/mysql/server-key.pem -check
RSA key okThe files were fine. They parsed cleanly. OpenSSL could read them. So why couldn’t MySQL?
More Logs review
We scanned /var/log/messages and journalctl for anything unusual around the time of the restart. No disk errors. No OOM kills. No kernel panics. Nothing that screamed “I am the Dhurandhar that’s destroyed your node.” At this point, most of the usual suspects were guilt-free, staring at us, asking, “Who did it?”
The Clue
It is good to communicate with stakeholders, and we did – “Was there any recent change on your side?” to the client, and then uttered the golden words “Last week the crypto-policy was updated on all of the DB servers to comply with PCI.”
PCI &amp;gt; Crypto-policy – Let’s go and check it !!$ update-crypto-policies --show
FUTUREThe system was running RHEL’s FUTURE cryptographic policy.
For those unfamiliar (including me at the time), Red Hat Enterprise Linux (and its derivatives, such as Rocky, Alma, and Oracle Linux) ships with a system-wide cryptographic policy framework. It’s a centralized way to enforce minimum standards for TLS versions, cipher suites, key lengths, and signature algorithms across all applications on the system that include OpenSS and yes, anything that links against those libraries… like MySQL.
Here’s a table that shows information about the crypto-policy levels:



Policy
RSA Minimum
TLS Minimum
SHA-1 Signatures
Use Case


LEGACY
1024-bit
TLS 1.0
Allowed
Old systems compatibility


DEFAULT
2048-bit
TLS 1.2
Allowed
Standard operations


FUTURE
3072-bit
TLS 1.2
Blocked
Forward-looking hardening


FIPS
2048-bit
TLS 1.2
Blocked
FIPS 140 compliance



 
 
 
 
 
 
 
 
So FUTURE demands a 3072-bit RSA key; otherwise, it is blocked. What do we have?
$ openssl rsa -in server-key.pem -text -noout | head -1
RSA Private Key: (2048 bit, 2 primes)2048 bits! C’mon! And now I recall the error log again… The hint was there:error:140AB18F:SSL routines:SSL_CTX_use_certificate:ee key too smallNow we have our story straight.
On restart, our PXC cluster node started a new process linked against OpenSSL, which now enforced the FUTURE policy. OpenSSL looked at the 2048-bit RSA certificate and said: “Nope. Too small.”
Fixture
The quick fix here would be to adjust the policy to DEFAULT.sudo update-crypto-policies --set DEFAULTThis will accept the current SSLs, and the node will join the cluster readily.
Alternatively, to remain compliant and adhere to the security policy strictness, the fixture will be to

Generate new certificates
Deploy the keys/certs to all Galera nodes
Perform a rolling restart

 
Conclusion
This was a classic case of a problem hiding at the boundary between two domains, database administration and operating system security. The DBA saw valid certificates and correct MySQL configuration. The sysadmin saw a properly hardened system with a strong crypto policy. Neither was wrong. But the intersection of their two correct configurations produced a failure.
This incident reinforces the importance of cross-domain awareness, where resolving database issues sometimes requires understanding and challenging system-level security decisions.
 
 
 
 
The post Curious case of PXC node that refused to start due to SSL appeared first on Percona.</description>
    <content:encoded><![CDATA[<p><span>In this blog, I am going to share a real-world debugging case study where a routine Percona XtraDB Cluster node restart led to an unexpected failure. I will walk through what we observed, what we checked, and how we ultimately identified the root cause.</span></p>
<p><span>Let’s see how the maintenance goes. It was supposed to be a simple restart. </span><span>The kind you’ve done a hundred times. You SSH in, run the maintenance, bring the node back up, and go grab a coffee. Except this time, the coffee went cold on the desk… because MySQL refused to start.</span></p>
<h2><span>The Problem</span></h2>
<p><span>The error log of Percona XtraDB Cluster (8.0) had the following information:</span></p><pre class="urvanov-syntax-highlighter-plain-tag">2025-11-05T05:26:10.982984Z 0 [ERROR] [MY-000059]   [Server] SSL error: Unable to get certificate from '/var/lib/mysql/server-cert.pem'.
2025-11-05T05:26:10.983030Z 0 [Warning] [MY-013595] [Server] Failed to initialize TLS for channel: mysql_main. See below for the description of exact issue.
2025-11-05T05:26:10.983045Z 0 [Warning] [MY-010069] [Server] Failed to set up SSL because of the following SSL library error: Unable to get certificate
2025-11-05T05:26:10.983052Z 0 [Note] [MY-000000] [WSREP] New joining cluster node configured to use specified SSL artifacts
2025-11-05T05:26:10.983083Z 0 [Note] [MY-000000] [Galera] Loading provider /usr/lib64/galera4/libgalera_smm.so initial position: 07c67757-0d18-11ef-b5a9-ee5d87b39aa8:4147053897
2025-11-05T05:26:10.983098Z 0 [Note] [MY-000000] [Galera] wsrep_load(): loading provider library '/usr/lib64/galera4/libgalera_smm.so'
2025-11-05T05:26:10.983742Z 0 [Note] [MY-000000] [Galera] wsrep_load(): Galera 4.22(f6c0465) by Codership Oy &lt;info@codership.com&gt; (modified by Percona &lt;https://percona.com/&gt;) loaded successfully.
2025-11-05T05:26:10.983771Z 0 [Note] [MY-000000] [Galera] Resolved symbol 'wsrep_node_isolation_mode_set_v1'
2025-11-05T05:26:10.983784Z 0 [Note] [MY-000000] [Galera] Resolved symbol 'wsrep_certify_v1'
2025-11-05T05:26:10.983807Z 0 [Note] [MY-000000] [Galera] CRC-32C: using 64-bit x86 acceleration.
2025-11-05T05:26:10.983995Z 0 [Note] [MY-000000] [Galera] not using SSL compression
2025-11-05T05:26:10.984341Z 0 [ERROR] [MY-000000] [Galera] Bad value '/var/lib/mysql/server-cert.pem' for SSL parameter 'socket.ssl_cert': 336245135: 'error:140AB18F:SSL routines:SSL_CTX_use_certificate:ee key too small'
         at /mnt/jenkins/workspace/pxc80-autobuild-RELEASE/test/rpmbuild/BUILD/Percona-XtraDB-Cluster-8.0.42/percona-xtradb-cluster-galera/galerautils/src/gu_asio.cpp:ssl_prepare_context():471
2025-11-05T05:26:10.984401Z 0 [ERROR] [MY-000000] [Galera] Failed to create a new provider '/usr/lib64/galera4/libgalera_smm.so' with options 'gcache.size=1G;gcache.recover=yes;socket.ssl=yes;socket.ssl_ca=/data00/mysqldata/ca.pem;socket.ssl_cert=/data00/mysqldata/server-cert.pem;socket.ssl_key=/data00/mysqldata/server-key.pem;socket.ssl_key=/var/lib/mysql/server-key.pem;socket.ssl_ca=/var/lib/mysql/ca.pem;socket.ssl_cert=/var/lib/mysql/server-cert.pem': Failed to initialize wsrep provider
2025-11-05T05:26:10.984434Z 0 [ERROR] [MY-000000] [WSREP] Failed to load provider
2025-11-05T05:26:10.984448Z 0 [ERROR] [MY-010119] [Server] Aborting
2025-11-05T05:26:10.984602Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.42-33.1)  Percona XtraDB Cluster (GPL), Release rel33, Revision 6673f8e, WSREP version 26.1.4.3.
2025-11-05T05:26:10.985473Z 0 [ERROR] [MY-010065] [Server] Failed to shutdown components infrastructure.</pre><p> </p>
<p><span>MySQL was down, and the maintenance clock was running. The certificate file sitting at <code>/var/lib/mysql/server-cert.pem</code> was the same file that had been working perfectly fine before the restart!!<br>
</span><span>From past history, it was known that the following commands were executed correctly on the same cluster node</span></p><pre class="urvanov-syntax-highlighter-plain-tag">SET GLOBAL ssl_ca = '/var/lib/mysql/ca.pem';
  SET GLOBAL ssl_cert = '/var/lib/mysql/server-cert.pem';
  SET GLOBAL ssl_key = '/var/lib/mysql/server-key.pem';
  ALTER INSTANCE RELOAD TLS;</pre><p><span>Clients connected over TLS. Galera nodes communicated securely. There were zero complaints from the error log.<br>
</span><span>In other words, the SSL reload at runtime inherited the process environment that existed when MySQL originally booted. Everything was smooth, but after a restart? MySQL complains and declines to start. So what has changed?</span></p>
<h2><span>Checking Usual Suspects</span></h2>
<p><b>File permissions</b></p>
<p><span>We checked the PEM files. </span></p>
<p><span>Ownership: <code>mysql:mysql</code>.<br>
</span><span>Permissions: <code>644</code> for the cert, <code>600</code> for the key. </span></p>
<p><span>We compared them against the other Galera nodes, and they were identical. This didn’t look like a permissions problem.</span></p>
<p><b>Is SELinux to blame here?</b></p>
<p><span>SELinux has ruined enough DBA time that it is one of the top spots on such checklists – but it was permissive.</span></p><pre class="urvanov-syntax-highlighter-plain-tag">$ getenforce
<span>Permissive</span></pre><p><span>That means it was logging any security issues, but not blocking. And there were no AVC denials related to MySQL or the PEM files in /var/log/audit/audit.log or dmesg!</span></p>
<p><b>File corruption</b></p>
<p><span>Did the files get corrupted/replaced during or before the MySQL restart?</span></p><pre class="urvanov-syntax-highlighter-plain-tag">$ openssl x509 -in /var/lib/mysql/server-cert.pem -noout -text
# Output looked perfectly valid when compared to the output from other nodes

$ openssl rsa -in /var/lib/mysql/server-key.pem -check
RSA key ok</pre><p><span>The files were fine. They parsed cleanly. OpenSSL could read them. So why couldn’t MySQL?</span></p>
<p><b>More Logs review</b></p>
<p><span>We scanned /var/log/messages and journalctl for anything unusual around the time of the restart. No disk errors. No OOM kills. No kernel panics. Nothing that screamed “I am the Dhurandhar that’s destroyed your node.” </span><span>At this point, most of the usual suspects were guilt-free, staring at us, asking, “Who did it?”</span></p>
<h2><span>The Clue</span></h2>
<p><span>It is good to communicate with stakeholders, and we did – “Was there any recent change on your side?” to the client, and then uttered the golden words “Last week the crypto-policy was updated on all of the DB servers to comply with PCI.”</span></p>
<p><span>PCI &gt; Crypto-policy – Let’s go and check it !!</span></p><pre class="urvanov-syntax-highlighter-plain-tag">$ update-crypto-policies --show
FUTURE</pre><p><span>The system was running RHEL’s FUTURE cryptographic policy.</span></p>
<p><span>For those unfamiliar (including me at the time), Red Hat Enterprise Linux (and its derivatives, such as Rocky, Alma, and Oracle Linux) ships with a system-wide cryptographic policy framework. It’s a centralized way to enforce minimum standards for TLS versions, cipher suites, key lengths, and signature algorithms across all applications on the system that include OpenSS and yes, anything that links against those libraries… like MySQL.</span></p>
<p>Here’s a table that shows information about the crypto-policy levels:</p>
<table class="alignleft" border="1">
<tbody>
<tr>
<td><span>Policy</span></td>
<td><span>RSA Minimum</span></td>
<td><span>TLS Minimum</span></td>
<td><span>SHA-1 Signatures</span></td>
<td><span>Use Case</span></td>
</tr>
<tr>
<td><span>LEGACY</span></td>
<td><span>1024-bit</span></td>
<td><span>TLS 1.0</span></td>
<td><span>Allowed</span></td>
<td><span>Old systems compatibility</span></td>
</tr>
<tr>
<td><span>DEFAULT</span></td>
<td><span>2048-bit</span></td>
<td><span>TLS 1.2</span></td>
<td><span>Allowed</span></td>
<td><span>Standard operations</span></td>
</tr>
<tr>
<td><span>FUTURE</span></td>
<td><span>3072-bit</span></td>
<td><span>TLS 1.2</span></td>
<td><span>Blocked</span></td>
<td><span>Forward-looking hardening</span></td>
</tr>
<tr>
<td><span>FIPS</span></td>
<td><span>2048-bit</span></td>
<td><span>TLS 1.2</span></td>
<td><span>Blocked</span></td>
<td><span>FIPS 140 compliance</span></td>
</tr>
</tbody>
</table>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p><span>So FUTURE demands a 3072-bit RSA key; otherwise, it is blocked. What do we have?</span><span><br>
</span></p><pre class="urvanov-syntax-highlighter-plain-tag">$ openssl rsa -in server-key.pem -text -noout | head -1
RSA Private Key: (2048 bit, 2 primes)</pre><p><span>2048 bits! C’mon! And now I recall the error log again… The hint was there:</span></p><pre class="urvanov-syntax-highlighter-plain-tag">error:140AB18F:SSL routines:SSL_CTX_use_certificate:ee key too small</pre><p><span>Now we have our story straight.<br>
</span><span>On restart, our PXC cluster node started a new process linked against OpenSSL, which now enforced the FUTURE policy. OpenSSL looked at the 2048-bit RSA certificate and said: “Nope. Too small.”</span></p>
<h2><span>Fixture</span></h2>
<p><span>The quick fix here would be to adjust the policy to DEFAULT.</span></p><pre class="urvanov-syntax-highlighter-plain-tag">sudo update-crypto-policies --set DEFAULT</pre><p><span>This will accept the current SSLs, and the node will join the cluster readily.</span></p>
<p><span>Alternatively, to remain compliant and adhere to the security policy strictness, the fixture will be to</span></p>
<ul>
<li aria-level="1"><span>Generate new certificates</span></li>
<li aria-level="1"><span>Deploy the keys/certs to all Galera nodes</span></li>
<li aria-level="1"><span>Perform a rolling restart</span></li>
</ul>
<p> </p>
<h2><span>Conclusion</span></h2>
<p><span>This was a classic case of a problem hiding at the boundary between two domains, database administration and operating system security. The DBA saw valid certificates and correct MySQL configuration. The sysadmin saw a properly hardened system with a strong crypto policy. Neither was wrong. But the intersection of their two correct configurations produced a failure.</span></p>
<p><span>This incident reinforces the importance of cross-domain awareness, where resolving database issues sometimes requires understanding and challenging system-level security decisions.</span></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>The post <a href="https://www.percona.com/blog/curious-case-of-pxc-node-that-refused-to-start-due-to-ssl/">Curious case of PXC node that refused to start due to SSL</a> appeared first on <a href="https://www.percona.com/">Percona</a>.</p>]]></content:encoded>
    <pubDate>Mon, 04 May 2026 05:45:15 +0000</pubDate>
    <dc:creator>MySQL Performance Blog</dc:creator>
    <category>Insight for DBAs</category>
    <category>MySQL</category>
    <category>database troubleshooting case study</category>
    <category>FUTURE crypto policy</category>
    <category>Galera cluster failure</category>
    <category>Linux security policy</category>
    <category>MySQL Galera SSL</category>
    <category>MySQL SSL error</category>
    <category>OpenSSL error debugging</category>
    <category>OpenSSL policy impact</category>
    <category>Percona XtraDB Cluster</category>
    <category>PXC troubleshooting</category>
    <category>RSA key </category>
  </item>

  <item>
    <title>Building Query Analysis and Insights Dashboard in PMM</title>
    <guid isPermaLink="false">https://www.percona.com/?p=43348</guid>
    <link>https://www.percona.com/blog/building-query-analysis-and-insights-dashboard-in-pmm/</link>
    <description>Percona Monitoring and Management is a great open source database monitoring, observability, and management tool. Query analytics is one of the prominent features DBA uses actively to trace the incidents and query performance identification.
We all know and love the Query Analytics (QAN) dashboard… It’s the first place we look when an incident alert fires or when a developer asks, “Why is the app slow?” or “What was going on during the midnight production outage?”
But sometimes, the standard dashboards just don’t tell the whole story or maybe are not clear enough. QAN is great, but shouldn’t we have more? If you have PMM running, you already have a Ferrari engine under the hood: ClickHouse. Most of us just drive it in first gear using the default UI.
In this post, we are going to take the training wheels off. We will bypass the standard QAN interface and talk directly to the ClickHouse backend to build highly specialised dashboards. We aren’t just looking for “slow” queries anymore; we are hunting for inefficiency, volatility, and the “silent killers” that standard monitoring often misses.
This is the hands-on blog, so grab your coffee and let’s turn that PMM instance into a deep-dive forensic tool.
Create a New Dashboard in PMM

Connect to PMM &amp;gt; Dashboards &amp;gt; Create New Dashboard
Save it with name “Slow Query Analysis” and Description “Slow Query Analysis from PMM’s QAN database (clickhouse)”
Click on add visualisation &amp;amp; select datasource “ClickHouse”


Choose SQL Builder


Paste the following query to get top 10 slow queries from the database

SELECT fingerprint
    FROM pmm.metrics
    WHERE service_type = 'mysql'
      AND $__timeFilter(period_start)
    GROUP BY fingerprint
    ORDER BY sum(m_query_time_sum) DESC
    LIMIT 10

Choose “Table View” on the top to view the list
When you click “Run Query” you will see the top 10 slow queries in the chosen time period.
Let’s Save the dashboard after Panel Options updates as follows7.1 Change Panel Name and Description to: “Slow Query Analysis”7.2 Legend Placement to “Bottom”, Values to “min”,”max”, “mean”7.3 Change Axis’ Scale to “Logarithmic”Logarithmic scale on an axis compresses large ranges of data, making it ideal for visualizing metrics with vastly different magnitudes. This provides good visualisation for queries of different execution time frames.7.4 Save DashboardAlright, we’re at our first step. This first result set shows the top 10 slow query fingerprints across all MySQL services tracked by PMM for the selected time range. It provides a quick, environment-wide view of the most expensive query patterns. But this does not provide a clear picture. Let’s refine the dashboard to focus on specific queries, servers and observe their performance over time.Now, let’s introduce a variable to filter the data.
Click on Settings on Dashboard’s home page8.1 Choose “Variables” tab and click on “Add Variable”8.2 Add variable configuration and Save Dashboard 
Go Back to Dashboard and Edit “Slow Query Analysis” Panel.

Now you should see the Query ID filter on the top.


Change the query to the following

SELECT
  period_start AS time,
  left(fingerprint, 80) AS query_text,
  sum(m_query_time_sum/m_query_time_cnt) AS query_time
FROM
  pmm.metrics
WHERE
  service_type = 'mysql'
  AND $__timeFilter(period_start)
  AND fingerprint IN (
    SELECT fingerprint
    FROM pmm.metrics
    WHERE service_type = 'mysql'
      AND $__timeFilter(period_start)
      AND ($queryid = '' OR queryid = $queryid)
    GROUP BY fingerprint
    ORDER BY sum(m_query_time_sum) DESC
    LIMIT 10
  )
GROUP BY
  time,
  fingerprint
ORDER BY
  time,
  query_time DESC

Basically the query is fetching start time, query text and average query time for the selected period for the top 10 Queries in that time-frame.
There is a filter for the “queryid” variable which you may use if you want to filter on a specific queryid.
Choose “Time Series” as “Query Type”


Adjust Panel Options11.1 Choose “Standard options” &amp;gt; “Unit” as “Time / Seconds (s)” from drop down.11.2 Choose “Standard options” &amp;gt; “Display name” as “${__field.labels.query_text}”11.3 Click on “Save Dashboard”
 Your dashboard should be ready

Now, by default this dashboard is plotting top 10 queries. If you have a query fingerprint handy, you may be able to filter the search by that specific query.  That said, this is still plotting queries across all the monitored instances. Let’s move on to add the service_name filter.
 
Adding service_name filter

Add Variable

Create new variable named “service_name”
Use variable type “Query”
Use Data Source as “ClickHouse”
Query:

select distinct service_name from pmm.metrics where service_type = 'mysql';

Unselect all checkboxes in “Selection options”
Save Dashboard


Update Query

SELECT
  period_start AS time,
  left(fingerprint, 80) AS query_text,
  sum(m_query_time_sum/m_query_time_cnt) AS query_time
FROM
  pmm.metrics
WHERE
  (service_name = '' OR service_name = '$service_name')
  AND service_type = 'mysql'
  AND $__timeFilter(period_start)
  AND fingerprint IN (
    SELECT fingerprint
    FROM pmm.metrics
    WHERE service_type = 'mysql'
      AND $__timeFilter(period_start)
      AND (service_name = '' OR service_name = '$service_name')
    GROUP BY fingerprint
    ORDER BY sum(m_query_time_sum) DESC
    LIMIT 10
  )
GROUP BY
  time,
  left(fingerprint, 80) 
ORDER BY
  time,
  query_time DESCI know many of you are naturally curious and enjoy experimenting with PMM and Grafana… So you’ve probably already started thinking about how far this can be taken. Feel free to share your ideas or custom dashboards in the comments.
Sample Dashboards:
 
The Query Analysis and Insights Dashboard
Okay, for those who are looking to have quick results, I’ve prepared the complete Query Analysis and Insights Dashboard for you to import and use instantly.
By importing the JSON file, you’ll get the full working dashboard with all panels preconfigured, including:

Slow Query Analysis
Latency Distribution Heatmap
Query Volatility (P99 vs Average)
Lock Wait Ratio Over Time (Top Contended Queries)
Temporary Table Usage (Disk &amp;amp; Memory)
Query Efficiency (Rows Examined vs Rows Sent)
Error Rate vs Throughput
Workload Distribution by User
Query Volume by Client Host
Execution Time vs Lock Wait Time

This allows you to instantly explore PMM Query Analytics data, adjust time ranges and filters, and correlate query performance, contention, and workload behavior without recreating the dashboard from scratch.
Dashboard JSON available here:

Grafana: https://grafana.com/grafana/dashboards/24896
GitHub:  https://github.com/Percona-Lab/pmm-dashboards/query_analysis_insights.json

Give it a go and let me know if you have suggestions or requests. Also consider sharing if you create something interesting.
Cheers.
The post Building Query Analysis and Insights Dashboard in PMM appeared first on Percona.</description>
    <content:encoded><![CDATA[<p><span>Percona Monitoring and Management is a great open source database monitoring, observability, and management tool. Query analytics is one of the prominent features DBA uses actively to trace the incidents and query performance identification.</span></p>
<p><span>We all know and love the Query Analytics (QAN) dashboard… It’s the first place we look when an incident alert fires or when a developer asks, </span><i><span>“Why is the app slow?” or “What was going on during the midnight production outage?”</span></i></p>
<p><span>But sometimes, the standard dashboards just don’t tell the whole story or maybe are not clear enough. QAN is great, but shouldn’t we have more? If you have PMM running, you already have a Ferrari engine under the hood: ClickHouse. Most of us just drive it in first gear using the default UI.</span></p>
<p><span>In this post, we are going to take the training wheels off. We will bypass the standard QAN interface and talk directly to the ClickHouse backend to build highly specialised dashboards. We aren’t just looking for “slow” queries anymore; we are hunting for inefficiency, volatility, and the “silent killers” that standard monitoring often misses.</span></p>
<p><span>This is the hands-on blog, so grab your coffee and let’s turn that PMM instance into a deep-dive forensic tool.</span></p>
<p><strong>Create a New Dashboard in PMM</strong></p>
<ol>
<li aria-level="1"><span>Connect to PMM &gt; Dashboards &gt; Create New Dashboard<img loading="lazy" decoding="async" class="alignnone wp-image-43360" src="https://www.percona.com/wp-content/uploads/2026/04/pmm-new-dashboard.png" alt="" width="172" height="160" srcset="https://www.percona.com/wp-content/uploads/2026/04/pmm-new-dashboard.png 338w, https://www.percona.com/wp-content/uploads/2026/04/pmm-new-dashboard-300x279.png 300w" sizes="auto, (max-width: 172px) 100vw, 172px"></span></li>
<li aria-level="1"><span>Save it with name “Slow Query Analysis” and Description “Slow Query Analysis from PMM’s QAN database (clickhouse)”</span><img loading="lazy" decoding="async" class="alignnone wp-image-43359" src="https://www.percona.com/wp-content/uploads/2026/04/pmm-save-dashboard.png" alt="" width="681" height="258" srcset="https://www.percona.com/wp-content/uploads/2026/04/pmm-save-dashboard.png 958w, https://www.percona.com/wp-content/uploads/2026/04/pmm-save-dashboard-300x114.png 300w, https://www.percona.com/wp-content/uploads/2026/04/pmm-save-dashboard-768x291.png 768w" sizes="auto, (max-width: 681px) 100vw, 681px"></li>
<li aria-level="1"><span>Click on add visualisation &amp; select datasource “ClickHouse”<br>
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-43358" src="https://www.percona.com/wp-content/uploads/2026/04/pmm-data-source.png" alt="" width="537" height="368" srcset="https://www.percona.com/wp-content/uploads/2026/04/pmm-data-source.png 537w, https://www.percona.com/wp-content/uploads/2026/04/pmm-data-source-300x206.png 300w" sizes="auto, (max-width: 537px) 100vw, 537px"><br>
</span></li>
<li aria-level="1"><span>Choose SQL Builder<br>
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-43357" src="https://www.percona.com/wp-content/uploads/2026/04/pmm-sql-builder-1024x574-1.png" alt="" width="1024" height="574" srcset="https://www.percona.com/wp-content/uploads/2026/04/pmm-sql-builder-1024x574-1.png 1024w, https://www.percona.com/wp-content/uploads/2026/04/pmm-sql-builder-1024x574-1-300x168.png 300w, https://www.percona.com/wp-content/uploads/2026/04/pmm-sql-builder-1024x574-1-768x431.png 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px"><br>
</span></li>
<li aria-level="1"><span>Paste the following query to get top 10 slow queries from the database<br>
</span><br>
<pre class="urvanov-syntax-highlighter-plain-tag">SELECT fingerprint
    FROM pmm.metrics
    WHERE service_type = 'mysql'
      AND $__timeFilter(period_start)
    GROUP BY fingerprint
    ORDER BY sum(m_query_time_sum) DESC
    LIMIT 10</pre>
</li>
<li aria-level="1"><span>Choose “Table View” on the top to view the list<br>
</span><span>When you click “Run Query” you will see the top 10 slow queries in the chosen time period.<img loading="lazy" decoding="async" class="alignnone size-full wp-image-43356" src="https://www.percona.com/wp-content/uploads/2026/04/pmm-table-view-1024x557-1.png" alt="" width="1024" height="557" srcset="https://www.percona.com/wp-content/uploads/2026/04/pmm-table-view-1024x557-1.png 1024w, https://www.percona.com/wp-content/uploads/2026/04/pmm-table-view-1024x557-1-300x163.png 300w, https://www.percona.com/wp-content/uploads/2026/04/pmm-table-view-1024x557-1-768x418.png 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px"></span></li>
<li aria-level="1"><span>Let’s Save the dashboard after Panel Options updates as follows</span><span>7.1 Change Panel Name and Description to: “Slow Query Analysis”</span><span>7.2 Legend Placement to “Bottom”, Values to “min”,”max”, “mean”</span><span>7.3 Change Axis’ Scale to “Logarithmic”</span><i><span>Logarithmic scale on an axis compresses large ranges of data, making it ideal for visualizing metrics with vastly different magnitudes. This provides good visualisation for queries of different execution time frames.</span></i><span>7.4 Save Dashboard<img loading="lazy" decoding="async" class="alignnone size-full wp-image-43355" src="https://www.percona.com/wp-content/uploads/2026/04/pmm-dashboard-config.png" alt="" width="401" height="829" srcset="https://www.percona.com/wp-content/uploads/2026/04/pmm-dashboard-config.png 401w, https://www.percona.com/wp-content/uploads/2026/04/pmm-dashboard-config-145x300.png 145w" sizes="auto, (max-width: 401px) 100vw, 401px"></span><span>Alright, we’re at our first step. This first result set shows the </span><b>top 10 slow query fingerprints across all MySQL services tracked by PMM</b><span> for the selected time range. It provides a quick, environment-wide view of the most expensive query patterns. But this does not provide a clear picture. Let’s refine the dashboard to focus on specific queries, servers and observe their performance over time.</span><span>Now, let’s introduce a variable to filter the data.</span></li>
<li aria-level="1"><span>Click on </span><b>Settings</b><span> on Dashboard’s home page</span><img loading="lazy" decoding="async" class="alignnone size-full wp-image-43354" src="https://www.percona.com/wp-content/uploads/2026/04/pmm-dashboard-settings.png" alt="" width="634" height="401" srcset="https://www.percona.com/wp-content/uploads/2026/04/pmm-dashboard-settings.png 634w, https://www.percona.com/wp-content/uploads/2026/04/pmm-dashboard-settings-300x190.png 300w" sizes="auto, (max-width: 634px) 100vw, 634px">8.1 Choose “Variables” tab and click on “Add Variable”<img loading="lazy" decoding="async" class="alignnone size-full wp-image-43353" src="https://www.percona.com/wp-content/uploads/2026/04/pmm-add-variables-1024x917-1.png" alt="" width="1024" height="917" srcset="https://www.percona.com/wp-content/uploads/2026/04/pmm-add-variables-1024x917-1.png 1024w, https://www.percona.com/wp-content/uploads/2026/04/pmm-add-variables-1024x917-1-300x269.png 300w, https://www.percona.com/wp-content/uploads/2026/04/pmm-add-variables-1024x917-1-768x688.png 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px">8.2 Add variable configuration and Save Dashboard </li>
<li aria-level="1"><span>Go Back to Dashboard and Edit “Slow Query Analysis” Panel.</span>
<ul>
<li aria-level="1"><span>Now you should see the Query ID filter on the top.</span></li>
</ul>
</li>
<li aria-level="1"><span>Change the query to the following<br>
</span><br>
<pre class="urvanov-syntax-highlighter-plain-tag">SELECT
  period_start AS time,
  left(fingerprint, 80) AS query_text,
  sum(m_query_time_sum/m_query_time_cnt) AS query_time
FROM
  pmm.metrics
WHERE
  service_type = 'mysql'
  AND $__timeFilter(period_start)
  AND fingerprint IN (
    SELECT fingerprint
    FROM pmm.metrics
    WHERE service_type = 'mysql'
      AND $__timeFilter(period_start)
      AND ($queryid = '' OR queryid = $queryid)
    GROUP BY fingerprint
    ORDER BY sum(m_query_time_sum) DESC
    LIMIT 10
  )
GROUP BY
  time,
  fingerprint
ORDER BY
  time,
  query_time DESC</pre>
<ul>
<li aria-level="1"><span>Basically the query is fetching start time, query text and average query time for the selected period for the top 10 Queries in that time-frame.</span></li>
<li aria-level="1"><span>There is a filter for the “queryid” variable which you may use if you want to filter on a specific queryid.</span></li>
<li aria-level="1">Choose “Time Series” as “Query Type”<img loading="lazy" decoding="async" class="alignnone size-full wp-image-43352" src="https://www.percona.com/wp-content/uploads/2026/04/pmm-adding-query-1024x667-1.png" alt="" width="1024" height="667" srcset="https://www.percona.com/wp-content/uploads/2026/04/pmm-adding-query-1024x667-1.png 1024w, https://www.percona.com/wp-content/uploads/2026/04/pmm-adding-query-1024x667-1-300x195.png 300w, https://www.percona.com/wp-content/uploads/2026/04/pmm-adding-query-1024x667-1-768x500.png 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px"></li>
</ul>
</li>
<li aria-level="1"><span>Adjust Panel Options</span><span>11.1 Choose “Standard options” &gt; “Unit” as “Time / Seconds (s)” from drop down.</span><span>11.2 Choose “Standard options” &gt; “Display name” as “</span><span>${__field.labels.query_text}</span><span>”</span><span>11.3 Click on “Save Dashboard”</span></li>
<li><span> Your dashboard should be ready<img loading="lazy" decoding="async" class="alignnone size-full wp-image-43351" src="https://www.percona.com/wp-content/uploads/2026/04/pmm-sample-query-chart-1024x549-1.png" alt="" width="1024" height="549" srcset="https://www.percona.com/wp-content/uploads/2026/04/pmm-sample-query-chart-1024x549-1.png 1024w, https://www.percona.com/wp-content/uploads/2026/04/pmm-sample-query-chart-1024x549-1-300x161.png 300w, https://www.percona.com/wp-content/uploads/2026/04/pmm-sample-query-chart-1024x549-1-768x412.png 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px"></span></li>
</ol>
<p><span>Now, by default this dashboard is plotting top 10 queries. If you have a query fingerprint handy, you may be able to filter the search by that specific query.  That said, this is still plotting queries across all the monitored instances. Let’s move on to add the service_name filter.</span></p>
<p> </p>
<h3><b>Adding service_name filter</b></h3>
<ol>
<li aria-level="1"><span>Add Variable</span>
<ol>
<li aria-level="2"><span>Create new variable named “service_name”</span></li>
<li aria-level="2"><span>Use variable type “Query”</span></li>
<li aria-level="2"><span>Use Data Source as “ClickHouse”</span></li>
<li aria-level="2"><span>Query:<br>
</span><br>
<pre class="urvanov-syntax-highlighter-plain-tag">select distinct service_name from pmm.metrics where service_type = 'mysql';</pre>
</li>
<li><span>Unselect all checkboxes in “Selection options”</span></li>
<li><span>Save Dashboard</span></li>
</ol>
</li>
<li>Update Query</li>
</ol>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">SELECT
  period_start AS time,
  left(fingerprint, 80) AS query_text,
  sum(m_query_time_sum/m_query_time_cnt) AS query_time
FROM
  pmm.metrics
WHERE
  (service_name = '' OR service_name = '$service_name')
  AND service_type = 'mysql'
  AND $__timeFilter(period_start)
  AND fingerprint IN (
    SELECT fingerprint
    FROM pmm.metrics
    WHERE service_type = 'mysql'
      AND $__timeFilter(period_start)
      AND (service_name = '' OR service_name = '$service_name')
    GROUP BY fingerprint
    ORDER BY sum(m_query_time_sum) DESC
    LIMIT 10
  )
GROUP BY
  time,
  left(fingerprint, 80) 
ORDER BY
  time,
  query_time DESC</pre><p><span>I know many of you are naturally curious and enjoy experimenting with PMM and Grafana… So you’ve probably already started thinking about how far this can be taken. Feel free to share your ideas or custom dashboards in the comments.</span></p>
<p><span>Sample Dashboards:</span></p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-43350" src="https://www.percona.com/wp-content/uploads/2026/04/pmm-dashboard-service-custom-1024x321-1.png" alt="" width="1024" height="321" srcset="https://www.percona.com/wp-content/uploads/2026/04/pmm-dashboard-service-custom-1024x321-1.png 1024w, https://www.percona.com/wp-content/uploads/2026/04/pmm-dashboard-service-custom-1024x321-1-300x94.png 300w, https://www.percona.com/wp-content/uploads/2026/04/pmm-dashboard-service-custom-1024x321-1-768x241.png 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px"> <img loading="lazy" decoding="async" class="alignnone size-full wp-image-43349" src="https://www.percona.com/wp-content/uploads/2026/04/pmm-sample-dashboard-1-1024x456-1.png" alt="" width="1024" height="456" srcset="https://www.percona.com/wp-content/uploads/2026/04/pmm-sample-dashboard-1-1024x456-1.png 1024w, https://www.percona.com/wp-content/uploads/2026/04/pmm-sample-dashboard-1-1024x456-1-300x134.png 300w, https://www.percona.com/wp-content/uploads/2026/04/pmm-sample-dashboard-1-1024x456-1-768x342.png 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px"></p>
<h1><span>The Query Analysis and Insights Dashboard</span></h1>
<p><span>Okay, for those who are looking to have quick results, I’ve prepared the complete Query Analysis and Insights Dashboard for you to import and use instantly.</span></p>
<p><span>By importing the JSON file, you’ll get the full working dashboard with all panels preconfigured, including:</span></p>
<ul>
<li><span>Slow Query Analysis</span></li>
<li><span>Latency Distribution Heatmap</span></li>
<li><span>Query Volatility (P99 vs Average)</span></li>
<li><span>Lock Wait Ratio Over Time (Top Contended Queries)</span></li>
<li><span>Temporary Table Usage (Disk &amp; Memory)</span></li>
<li><span>Query Efficiency (Rows Examined vs Rows Sent)</span></li>
<li><span>Error Rate vs Throughput</span></li>
<li><span>Workload Distribution by User</span></li>
<li><span>Query Volume by Client Host</span></li>
<li><span>Execution Time vs Lock Wait Time</span></li>
</ul>
<p><span>This allows you to instantly explore PMM Query Analytics data, adjust time ranges and filters, and correlate query performance, contention, and workload behavior without recreating the dashboard from scratch.</span></p>
<p><span>Dashboard JSON available here:</span></p>
<ul>
<li aria-level="1"><span>Grafana: https://grafana.com/grafana/dashboards/24896</span></li>
<li aria-level="1"><span>GitHub:  https://github.com/Percona-Lab/pmm-dashboards/query_analysis_insights.json</span></li>
</ul>
<p><span>Give it a go and let me know if you have suggestions or requests. Also consider sharing if you create something interesting.</span></p>
<p>Cheers.</p>
<p>The post <a href="https://www.percona.com/blog/building-query-analysis-and-insights-dashboard-in-pmm/">Building Query Analysis and Insights Dashboard in PMM</a> appeared first on <a href="https://www.percona.com/">Percona</a>.</p>]]></content:encoded>
    <pubDate>Mon, 04 May 2026 05:00:52 +0000</pubDate>
    <dc:creator>MySQL Performance Blog</dc:creator>
    <category>Monitoring</category>
    <category>MySQL</category>
    <category>Percona Software</category>
  </item>

  <item>
    <title>Run an ALTER TABLE for a huge table in Aurora</title>
    <guid isPermaLink="false">https://www.percona.com/?p=43371</guid>
    <link>https://www.percona.com/blog/run-an-alter-table-for-a-huge-table-in-aurora/</link>
    <description>Recently, we received an alert for one of our Managed Services customers indicating that the auto_increment value for the table was 80% of its maximum capacity. The column was INT UNSIGNED, which has a limit of 4,294,967,295.
At 80%, we have enough time to change it to BIGINT.…. Right? Let’s see.
So we used pt-online-schema-change to perform the alter.
It started running at a good pace but slowed over time.
 
Why?
Well, let’s look at the definition of the table:mysql&amp;gt; show create table myschema.mytableG
*************************** 1. row ***************************
       Table: mytable
Create Table: CREATE TABLE `mytable` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `long_column` varchar(1000) NOT NULL,
  `state` tinyint unsigned NOT NULL,
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `short_column` varchar(30) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_long_column` (`long_column`,`state`),
  KEY `idx_short_column` (`short_column`,`state`),
  KEY `idx_short_col2` (`short_column`)
) ENGINE=InnoDB AUTO_INCREMENT=4009973818 DEFAULT CHARSET=utf8mb3NOTE1: The index on long_column is for a varchar column with a length of 1000; it may not be required, and an index prefix may be more helpful here.
NOTE2: The index idx_short_col2 is duplicated, as it is covered by the index idx_short_column.
Those changes require testing and are out of scope for this emergency, but they are worth mentioning.
 
Table size:
+---------------+------------+------------+---------+----------+---------+----------+--------+
| TABLE_SCHEMA  | TABLE_NAME | TABLE_ROWS | DATA_GB | INDEX_GB | FREE_GB | TOTAL_GB | ENGINE |
+---------------+------------+------------+---------+----------+---------+----------+--------+
| myschema      | mytable    | 3906921584 |    1118 |     1790 |       0 |     2907 | InnoDB |
+---------------+------------+------------+---------+----------+---------+----------+--------+Look at the indexes being way bigger than the data.mysql&amp;gt; SELECT database_name, table_name, index_name, ROUND(stat_value * @@innodb_page_size / 1024 / 1024, 2) AS size_in_mb FROM mysql.innodb_index_stats WHERE stat_name = 'size' AND index_name != 'PRIMARY' and database_name='myschema' and table_name='mytable' ORDER BY size_in_mb DESC;
+---------------+------------+-------------------+------------+
| database_name | table_name | index_name        | size_in_mb |
+---------------+------------+-------------------+------------+
| myschema      | mytable    | idx_long_column   | 1583538.95 |
| myschema      | mytable    | idx_short_column  |  126432.98 |
| myschema      | mytable    | idx_short_col2    |  122699.95 |
+---------------+------------+-------------------+------------+
3 rows in set (0.01 sec)While the pt-online-schema-change runs, it copies the data to a new table. As the data is being copied, the secondary indexes must be maintained.
NOTE the huge index for a varchar(1000) that is ~1.5T in size. Maintaining such an index becomes increasingly expensive as the data size increases.
The pt-online-schema-change had been running for ~8 days, and its latest estimate was 53 more days, which we can’t afford, since the maximum value would be exceeded in ~15 days. Copying `myschema`.`mytable`:  12% 53+16:48:01 remain
Copying `myschema`.`mytable`:  12% 53+16:48:30 remain
Copying `myschema`.`mytable`:  12% 53+16:48:59 remain
Copying `myschema`.`mytable`:  12% 53+16:49:26 remain
Copying `myschema`.`mytable`:  12% 53+16:49:53 remain
Copying `myschema`.`mytable`:  12% 53+16:50:19 remain
Copying `myschema`.`mytable`:  12% 53+16:50:49 remain
Copying `myschema`.`mytable`:  12% 53+16:51:17 remain
Copying `myschema`.`mytable`:  12% 53+16:51:45 remain 
So what do we do now?
We suggested canceling the pt-online-schema-change and creating an Aurora blue-green deployment.
Then perform the direct ALTER on the green cluster. And finally, when ready, do the failover.
 
Sounds good, doesn’t it?
 
First, we need to ensure that the new cluster (green) has the replica_type_conversions  parameter in its cluster parameter group to “ALL_NON_LOSSY, ALL_UNSIGNED” in order to be able to replicate from an int unsigned column to a bigint unsigned column.
So we tried that, it started too fast ~0.036% per minute, that’s 2 days. That’s great!
We left the process running over the weekend, but we noticed it started to slow down again… By Monday, it was advancing at ~0.01% every 5 mins, which gives an ETA of 34 days. 
Why? 
Again, using the direct ALTER MySQL copies the data to a temp table, and the bigger the data, the harder it is to maintain the indexes. 
Again, unacceptable.
Note that with the above 2 approaches, we lost ~12 days of precious time, and the deadline for auto_increment exhaustion was approaching.
Then we thought: What if we drop the secondary indexes, do the alter, and then add the indexes back?
In theory, it should be faster, as:

Dropping the indexes is a metadata-only operation with ONLINE DDL.
Altering the column datatype from INT to BIGINT is not an ONLINE operation, but the fact that it doesn’t have to update secondary indexes during row copying to a new temporary table prevents the slowdown.

Adding back the secondary indexes is an ONLINE DDL operation:

 
“Online DDL support for adding secondary indexes means that you can generally speed the overall process of creating and loading a table and associated indexes by creating the table without secondary indexes, then adding secondary indexes after the data is loaded.”
https://dev.mysql.com/doc/refman/8.4/en/innodb-online-ddl-operations.html
So let’s do this:
The deletion of the indexes was really quick, as expected (metadata-only operation):mysql&amp;gt; ALTER TABLE myschema.mytable DROP INDEX idx_long_column, DROP INDEX idx_short_column, DROP INDEX idx_short_col2;
Query OK, 0 rows affected (49.40 sec)
Records: 0  Duplicates: 0  Warnings: 0 
Then the change of the datatype:mysql&amp;gt; ALTER TABLE myschema.mytable CHANGE COLUMN id id bigint unsigned NOT NULL AUTO_INCREMENT;
Query OK, 4058047205 rows affected (13 hours 9 min 10.62 sec)
Records: 4058047205  Duplicates: 0  Warnings: 0 
Looks very promising!!!
 
The final step, add back the indexes:mysql&amp;gt; ALTER TABLE myschema.mytable ADD INDEX `idx_long_column` (`long_column`,`state`), ADD INDEX `idx_short_column` (`short_column`,`state`), ADD INDEX `short_col2` (`short_column`);
ERROR 1878 (HY000): Temporary file write failure. 
Why?
Well, the INPLACE operation uses the tmp dir to write sort files. In Aurora, there are certain limits for the temporary space based on the instance type. 
In a regular MySQL instance, we can modify the innodb_tmpdir to another location with enough disk space; however, in Aurora, the parameter is not modifiable, which could have made the whole process easier.
Even with a larger instance type, it’s hard to create the 1.5T index without breaking open the piggy bank.
 
Last resort, add the indexes back with the COPY algorithm:mysql&amp;gt; ALTER TABLE myschema.mytable ALGORITHM=COPY, ADD INDEX `idx_long_column` (`long_column`,`state`), ADD INDEX `idx_short_column` (`short_column`,`state`), ADD INDEX `idx_short_col2` (`short_column`);
Query OK, 4147498819 rows affected (6 days 1 hour 55 min 57.00 sec)
Records: 4147498819  Duplicates: 0  Warnings: 0 
Why does it work? Because ALTER TABLE using the COPY algorithm uses the datadir as the destination for the temporary table, the rows are copied there. It doesn’t have the limitation of the temporary directory mentioned above.
We were able to make it on time about 4 days before the auto_increment exhaustion, preventing downtime.
 
In retrospective we could have used the following approach to avoid the use of the blue/green deployment:

Perform a pt-online-schema-change on the main table, dropping the indexes, and changing the column type to bigint. ( with –no-swap-tables –no-drop-old-table –no-drop-new-table –no-drop-triggers).
Add the secondary indexes using the direct alter with the COPY algorithm in the _new table.
Once the alter finishes, swap the tables and drop the triggers.

 
Conclusion:
What initially looked like an easy task with pt-online-schema-change, ended up being more complex. 
You need to check the data definition, the index sizes, the Aurora limits, and how the different algorithms work to make a decision on the best way to proceed with those tasks, specially on situations like these where you have the pressure of the auto_increment being exhausted and there’s risk of downtime if it is not done on time.
And of course, monitor auto_increment exhaustion for your tables, and use a reasonable threshold that gives you enough time to plan and change the table definition. You can use Percona Monitoring and Management for this, specifically on the MySQL &amp;gt; MySQL Table Details dashboard.
The post Run an ALTER TABLE for a huge table in Aurora appeared first on Percona.</description>
    <content:encoded><![CDATA[<p><span>Recently, we received an alert for one of our </span><a href="https://www.percona.com/services/managed-services"><span>Managed Services</span></a><span> customers indicating that the auto_increment value for the table was 80% of its maximum capacity. The column was INT UNSIGNED, which has a limit of 4,294,967,295.</span></p>
<p><span>At 80%, we have enough time to change it to BIGINT.…. Right? Let’s see.</span></p>
<p><span>So we used </span><a href="https://docs.percona.com/percona-toolkit/pt-online-schema-change.html"><span>pt-online-schema-change</span></a><span> to perform the alter.</span></p>
<p><span>It started running at a good pace but slowed over time.</span></p>
<p> </p>
<p><b>Why?</b></p>
<p><span>Well, let’s look at the definition of the table:</span></p><pre class="urvanov-syntax-highlighter-plain-tag">mysql&gt; show create table myschema.mytableG
*************************** 1. row ***************************
       Table: mytable
Create Table: CREATE TABLE `mytable` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `long_column` varchar(1000) NOT NULL,
  `state` tinyint unsigned NOT NULL,
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `short_column` varchar(30) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_long_column` (`long_column`,`state`),
  KEY `idx_short_column` (`short_column`,`state`),
  KEY `idx_short_col2` (`short_column`)
) ENGINE=InnoDB AUTO_INCREMENT=4009973818 DEFAULT CHARSET=utf8mb3</pre><p><b>NOTE</b><b>1</b><b>: </b><span>The index on </span><i><span>long_column</span></i><span> is for a varchar column with a length of 1000; it may not be required, and an index prefix may be more helpful here.</span></p>
<p><b>NOTE</b><b>2</b><b>:</b><span> The index </span><i><span>idx_short_col2</span></i><span> is duplicated, as it is covered by the index </span><i><span>idx_short_column</span></i><span>.</span></p>
<p><span>Those changes require testing and are out of scope for this emergency, but they are worth mentioning.</span></p>
<p> </p>
<p><strong>Table size:</strong><span><br>
</span></p><pre class="urvanov-syntax-highlighter-plain-tag">+---------------+------------+------------+---------+----------+---------+----------+--------+
| TABLE_SCHEMA  | TABLE_NAME | TABLE_ROWS | DATA_GB | INDEX_GB | FREE_GB | TOTAL_GB | ENGINE |
+---------------+------------+------------+---------+----------+---------+----------+--------+
| myschema      | mytable    | 3906921584 |    1118 |     1790 |       0 |     2907 | InnoDB |
+---------------+------------+------------+---------+----------+---------+----------+--------+</pre><p><span>Look at the indexes being way bigger than the data.</span></p><pre class="urvanov-syntax-highlighter-plain-tag">mysql&gt; SELECT database_name, table_name, index_name, ROUND(stat_value * @@innodb_page_size / 1024 / 1024, 2) AS size_in_mb FROM mysql.innodb_index_stats WHERE stat_name = 'size' AND index_name != 'PRIMARY' and database_name='myschema' and table_name='mytable' ORDER BY size_in_mb DESC;
+---------------+------------+-------------------+------------+
| database_name | table_name | index_name        | size_in_mb |
+---------------+------------+-------------------+------------+
| myschema      | mytable    | idx_long_column   | 1583538.95 |
| myschema      | mytable    | idx_short_column  |  126432.98 |
| myschema      | mytable    | idx_short_col2    |  122699.95 |
+---------------+------------+-------------------+------------+
3 rows in set (0.01 sec)</pre><p><span>While the pt-online-schema-change runs, it copies the data to a new table. As the data is being copied, the secondary indexes must be maintained.</span></p>
<p><span>NOTE the huge index for a varchar(1000) that is ~1.5T in size. </span><span>Maintaining such an index becomes increasingly expensive as the data size increases.</span></p>
<p><span>The pt-online-schema-change had been running for ~8 days, and its latest estimate was 53 more days, which we can’t afford, since the maximum value would be exceeded in ~15 days. </span></p><pre class="urvanov-syntax-highlighter-plain-tag">Copying `myschema`.`mytable`:  12% 53+16:48:01 remain
Copying `myschema`.`mytable`:  12% 53+16:48:30 remain
Copying `myschema`.`mytable`:  12% 53+16:48:59 remain
Copying `myschema`.`mytable`:  12% 53+16:49:26 remain
Copying `myschema`.`mytable`:  12% 53+16:49:53 remain
Copying `myschema`.`mytable`:  12% 53+16:50:19 remain
Copying `myschema`.`mytable`:  12% 53+16:50:49 remain
Copying `myschema`.`mytable`:  12% 53+16:51:17 remain
Copying `myschema`.`mytable`:  12% 53+16:51:45 remain</pre><p> </p>
<p><span>So what do we do now?</span></p>
<p><span>We suggested canceling the pt-online-schema-change and creating an Aurora </span><a href="https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/blue-green-deployments-overview.html"><span>blue-green deployment</span></a><span>.</span></p>
<p><span>Then perform the direct ALTER on the green cluster. And finally, when ready, do the failover.</span></p>
<p> </p>
<p><span>Sounds good, doesn’t it?</span></p>
<p> </p>
<p><span>First, we need to ensure that the new cluster (green) has the </span><a href="https://dev.mysql.com/doc/refman/8.4/en/replication-options-replica.html#sysvar_replica_type_conversions"><b>replica_type_conversions</b></a><span>  parameter in its cluster parameter group to “</span><i><span>ALL_NON_LOSSY, ALL_UNSIGNED”</span></i><span> in order to be able to replicate from an int unsigned column to a bigint unsigned column.</span></p>
<p><span>So we tried that, it started too fast ~0.036% per minute, that’s 2 days. That’s great!</span></p>
<p><span>We left the process running over the weekend, but we noticed it started to slow down again… By Monday, it was advancing at ~0.01% every 5 mins, which gives an ETA of 34 days. </span></p>
<p><strong>Why? </strong></p>
<p><span>Again, using the direct ALTER MySQL copies the data to a temp table, and the bigger the data, the harder it is to maintain the indexes. </span></p>
<p><span>Again, unacceptable.</span></p>
<p><span>Note that with the above 2 approaches, we lost ~12 days of precious time, and the deadline for auto_increment exhaustion was approaching.</span></p>
<p><span>Then we thought: What if we drop the secondary indexes, do the alter, and then add the indexes back?</span></p>
<p><span>In theory, it should be faster, as:</span></p>
<ul>
<li aria-level="1"><span>Dropping the indexes is a metadata-only operation with </span><a href="https://dev.mysql.com/doc/refman/8.4/en/innodb-online-ddl-operations.html"><span>ONLINE DDL</span></a><span>.</span></li>
<li aria-level="1"><span>Altering the column datatype from INT to BIGINT is not an ONLINE operation, but the fact that it doesn’t have to update secondary indexes during row copying to a new temporary table prevents the slowdown.</span><span><br>
</span></li>
<li aria-level="1"><span>Adding back the secondary indexes is an ONLINE DDL operation:</span></li>
</ul>
<p> </p>
<p><span>“Online DDL support for adding secondary indexes means that you can generally speed the overall process of creating and loading a table and associated indexes by creating the table without secondary indexes, then adding secondary indexes after the data is loaded.”</span></p>
<p><a href="https://dev.mysql.com/doc/refman/8.4/en/innodb-online-ddl-operations.html"><span>https://dev.mysql.com/doc/refman/8.4/en/innodb-online-ddl-operations.html</span></a></p>
<p><span>So let’s do this:</span></p>
<p><span>The deletion of the indexes was really quick, as expected (metadata-only operation):</span></p><pre class="urvanov-syntax-highlighter-plain-tag">mysql&gt; ALTER TABLE myschema.mytable DROP INDEX idx_long_column, DROP INDEX idx_short_column, DROP INDEX idx_short_col2;
Query OK, 0 rows affected (49.40 sec)
Records: 0  Duplicates: 0  Warnings: 0</pre><p> </p>
<p><span>Then the change of the datatype:</span></p><pre class="urvanov-syntax-highlighter-plain-tag">mysql&gt; ALTER TABLE myschema.mytable CHANGE COLUMN id id bigint unsigned NOT NULL AUTO_INCREMENT;
Query OK, 4058047205 rows affected (13 hours 9 min 10.62 sec)
Records: 4058047205  Duplicates: 0  Warnings: 0</pre><p> </p>
<p><span>Looks very promising!!!</span></p>
<p> </p>
<p><span>The final step, add back the indexes:</span></p><pre class="urvanov-syntax-highlighter-plain-tag">mysql&gt; ALTER TABLE myschema.mytable ADD INDEX `idx_long_column` (`long_column`,`state`), ADD INDEX `idx_short_column` (`short_column`,`state`), ADD INDEX `short_col2` (`short_column`);
ERROR 1878 (HY000): Temporary file write failure.</pre><p> </p>
<p><b>Why?</b></p>
<p><span>Well, the INPLACE operation uses the tmp dir to write sort files. In Aurora, there are </span><a href="https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Managing.Performance.html#AuroraMySQL.Managing.TempStorage"><span>certain limits for the temporary space based on the instance type</span></a><span>. </span></p>
<p>In a regular MySQL instance, we can modify the <strong>innodb_tmpdir</strong> to another location with enough disk space; however, in Aurora, the parameter is not modifiable, which could have made the whole process easier.</p>
<p><span>Even with a larger instance type, it’s hard to create the 1.5T index without breaking open the piggy bank.</span></p>
<p> </p>
<p><b><i>Last resort</i></b><span>, add the indexes back with the COPY algorithm:</span></p><pre class="urvanov-syntax-highlighter-plain-tag">mysql&gt; ALTER TABLE myschema.mytable ALGORITHM=COPY, ADD INDEX `idx_long_column` (`long_column`,`state`), ADD INDEX `idx_short_column` (`short_column`,`state`), ADD INDEX `idx_short_col2` (`short_column`);
Query OK, 4147498819 rows affected (6 days 1 hour 55 min 57.00 sec)
<span>Records: 4147498819  Duplicates: 0  Warnings: 0</span></pre><p> </p>
<p><span>Why does it work? Because ALTER TABLE using the COPY algorithm uses the datadir as the destination for the temporary table, the rows are copied there. It doesn’t have the limitation of the temporary directory mentioned above.</span></p>
<p><span>We were able to make it on time about 4 days before the auto_increment exhaustion, preventing downtime.</span></p>
<p> </p>
<p><span>In retrospective we could have used the following approach to avoid the use of the blue/green deployment:</span></p>
<ol>
<li aria-level="1"><span>Perform a pt-online-schema-change on the main table, dropping the indexes, and changing the column type to bigint. ( with –no-swap-tables –no-drop-old-table –no-drop-new-table –no-drop-triggers).</span></li>
<li aria-level="1"><span>Add the secondary indexes using the direct alter with the COPY algorithm in the _new table.</span></li>
<li aria-level="1"><span>Once the alter finishes, swap the tables and drop the triggers.</span></li>
</ol>
<p> </p>
<h2><span>Conclusion:</span></h2>
<p><span>What initially looked like an easy task with </span><a href="https://docs.percona.com/percona-toolkit/pt-online-schema-change.html"><span>pt-online-schema-change</span></a><span>, ended up being more complex. </span></p>
<p><span>You need to check the data definition, the index sizes, the Aurora limits, and how the different algorithms work to make a decision on the best way to proceed with those tasks, specially on situations like these where you have the pressure of the auto_increment being exhausted and there’s risk of downtime if it is not done on time.</span></p>
<p><span>And of course, monitor auto_increment exhaustion for your tables, and use a reasonable threshold that gives you enough time to plan and change the table definition. You can use </span><a href="https://www.percona.com/software/database-tools/percona-monitoring-and-management"><span>Percona Monitoring and Management</span></a><span> for this, specifically on the MySQL &gt; MySQL Table Details dashboard.</span></p>
<p>The post <a href="https://www.percona.com/blog/run-an-alter-table-for-a-huge-table-in-aurora/">Run an ALTER TABLE for a huge table in Aurora</a> appeared first on <a href="https://www.percona.com/">Percona</a>.</p>]]></content:encoded>
    <pubDate>Fri, 01 May 2026 01:55:40 +0000</pubDate>
    <dc:creator>MySQL Performance Blog</dc:creator>
    <category>Cloud</category>
    <category>MySQL</category>
    <category>Percona Software</category>
  </item>

  <item>
    <title>MySQL Tuning on OCI HeatWave: What Still Matters, What OCI Manages, and What You Should Actually Tune</title>
    <guid isPermaLink="false">e2f499f811bbe02ae54aba0d200ae1bd</guid>
    <link>https://blogs.oracle.com/mysql/mysql-tuning-on-oci-heatwave-what-still-matters-what-oci-manages-and-what-you-should-actually-tune</link>
    <description>Once you move from self-managed MySQL to a MySQL DB System with HeatWave on OCI, the tuning story changes in an important way. On a self-managed server, you worry about two layers: MySQL and the operating system. On OCI MySQL DB Systems with HeatWave, Oracle runs your MySQL instance as a fully-managed service and explicitly […]</description>
    <pubDate>Thu, 30 Apr 2026 20:13:58 +0000</pubDate>
    <dc:creator>Oracle MySQL Group</dc:creator>
    <category>HeatWave AI</category>
    <category>MySQL</category>
    <category>MySQL HeatWave</category>
  </item>

  <item>
    <title>No More Silent Foreign Key Cascades: MySQL 9.7 Lets Child Triggers Speak Up</title>
    <guid isPermaLink="false">d07e9482743d52c4b09c79de4a813845</guid>
    <link>https://blogs.oracle.com/mysql/no-more-silent-foreign-key-cascades-mysql-9-7-lets-child-triggers-speak-up</link>
    <description>MySQL 9.7 introduces a long-requested improvement: Child table triggers are executed during SQL-layer foreign key cascades. Historically, cascades executed inside InnoDB did not invoke child table triggers, which created gaps in auditing, derived data maintenance, and observability. When a parent row change triggered cascading changes in child tables, those child table triggers were not executed. This […]</description>
    <pubDate>Thu, 30 Apr 2026 05:37:57 +0000</pubDate>
    <dc:creator>Oracle MySQL Group</dc:creator>
    <category>mysql</category>
    <category>mysqlcommunity</category>
  </item>

  <item>
    <title>Announcing Vitess 24</title>
    <guid isPermaLink="false">https://vitess.io/blog/2026-04-30-announcing-vitess-24/</guid>
    <link>https://vitess.io/blog/2026-04-30-announcing-vitess-24/</link>
    <description>Announcing Vitess 24 # The Vitess maintainers are happy to announce the release of version 24.0.0, along with version 2.17.0 of the Vitess Kubernetes Operator.
Version 24.0.0 expands query serving capabilities for sharded keyspaces, modernizes Vitess's observability stack, and introduces faster replica provisioning through native MySQL CLONE support. The companion v2.17.0 operator release brings significant improvements to scheduled backups, with new cluster- and keyspace-level schedules that make production backup management much easier to configure at scale.</description>
    <pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate>
    <dc:creator>Vitess</dc:creator>
    <category>release</category>
    <category>Vitess</category>
    <category>v24</category>
    <category>MySQL</category>
    <category>kubernetes</category>
    <category>operator</category>
    <category>vreplication</category>
    <category>tracing</category>
    <category>observability</category>
    <category>backup</category>
  </item>

  <item>
    <title>AI Is Raising the Bar for MySQL Database Security</title>
    <guid isPermaLink="false">73189ab761820afcaa529b3a1fe8b394</guid>
    <link>https://blogs.oracle.com/mysql/ai-is-raising-the-bar-for-mysql-database-security</link>
    <description>Best practices for MySQL customers and users in an AI-accelerated security landscape: A practical guide to hardening MySQL and the environment around it Oracle recently described how AI is transforming vulnerability detection and response. The latest generation of AI is increasing the speed and scale at which vulnerabilities can be identified and remediated. Oracle is […]</description>
    <pubDate>Wed, 29 Apr 2026 23:51:05 +0000</pubDate>
    <dc:creator>Oracle MySQL Group</dc:creator>
    <category>MySQL</category>
    <category>MySQL Community</category>
    <category>MySQL Enterprise</category>
    <category>AI security</category>
    <category>mysql</category>
    <category>mysqlcommunity</category>
    <category>Security</category>
  </item>

  <item>
    <title>XtraBackup incremental prepare phase is 2x-3x faster!</title>
    <guid isPermaLink="false">https://www.percona.com/?p=44623</guid>
    <link>https://www.percona.com/blog/xtrabackup-incremental-prepare-phase-is-2x-3x-faster/</link>
    <description>TL;DR
Percona XtraBackup is a 100% open-source backup solution for Percona Server for MySQL and MySQL®. It is designed for high-availability environments, performing online, non-blocking, and highly secure backups of transactional systems without interrupting your production traffic.
While full backups work for small databases, large-scale systems rely on incremental backups to save space and time. However, the “prepare” stage, required to make the incremental backups consistent, was slow because XtraBackup processed the .delta files serially. The .delta files are generated per table and store only the modifications since the last backup.
Great news! In XtraBackup versions 8.0.35-33 and 8.4.0-3 and later, we’ve added support for the --parallel option during the prepare stage. This option lets XtraBackup process multiple .delta files simultaneously, significantly reducing the preparation time, especially when you have a large number of IBD files.
Please add --parallel=X, with the number of threads to use, to the xtrabackup --prepare --apply-log-only command to speed up the incremental prepare operation.
The Incremental Backup Workflow
Before we dive into the performance gains, it’s important to understand how Incremental backups work.
1. Creating the Backups
The process starts with a full backup followed by a backup that captures the changes since the last backup. This smaller backup is called an incremental backup. XtraBackup creates .delta files during incremental backups. Let’s review an example.

Take Full Backup: Your starting point is Point A. This backup is an entire copy of your data.
Take Inc1 Backup: XtraBackup identifies the changes between Point A and Point B. It creates a .delta file for every table that has been changed. Delta files contain only the pages that changed between the backups.
Take Inc2 Backup: XtraBackup identifies the changes between Point B and Point C. It creates a new set of .delta files for this specific period.

For more detailed steps/commands, please check the documentation here: https://docs.percona.com/percona-xtrabackup/8.0/create-incremental-backup.html
2. Preparing the Backups
To restore the data to the latest point, you must merge these changes back into the full backup. The “prepare” phase works differently here:

Prepare Inc1: You merge the Inc1 changes into the full backup using the --apply-log-only option. In this step, XtraBackup applies the .delta files and the redo logs, but does not apply the Undo logs
Prepare Inc2: You merge the Inc2 changes into the updated base using the --apply-log-only option. XtraBackup applies the .delta files and the Redo logs but skips the Undo logs.
Final Prepare: After all the incremental backups are merged, you run a final prepare command on the full backup. This final step applies the Undo logs to make the entire dataset consistent. If you apply the Undo logs during the intermediate steps, you cannot merge any further backups.

More detailed steps to prepare an incremental backup are described here: https://docs.percona.com/percona-xtrabackup/8.0/prepare-incremental-backup.html
The Improvement: Parallel Incremental Delta Apply
We have improved the Incremental Delta Apply phase. These are “Prepare inc1” and “Prepare inc2” phases as described above. --parallel option should be used along with the --apply-log-only to apply the .delta files in parallel.
We completed this essential improvement as part of [PXB-3427].
In previous versions, XtraBackup applied the .delta files as soon as a file was discovered in the incremental backup directory. Starting with versions 8.0.35-33 and 8.4.0-3, to apply the .delta files, XtraBackup scans the backup directory and builds a queue of delta files. Multiple threads (defined by --parallel ) consume this queue simultaneously. Each thread reads a .delta file and writes its pages to the corresponding InnoDB Data File (.ibd file).
Benchmarks
This benchmark is created using the scripts, and the instructions are in JIRA: PXB-3427

When your backup contains a large number of small .delta files, increasing the --parallel value can drastically reduce the time taken to prepare the incremental backup by distributing the high per-file overhead across more threads. However, for other categories with fewer or larger files, performance typically plateaus after 16 threads, and pushing higher can even lead to slight regressions due to thread management overhead. While there is no single “golden value” to recommend for every scenario, we recommend starting with a value of 8 to find the optimal balance for your specific environment.
Disk Utilization with XtraBackup prepare using --parallel=1 vs --parallel=64
The PMM graphs below show the Disk IOPs used by the XtraBackup prepare command. The graph is generated when XtraBackup applies the incremental backup to a full backup directory. Incremental backup directory that has 20,608 .delta files, each of which is 2.5 MB.
With --parallel=1

With --parallel=1, max Disk IOPs utilized is 18.2 K, and the XtraBackup prepare operation finished in 3.76 minutes.
With --parallel=64


 
With --parallel=64, the max Disk Write IOPs utilized is 85K, and the XtraBackup prepare operation finished in around a minute. XtraBackup utilized 4.67x more disk IOPS and finished 3.49x faster.
Results from the bug reporter
We saw some amazing results shared by the reporter on PXB-3427.  The time required for XtraBackup prepare command (--prepare --apply-log-only)  to complete, reduced from 237 minutes to just 6 minutes. That’s an incredible 40X speed-up!
Here are the details from their setup:

Full backup: 235,188 *.ibd files
Incremental backup: 236,214 *.ibd.delta files
Average .delta size: 53,041 bytes (~53KB)
Threads used: 48 (–parallel=48)
Disk specs: 25K IOPS performance and an average of 500 to 600 MB/s of throughput

We hear you! This specific feature came to us from a post on the community forum. We reached out, asked them to create a JIRA ticket, and then implemented the improvement. We wanted to share this story as a demonstration of our commitment to listening to and acting on community feedback!
The post XtraBackup incremental prepare phase is 2x-3x faster! appeared first on Percona.</description>
    <content:encoded><![CDATA[<h2><b>TL;DR</b></h2>
<p><b>Percona XtraBackup</b> is a 100% open-source backup solution for Percona Server for MySQL and MySQL®. It is designed for high-availability environments, performing online, non-blocking, and highly secure backups of transactional systems without interrupting your production traffic.</p>
<p>While <a href="https://docs.percona.com/percona-xtrabackup/8.0/create-full-backup.html">full backups</a> work for small databases, large-scale systems rely on <a href="https://docs.percona.com/percona-xtrabackup/8.0/create-incremental-backup.html"><b>incremental backups</b></a> to save space and time. However, the “prepare” stage, required to make the incremental backups consistent, was slow because XtraBackup processed the .delta files serially. The .delta files are generated per table and store only the modifications since the last backup.</p>
<p>Great news! In XtraBackup versions <span><b>8.0.35-33</b></span> and <span><b>8.4.0-3</b></span> and later, we’ve added support for the <code><a href="https://docs.percona.com/percona-xtrabackup/8.0/xtrabackup-option-reference.html#parallel">--parallel</a></code> option during the prepare stage. This option lets XtraBackup process multiple .delta files simultaneously, <i>significantly</i> reducing the preparation time, especially when you have a large number of IBD files.</p>
<p>Please add <code><i><strong>--parallel=X</strong></i></code>, with the number of threads to use, to the <code><i><strong>xtrabackup --prepare --apply-log-only</strong></i></code> command to speed up the<a href="https://docs.percona.com/percona-xtrabackup/8.0/prepare-incremental-backup.html#faster-prepare-step-with-parallel"> incremental prepare</a> operation.</p>
<h2><b>The Incremental Backup Workflow</b></h2>
<p>Before we dive into the performance gains, it’s important to understand how Incremental backups work.</p>
<h3><b>1. Creating the Backups</b></h3>
<p>The process starts with a full backup followed by a backup that captures the changes since the last backup. This smaller backup is called an incremental backup. XtraBackup creates .delta files during incremental backups. Let’s review an example.</p>
<ul>
<li aria-level="1"><b>Take Full Backup:</b> Your starting point is Point A. This backup is an entire copy of your data.</li>
<li aria-level="1"><b>Take Inc1 Backup:</b> XtraBackup identifies the changes between Point A and Point B. It creates a .delta file for every table that has been changed. Delta files contain only the pages that changed between the backups.</li>
<li aria-level="1"><b>Take Inc2 Backup:</b> XtraBackup identifies the changes between Point B and Point C. It creates a new set of .delta files for this specific period.</li>
</ul>
<p>For more detailed steps/commands, please check the documentation here: <a href="https://docs.percona.com/percona-xtrabackup/8.0/create-incremental-backup.html">https://docs.percona.com/percona-xtrabackup/8.0/create-incremental-backup.html</a></p>
<h3><b>2. Preparing the Backups</b></h3>
<p>To restore the data to the latest point, you must merge these changes back into the full backup. The “prepare” phase works differently here:</p>
<ul>
<li aria-level="1"><b>Prepare Inc1:</b> You merge the Inc1 changes into the full backup using the <code><i>--apply-log-only</i></code> option. In this step, XtraBackup applies the .delta files and the redo logs, but does <b>not</b> apply the Undo logs</li>
<li aria-level="1"><b>Prepare Inc2:</b> You merge the Inc2 changes into the updated base using the <code><i>--apply-log-only</i></code> option. XtraBackup applies the .delta files and the Redo logs but skips the Undo logs.</li>
<li aria-level="1"><b>Final Prepare:</b> After all the incremental backups are merged, you run a final prepare command on the full backup. This final step applies the <b>Undo logs</b> to make the entire dataset consistent. If you apply the Undo logs during the intermediate steps, you cannot merge any further backups.</li>
</ul>
<p>More detailed steps to prepare an incremental backup are described here: <a href="https://docs.percona.com/percona-xtrabackup/8.0/prepare-incremental-backup.html">https://docs.percona.com/percona-xtrabackup/8.0/prepare-incremental-backup.html</a></p>
<h2><b>The Improvement: Parallel Incremental Delta Apply</b></h2>
<p>We have improved the <b>Incremental Delta Apply</b> phase. These are “<b>Prepare inc1”</b> and “<b>Prepare inc2</b>” phases as described above. <code><a href="https://docs.percona.com/percona-xtrabackup/8.0/xtrabackup-option-reference.html#parallel">--parallel</a></code> option should be used along with the <code>--apply-log-only</code> to apply the .delta files in parallel.</p>
<p>We completed this essential improvement as part of <b>[</b><a href="https://perconadev.atlassian.net/browse/PXB-3427"><b>PXB-3427</b></a><b>]</b>.</p>
<p>In previous versions, XtraBackup applied the .delta files as soon as a file was discovered in the incremental backup directory. Starting with versions <b>8.0.35-33</b> and <b>8.4.0-3</b>, to apply the .delta files, XtraBackup scans the backup directory and builds a queue of delta files. Multiple threads (defined by <code><a href="https://docs.percona.com/percona-xtrabackup/8.0/xtrabackup-option-reference.html#parallel">--parallel</a></code> ) consume this queue simultaneously. Each thread reads a .delta file and writes its pages to the corresponding InnoDB Data File (.ibd file).</p>
<h2><b>Benchmarks</b></h2>
<p>This benchmark is created using the scripts, and the instructions are in JIRA: <a href="https://perconadev.atlassian.net/browse/PXB-3427?focusedCommentId=454634">PXB-3427</a></p>
<p><img loading="lazy" decoding="async" class="alignnone size-large wp-image-44624" src="https://www.percona.com/wp-content/uploads/2026/04/prepare_performance_plot-1024x640.png" alt="xtrabackup prepare performance" width="1024" height="640" srcset="https://www.percona.com/wp-content/uploads/2026/04/prepare_performance_plot-1024x640.png 1024w, https://www.percona.com/wp-content/uploads/2026/04/prepare_performance_plot-300x188.png 300w, https://www.percona.com/wp-content/uploads/2026/04/prepare_performance_plot-768x480.png 768w, https://www.percona.com/wp-content/uploads/2026/04/prepare_performance_plot-1536x960.png 1536w, https://www.percona.com/wp-content/uploads/2026/04/prepare_performance_plot-2048x1280.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px"></p>
<p>When your backup contains a large number of small .delta files, increasing the <code><a href="https://docs.percona.com/percona-xtrabackup/8.0/xtrabackup-option-reference.html#parallel">--parallel</a></code> value can drastically reduce the time taken to prepare the incremental backup by distributing the high per-file overhead across more threads. However, for other categories with fewer or larger files, performance typically plateaus after <b>16 threads</b>, and pushing higher can even lead to slight regressions due to thread management overhead. While there is no single “golden value” to recommend for every scenario, we recommend starting with a value of <b>8</b> to find the optimal balance for your specific environment.</p>
<h2><b>Disk Utilization with XtraBackup prepare using <code>--parallel=1</code> vs <code>--parallel=64</code></b></h2>
<p>The <a href="https://www.percona.com/monitoring/">PMM</a> graphs below show the Disk IOPs used by the XtraBackup prepare command. The graph is generated when XtraBackup applies the incremental backup to a full backup directory. Incremental backup directory that has 20,608 .delta files, each of which is 2.5 MB.</p>
<h3><b>With <code>--parallel=1</code></b></h3>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-44625" src="https://www.percona.com/wp-content/uploads/2026/04/parallel_00.png" alt="xtrabackup incremental disk IOPs with --parllel=1" width="713" height="392" srcset="https://www.percona.com/wp-content/uploads/2026/04/parallel_00.png 713w, https://www.percona.com/wp-content/uploads/2026/04/parallel_00-300x165.png 300w" sizes="auto, (max-width: 713px) 100vw, 713px"></p>
<p>With <code>--parallel=1</code>, max Disk IOPs utilized is 18.2 K, and the XtraBackup prepare operation finished in 3.76 minutes.</p>
<h3><b>With <code>--parallel=64</code></b><b><br>
</b></h3>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-44626" src="https://www.percona.com/wp-content/uploads/2026/04/parallel_64_11.png" alt="xtrabackup incremental delta prepare performance with parallel 64" width="719" height="404" srcset="https://www.percona.com/wp-content/uploads/2026/04/parallel_64_11.png 719w, https://www.percona.com/wp-content/uploads/2026/04/parallel_64_11-300x169.png 300w" sizes="auto, (max-width: 719px) 100vw, 719px"></p>
<p> </p>
<p>With <code><strong>--parallel=64</strong></code>, the max Disk Write IOPs utilized is 85K, and the XtraBackup prepare operation finished in around a minute. XtraBackup utilized<b> 4.67x</b> more disk IOPS and finished <b>3.49x</b> faster.</p>
<h2><b>Results from the bug reporter</b></h2>
<p>We saw some amazing results shared by the reporter on <a href="https://perconadev.atlassian.net/browse/PXB-3427">PXB-3427</a>.  The time required for XtraBackup prepare command (<code>--prepare --apply-log-only</code>)  to complete, reduced from <b>237 minutes to just 6 minutes</b>. That’s an incredible <b>40X speed-up</b>!</p>
<p>Here are the details from their setup:</p>
<ul>
<li aria-level="1"><b>Full backup:</b> 235,188 *.ibd files</li>
<li aria-level="1"><b>Incremental backup:</b> 236,214 *.ibd.delta files</li>
<li aria-level="1"><b>Average </b><b>.delta</b><b> size:</b> 53,041 bytes (~53KB)</li>
<li aria-level="1"><b>Threads used:</b> 48 (–parallel=48)</li>
<li aria-level="1"><b>Disk specs:</b> 25K IOPS performance and an average of 500 to 600 MB/s of throughput</li>
</ul>
<p><b>We hear you!</b> This specific feature came to us from a post on the community <a href="https://forums.percona.com/t/mysql-8-4-disabling-innodb-redo-log-during-restore-safe-practice/35675">forum</a>. We reached out, asked them to create a JIRA ticket, and then implemented the improvement. We wanted to share this story as a demonstration of our commitment to listening to and acting on community feedback!</p>
<p>The post <a href="https://www.percona.com/blog/xtrabackup-incremental-prepare-phase-is-2x-3x-faster/">XtraBackup incremental prepare phase is 2x-3x faster!</a> appeared first on <a href="https://www.percona.com/">Percona</a>.</p>]]></content:encoded>
    <pubDate>Wed, 29 Apr 2026 18:52:44 +0000</pubDate>
    <dc:creator>MySQL Performance Blog</dc:creator>
    <category>MySQL</category>
    <category>Open Source</category>
    <category>Xtrabackup</category>
    <category>.delta file</category>
    <category>apply-log-only</category>
    <category>incremental</category>
    <category>incremental backup</category>
    <category>MySQL Backup</category>
    <category>MySQL Backup tools</category>
    <category>Percona XtraBackup</category>
    <category>prepare</category>
    <category>xtrabackup</category>
  </item>

  <item>
    <title>Orchestrator’s Next Chapter: What It Means for Percona Customers</title>
    <guid isPermaLink="false">https://www.percona.com/?p=45274</guid>
    <link>https://www.percona.com/blog/orchestrators-next-chapter-what-it-means-for-percona-customers/</link>
    <description>Last week, ProxySQL announced that they are taking over the maintenance and development of Orchestrator, the MySQL high-availability and topology management tool originally authored by Shlomi Noach. You can read their announcement here: Announcing the future of Orchestrator.
We want to briefly share Percona’s position on the news.
We welcome this
Orchestrator became the de facto standard for MySQL topology management and automated failover, and it has been a foundational tool in the ecosystem for over a decade. When the upstream project was archived, many operators were left running internal forks. A revived project under active development, with a stated roadmap and continued Apache 2.0 licensing, is good news for the MySQL community, and we’re glad to see ProxySQL step up to take it on. Thanks are due to Shlomi Noach for creating Orchestrator in the first place, and to everyone who contributed to it over the years.
A small clarification on Percona’s role
The ProxySQL announcement kindly credited Percona alongside GitHub for “stewardship over the years.” To be accurate: Percona has never been a maintainer of the upstream Orchestrator project. What we have done, and will continue to do, is support our customers who rely on it. That includes operational guidance, troubleshooting, and carrying internal patches where a customer situation requires it. The upstream project itself has always lived with Shlomi and later with the team at GitHub.
Nothing changes for Percona customers
If you are a Percona customer running Orchestrator today, your support experience is unchanged. We will continue helping you operate it in production, diagnose issues, and plan around its role in your high-availability stack. That commitment is steady regardless of where the upstream project lives.
Orchestrator’s maintenance also matters to us beyond support engagements. Percona Operator for MySQL uses Orchestrator to manage asynchronous topologies, so our own product depends on the project staying healthy. That’s part of why we plan to coordinate closely with the ProxySQL team as the next chapter unfolds.
Coordinating with the ProxySQL team
We plan to open coordination conversations with the ProxySQL team to make sure that operators running Orchestrator today, including our customers, have a smooth path as the project evolves. We wish the ProxySQL team well in this next chapter and look forward to supporting the community alongside them.
If you’re a Percona customer, reach out to your account team with any questions about your Orchestrator deployment. If you’re running Orchestrator outside of a Percona engagement and want to talk through support options, get in touch with our MySQL team.
 

The post Orchestrator’s Next Chapter: What It Means for Percona Customers appeared first on Percona.</description>
    <content:encoded><![CDATA[<p>Last week, ProxySQL announced that they are taking over the maintenance and development of Orchestrator, the MySQL high-availability and topology management tool originally authored by Shlomi Noach. You can read their announcement here: <a href="https://proxysql.com/blog/announcing-proxysql-takes-over-orchestrator/" target="_blank" rel="noopener">Announcing the future of Orchestrator</a>.</p>
<p>We want to briefly share Percona’s position on the news.</p>
<h4>We welcome this</h4>
<p>Orchestrator became the de facto standard for MySQL topology management and automated failover, and it has been a foundational tool in the ecosystem for over a decade. When the upstream project was archived, many operators were left running internal forks. A revived project under active development, with a stated roadmap and continued Apache 2.0 licensing, is good news for the MySQL community, and we’re glad to see ProxySQL step up to take it on. Thanks are due to Shlomi Noach for creating Orchestrator in the first place, and to everyone who contributed to it over the years.</p>
<h4>A small clarification on Percona’s role</h4>
<p>The ProxySQL announcement kindly credited Percona alongside GitHub for “stewardship over the years.” To be accurate: Percona has never been a maintainer of the upstream Orchestrator project. What we have done, and will continue to do, is support our customers who rely on it. That includes operational guidance, troubleshooting, and carrying internal patches where a customer situation requires it. The upstream project itself has always lived with Shlomi and later with the team at GitHub.</p>
<h4>Nothing changes for Percona customers</h4>
<p>If you are a Percona customer running Orchestrator today, your support experience is unchanged. We will continue helping you operate it in production, diagnose issues, and plan around its role in your high-availability stack. That commitment is steady regardless of where the upstream project lives.</p>
<p>Orchestrator’s maintenance also matters to us beyond support engagements. Percona Operator for MySQL uses Orchestrator to manage asynchronous topologies, so our own product depends on the project staying healthy. That’s part of why we plan to coordinate closely with the ProxySQL team as the next chapter unfolds.</p>
<h4>Coordinating with the ProxySQL team</h4>
<p>We plan to open coordination conversations with the ProxySQL team to make sure that operators running Orchestrator today, including our customers, have a smooth path as the project evolves. We wish the ProxySQL team well in this next chapter and look forward to supporting the community alongside them.</p>
<p>If you’re a Percona customer, reach out to your account team with any questions about your Orchestrator deployment. If you’re running Orchestrator outside of a Percona engagement and want to talk through support options, <a href="https://www.percona.com/mysql/support/">get in touch with our MySQL team</a>.</p>
<p> </p>
<p><!-- notionvc: 1a4652ac-6c9a-433e-8656-d58627a32d40 --></p>
<p>The post <a href="https://www.percona.com/blog/orchestrators-next-chapter-what-it-means-for-percona-customers/">Orchestrator’s Next Chapter: What It Means for Percona Customers</a> appeared first on <a href="https://www.percona.com/">Percona</a>.</p>]]></content:encoded>
    <pubDate>Wed, 29 Apr 2026 17:55:10 +0000</pubDate>
    <dc:creator>MySQL Performance Blog</dc:creator>
    <category>Cloud</category>
    <category>Kubernetes</category>
    <category>MySQL</category>
    <category>Operator</category>
    <category>ProxySQL</category>
  </item>

  <item>
    <title>Introducing the Change Stream Applier (CSA): A New MySQL Replication Applier in Labs</title>
    <guid isPermaLink="false">d58830a866aaa70e1e7b98f4dcb178ed</guid>
    <link>https://blogs.oracle.com/mysql/introducing-the-change-stream-applier-csa-a-new-mysql-replication-applier-in-labs</link>
    <description>Introduction Replication performance depends on every stage in the pipeline, from the source database to transport and ultimately to commit on the replica. On the replica side, much of that performance comes down to how efficiently changes are read, scheduled, and applied under real operational pressure. In practice, that directly affects steady-state lag, backlog recovery […]</description>
    <pubDate>Wed, 29 Apr 2026 13:39:58 +0000</pubDate>
    <dc:creator>Oracle MySQL Group</dc:creator>
    <category>MySQL</category>
    <category>MySQL Community</category>
    <category>Database</category>
    <category>mysql</category>
    <category>mysqlcommunity</category>
    <category>OpenSource</category>
    <category>Performance</category>
    <category>Replication</category>
  </item>

  <item>
    <title>The hypergraph optimizer is now available in MySQL 9.7 Community Edition</title>
    <guid isPermaLink="false">tag:blogger.com,1999:blog-1508669603650457962.post-3998264298444207249</guid>
    <link>https://oysteing.blogspot.com/2026/04/the-hypergraph-optimizer-is-now.html</link>
    <description>I have written a new post on the MySQL blog about the hypergraph optimizer, which is now available in MySQL 9.7 Community Edition.

The post gives a high-level technical overview of what is different from the classic join optimizer, why it can produce better plans for some multi-table queries, and where it is most useful to try. It also includes early benchmark results and some caveats, since the feature is still evolving and remains off by default.</description>
    <content:encoded><![CDATA[I have written a <a href="https://blogs.oracle.com/mysql/the-hypergraph-optimizer-is-now-available-in-mysql-9-7-community-edition">new post on the MySQL blog</a> about the hypergraph optimizer, which is now available in MySQL 9.7 Community Edition.

The post gives a high-level technical overview of what is different from the classic join optimizer, why it can produce better plans for some multi-table queries, and where it is most useful to try. It also includes early benchmark results and some caveats, since the feature is still evolving and remains off by default.]]></content:encoded>
    <pubDate>Tue, 28 Apr 2026 14:15:00 +0000</pubDate>
    <dc:creator>Øystein Grøvlen</dc:creator>
  </item>

  <item>
    <title>Strengthening the MySQL Community: Highlights from Our Third Public Discussion</title>
    <guid isPermaLink="false">3b7c05af1f41f2653323d715e84efc28</guid>
    <link>https://blogs.oracle.com/mysql/strengthening-the-mysql-community-highlights-from-our-third-public-discussion</link>
    <description>On April 21, 2026, our third public discussion continued the conversation around transparency, participation, and the future of MySQL. Building on the momentum from earlier sessions, the discussion focused on progress and improvements to increase community transparency and practical ways for community members to get involved. At the center of the discussion was the MySQL […]</description>
    <pubDate>Mon, 27 Apr 2026 23:56:35 +0000</pubDate>
    <dc:creator>Oracle MySQL Group</dc:creator>
    <category>MySQL</category>
    <category>MySQL Community</category>
    <category>mysql</category>
    <category>mysqlcommunity</category>
  </item>

  <item>
    <title>The hypergraph optimizer is now available in MySQL 9.7 Community Edition</title>
    <guid isPermaLink="false">e0c08cd68eec3f87536af225eab041bc</guid>
    <link>https://blogs.oracle.com/mysql/the-hypergraph-optimizer-is-now-available-in-mysql-9-7-community-edition</link>
    <description>MySQL 9.7 Community Edition now includes the hypergraph optimizer as an alternative to the classic join optimizer, making this capability available across all MySQL editions. This is not a cosmetic change. The hypergraph optimizer uses a new join-planning framework aimed at queries where plan shape can make a real difference, particularly for multi-table joins, workloads […]</description>
    <pubDate>Mon, 27 Apr 2026 17:19:22 +0000</pubDate>
    <dc:creator>Oracle MySQL Group</dc:creator>
    <category>MySQL</category>
    <category>MySQL Community</category>
    <category>hypergraph optimizer</category>
    <category>mysql</category>
    <category>query optimization</category>
  </item>

</channel>
</rss>
