Skip to main content

MariaDB Crash-Consistent Backup — Missing InnoDB Tablespace Files

Document Type: Known Issue / Troubleshooting Reference Audience: L2 / L3 Last Updated: March 2026 Source Ticket: HALO 1136749 — McLean Family Dentistry


Symptoms

  • Veeam backup completes successfully (Agent or Hyper-V level).
  • After restore (IR or Full VM Restore), MariaDB/MySQL fails to start.
  • MariaDB error log (SERVER.err) shows:
InnoDB: Tablespace 7 was not found at .\opendental\activeinstance.ibd.
InnoDB: Tablespace 359 was not found at .\opendental\smstomobile.ibd.
InnoDB: Tablespace 530 was not found at .\opendental\userod.ibd.
InnoDB: Plugin initialization aborted with error Tablespace not found
Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
Unknown/unsupported storage engine: InnoDB
  • The opendental data directory contains most .ibd files (e.g., 438 of 441) but a small number are missing.
  • The missing files vary — they are whichever tablespaces had unflushed writes at the moment the backup snapshot was taken.

Root Cause

MariaDB and MySQL do not have a native VSS (Volume Shadow Copy Service) writer. Unlike SQL Server, which has a VSS writer that quiesces the database and flushes all dirty pages to disk before a snapshot, MariaDB relies entirely on InnoDB's crash recovery mechanism.

When Veeam takes a backup with MariaDB running:

  1. Veeam triggers a VSS snapshot of the volume.
  2. MariaDB has no VSS writer — it does not receive a freeze/thaw notification.
  3. InnoDB may have dirty pages in its buffer pool that have not been flushed to the .ibd files on disk.
  4. The snapshot captures whatever is on disk at that instant — some .ibd files may be partially written, zero-length, or missing entirely.
  5. On restore, InnoDB attempts crash recovery from the redo log. If the redo log references tablespace files that don't exist on disk (because they were only in the buffer pool), recovery fails.

This produces a crash-consistent backup, not an application-consistent backup. InnoDB's crash recovery can handle most scenarios (it replays the redo log), but if the .ibd file itself was never written to disk before the snapshot, there is nothing to recover.

Who Is Affected

Any environment running MariaDB or MySQL where:

  • Veeam Agent backup is taken with the database service running
  • Veeam Hyper-V backup is taken with the database service running
  • Any VSS-based snapshot tool is used without first quiescing MariaDB

Open Dental environments are the most common DTC case, as Open Dental uses MariaDB 10.x.

Resolution

Preferred — Stop MariaDB Before Backup

Stop the MariaDB service before taking the backup. With the service stopped, InnoDB performs a clean shutdown — all dirty pages are flushed to disk, the buffer pool is dumped, and every .ibd file is complete and consistent.

Stop-Service MariaDB -Force
# If Stop-Service hangs, kill the process:
Stop-Process -Name mysqld -Force

Verify clean shutdown in the error log before proceeding with the backup:

Get-Content "D:\MariaDB\SERVER.err" -Tail 10

Look for:

InnoDB: FTS optimize thread exiting.
InnoDB: Starting shutdown...
InnoDB: Dumping buffer pool(s) to D:\MariaDB\ib_buffer_pool
InnoDB: Buffer pool(s) dump completed at [timestamp]

"Normal shutdown" and "Buffer pool(s) dump completed" confirm all data is on disk. Run the Veeam backup after this confirmation.

After the backup completes, restart MariaDB:

Start-Service MariaDB

For VMs that will be powered off during backup (e.g., Veeam Hyper-V backup of a powered-off VM), stopping MariaDB first is still recommended but not strictly required — the VM power-off closes all file handles at the OS level. However, InnoDB's crash recovery will need to run on next boot, which adds startup time.

Alternative — innodb_force_recovery (Emergency Only)

If you have a restore with missing .ibd files and cannot re-take the backup:

  1. Identify the missing tables from the error log.
  2. Assess criticality — some tables are safe to lose (session tracking, temp queues), others are not:
Table Critical? Notes
activeinstance No Tracks logged-in OD sessions. Recreated automatically.
smstomobile No SMS/text queue. Can be recreated.
userod YES User accounts, provider definitions, security permissions. Cannot be recreated — must be recovered from source.
patient YES Patient records.
appointment YES Appointment schedule.
Any claim* table YES Insurance claims.
  1. If only non-critical tables are missing, add innodb_force_recovery=1 to my.ini under [mysqld]:
[mysqld]
innodb_force_recovery=1
  1. Start MariaDB — it will skip the missing tablespaces and start.
  2. Drop the missing tables: DROP TABLE IF EXISTS opendental.<table>;
  3. Remove innodb_force_recovery=1 from my.ini.
  4. Restart MariaDB normally.
  5. Open Dental will recreate non-critical tables on first connect.

WARNING: innodb_force_recovery=1 tells InnoDB to ignore missing tablespaces and skip crash recovery. Do NOT leave this setting in production. Do NOT drop critical tables — recover them from the source system instead.

File Copy from Source (If Source Is Available)

If the source server is still available with a running MariaDB:

  1. Mount the source data VHDX read-only on the source host: Mount-VHD -Path "<path>" -ReadOnly
  2. Copy the missing .ibd files from the mounted volume to the restored VM.
  3. Do NOT mount the source VHDX while a Veeam IR is active from the same backup — this causes a Veeam conflict on simultaneous VHDX access and breaks the IR.
  4. Use PowerShell Direct (New-PSSession -VMName <n> + Copy-Item -ToSession) to transfer files into the VM without a NIC if the synthetic NIC is non-functional.
  5. Note: the D:\MariaDB\opendental\ directory may have restricted permissions (MariaDB service account). Copy to C:\temp first, then use Invoke-Command -Session $session to move files locally inside the VM with elevated permissions.

Automation Opportunity

For scheduled Veeam backup jobs on servers running MariaDB:

  • Create a pre-job script that stops MariaDB before the backup.
  • Create a post-job script that starts MariaDB after the backup completes.
  • Veeam supports pre/post scripts natively in job settings.

Example pre-job script (stop-mariadb.ps1):

Stop-Service MariaDB -Force
Start-Sleep -Seconds 10
$status = (Get-Service MariaDB).Status
if ($status -ne 'Stopped') {
    Stop-Process -Name mysqld -Force
    Start-Sleep -Seconds 5
}

Example post-job script (start-mariadb.ps1):

Start-Service MariaDB
Start-Sleep -Seconds 30
$status = (Get-Service MariaDB).Status
if ($status -ne 'Running') {
    Start-Service MariaDB
}
  • Veeam Backup and Replication Standards (Page 1004) — backup job configuration
  • Veeam Troubleshooting Playbook (Page 1115) — general Veeam troubleshooting
  • Open Dental Operational Reference — MariaDB configuration
  • HALO 1136749 — McLean Family Dentistry — source ticket