Converting InnoDB tables to ROW_FORMAT=DYNAMIC
in Nextcloud is not something that can be solved with a quick fix.

It required careful research and testing to understand the best approach and potential pitfalls. This documentation consolidates those findings, providing a clear, step-by-step guide to help others perform the conversion safely and efficiently.
Using ROW_FORMAT=DYNAMIC
is recommended for optimal performance with utf8mb4 encoding, as ignoring it can lead to issues with large indexes or future updates.
Error message in administrative dashboard: Incorrect row format found in your database. ROW_FORMAT=Dynamic offers the best database performances for Nextcloud. Please update row format on the following list: …

Step 1: Finding your Nextcloud database settings
Before making any database changes, you need to know your database name. You can find it quickly from the Nextcloud configuration file.
Finding Your Nextcloud Database Settings:
grep db /var/www/nextcloud/config/config.php
Step 2: Backup First
Before touching the database, always make a full backup. This ensures you can roll back if something goes wrong.
Database Backup:
# Export the Nextcloud database
mariadb-dump -u root -p nextcloud > nextcloud_db_backup_$(date +%F).sql
File Backup (optional but recommended):
tar -czf nextcloud_files_backup_$(date +%F).tar.gz /var/www/nextcloud
✅ With this, you can restore both your database and Nextcloud files if needed.
Step 3: Prepare Your Database-Engine for DYNAMIC Row Format (Optional)
Make sure your MySQL/MariaDB is configured to support DYNAMIC
row format.
- Edit the database config file (usually
/etc/my.cnf.d/server.cnf
or/etc/mysql/my.cnf
):
[mysqld]
innodb_file_per_table=1
innodb_file_format=Barracuda
innodb_default_row_format=DYNAMIC
- Restart the database:
sudo systemctl restart mariadb
Step 4: Convert Tables to DYNAMIC
To improve database performance and eliminate warnings, you can convert all InnoDB tables in your Nextcloud database to ROW_FORMAT=DYNAMIC
. Follow these steps carefully:
Step 4.1: Checking Table Engines and Row Formats in Nextcloud
When managing a Nextcloud database, it’s useful to know which tables use modern InnoDB with dynamic or compressed row formats and which still rely on legacy engines like MyISAM. This helps to optimize performance and ensures compatibility with utf8mb4.
You can quickly get an overview using a single MySQL command:
mysql -uroot -p -e "
SELECT engine, row_format, COUNT(*) AS table_count
FROM information_schema.tables
WHERE table_schema='nextcloud'
GROUP BY engine, row_format
ORDER BY engine, row_format;
"
Sample Output
engine | row_format | table_count |
---|---|---|
InnoDB | Dynamic | 42 |
InnoDB | Compressed | 5 |
InnoDB | Compact | 2 |
MyISAM | Fixed | 1 |
Aria | Fixed | 3 |
What This Tells You
- Dynamic / Compressed InnoDB tables → modern, recommended for utf8mb4 and large indices
- Compact InnoDB tables → older InnoDB format, might need conversion
- MyISAM / Aria tables → legacy engines, usually less efficient and lack some InnoDB features
This simple check helps administrators identify tables that might need optimization or migration to the recommended formats, improving database reliability and performance.
Step 4.2: MyISAM
- Classic storage engine, mostly deprecated, non-transactional.
DYNAMIC
works fine and can be changed withALTER TABLE
.- ROW_FORMATs:
FIXED
,DYNAMIC
,COMPRESSED
- Downsides: no transactions, no crash recovery, no MVCC → mainly for legacy or small tables.
Create a file named:
nextcloud_rowformat_fix.sql
Add the following content:
USE database_name;
SELECT CONCAT('ALTER TABLE ', table_name, ' ROW_FORMAT=DYNAMIC, KEY_BLOCK_SIZE=0;')
FROM information_schema.tables
WHERE table_schema='database_name'
AND ENGINE='InnoDB'
AND ROW_FORMAT <> 'Dynamic';
Replace
database_name
with the actual name of your Nextcloud database.
Execute the SQL File
mariadb -u root -p < nextcloud_rowformat_fix.sql
Sample Output:
ALTER TABLE oc_direct_edit ROW_FORMAT=COMPACT; ALTER TABLE oc_direct_edit ROW_FORMAT=DYNAMIC;
ALTER TABLE oc_jobs ROW_FORMAT=COMPACT; ALTER TABLE oc_jobs ROW_FORMAT=DYNAMIC;
ALTER TABLE oc_circles_share_lock ROW_FORMAT=COMPACT; ALTER TABLE oc_circles_share_lock ROW_FORMAT=DYNAMIC;
ALTER TABLE oc_storages ROW_FORMAT=COMPACT; ALTER TABLE oc_storages ROW_FORMAT=DYNAMIC;
ALTER TABLE oc_twofactor_totp_secrets ROW_FORMAT=COMPACT; ALTER TABLE oc_twofactor_totp_secrets ROW_FORMAT=DYNAMIC;
...
Step 4.3: InnoDB (MariaDB 10.2+ with Barracuda)
- Supports
DYNAMIC
andCOMPRESSED
row formats via Barracuda file format. - Important: existing
COMPRESSED
InnoDB tables cannot simply be altered to DYNAMIC. You need to dump and recreate the table.
Dump current DB
mariadb-dump -u root -p --single-transaction --skip-extended-insert nextcloud > nextcloud_dump_migration.sql
Replace row format in dump
sed -i 's/ROW_FORMAT=COMPRESSED/ROW_FORMAT=DYNAMIC/g' nextcloud_dump_migration.sql
Create new DB
mariadb -u root -p -e "CREATE DATABASE nextcloud_dynamic CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"
Restore dump to new database
mariadb -u root -p nextcloud_dynamic < nextcloud_dump_migration.sql
Copy privileges from old DB to new DB
To identify the database user, refer to your Nextcloud configuration. See Step 1: Finding Your Nextcloud Database Settings for guidance.
mariadb -u root -p -e "GRANT ALL PRIVILEGES ON nextcloud_dynamic.* TO 'nc_user'@'localhost'; FLUSH PRIVILEGES;"
Update Nextcloud config
Before proceeding with the migration, make sure the database can be cleanly converted to ROW_FORMAT=DYNAMIC
. See Step 6: Verify the Conversion for details.
To ensure that the user has the correct permissions on the new database, you can run the following command for a local user:
mariadb -u root -p -e "SHOW GRANTS FOR 'username'@'localhost';"
Output should be:
+------------------------------------------------------------------------------------------------------------------+
| Grants for nextcloud@localhost |
+------------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `dbo_cloud`@`localhost` IDENTIFIED BY PASSWORD '*ABCDEFGHIJK12345679' |
| GRANT ALL PRIVILEGES ON `nextcloud`.* TO `dbo_cloud`@`localhost` WITH GRANT OPTION |
| GRANT ALL PRIVILEGES ON `nextcloud_dynamic`.* TO `dbo_cloud`@`localhost` |
+------------------------------------------------------------------------------------------------------------------+
Replace username
with your database user. This will display all privileges assigned to that user on the local server.
'dbname' => 'nextcloud_dynamic',
Step 5: Clear Nextcloud Cache (Optional)
After converting the tables, clear the Nextcloud cache and repair the installation:
sudo -u www-data php /var/www/nextcloud/occ maintenance:repair
Step 6: Verify the Conversion
Check that all tables now have the correct row format:
mariadb -u root -p -e "SELECT table_name, row_format FROM information_schema.tables WHERE table_schema='nextcloud' AND row_format <> 'Dynamic';"
If nothing is returned, all tables are properly converted, otherwise:
+-----------------------------+------------+
| table_name | row_format |
+-----------------------------+------------+
| oc_direct_edit | Compressed |
| oc_jobs | Compressed |
| oc_circles_share_lock | Compressed |
| oc_storages | Compressed |
| oc_twofactor_totp_secrets | Compressed |
...
Step 7: Celebrate or Restore
- ✅ If everything looks good: enjoy better performance and cleaner Nextcloud database.
- 🔄 If something went wrong: restore from backup:
mariadb -u root -p nextcloud < nextcloud_backup.sql
By carefully following these steps, your Nextcloud database is now properly configured with ROW_FORMAT=DYNAMIC
where needed, ensuring better compatibility and performance. You’ve documented the process, verified the changes, and can move forward with confidence. With a clean and optimized database, future updates and features will run smoothly, and your Nextcloud instance is more resilient for the long term.