20,919,685Total Points24,106Total Sites23,382Cell Towers69,500Racks Monitored56,753HVAC Units Monitored31,322UPS Units Monitored24,788Generators Monitored20,919,685Total Points24,106Total Sites23,382Cell Towers69,500Racks Monitored56,753HVAC Units Monitored31,322UPS Units Monitored24,788Generators Monitored20,919,685Total Points24,106Total Sites23,382Cell Towers69,500Racks Monitored56,753HVAC Units Monitored31,322UPS Units Monitored24,788Generators Monitored

Chapter 10: Scalability & System AdminLesson 54 of 65

How to Migrate from H2 to a Production Database

Step-by-step guide to converting your Mango by Radix IoT SQL database from the default H2 to MySQL or PostgreSQL for production deployment, using Mango's built-in database conversion.

  • 10 min read
  • Advanced
  • Mango 4.x / 5.x

Overview

Many Mango by Radix IoT installations start on the default H2 database, and nothing in Mango disqualifies H2 from production. Move the SQL database to MySQL or PostgreSQL when you need what H2 cannot do: access to the database from outside Mango while it runs, replication, or backup and restore that do not depend on Mango. How to Choose and Configure Your Mango Database (MySQL, PostgreSQL, MariaDB) covers that decision.

Mango has a built-in database conversion for exactly this, and it is the method to use. You configure the empty target under the db.* properties, point convert.db.* at your existing H2 database, and Mango copies the tables across on startup — Core schema tables plus the tables belonging to every loaded module. This preserves the actual database contents, including relational IDs, event and audit history, and module data.

Danger

Changing db.* to a new database and restarting is not a migration. Without convert.db.type set, Mango sees a database that does not exist yet, creates an empty schema, and starts as a brand-new installation. Your users, data sources, and data points will appear to be gone. They are still in the H2 files, but you will be looking at an empty Mango on what may be a production system.

Supported Target Databases

Mango's DatabaseType lists five names — DERBY, H2, MSSQL, MYSQL and POSTGRES — but only MySQL and PostgreSQL are conversion targets. DERBY is deprecated, with no driver and no proxy left in the product. MSSQL has a proxy but no bundled driver, and the conversion itself rejects it: after copying each table Mango resets that table's autoincrement sequence, and that step is implemented for H2, PostgreSQL and MySQL only, so any other target fails on the first table with an identity column.

There is no separate MariaDB database type. MariaDB is wire-compatible with MySQL and may work through the MySQL type and driver, but that is a compatibility assumption rather than a distinct supported target — check the supported-versions documentation for your release, and test the full conversion on a disposable instance before committing a production system to it.

MySQL must be at least 5.7.8; Mango checks for JSON column support at startup and refuses to start on older versions.

Note

Do not copy a JDBC driver into lib. Mango 5.7.4 already ships the H2, MySQL and PostgreSQL connectors, and adding a second copy risks a classpath conflict that is harder to diagnose than the problem it was meant to solve. No SQL Server driver ships at all, which is the other reason MSSQL is not a route off H2.

Prerequisites

  • Back up everything — take a full Mango backup (SQL database + NoSQL + mango.properties + file store). This is your only route back
  • Do not combine this with an upgrade — upgrade Mango first, confirm the system is healthy on H2, then convert as a separate exercise. Running both at once is explicitly not supported
  • Plan downtime — conversion happens during a Mango startup, and it copies row by row. How long it takes tracks the number of rows in your SQL tables, which in practice means event and audit history; time-series point values are not copied and do not affect it
  • Create the target database — the database and its user must already exist and be reachable. Mango creates the tables; it does not create the database
  • The target must be empty — conversion only runs when Mango finds no existing schema in the target. Pointing it at a database that already has Mango tables skips conversion entirely
  • Rehearse on a staging copy first — take a copy of the H2 files onto a disposable instance and run the whole procedure there. Copy the whole databases directory: Mango appends H2's own build number to the base name, so the file on disk is mah2.<build>.mv.db, not mah2.mv.db

Migration Method: Built-In Database Conversion

Step 1: Stop Mango

Shut down the Mango service cleanly and confirm the process has exited before touching the H2 files.

Step 2: Create the Target Database

Create an empty database and a user with full rights on it (see How to Choose and Configure Your Mango Database (MySQL, PostgreSQL, MariaDB)). Confirm you can connect to it from the Mango host before going further.

Step 3: Configure Both Ends in mango.properties

The db.* block describes where you are going. The convert.db.* block describes where you are coming from.

# Target: the new, empty production database
db.type=postgres
db.url=jdbc:postgresql://localhost/mango
db.username=mango
db.password=<target password>

# Source: the existing H2 database you are converting from
convert.db.type=h2
convert.db.url=jdbc:h2:databases/mah2
convert.db.username=
convert.db.password=

For a MySQL target, use db.type=mysql with a jdbc:mysql://... URL instead.

Warning

convert.db.username and convert.db.password ship as ${db.username} and ${db.password}, so leaving them unset makes them inherit the production credentials you just set for the target, and H2 refuses the connection. A default H2 database has an empty username and password. Set both explicitly, even when the correct value is blank.

Copy the H2 URL from the db.url value the installation was using before your edit, so the source path is exactly right. The path is relative to the data directory unless it is absolute.

Step 4: Start Mango and Watch the Conversion

Start Mango and follow ma.log. Conversion runs during startup, before normal operation, and logs its progress at warning level: it announces the conversion from source type to target type, names each table as it is copied, reports the record count for each, and finally logs that the conversion has completed.

Do not interrupt this. Table copying happens inside transactions, and tables with foreign key dependencies are automatically retried after the tables they reference have been copied, so out-of-order warnings during the run are expected.

Step 5: Remove the Conversion Setting

Once the conversion has completed and you have verified the result, clear convert.db.type back to blank. Leaving it set is harmless while the target has a schema — conversion is gated on the target being new — but clearing it removes any chance of a future empty-target situation re-running it unexpectedly.

Step 6: Verify

  1. Log in and confirm your existing users are present — including their passwords
  2. Check that all data sources appear, are enabled, and are polling
  3. Verify data points are collecting new values
  4. Confirm historical data is queryable
  5. Check dashboards, watch lists, and reports
  6. Verify event detectors and handlers are active, and that event history is present

Historical Data and the NoSQL Store

This conversion moves the SQL database only. Time-series point values live in a separate point value store, commonly the NoSQL database under the data directory, and are untouched by the conversion.

Leave db.nosql.location and db.nosql.pointValueStoreName pointing at the same directory they already used and your history carries over unchanged. This is also why history is not something you can lose to a botched SQL conversion — but it is equally why a successful SQL conversion tells you nothing about the health of your history. Verify both.

What the Conversion Covers

ConvertedNot part of the SQL conversion
Core schema tables — users, roles, permissions, data sources, data points, event detectors and handlers, system settingsTime-series point values (separate store, left in place)
Schema tables belonging to every loaded moduleThe H2 files themselves, left untouched on disk — your rollback path
Event and audit history held in SQLGenerated report output, which is written to a file store on disk and stays there
Relational IDs and autoincrement sequences, which are reset to stay consistent after the copyFiles in the file store (left in place on disk)

Note

Only tables declared by Core and by the modules loaded at conversion time are copied. If a module is installed on the source but not present when you convert, its tables are not carried over. Have the same module set installed before you start.

Alternative: JSON Export/Import

Mango's configuration export/import can move configuration between installations, and it has its uses — moving a subset of configuration between environments, or as a fallback when direct conversion is not viable. It is not equivalent to a database conversion and should not be presented as the same operation.

What a JSON export/import does not carry across:

  • Relational identifiers — objects are recreated in the target and receive new internal IDs
  • Event history and audit history
  • Active event state
  • Any module data that is not represented in the export format

User password hashes can be exported and imported, but the importer skips the user currently performing the import, so do not assume every account arrives ready to log in. If you use this path, test the resulting user accounts explicitly rather than promising an identical restoration.

When the goal is converting the SQL database with its contents intact, use the built-in conversion.

Verification

Work the full post-migration checklist before you consider the conversion done:

  • ☐ ma.log shows the conversion completing, and the per-table record counts match the row counts in the H2 source — not just that it finished
  • ☐ Existing users are present and can log in with their previous credentials
  • ☐ All data sources enabled and polling
  • ☐ Data points receiving new values
  • ☐ Historical data accessible (point value store unchanged)
  • ☐ Event and audit history present
  • ☐ Dashboards and watch lists display correctly
  • ☐ Event detectors are active
  • ☐ Email handlers can send (test SMTP)
  • ☐ convert.db.type cleared back to blank
  • ☐ Backups configured for the new database, and the old H2 files retained until you are confident
  • ☐ Monitor for errors in ma.log for 24 hours

Troubleshooting

IssueCauseFix
Mango starts empty, with only the default adminconvert.db.type was blank, so Mango created a fresh schema instead of convertingStop Mango, drop the empty target schema so the target is new again, set the convert.db.* properties, and start again. The H2 data is untouched
The log shows the conversion running and completing, but Mango still has only the default admin and every table reports a handful of recordsconvert.db.url pointed at an H2 database that is not there. Mango does not require the file to exist — H2 creates it, Mango builds a fresh schema and default admin inside it, and the conversion then faithfully copies that empty installation into your targetStop Mango, drop the target schema, and set convert.db.url to the exact value db.url held before your edit. This is why you read the record counts rather than the completion line
No conversion appears in the log and the target already has dataConversion only runs when the target has no existing schemaConvert into a genuinely empty database
Conversion fails connecting to the sourceconvert.db.username and convert.db.password inherited the target credentialsSet them explicitly for H2, usually to blank, and check the convert.db.url path
Startup fails naming a MySQL versionMySQL older than 5.7.8 lacks the JSON column support Mango requiresUpgrade MySQL, or target PostgreSQL instead
Schema version errors during startupAn upgrade and a conversion were attempted togetherRestore the backup, upgrade on H2 first, confirm the system is healthy, then convert
Some module data is missing after conversionThat module was not loaded when the conversion ran, so its tables were not copiedRestore, install the same module set as the source, and convert again into a fresh target
Historical data missingPoint value store location changed along with the SQL settingsVerify db.nosql.location and db.nosql.pointValueStoreName point at the existing store
Driver or classpath errorsA JDBC driver was added to lib alongside the bundled connectorRemove the added driver and rely on the bundled one

Summary

Convert from H2 using Mango's built-in database conversion: create an empty MySQL or PostgreSQL database, point db.* at it, point convert.db.* at the existing H2 database, and start Mango. Mango copies the Core and module schema tables across, preserving contents rather than recreating configuration. Changing db.* alone does not migrate anything — it starts a new, empty installation. Do not combine the conversion with a Mango upgrade, do not add JDBC drivers to lib, and remember the time-series point value store is separate and stays where it is. Always back up first and rehearse the whole procedure on a disposable copy.

Get free access to all 65 Mango by Radix IoT training lessons

One short form unlocks every lesson and its video in this browser.

This form is hosted by Zoho. It loads only after you enable support cookies or choose to load it below.

We honored your browser’s Global Privacy Control signal — optional cookies are off and nothing is tracked.