<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged data-migration</title>
<link>https://coderlegion.com/tag/data-migration</link>
<description>Powered by Question2Answer</description>
<item>
<title>The Legacy Report Was Going Away. The Agent Still Needed the Answer.</title>
<link>https://coderlegion.com/32464/the-legacy-report-was-going-away-the-agent-still-needed-the-answer</link>
<description>&lt;p&gt;&lt;em&gt;An anonymized banking modernization case study about replacing SAS-backed operational reports with APIs that agents could use in Salesforce.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Imagine an agent opening a fraud or exception report during a customer call. The report appears in a legacy system, but the agent’s real task is to make a timely, authorized decision. If the system is retired and the same answer becomes slow, incomplete, or visible to the wrong person, the migration has failed—even if the new application looks better.&lt;/p&gt;
&lt;p&gt;That was the challenge in a banking modernization program I worked on. Operational and business reporting functionality hosted on SAS needed to move into a Salesforce-centered workflow. My responsibilities included designing Spring Boot GET APIs for several report domains, connecting the service to Snowflake, applying agent role-based access, and exposing the endpoints to the Salesforce team. The architecture below is deliberately simplified; it describes the engineering pattern without disclosing internal systems or customer data.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=9107409727456458812&quot; alt=&quot;Simplified architecture: agent in Salesforce requests a report through a role-aware Spring Boot API backed by Snowflake&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;first-migrate-the-decision-not-the-screen&quot;&gt;First, migrate the decision—not the screen&lt;/h3&gt;
&lt;p&gt;A legacy report often contains more than a table. It can encode filters, calculations, refresh timing, exception definitions, and the habits people have built around it. Copying its columns into a new UI does not prove that an agent receives the same answer.&lt;/p&gt;
&lt;p&gt;For each report, the useful questions were: &lt;strong&gt;Who uses it? Which decision does it support? What does each field mean? How fresh must it be? What should happen when the data is missing?&lt;/strong&gt; These questions turn a screen replacement into a contract that the new service can implement and test.&lt;/p&gt;
&lt;p&gt;An example is an exception report. A row count can match while the underlying definition of “open” changes, or a date filter shifts at midnight in a different time zone. The result looks plausible, but an agent may follow up on the wrong cases. A migration test therefore needs representative records and business-rule comparisons, not only a schema check.&lt;/p&gt;
&lt;h3 id=&quot;put-a-stable-api-between-salesforce-and-reporting-data&quot;&gt;Put a stable API between Salesforce and reporting data&lt;/h3&gt;
&lt;p&gt;We used RESTful GET endpoints to give the Salesforce experience a focused way to request report data. A service layer can validate inputs, apply business rules, authorize the caller, query Snowflake, and return a consistent response contract. It also gives the UI team a stable interface while the data or report logic evolves behind it.&lt;/p&gt;
&lt;p&gt;Salesforce documents a &lt;strong&gt;request-and-reply&lt;/strong&gt; integration pattern for user actions that call an external system and wait for the result. That pattern is useful for interactive reporting, but it makes latency and failure behavior part of the user experience. A timeout is not an empty report. The API should distinguish “no matching records” from “the source was unavailable,” use bounded queries and pagination where appropriate, and make error states clear enough for the UI to handle.&lt;/p&gt;
&lt;p&gt;This service boundary also limits how much reporting logic leaks into the frontend. The API should expose business concepts the agent understands rather than Snowflake table names or a direct translation of old SAS implementation details.&lt;/p&gt;
&lt;h3 id=&quot;access-control-must-follow-the-data-all-the-way-through&quot;&gt;Access control must follow the data all the way through&lt;/h3&gt;
&lt;p&gt;“The agent is signed into Salesforce” is only the start of an authorization decision. The backend still needs to know which report and which records that agent may access. Role checks at the API boundary protect the endpoint; data-scoped controls protect the result set. The two should agree, and denied access should be tested as carefully as successful access.&lt;/p&gt;
&lt;p&gt;Snowflake supports row access policies that determine which rows a query returns. They are one possible defense in depth, subject to the organization’s roles and policy design. They also affect query behavior and performance, so access rules should be validated with realistic report requests. The point is broader than a particular Snowflake feature: &lt;strong&gt;a correct report returned to the wrong role is a production defect.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For a banking workflow, logs and traces also need restraint. A useful audit trail records who requested which report, when, and whether it succeeded. It does not need to dump sensitive report contents into application logs.&lt;/p&gt;
&lt;h3 id=&quot;prove-the-new-path-under-production-like-conditions&quot;&gt;Prove the new path under production-like conditions&lt;/h3&gt;
&lt;p&gt;Functional tests answer whether the endpoint returns the right data for a known case. They do not answer whether a team of agents can use it at the same time on a busy morning. We developed performance tests with JMeter and Gatling to exercise the services against SLA requirements under load.&lt;/p&gt;
&lt;p&gt;A meaningful test model includes the report mix, concurrent users, query sizes, authorized and unauthorized requests, and the effect of a slow data source. Measure end-to-end response time from the agent-facing API, not just the time taken by one SQL query. Check the long tail as well as the average. If a report is large, test pagination and the cost of repeated requests. If a dependency fails, verify that the service fails clearly and recovers.&lt;/p&gt;
&lt;p&gt;I would also treat the cutover as a comparison exercise: sample the same business cases through the legacy and new paths, explain any differences, and have report owners validate them. Where old behavior was wrong, document the intended correction explicitly. Otherwise a “fixed” report can look like an unexplained regression to the people using it.&lt;/p&gt;
&lt;h3 id=&quot;what-this-kind-of-migration-teaches&quot;&gt;What this kind of migration teaches&lt;/h3&gt;
&lt;p&gt;The visible technology changes from SAS reports to Salesforce screens, Spring Boot APIs, and Snowflake queries. The hard part is preserving the &lt;strong&gt;meaning, access, and timing&lt;/strong&gt; of the answer that an agent needs.&lt;/p&gt;
&lt;p&gt;The reusable sequence is straightforward: inventory the decisions supported by each report; define the API contract and data semantics; enforce access at the service and data layers; compare old and new results; test peak traffic and failure modes; then cut over with clear ownership of discrepancies. That is how a platform retirement becomes a reliable workflow change instead of a prettier route to the wrong answer.&lt;/p&gt;
&lt;p&gt;What has been the hardest part of a legacy reporting migration in your experience: report logic, data quality, access control, or cutover?&lt;/p&gt;
&lt;h4 id=&quot;references&quot;&gt;References&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Salesforce, &lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.salesforce.com/docs/atlas.en-us.integration_patterns_and_practices.meta/integ_pat_patterns_platform.htm&quot;&gt;Integration Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Snowflake, &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.snowflake.com/en/user-guide/security-row-intro&quot;&gt;Understanding row access policies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Apache JMeter, &lt;a rel=&quot;nofollow&quot; href=&quot;https://jmeter.apache.org/usermanual/index.html&quot;&gt;User's Manual&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Gatling, &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.gatling.io/&quot;&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/32464/the-legacy-report-was-going-away-the-agent-still-needed-the-answer</guid>
<pubDate>Mon, 26 Oct 2026 04:08:02 +0000</pubDate>
</item>
<item>
<title>MySQL HeatWave: Migrating Your Data to HeatWave Service</title>
<link>https://coderlegion.com/7832/mysql-heatwave-migrating-your-data-to-heatwave-service</link>
<description>&lt;p&gt;Migrating data to MySQL HeatWave is a critical step in leveraging the cloud's power for your database workloads. MySQL Shell dump utilities provide the recommended method for exporting data from source MySQL databases and importing them into HeatWave DB systems. These utilities offer HeatWave-specific compatibility checks, parallel processing, and automatic modifications to ensure smooth migrations.&lt;/p&gt;
&lt;p&gt;This guide covers dump utilities, compatibility checks, and best practices for successful data migration to MySQL HeatWave.&lt;/p&gt;
&lt;h3 id=&quot;understanding-data-migration&quot;&gt;Understanding Data Migration&lt;/h3&gt;
&lt;p&gt;Data migration to MySQL HeatWave involves moving data from a source MySQL database (on-premises, cloud, or other infrastructure) to a target MySQL HeatWave DB system in Oracle Cloud Infrastructure.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Migration Process&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Export data from source using MySQL Shell dump utilities&lt;/li&gt;
&lt;li&gt;Store dump files in OCI Object Storage or locally&lt;/li&gt;
&lt;li&gt;Run compatibility checks for HeatWave&lt;/li&gt;
&lt;li&gt;Apply necessary modifications&lt;/li&gt;
&lt;li&gt;Import data into HeatWave DB system using &lt;code&gt;util.loadDump()&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;mysql-shell-dump-utilities&quot;&gt;MySQL Shell Dump Utilities&lt;/h3&gt;
&lt;p&gt;MySQL Shell provides three dump utilities: util.dumpInstance(), util.dumpSchemas(), and util.dumpTables(). Each serves different migration scenarios.&lt;/p&gt;
&lt;h4 id=&quot;1-util-dumpinstance-&quot;&gt;1. util.dumpInstance()&lt;/h4&gt;
&lt;p&gt;Exports all compatible schemas to Object Storage bucket or local files, including users, events, routines, and triggers by default&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What It Exports&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All user schemas (excludes system schemas)&lt;/li&gt;
&lt;li&gt;User accounts and privileges&lt;/li&gt;
&lt;li&gt;Events, routines, and triggers&lt;/li&gt;
&lt;li&gt;Complete database structure&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;What It Excludes&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;System schemas: mysql, sys, performance_schema, information_schema, ndbinfo&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example Usage&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;util.dumpInstance(&quot;/path/to/dump&quot;, {
  ocimds: true,
  threads: 8,
  compatibility: [&quot;force_innodb&quot;, &quot;strip_definers&quot;, &quot;strip_tablespaces&quot;]
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;To Object Storage&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;util.dumpInstance(&quot;&quot;, {
  osBucketName: &quot;myMigrationBucket&quot;,
  osNamespace: &quot;my-namespace&quot;,
  ocimds: true,
  threads: 16,
  compatibility: [&quot;force_innodb&quot;, &quot;strip_definers&quot;, &quot;strip_restricted_grants&quot;, 
                  &quot;strip_tablespaces&quot;, &quot;create_invisible_pks&quot;]
})
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;2-util-dumpschemas-&quot;&gt;2. util.dumpSchemas()&lt;/h4&gt;
&lt;p&gt;Exports selected schemas with all tables, triggers, routines, and events of those schemas&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What It Exports&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All tables in specified schemas&lt;/li&gt;
&lt;li&gt;Triggers associated with tables&lt;/li&gt;
&lt;li&gt;Routines (stored procedures and functions)&lt;/li&gt;
&lt;li&gt;Events&lt;/li&gt;
&lt;li&gt;Views&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example Usage&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;util.dumpSchemas([&quot;sales&quot;, &quot;inventory&quot;, &quot;customers&quot;], &quot;/path/to/dump&quot;, {
  ocimds: true,
  threads: 4,
  compatibility: [&quot;force_innodb&quot;, &quot;strip_definers&quot;]
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Multiple Schemas to Object Storage&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;util.dumpSchemas(
  [&quot;tpch&quot;, &quot;employees&quot;], 
  &quot;&quot;, 
  {
    osBucketName: &quot;mysqlData&quot;,
    osNamespace: &quot;abcdefghijkl&quot;,
    ocimds: true,
    threads: 16,
    compatibility: [&quot;force_innodb&quot;, &quot;strip_restricted_grants&quot;, 
                    &quot;strip_definers&quot;, &quot;strip_tablespaces&quot;, &quot;create_invisible_pks&quot;]
  }
)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;3-util-dumptables-&quot;&gt;3. util.dumpTables()&lt;/h4&gt;
&lt;p&gt;Exports selected tables or views from a schema, including triggers of exported tables&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What It Exports&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Specified tables or views&lt;/li&gt;
&lt;li&gt;Triggers associated with those tables&lt;/li&gt;
&lt;li&gt;Schema structure needed to recreate tables&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example Usage&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;util.dumpTables(&quot;sales&quot;, [&quot;orders&quot;, &quot;order_items&quot;, &quot;customers&quot;], &quot;/path/to/dump&quot;, {
  ocimds: true,
  threads: 2,
  compatibility: [&quot;force_innodb&quot;]
})
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;dump-utility-options&quot;&gt;Dump Utility Options&lt;/h3&gt;
&lt;p&gt;Dump utilities support parallel dumping with multiple threads, file compression, OCI Object Storage streaming, and MySQL HeatWave compatibility checks and modifications&lt;/p&gt;
&lt;h4 id=&quot;essential-options&quot;&gt;Essential Options&lt;/h4&gt;
&lt;h5 id=&quot;ocimds&quot;&gt;ocimds&lt;/h5&gt;
&lt;p&gt;Enables HeatWave Service compatibility checks. When set to &lt;code&gt;true&lt;/code&gt;, the dump cannot proceed if incompatibilities exist.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ocimds: true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Critical&lt;/strong&gt;: Dumps loaded into HeatWave must be created with &lt;code&gt;ocimds: true&lt;/code&gt;.&lt;/p&gt;
&lt;h5 id=&quot;threads&quot;&gt;threads&lt;/h5&gt;
&lt;p&gt;Number of parallel threads for dump operation. More threads = faster dumps but higher source load.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;threads: 16  // Use 4-16 for most workloads
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;compatibility&quot;&gt;compatibility&lt;/h5&gt;
&lt;p&gt;Array of modifications to apply during export to ensure HeatWave compatibility.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;compatibility: [&quot;force_innodb&quot;, &quot;strip_definers&quot;, &quot;strip_tablespaces&quot;, 
                &quot;create_invisible_pks&quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;bytesperchunk&quot;&gt;bytesPerChunk&lt;/h5&gt;
&lt;p&gt;Defines chunk size for large datasets. Default is 64MB.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;bytesPerChunk: &quot;128M&quot;  // For large datasets
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;compression&quot;&gt;compression&lt;/h5&gt;
&lt;p&gt;Compression algorithm for dump files.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;compression: &quot;zstd&quot;  // Options: zstd (default), gzip, none
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;maxrate&quot;&gt;maxRate&lt;/h5&gt;
&lt;p&gt;Maximum data read throughput during dump (in bytes per second).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;maxRate: &quot;50M&quot;  // Limit to 50 MB/s to reduce source impact
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;advanced-options&quot;&gt;Advanced Options&lt;/h4&gt;
&lt;h5 id=&quot;dryrun&quot;&gt;dryRun&lt;/h5&gt;
&lt;p&gt;Displays what would be dumped and results of compatibility checks without proceeding&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mode: &quot;dryrun&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Always run dryRun first&lt;/strong&gt; to identify issues before actual export.&lt;/p&gt;
&lt;h5 id=&quot;consistent&quot;&gt;consistent&lt;/h5&gt;
&lt;p&gt;Ensures data consistency by using FLUSH TABLES WITH READ LOCK.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;consistent: true  // Default
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;excludeschemas-includeschemas&quot;&gt;excludeSchemas / includeSchemas&lt;/h5&gt;
&lt;p&gt;Filter which schemas to dump.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;excludeSchemas: [&quot;test&quot;, &quot;staging&quot;]
// Or
includeSchemas: [&quot;production&quot;, &quot;analytics&quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;excludetables-includetables&quot;&gt;excludeTables / includeTables&lt;/h5&gt;
&lt;p&gt;Filter tables within schemas (for dumpSchemas and dumpInstance).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;excludeTables: [&quot;sales.temp_*&quot;, &quot;logs.old_*&quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;defaultcharacterset&quot;&gt;defaultCharacterSet&lt;/h5&gt;
&lt;p&gt;Specify character set for dump files.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;defaultCharacterSet: &quot;utf8mb4&quot;  // Recommended
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;performing-a-dry-run&quot;&gt;Performing a Dry Run&lt;/h3&gt;
&lt;p&gt;Always perform a dry run before actual export to identify compatibility issues&lt;/p&gt;
&lt;h4 id=&quot;dry-run-command&quot;&gt;Dry Run Command&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;util.dumpInstance(&quot;&quot;, {
  mode: &quot;dryrun&quot;,
  ocimds: true
})
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;what-dry-run-does&quot;&gt;What Dry Run Does&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Connects to source database&lt;/li&gt;
&lt;li&gt;Analyzes schemas, tables, and objects&lt;/li&gt;
&lt;li&gt;Runs HeatWave compatibility checks&lt;/li&gt;
&lt;li&gt;Lists all objects to be dumped&lt;/li&gt;
&lt;li&gt;Reports compatibility issues&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Does not export any data&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;sample-dry-run-output&quot;&gt;Sample Dry Run Output&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;Checking for compatibility with MySQL HeatWave Service

Compatibility issues with MySQL HeatWave Service 8.0.32
1) Schema 'sales'
  Table 'legacy_orders' uses MyISAM storage engine (issue: engine)
  Table 'customers' has no primary key (issue: no_pk)
  View 'active_orders' has DEFINER='admin'@'localhost' (issue: definer)

2) Schema 'inventory'
  Table 'items' uses MyISAM storage engine (issue: engine)
  
Compatibility issues found. Use 'compatibility' option to apply modifications.
Suggested options: [&quot;force_innodb&quot;, &quot;strip_definers&quot;, &quot;create_invisible_pks&quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;heatwave-compatibility-checks&quot;&gt;HeatWave Compatibility Checks&lt;/h3&gt;
&lt;p&gt;Setting ocimds option to true enables compatibility checks that list all issues when instance is dumped&lt;/p&gt;
&lt;h4 id=&quot;common-compatibility-issues&quot;&gt;Common Compatibility Issues&lt;/h4&gt;
&lt;h5 id=&quot;1-non-innodb-storage-engines&quot;&gt;1. Non-InnoDB Storage Engines&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;Issue&lt;/strong&gt;: HeatWave only supports InnoDB&lt;br&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Use &lt;code&gt;force_innodb&lt;/code&gt; compatibility option&lt;/p&gt;
&lt;h5 id=&quot;2-missing-primary-keys&quot;&gt;2. Missing Primary Keys&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;Issue&lt;/strong&gt;: High Availability requires primary keys on all tables&lt;br&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Use &lt;code&gt;create_invisible_pks&lt;/code&gt; or &lt;code&gt;ignore_missing_pks&lt;/code&gt;&lt;/p&gt;
&lt;h5 id=&quot;3-definer-clauses&quot;&gt;3. DEFINER Clauses&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;Issue&lt;/strong&gt;: Requires special privileges to create with custom definer&lt;br&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Use &lt;code&gt;strip_definers&lt;/code&gt;&lt;/p&gt;
&lt;h5 id=&quot;4-tablespace-clauses&quot;&gt;4. Tablespace Clauses&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;Issue&lt;/strong&gt;: HeatWave has tablespace restrictions&lt;br&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Use &lt;code&gt;strip_tablespaces&lt;/code&gt;&lt;/p&gt;
&lt;h5 id=&quot;5-restricted-grants&quot;&gt;5. Restricted Grants&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;Issue&lt;/strong&gt;: Some privileges not supported in HeatWave&lt;br&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Use &lt;code&gt;strip_restricted_grants&lt;/code&gt;&lt;/p&gt;
&lt;h5 id=&quot;6-external-authentication&quot;&gt;6. External Authentication&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;Issue&lt;/strong&gt;: Some authentication plugins not supported&lt;br&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Use &lt;code&gt;skip_invalid_accounts&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;heatwave-compatibility-modifications&quot;&gt;HeatWave Compatibility Modifications&lt;/h3&gt;
&lt;p&gt;Compatibility options automatically modify exported data to resolve compatibility issues&lt;/p&gt;
&lt;h4 id=&quot;available-compatibility-options&quot;&gt;Available Compatibility Options&lt;/h4&gt;
&lt;h5 id=&quot;force-innodb&quot;&gt;force_innodb&lt;/h5&gt;
&lt;p&gt;Modifies ENGINE clause of CREATE TABLE statements to specify InnoDB for tables using incompatible storage engines&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What It Does&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Changes &lt;code&gt;ENGINE=MyISAM&lt;/code&gt; to &lt;code&gt;ENGINE=InnoDB&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Changes other engines (MEMORY, CSV, etc.) to InnoDB&lt;/li&gt;
&lt;li&gt;Leaves InnoDB tables unchanged&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Before
CREATE TABLE orders (...) ENGINE=MyISAM;

-- After
CREATE TABLE orders (...) ENGINE=InnoDB;
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;strip-definers&quot;&gt;strip_definers&lt;/h5&gt;
&lt;p&gt;Removes DEFINER=account clause from views, routines, events, and triggers, changing SQL SECURITY to INVOKER&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What It Does&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Removes DEFINER clause&lt;/li&gt;
&lt;li&gt;Changes SQL SECURITY from DEFINER to INVOKER&lt;/li&gt;
&lt;li&gt;Objects created with default definer (user loading schema)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Before
CREATE DEFINER=`admin`@`localhost` VIEW active_orders AS ...

-- After
CREATE VIEW active_orders AS ...
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;strip-tablespaces&quot;&gt;strip_tablespaces&lt;/h5&gt;
&lt;p&gt;Removes TABLESPACE clause from CREATE TABLE statements so tables are created in default tablespaces&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What It Does&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Removes TABLESPACE option from CREATE TABLE&lt;/li&gt;
&lt;li&gt;Comments out DATA DIRECTORY, INDEX DIRECTORY, ENCRYPTION options&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Before
CREATE TABLE orders (...) TABLESPACE=ts1;

-- After
CREATE TABLE orders (...);
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;create-invisible-pks&quot;&gt;create_invisible_pks&lt;/h5&gt;
&lt;p&gt;Adds invisible primary keys to tables without primary keys, required for High Availability DB systems&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What It Does&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Adds invisible AUTO_INCREMENT column named &lt;code&gt;my_row_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Sets as primary key&lt;/li&gt;
&lt;li&gt;No impact on applications (column is invisible)&lt;/li&gt;
&lt;li&gt;Requires MySQL 8.0.24+ on target&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Before
CREATE TABLE logs (
  timestamp DATETIME,
  message TEXT
);

-- After
CREATE TABLE logs (
  my_row_id BIGINT UNSIGNED AUTO_INCREMENT INVISIBLE PRIMARY KEY,
  timestamp DATETIME,
  message TEXT
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Alternative&lt;/strong&gt;: &lt;code&gt;ignore_missing_pks&lt;/code&gt; - ignores missing PKs but cannot load to HA systems.&lt;/p&gt;
&lt;h5 id=&quot;strip-restricted-grants&quot;&gt;strip_restricted_grants&lt;/h5&gt;
&lt;p&gt;Removes privileges that are restricted in MySQL HeatWave Service&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Restricted Privileges&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SUPER&lt;/li&gt;
&lt;li&gt;FILE&lt;/li&gt;
&lt;li&gt;RELOAD&lt;/li&gt;
&lt;li&gt;BINLOG_ADMIN&lt;/li&gt;
&lt;li&gt;Others specific to managed service&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&quot;skip-invalid-accounts&quot;&gt;skip_invalid_accounts&lt;/h5&gt;
&lt;p&gt;Skips user accounts with external authentication plugins not supported in HeatWave.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Also removes&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Accounts without passwords (except roles)&lt;/li&gt;
&lt;li&gt;Accounts using unsupported plugins&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;applying-compatibility-options&quot;&gt;Applying Compatibility Options&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;util.dumpInstance(&quot;&quot;, {
  osBucketName: &quot;migrationBucket&quot;,
  ocimds: true,
  compatibility: [
    &quot;force_innodb&quot;,
    &quot;strip_definers&quot;,
    &quot;strip_restricted_grants&quot;,
    &quot;strip_tablespaces&quot;,
    &quot;create_invisible_pks&quot;
  ]
})
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;step-by-step-migration-process&quot;&gt;Step-by-Step Migration Process&lt;/h3&gt;
&lt;h4 id=&quot;step-1-prepare-source-database&quot;&gt;Step 1: Prepare Source Database&lt;/h4&gt;
&lt;p&gt;Ensure MySQL Shell is installed and source is accessible:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mysqlsh --version  # Should be 8.0.21 or later
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;step-2-run-dry-run&quot;&gt;Step 2: Run Dry Run&lt;/h4&gt;
&lt;p&gt;Identify compatibility issues:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mysqlsh admin@source_server:3306 -- util dump-instance &quot;&quot; \
  --mode=dryrun \
  --ocimds=true
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;step-3-analyze-dry-run-output&quot;&gt;Step 3: Analyze Dry Run Output&lt;/h4&gt;
&lt;p&gt;Review compatibility issues and note suggested options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Storage engine issues → &lt;code&gt;force_innodb&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Missing PKs → &lt;code&gt;create_invisible_pks&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Definer clauses → &lt;code&gt;strip_definers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Tablespace issues → &lt;code&gt;strip_tablespaces&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;step-4-export-data-with-modifications&quot;&gt;Step 4: Export Data with Modifications&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;To Local Files&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mysqlsh admin@source_server:3306 -- util dump-instance /backup/migration \
  --ocimds=true \
  --threads=8 \
  --bytesPerChunk=128M \
  --compatibility='[&quot;force_innodb&quot;,&quot;strip_definers&quot;,&quot;strip_tablespaces&quot;,&quot;create_invisible_pks&quot;]'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;To Object Storage&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mysqlsh admin@source_server:3306 -- util dump-instance &quot;&quot; \
  --osBucketName=migrationBucket \
  --osNamespace=my-namespace \
  --ocimds=true \
  --threads=16 \
  --compression=zstd \
  --compatibility='[&quot;force_innodb&quot;,&quot;strip_definers&quot;,&quot;strip_restricted_grants&quot;,&quot;strip_tablespaces&quot;,&quot;create_invisible_pks&quot;]'
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;step-5-import-data-into-heatwave&quot;&gt;Step 5: Import Data into HeatWave&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;From Object Storage&lt;/strong&gt; (during DB system creation):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Select &quot;Import data from Object Storage&quot;&lt;/li&gt;
&lt;li&gt;Provide bucket details&lt;/li&gt;
&lt;li&gt;HeatWave automatically imports during provisioning&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;To Existing DB System&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mysqlsh admin@heatwave_endpoint:3306 -- util load-dump /backup/migration \
  --threads=16 \
  --progressFile=/tmp/load-progress.json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;From Object Storage to Existing System&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mysqlsh admin@heatwave_endpoint:3306 -- util load-dump migrationBucket \
  --osBucketName=migrationBucket \
  --osNamespace=my-namespace \
  --threads=16
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;best-practices&quot;&gt;Best Practices&lt;/h3&gt;
&lt;h4 id=&quot;1-always-use-ocimds-true&quot;&gt;1. Always Use ocimds: true&lt;/h4&gt;
&lt;p&gt;Ensures HeatWave compatibility checks run during export. Dumps without this cannot be loaded into HeatWave.&lt;/p&gt;
&lt;h4 id=&quot;2-run-dry-run-first&quot;&gt;2. Run Dry Run First&lt;/h4&gt;
&lt;p&gt;Identify compatibility issues before actual export to avoid failed migrations&lt;/p&gt;
&lt;h4 id=&quot;3-use-appropriate-thread-count&quot;&gt;3. Use Appropriate Thread Count&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Small databases (&amp;lt; 10GB): 2-4 threads&lt;/li&gt;
&lt;li&gt;Medium databases (10-100GB): 8-12 threads&lt;/li&gt;
&lt;li&gt;Large databases (&amp;gt; 100GB): 16-32 threads&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Balance&lt;/strong&gt;: More threads = faster but higher source load.&lt;/p&gt;
&lt;h4 id=&quot;4-chunk-large-tables&quot;&gt;4. Chunk Large Tables&lt;/h4&gt;
&lt;p&gt;For very large tables, use bytesPerChunk:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;bytesPerChunk: &quot;256M&quot;  // For tables &amp;gt; 10GB
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;5-use-compression&quot;&gt;5. Use Compression&lt;/h4&gt;
&lt;p&gt;Reduces storage and transfer costs:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;compression: &quot;zstd&quot;  // Best compression ratio and speed
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;6-monitor-dump-progress&quot;&gt;6. Monitor Dump Progress&lt;/h4&gt;
&lt;p&gt;Dumps display progress including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Total rows to dump&lt;/li&gt;
&lt;li&gt;Rows dumped so far&lt;/li&gt;
&lt;li&gt;Percentage complete&lt;/li&gt;
&lt;li&gt;Throughput (rows/sec, MB/sec)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;7-test-with-subset-first&quot;&gt;7. Test with Subset First&lt;/h4&gt;
&lt;p&gt;For large migrations, test with single schema:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;util.dumpSchemas([&quot;test_schema&quot;], ...)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Validate before full migration.&lt;/p&gt;
&lt;h4 id=&quot;8-plan-for-downtime&quot;&gt;8. Plan for Downtime&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Read-only mode during export for consistency&lt;/li&gt;
&lt;li&gt;Or use consistent: true for point-in-time snapshot&lt;/li&gt;
&lt;li&gt;Plan maintenance window for production migrations&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;9-validate-after-import&quot;&gt;9. Validate After Import&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Check row counts
SELECT COUNT(*) FROM imported_table;

-- Verify structure
SHOW CREATE TABLE imported_table;

-- Test queries
SELECT * FROM imported_table LIMIT 10;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;10-keep-dump-files&quot;&gt;10. Keep Dump Files&lt;/h4&gt;
&lt;p&gt;Retain dump files until migration validated:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Local backups or Object Storage&lt;/li&gt;
&lt;li&gt;Useful for troubleshooting&lt;/li&gt;
&lt;li&gt;Allows re-import if needed&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;troubleshooting-common-issues&quot;&gt;Troubleshooting Common Issues&lt;/h3&gt;
&lt;h4 id=&quot;issue-1-dump-fails-with-compatibility-errors&quot;&gt;Issue 1: Dump Fails with Compatibility Errors&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Symptoms&lt;/strong&gt;: Export aborts with list of incompatible objects&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Run dry run to see all issues&lt;/li&gt;
&lt;li&gt;Apply suggested compatibility options&lt;/li&gt;
&lt;li&gt;For manual issues, fix source schema&lt;/li&gt;
&lt;li&gt;Re-run export&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;issue-2-out-of-memory-during-dump&quot;&gt;Issue 2: Out of Memory During Dump&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Symptoms&lt;/strong&gt;: Process killed, &quot;out of memory&quot; errors&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reduce thread count&lt;/li&gt;
&lt;li&gt;Increase system memory&lt;/li&gt;
&lt;li&gt;Use bytesPerChunk to process smaller chunks&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;issue-3-load-fails-with-local-infile-error&quot;&gt;Issue 3: Load Fails with &quot;local_infile&quot; Error&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Symptoms&lt;/strong&gt;: Import fails, local_infile error&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- On HeatWave DB system
SET GLOBAL local_infile = ON;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(Default is ON in HeatWave, but verify)&lt;/p&gt;
&lt;h4 id=&quot;issue-4-tables-missing-after-import&quot;&gt;Issue 4: Tables Missing After Import&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Symptoms&lt;/strong&gt;: Some tables not imported&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Check excluded tables in dump command&lt;/li&gt;
&lt;li&gt;Verify tables exported in dump metadata&lt;/li&gt;
&lt;li&gt;Check for errors in load-progress.json&lt;/li&gt;
&lt;li&gt;Ensure compatibility options applied correctly&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Migrating data to MySQL HeatWave using MySQL Shell dump utilities provides a reliable, efficient path to the cloud. By understanding the three dump utilities, running compatibility checks, and applying appropriate modifications, you can ensure smooth migrations with minimal issues.&lt;/p&gt;
&lt;p&gt;Key takeaways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Use util.dumpInstance()&lt;/strong&gt; for complete database migrations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use util.dumpSchemas()&lt;/strong&gt; for selective schema migrations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use util.dumpTables()&lt;/strong&gt; for specific table exports&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Always run dry run first&lt;/strong&gt; to identify compatibility issues&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Apply compatibility options&lt;/strong&gt; to auto-fix common issues&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test with subset&lt;/strong&gt; before full migration&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitor and validate&lt;/strong&gt; throughout the process&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Whether migrating from on-premises, other clouds, or between HeatWave regions, MySQL Shell dump utilities provide the tools needed for successful data migration to MySQL HeatWave.&lt;/p&gt;
</description>
<category>mysql</category>
<guid isPermaLink="true">https://coderlegion.com/7832/mysql-heatwave-migrating-your-data-to-heatwave-service</guid>
<pubDate>Wed, 26 Nov 2025 10:08:43 +0000</pubDate>
</item>
</channel>
</rss>