All pages
Powered by GitBook
1 of 26

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Migrating to MariaDB

Learn how to migrate your existing databases to MariaDB Server. This section provides comprehensive guides and best practices for a smooth and successful data transfer.

Migrating to MariaDB from SQL Server

Migrate from SQL Server to MariaDB. This section provides detailed guidance, tools, and best practices for a smooth and efficient transition of your databases and applications to MariaDB.

Migrating to MariaDB from Oracle

Migrate from Oracle to MariaDB Server. This section provides detailed guidance, tools, and best practices for a smooth and efficient transition of your databases and applications.

Migrating to MariaDB from MySQL

Move from MySQL to MariaDB Server seamlessly. This section provides detailed instructions, tools, and best practices for migrating your databases and applications with ease.

Upgrading from MySQL to MariaDBMigration from MySQL Galera Cluster to MariaDB Galera Cluster using ReplicationMigrating to MariaDB from MySQL - Obsolete Articles

Upgrading from MySQL 5.7 to MariaDB 10.2

Outdated page regarding migrating from MySQL to MariaDB Server. While potentially outdated, these resources may offer historical context or insights for specific scenarios.

Following compatibility report was done on 10.2.4 and may get some fixing in next minor releases

  • MySQL unix socket plugin can be different. MariaDB can get similar usage via INSTALL PLUGIN unix_socket SONAME 'auth_socket.so'; you may have to enable this plugin in config files via load plugin.

  • When using data type JSON , one should convert type to TEXT, virtual generated column works the same after.

  • When using InnoDB FULLTEXT index one should not use innodb_defragment

  • MySQL re-implemented partitioning in 5.7, thus you cannot perform in-place upgrades for partitioned tables. They will require mysqldump/import to work correctly in MariaDB.

This page is licensed: CC BY-SA / Gnu FDL

Screencast for Upgrading MySQL to MariaDB (Obsolete)

Outdated page regarding migrating from MySQL to MariaDB Server. While potentially outdated, these resources may offer historical context or insights for specific scenarios.

There is a screencast for upgrading from MySQL 5.1.55 to MariaDB. Watch this example to see how easy this process is. It really is just a "drop in replacement" to MySQL.

This page is licensed: CC BY-SA / Gnu FDL

Differences Between MariaDB and Other DBMSs

A high-level comparison of MariaDB's architecture, including its pluggable storage engines, transaction log handling, and buffer pool management versus other databases.

This page lists general differences between MariaDB and other DBMSs (database management systems). For specific differences (for instance, between MariaDB and PostgreSQL), refer to the respective pages in this section.

Database vs. Schema

In MariaDB, the terms "schema" and "database" are synonymous and used interchangeably. The CREATE SCHEMA statement is a direct synonym for CREATE DATABASE, meaning they create the same object—a container for database objects like tables and views.

Migrating to MariaDB from MySQL - Obsolete Articles

This section contains obsolete articles regarding migrating from MySQL to MariaDB Server. While potentially outdated, these resources may offer historical context or insights for specific scenarios.

MariaDB does not support a distinction between schema and database as seen in other systems like SQL Server or PostgreSQL, where a schema is a logical container within a database. Instead, a database in MariaDB serves as both a namespace and a logical container to separate objects, and it has a default character set and collation that are inherited by its tables.
Screencast for Upgrading MySQL to MariaDB (Obsolete)
Upgrading from MySQL 5.7 to MariaDB 10.2
Upgrading to MariaDB From MySQL 5.0 or Older

Upgrading to MariaDB From MySQL 5.0 or Older

Outdated page regarding migrating from MySQL to MariaDB Server. While potentially outdated, these resources may offer historical context or insights for specific scenarios.

If you upgrade to from MySQL 5.1 you don't have to do anything with your data or MySQL clients. Things should "just work".

When upgrading between different major versions of MariaDB or MySQL you need to run the mysql_upgrade program to convert data that are incompatible between versions. This will also update your privilege tables in the mysql database to the latest format.

In almost all cases mysql_upgrade should be able to convert your tables, without you having to dump and restore your data.

After installing MariaDB, just do:

If you want to run with a specific TCP/IP port do:

If you want to connect with a socket do:

To see other options, use --help.

"mysql_upgrade" reads the my.cnf sections [mysql_upgrade] and [client] for default values.

There are a variety of reasons tables need to be converted; they could be any of the following:

  • The collation (sorting order) for an index column has changed

  • A field type has changed storage format

    • and changed format between MySQL 4.1 and MySQL 5.0

  • An engine has a new storage format

in SHOW TABLES until you convert them.

If you don't convert the tables, one of the following things may happen:

  • You will get warnings in the error log every time you access a table with an invalid (old) file name.

  • When searching on key values you may not find all rows

  • You will get an error "ERROR 1459 (HY000): Table upgrade required" when accessing the table.

  • You may get crashes

"mysql_upgrade" works by calling mysqlcheck with different options and running the "mysql_fix_privileges" script. If you have trouble with "mysql_upgrade", you can run these commands separately to get more information of what is going on.

Most of the things in the section also applies to MariaDB.

The following differences exists between "mysql_upgrade" in MariaDB and MySQL (as of ):

  • MariaDB will convert long table names properly.

  • MariaDB will convert tables (no need to do a dump/restore or ).

  • MariaDB will convert old archive tables to the new 5.1 format (note: new feature in testing).

  • "mysql_upgrade --verbose" will run "mysqlcheck --verbose" so that you get more information of what is happening.

This page is licensed: CC BY-SA / Gnu FDL

Setting Up MariaDB for Testing for SQL Server Users

From selecting a MariaDB version to setting it up on Windows, using various packages or Docker, this page covers multiple scenarios.

This page contains links and hints to setup MariaDB for testing. The page is designed for SQL Server users, assuming that they are mostly familiar with Windows and they are not familiar with MariaDB.

Choosing a MariaDB Version

As a general rule, for new installations it's better to choose the .

If you need a feature that is only present in a version that is not yet production-ready, and the project will surely not go to production before that version is GA, it could make sense to use a non-GA version. In this case however, keep in mind that you are using a version that is only suitable for testing.

If you need to work with an existing production instance, you should of course use the same version in testing. However, deprecated versions should not be used in production, because they could be exposed to vulnerabilities that will never be fixed. See if you are not sure about the version you are using.

Setting up MariaDB on Windows

There are two different ways to use MariaDB on Windows natively: using Zip packages or MSI packages.

In both cases, 32-bit platforms are still supported.

Check the page to verify if current versions of MariaDB have troubles on Windows. More generally, it is a good idea to check the category.

ZIP Packages

Windows users don't necessarily need to install MariaDB to use it. They can download ready-to-use ZIP packages to avoid any change in the system (except for downloading MariaDB and writing databases on the disk). This is very useful for testing without risking some undesired side effect on the machine in use. And it avoids the hassle of installing Docker or virtual machines.

It is necessary to run to install the data directory.

The drawback is that MariaDB will need to be started and stopped from the command line.

See .

MSI Packages

MSI packages provide a friendly graphical interface to install MariaDB. The installation process is easy but flexible. For example, the user can decide which components to install, whether to install it as a service or not, and if networking should be enabled. An interface to uninstall MariaDB is also provided.

See .

Installing MariaDB on Docker

Docker is a container platform that runs natively on Linux. A Docker image is a representation of a basic Linux system, which usually runs a single process - in our case, that process is MariaDB. A container is an instance of an image, which can be created or destroyed instantaneously. Once a container is started, it can be used just like a normal system.

Docker runs on all major operating systems. On Windows and MacOS it runs on a Linux virtual machine, but this additional complexity is transparent for the end user.

Docker's characteristics makes it optimal to test MariaDB functionalities without wasting time on installation and without making changes to the host system. However, it is not ideal to test MariaDB performance.

See .

Reinitializing MariaDB Data Directory

While experimenting with MariaDB, you could end up with an unusable installation. This occurs for example if you deliberately delete files that you shouldn't delete. If it happens, there is no need to uninstall and reinstall MariaDB. Instead, you can simply delete the contents of the data directory and run . The program will recreate your system tables and the essential files.

To know where your data directory is, check the system variable.

This page is licensed: CC BY-SA / Gnu FDL

Migration from MySQL Galera Cluster to MariaDB Galera Cluster using Replication

A strategy for migrating from a MySQL Galera Cluster to a MariaDB Galera Cluster by setting up the new cluster as an asynchronous replica, minimizing downtime.

This guide details migrating a live database from a MySQL Galera Cluster to a . The migration strategy requires setting up a new MariaDB Cluster and using to sync it with the existing MySQL Cluster. The method includes a reliable failback route.

This document focuses on the migration process itself. For detailed comparisons between the two database systems, please refer to

Prerequisites

  • MySQL Server: A running MySQL Galera Cluster (version 8.0 or 8.4) to migrate.

  • MariaDB Server: The target . This guide assumes the latest stable version.

  • mysqldump: A command-line utility by MySQL to create initial database backup.

Due to changes in MySQL 8.0+, mariadb-dump may not be compatible for this initial step.

  • Root or Sudo Access: Administrative are required on all servers involved in the migration.

Migration Steps

1

Check for Incompatibilities

While MariaDB maintains a high degree of compatibility with MySQL, it is crucial to review any differences that could impact your applications.

SQL Server Features Not Available in MariaDB

Features available in Microsoft SQL Server that aren't available in MariaDB.

When planning a migration between different DBMSs, one of the most important aspects to consider is that the new database system will probably miss some features supported by the old one. This is not relevant for all users. The most widely used features are supported by most DBMSs. However, it is important to make a list of unsupported features and check which of them are currently used by applications. In most cases it is possible to implement such features on the application side, or simply stop using them.

This page has a list of SQL Server features that are not supported in MariaDB. The list is not exhaustive.

Introduced in SQL Server versions older than 2016

mysql_upgrade --verbose
mysql_upgrade --host=127.0.0.1 --port=3308 --protocol=tcp
mysql_upgrade --socket=127.0.0.1 --protocol=socket

ARCHIVE changed storage format between 5.0 and 5.1

  • The format for storing table names has changed

    • In MySQL 5.1 table names are encoded so that the file names are identical on all computers. Old table names that contains forbidden file name characters will show up prefixed with #mysql50

  • DECIMAL
    VARCHAR
    MySQL 5.1 manual
    InnoDB
    ALTER TABLE
  • Version Compatibility: Select a with your MySQL version for replication.

  • Feature Differences: Review the to identify any deprecated features or changes in system tables, user accounts, and authentication that might affect your setup.

  • Replication Compatibility

    MySQL Version
    Compatible MariaDB Version

    5.7

    10.2 and newer

    8.0

    10.6.21, 10.11.11, 11.4.5, 11.7.2 and newer

    For more details, see y.

    2

    Install and Configure a New MariaDB Galera Cluster

    Set up a new, empty that will become the target for the migration.

    1. Install MariaDB Server and Galera Provider

    Install MariaDB Server package and Galera wsrep provider library on each node of the new cluster. Refer and for detailed instructions.

    1. Configure Each MariaDB Node

    at /etc/mysql/conf.d/galera.cnf on each node. The configuration will be mostly identical across nodes, except for node-specific details like wsrep_node_name and wsrep_node_address.

    Example galera.cnf:

    It is recommended to set wsrep_sst_method on all nodes to ensure consistency during (SST).

    3

    Back Up the MySQL Database

    A full logical backup of the MySQL database is required to seed the new MariaDB Cluster.

    1. Enable Binary Logging on MySQL

      requires the to be enabled on the MySQL source. If not enabled, enable it on at least one node in your MySQL cluster.

      1. Edit my.cnf: In the [mysqld] section of your , add log-bin=mysql-bin.

      2. Restart MySQL: A server restart is required for the change to take effect.

    Restarting MySQL will cause a brief outage for the node.

    1. Create the Backup with mysqldump

    Use mysqldump from the source MySQL server to create a full backup. Using --all-databases and --master-data will include all databases and the binary log position needed to start replication.

    This above command generates a backup file and logs the source's binary log file name and position in the output.

    4

    Bootstrap the MariaDB Cluster and Restore Data

    Start the first node of the MariaDB cluster and load the MySQL backup.

    1. Bootstrap the First Node

    Start the first MariaDB node with the --wsrep-new-cluster option. This initializes the cluster.

    1. Load the Backup File

    Transfer the backup.sql file to the first MariaDB node and import it:

    1. Start Subsequent Nodes

    Start the MariaDB service normally on the remaining nodes. They will connect to the first node, and a State Snapshot Transfer (SST) will automatically sync their data.

    1. Verify the Cluster

    Connect to any node and check the cluster size to ensure all nodes have joined successfully.

    Cluster size should match the number of nodes in your cluster.

    5

    Set Up Asynchronous Replication

    Configure one of the MariaDB nodes to act as a replica of the source MySQL cluster.

    1. Create a Replication User on MySQL

    On the MySQL source node where binlogging is enabled, create a dedicated user for replication.

    1. Configure the MariaDB Replica

    On one of the MariaDB nodes, configure and start the . Use the binary log file and position noted from the mysqldump output (MASTER_LOG_FILE and MASTER_LOG_POS) or use GTID-based replication.

    6

    Monitor and Failover

    With replication running, the MariaDB cluster will catch up with any changes made to the MySQL cluster since the backup was taken.

    1. Monitor Replication Lag

    Check the replica status on the MariaDB node to ensure it is synchronized.

    Ensure the following conditions are met on the replica:

    • Slave_IO_Running: Yes

    • Slave_SQL_Running: Yes

    • Seconds_Behind_Master: 0

    A Seconds_Behind_Master value of 0 indicates the replica is completely synchronized.

    1. Perform the Failover

    Once the MariaDB cluster is fully synchronized, follow these steps:

    1. Stop Application Traffic: Cease traffic to the MySQL cluster.

    2. Verify Synchronization: Confirm the MariaDB replica has processed all events from the MySQL binary log.

    3. Promote MariaDB:

      • Stop replication on the MariaDB node using STOP SLAVE;

    privileges

    Full outer joins.

  • GROUP BY CUBE syntax.

  • MERGE statement.

  • In MariaDB, indexes are always ascending. Defining them as ASC or DESC has no effect.

    • For single-column indexes, the performance difference between an ORDER BY ... ASC and DESC is negligible.

    • For multiple-column indexes, an index may be unusable for certain queries because DESC is not supported. In some cases, a can be used to invert the order of an index (for example, the expression 0 - price can be indexed to index the prices in a descending order).

  • The WITH syntax is currently only supported for the SELECT statement.

  • Filtered indexes (CREATE INDEX ... WHERE).

  • Autonomous transactions.

  • User-defined types.

  • Rules.

  • Triggers don't support the following features:

    • Triggers on DDL and login.

    • INSTEAD OF triggers.

    • The DISABLE TRIGGER syntax.

  • Cursors advanced features.

    • Global cursors.

    • DELETE ... CURRENT OF, UPDATE ... CURRENT OF statements: MariaDB cursors are read-only.

    • Specifying a direction (MariaDB cursors can only advance by one row).

  • Synonyms.

  • Table variables.

  • Queues.

  • XML indexes, XML schema collection, XQuery.

  • User access to system functionalities, for example:

    • Running system commands (xp_cmdshell()).

    • Sending emails (sp_send_dbmail()).

    • Sending HTTP requests.

  • External languages, external libraries (MariaDB only supports procedural SQL and PL/SQL).

  • Negative permissions (the DENY command).

  • Snapshot replication. See Provisioning a Slave.

  • Introduced in SQL Server 2016

    • Native data masking

    • PolyBase (however, supports accessing Amazon S3 via the S3 storage engine and several DBMSs via CONNECT)

    • R and Python services

    • ColumnStore indexes. MariaDB has a storage engine called ColumnStore, but this is a completely different feature.

    Introduced in SQL Server 2017

    • Adaptive joins

    • Graph SQL

    See Also

    • SQL Server Features Implemented Differently in MariaDB

    This page is licensed: CC BY-SA / Gnu FDL

    Installation issues on Windows
    Troubleshooting Installation Issues
    mysql_install_db.exe
    Installing MariaDB Windows ZIP Packages
    Installing MariaDB MSI Packages on Windows
    Installing and Using MariaDB via Docker
    mariadb-install-db
    datadir

    SQL Server Features Implemented Differently in MariaDB

    Differences between features in Microsoft SQL Server and MariaDB.

    Modern DBMSs implement several advanced features. While an SQL standard exists, the complete feature list is different for every database system. Sometimes different features allow achieving the same purpose, but with a different logic and different limitations. This is something to take into account when planning a migration.

    Some features are implemented by different DBMSs, with a similar logic and similar syntax. But there could be important differences that users should be aware of.

    This page has a list of SQL Server features that MariaDB implements in a different way, and SQL Server features for which MariaDB has an alternative feature. Minor differences are not taken into account here. The list is not exhaustive.

    SQL

    • The list of supported is different.

    • There are relevant .

    • SNAPSHOT isolation level is not supported. Instead, you can use START TRANSACTION WITH CONSISTENT SNAPSHOT to acquire a snapshot at the beginning of the transaction. This is compatible with all isolation levels. See .

    • JSON support is .

    Indexes and Performance

    • Clustered indexes. In MariaDB, the physical order of rows is delegated to the storage engine. InnoDB uses the primary key as a clustered index.

    • Hash indexes. Only some storage engines support HASH indexes.

      • The storage engine has a feature called adaptive hash index, enabled by default. It means that in InnoDB all indexes are created as BTREE, and depending on how they are used, InnoDB could convert them from BTree to hash indexes, or the other way around. This happens in the background.

    Tables

    • Computed columns are called in MariaDB and are created with a different syntax. See also .

    • use a different (more standard) syntax on MariaDB. In MariaDB, the history is stored in the same table as current data (but optionally in different partitions). MariaDB supports both and .

    • Hidden columns are in MariaDB.

    • are implemented and used differently.

    High Availability

    • NOT FOR REPLICATION

      • MariaDB supports to exclude some tables or databases from replication

      • It is possible to keep a table empty in a slave (or in the master) by using the .

      • The master can have columns that are not present in a slave (the other way around is also supported). Before using this feature, carefully read the

    Security

    • The list of is different.

    • Security policies. MariaDB allows one to achieve the same results by assigning permissions on views and stored procedures. However, this is not a common practice and it's more complicated than defining security policies. See .

    • MariaDB does not support an OUTPUT clause. Instead, we can use and, since , and .

    Other Features

    • Linked servers. MariaDB supports storage engines to read from, and write to, remote tables. When using the engine, those tables could be in different DBMSs, including SQL Server.

    • Job scheduler: MariaDB uses an to schedule events instead.

    See Also

    This page is licensed: CC BY-SA / Gnu FDL

    MariaDB Backups Overview for SQL Server Users

    Maps SQL Server backup concepts like differential and transaction log backups to MariaDB equivalents such as `mariadb-backup` (hot backups) and binary logs for incremental recovery.

    MariaDB has the following types of backups:

    • Logical backups (dumps).

    • Hot backups with mariadb-backup.

    • Snapshots.

    Migration from MySQL to MariaDB Cluster (Node-by-Node In-Place)

    Instructions for a rolling migration where individual nodes in a MySQL cluster are taken offline, wiped, and replaced with MariaDB nodes, eventually forming a new cluster.

    Version Requirement

    This guide provides instructions for migrating a MySQL 8.0 Galera Cluster to a MariaDB Galera Cluster 11.4. Ensure that your systems meet or exceed these version requirements before proceeding. Please refer to the for detailed version information.

    The End-of-Life (EOL) date for continued maintenance and regular binary releases of MySQL Galera Cluster will be

    Migrating to MariaDB from PostgreSQL

    Strategies for moving data from PostgreSQL to MariaDB, using the CONNECT storage engine with ODBC/JDBC or foreign data wrappers.

    There are many different ways to migrate from to MariaDB. This article will discuss some of those options.

    MariaDB's CONNECT Storage Engine

    MariaDB's storage engine can be used to migrate from PostgreSQL to MariaDB. There are two primary ways that this can be done.

    See for information on how to install the CONNECT storage engine.

    .
  • Update your application to connect to the MariaDB Galera Cluster.

  • Resume Application Traffic: Redirect traffic to the MariaDB cluster.

  • Decommission MySQL: After confirming the application runs smoothly on MariaDB, decommission the MySQL cluster.

  • Install
    Upgrade MariaDB
    binary log
    MySQL configuration file

    The MEMORY storage engine uses hash indexes by default, if we don't specify the BTREE keyword.

  • See Storage Engine Index Types for more information.

  • Query store. MariaDB allows query performance analysis using the slow log and performance_schema. Some open source or commercial 3rd party tools read that information to produce statistics and make it easy to identify slow queries.

  • page.
  • With MariaDB it's possible to prevent a trigger from running on slaves.

  • It's possible to run events without replicating them. The same applies to some administrative statements.

  • MariaDB superusers can run statements without replicating them, by using the sql_log_bin system variable.

  • Constraints and triggers cannot be disabled for replication, but it is possible to drop them on the slaves.

  • The IF EXISTS syntax allows one to easily create a table on the master that already exists (possibly in a different version) on a slave.

  • pollinginterval option. See Delayed Replication.

  • data types
    differences in transaction isolation levels
    How Isolation Levels are Implemented in MariaDB
    different
    InnoDB
    generated columns
    Implementation Differences Compared to Microsoft SQL Server
    Temporal tables
    SYSTEM_TIME
    APPLICATION_TIME
    Invisible columns
    Temporary tables
    replication filters
    BLACKHOLE storage engine
    permissions
    Other Uses of Views
    DELETE RETURNING
    INSERT RETURNING
    REPLACE RETURNING
    CONNECT
    event scheduler
    SQL Server features not available in MariaDB
    Replication When the Master and Slave Have Different Table Definitions

    Incremental backups.

    Logical Backups (Dumps)

    A dump, also called a logical backup, consists of the SQL statements needed to recreate MariaDB databases and their data into another server. A dump is the slowest form of backup to restore, because it implies executing all the SQL statements needed to recreate data. However it is also the most flexible, because restoring will work on any MariaDB version, because the SQL syntax is usually compatible. It is even possible to restore a dump into an older version, though the incompatible syntax (new features) will be ignored. Under certain conditions, MariaDB dumps may also be restored on other DBMSs, including SQL Server.

    The compatibility between different versions and technologies is achieved by using executable comments, but we should be aware of how they work. If we use a feature introduced in version 11.1, for example, it will be included in the dump inside an executable comment. If we restore that backup on a server with MariaDB 10.11, the 11.1 feature will be ignored. This is the only way to restore backups in older MariaDB versions.

    mariadb-dump

    Logical backups are usually taken with mariadb-dump (previously called mysqldump).

    mariadb-dump allows one to dump all databases, a single database, or a set of tables from a database. It is even possible to specify a WHERE clause, which under certain circumstances allows to obtain incremental dumps.

    For consistency reasons, when using the default storage engine InnoDB, it is important to use the --single-transaction option. This will read all data in a single transaction. It's important however to understand that long transactions may have a big impact on performance.

    The --master-data option adds the statements to setup a slave to the dump.

    MariaDB also supports statements which make easy to write applications to obtain custom types of dumps. For most CREATE <object_type> statement, a corresponding SHOW CREATE <object_type> exists. For example, SHOW CREATE TABLE returns the CREATE TABLE statement that can be used to recreate a certain table, without data.

    mydumper

    mydumper is a 3rd party tools to take dumps from MariaDB and MySQL databases. It is much faster than mariadb-dump because it takes backups with several parallel threads, usually one thread for each available CPU core. It produces several files, that can be used to restore a database using the related tool myloader.

    Since is it a 3rd party tool, it could be incompatible with some present or future MariaDB features.

    Hot Backups (mariadb-backup)

    mariadb-backup is a tool for taking a backup of MariaDB files while MariaDB is working. A lock is only held for a small amount of time, so it is suitable to backup a server without causing disruptions. It works by taking corrupted backups and then bringing them to a consistent state by using the InnoDB undo log. mariadb-backup also properly backups MyRocks tables and non-transactional storage engines.

    Cold Backups and Snapshots

    A copy of all MariaDB files is a working backup. Therefore, the easiest way to backup a dataset is to shutdown the server and copy all its files. It will be entirely possible to start another server with a copy of those files. This is often referred to as a cold backup. However, in most cases we don't want to do this, because it implies downtime for the server: it will not be working at least for the time necessary to copy the files.

    Snapshots are usually a better idea, as they are a consistent copy of the files at a given moment in time, taken without stopping the normal operations.

    A snapshot of the files can be taken at several levels: filesystem level, if the filesystem supports snapshots, for example zfs; Linux Logical Volume Manager (LVM) also supports snapshots; and virtual machines also allow one to take snapshots. Windows shadow copies are also snapshots, with a benefit: it is possible to restore a single file from a shadow copy. A snapshot is not an expensive operation, because it does not imply a copy of the files. The current files will not be modified anymore, and changes to them will be written in separate places.

    The problem with snapshots is that they behave like a logical copy of the files as they are in a given point in time. But database files are not guaranteed to be consistent in every moment, because contents can be buffered before being flushed to the disk. You can think a database snapshot like a database after an operating system crash.

    With non-transactional tables, some data is typically lost. Data changes that are present in a buffer before the snapshot, but not written on a disk, cannot be recovered in any way. Data changes in transactional tables, like InnoDB tables, can always be recovered after restoring a snapshot (or after a crash), as long as a commit was done. Tables will still need to be repaired, just like it happens after an SQL Server crash.

    Snapshots can be taken while MariaDB is running. To restore them, stop MariaDB first - or kill the process, because you don't really care of the consequences in this case. Then restore a snapshot and start MariaDB again.

    For more information about snapshots, check your filesystem, LVM or virtual machine documentation.

    Incremental Backups

    The term incremental backup in MariaDB indicates what SQL Server calls a differential backup. An important difference is that in SQL Server such backups are based on the transaction log, which wouldn't be possible in MariaDB because transaction logs are handled at storage engine level.

    As mentioned here, MariaDB can use the binary log instead for backup purposes. Such incremental backups can be done manually. This means that:

    • The binary log files are copied just like any other regular file.

    • To copy those files it is necessary to have the proper permissions at filesystem level, not in MariaDB.

    • Backups do not expire until we delete the last needed complete backup.

    Replaying the Binary Log

    The page Using mariadb-binlog shows how to use the mariadb-binlog utility to replay a binary log file.

    The page also shows how to edit the binary log before replaying it. This allows one to undo an SQL statement that was executed by mistake, for example a DROP TABLE against a wrong table. The high level procedure is the following:

    • Restore a backup that is older than the SQL statement to undo.

    • Use mariadb-binlog to generate a file with the SQL statements that were executed after the backup.

    • Edit the SQL file, erasing the unwanted statement.

    • Run the SQL file.

    Incremental Backups with mariadb-backup

    The simplest way to take an incremental backup is to use mariadb-backup. This tool is able to take and restore incremental backups. For the complete procedure to use, see Incremental Backup and Restore with mariadb-backup.

    mariadb-backup can run on both Linux and Windows systems.

    Flashback

    Flashback is a feature that allows one to bring all databases, some databases or some tables back to a certain point in time. This can only be done if the binary log is enabled. Flashback is not a proper backup, but it can be used to restore a certain set of data.

    Copying Individual Tables

    It is entirely possible to restore a single table from a physical backup, or to copy the table to another server.

    With the MyISAM storage engine it was very easy to move tables between different servers, as long as the MySQL or MariaDB version was the same.

    InnoDB is nowadays the default storage engine, and it is more complex, as it supports transactions for example. It still supports restoring a table from a physical file, this feature is called transportable tablespaces. There is a particular procedure to follow, and some limitations. This is basically the MariaDB equivalent of detaching and re-attaching tables in SQL Server.

    For more information, see InnoDB File-Per-Table Tablespaces.

    By default. all table files are located in the data directory, which is defined by the system variable datadir. There may be exceptions, because a table's files can be located elsewhere using the DATA DIRECTORY and INDEX DIRECTORY options in CREATE TABLE.

    Regardless of the storage engine used, each table's structure is generally stored in a file with the .frm extension.

    The files used for partitioned tables are different from the files used for non-partitioned tables. See Partitions Files for details.

    This page is licensed: CC BY-SA / Gnu FDL

    September 30, 2026
    .

    This guide outlines the procedure for migrating a live MySQL Galera Cluster to a MariaDB Galera Cluster. It follows the process for migrating a live MySQL Galera Cluster to a MariaDB Galera Cluster by replacing the binaries on each node sequentially. This "In-Place" method maintains cluster availability during the migration, although the cluster capacity will be reduced while individual nodes are being processed.

    Prerequisites

    • Source: MySQL Galera Cluster 8.0.43-26.4.24 or later.

    • Target: MariaDB Community Server 11.4 (LTS) or later.

    • Library: MariaDB Galera library 26.4.24 or latest stable edition.

    • Tools:

      • mysqldump (installed with the server).

      • mariadb-backup (installed with MariaDB).

    • Access: Root access to the operating system and the database.

    Cluster Backup

    This migration involves uninstalling software and wiping data directories on live nodes. A full cluster backup (using Xtrabackup or Volume Snapshot) is mandatory before proceeding.

    Incompatibility Check & Data Preparation

    Perform these steps on the running MySQL Cluster BEFORE shutting down any nodes.

    Incompatibilities and Feature Differences

    MariaDB maintains high levels of compatibility with MySQL, but you still need to to select the most suitable MariaDB version compatible with your current MySQL server.

    While MariaDB and MySQL share a common history, they have diverged significantly. You must "clean" the schema and configurations to ensure data compatibility before the migration begins.

    1. Authentication Protocol

    MySQL 8.0 defaults to caching_sha256_password. MariaDB does not support the caching_sha256_password authentication protocol in all released versions (which is cumbersome and not secure for in-house attacks, since clear-text passwords are available inside the server).

    Support Status:

    • Implemented via MDEV-9804 for version 12.1.1.

    • Available in the CS release based on MDEV-37600.

    • Already supported in 11.8 Enterprise Server via MENT-2359.

    • Available in 11.4 Enterprise Server with the December 2025 release as a rebase of MDEV-37600.

    For MySQL 8.4 Users

    Ensure mysql_native_password=ON is set in your configuration, or you will receive the error: Plugin 'mysql_native_password' is not loaded.

    You can check which MySQL users are using SHA-256 or caching_sha256_password by executing:

    You can change the user to use a protocol compatible with both MySQL and MariaDB with:

    2. JSON Column Conversion

    MySQL stores JSON as a native binary type. MariaDB stores JSON as an alias for LONGTEXT with constraint checks. Galera replication may break if you attempt to replicate binary JSON objects from MySQL to MariaDB.

    Check if you have tables that use the MySQL JSON type:

    You can convert the JSON column to text with:

    3. Encryption and Compression

    Encryption and compression table options are very different in MySQL compared to MariaDB. Logical dump will naturally de-encrypt/de-compress table contents but syntax used for creating tables is not supported by MariaDB.

    For example:

    leads to: ERROR 1911 (HY000) at line 1174: Unknown option 'COMPRESSION'

    Therefore, encrypted/compressed tables need to be de-encrypted/de-compressed before starting the conversion, and then encrypted/compressed again afterwards using MariaDB syntax.

    Detect encrypted tables:

    Detect compressed tables:

    Action: Run ALTER TABLE to remove the conflicting ENCRYPTION and COMPRESSION attributes. They can be re-enabled using MariaDB syntax after the full migration is complete.

    4. General Tablespaces

    MariaDB does not support MySQL general tablespaces. In MySQL, these are used to store tables in specific external files rather than the default data directory. During migration, this TABLESPACE argument is ignored.

    Example Scenario: In MySQL, a user creates a custom tablespace file at a specific path and assigns a table to it:

    If you examine the table definition in MySQL, you will see the tablespace assignment:

    Migration Behavior: When this table is migrated to MariaDB (via mysqldump), the TABLESPACE 'ts1' attribute is ignored.

    • Result: The table t1 will be created as a standard file-per-table in the default MariaDB data directory (e.g., /var/lib/mysql/dbname/t1.ibd).

    • Loss of Path: It will not use the custom path /home/jan/galeradb/node1/ts1.ibd.sq

    During cluster migration make sure that no new tablespaces are created and no new tables created inside a general tablespaces.

    5. XA Transactions

    Ensure no XA transactions are in a PREPARED state, as these cannot be migrated cleanly.

    Global Cluster Preparation

    Perform these steps on the running MySQL Cluster.

    1. Create the SST User (Crucial)

    The mysql.user system table structure differs between vendors and will not migrate automatically. You must create the SST user now so it exists in the data stream before the switch.

    2. Configure InnoDB Settings

    Ensure these settings are active on the MySQL cluster.

    • innodb_file_per_table = 1

      • This is the default setting for MySQL and MariaDB. If this is not set, you must use mysqldump for the entire migration, as specific recommendations regarding tablespaces will not work.

    • innodb_flush_log_at_trx_commit = 1

      • InnoDB writes the log buffer to the log file and flushes it to disk after every transaction commit. This is the safest option, ensuring no data loss in a crash, though it comes at the cost of slower performance due to frequent disk I/O.

    3. Galera Provider Options

    • gcache.size: Should be large enough to avoid SST (State Snapshot Transfer) when a node is temporarily out of the cluster. A larger cache increases the chance of a faster IST (Incremental State Transfer).

      • See: Customizing gcache.size

    Migrating the First Node ("The Bridge")

    This is the most complex step. This node will bridge the gap between the MySQL cluster and the new MariaDB environment.

    1

    Isolate and Shutdown

    1. Remove from Load Balancer: Ensure no application traffic is hitting this node.

    2. Clean Shutdown Prep:

    3. Stop the Service:

    2

    Swap Binaries & Wipe Data

    1. Uninstall MySQL: Remove all MySQL server and client packages using your OS package manager (e.g., apt remove, dnf remove).

    3

    Configure MariaDB (my.cnf)

    Update the configuration file to work with both MariaDB and MySQL.

    Verify Configuration: Before starting the service, verify that your configuration file does not contain unsupported options (such as regexp-time-limit).

    Check /tmp/log

    4

    Start and Join

    Start the MariaDB service:

    When initiated, the node connects to the MySQL cluster and automatically triggers a mysqldump on a designated MySQL donor node. It then imports the SQL dump stream, effectively reconstructing the database in MariaDB's native format.

    5

    Post-Join Upgrade

    Once the node is Synced, run mariadb-upgrade to fix system tables.

    Migrating Subsequent Nodes

    Once the first node (Node A) is successfully running MariaDB, you can migrate Node B, Node C, etc.

    1

    Shutdown and Replace

    1. Set Fast Shutdown:

      Required because undo/redo log formats may change between versions.

    2. Shutdown: mysqladmin -u root -p shutdown

    3. Wipe & Install: Uninstall MySQL, Wipe Datadir, Install MariaDB.

    2

    Configure MariaDB

    The configuration differs slightly for subsequent nodes. We switch back to Physical Backups for speed.

    3

    Start and Join

    Start the service. The node will perform a binary snapshot transfer (mariabackup) from the first MariaDB node.

    Repeat the above 3 steps for all remaining nodes.

    Finalization

    Once all nodes are running MariaDB:

    1. Cleanup Config: Remove gcs.check_appl_proto=0 and wsrep_sst_donor from my.cnf on all nodes. Reset wsrep_sst_method to mariabackup on the first node.

    2. Security: Run mariadb-secure-installation to secure the root account and remove anonymous users.

    3. Features: Re-enable encryption or compression using MariaDB-supported syntax if required.

    Known Issues & Limitations

    1. mysql.user Migration

    The mysql.user table structure is not fully compatible and cannot be migrated automatically.

    • Impact: The administrator must create necessary users for the MariaDB database manually.

    • Workaround: In testing, using --skip-table=mysql.user during dump/restore and manually creating the necessary SST user was required.

    • Reference: MDEV-33486

    2. regexp-time-limit Parameter

    MariaDB currently does not support the regexp-time-limit parameter.

    • Impact: If this variable exists in your configuration or scripts, the server may fail to start or throw errors.

    • Reference: MySQL Sysvar: regexp_time_limit, MDEV-37403

    3. wsrep_start_position Mismatch

    MariaDB does not understand the wsrep_start_position format provided by MySQL due to GTID formatting differences.

    • Example: MySQL node will use a set wsrep_start_position like: ”60e63a7-734c-11f0-bd90-97669e82ccf4:2284/2281/11/0747b7c5-734c-11f0-a69b-00e04ca2f8fe”

    • Reference: MGL-57

    4. Replication Direction

    Replication from MariaDB → MySQL is not supported.

    • Impact: During migration, there can be no load directed to the MariaDB nodes until the entire cluster is migrated.

    5. Testing Scope

    Currently, migration from 8.0.x has been verified to work on a simple sysbench database workload.

    Required Code Changes (References)

    For developers or those compiling from source, the following changes were relevant to this migration path:

    • codership-mariadb-server Pull Request #519

    • codership-mysql Pull Request #2062

    Prerequisites
    Tables with ODBC table_type

    The CONNECT storage engine allows you to create tables that refer to tables on an external server, and it can fetch the data using a compatible ODBC driver. PostgreSQL does have a freely available ODBC driver called psqlODBC. Therefore, if you install psqlODBC on the MariaDB Server, and then configure the system's ODBC framework (such as unixODBC), then the MariaDB server will be able to connect to the remote PostgreSQL server. At that point, you can create tables with the ENGINE=CONNECT and table_type=ODBC table options set, so that you can access the PostgreSQL tables from MariaDB.

    See CONNECT ODBC Table Type: Accessing Tables From Another DBMS for more information on how to do that.

    Once the remote table is setup, you can migrate the data to local tables very simply. For example:

    Tables with JDBC table_type

    The CONNECT storage engine allows you to create tables that refer to tables on an external server, and it can fetch the data using a compatible JDBC driver. PostgreSQL does have a freely available JDBC driver. If you install this JDBC driver on the MariaDB server, then the MariaDB server will be able to connect to the remote PostgreSQL server via JDBC. At that point, you can create tables with the ENGINE=CONNECT and table_type=JDBC table options set, so that you can access the PostgreSQL tables from MariaDB.

    See CONNECT JDBC Table Type: Accessing Tables from Another DBMS for more information on how to do that.

    Once the remote table is setup, you can migrate the data to local tables very simply. For example:

    PostgreSQL's Foreign Data Wrappers

    PostgreSQL's foreign data wrappers can also be used to migrate from PostgreSQL to MariaDB.

    mysql_fdw

    mysql_fdw allows you to create a table in PostgreSQL that actual refers to a remote MySQL or MariaDB server. Since MySQL and MariaDB are compatible at the protocol level, this should also support MariaDB.

    The foreign data wrapper also supports writes, so you should be able to write to the remote MariaDB table to migrate your PostgreSQL data. For example:

    PostgreSQL's COPY TO

    PostgreSQL's COPY TO allows you to copy the data from a PostgreSQL table to a text file. This data can then be loaded into MariaDB with LOAD DATA INFILE.

    MySQL Workbench

    MySQL Workbench has a migration feature that requires an ODBC driver. PostgreSQL does have a freely available ODBC driver called psqlODBC.

    See Set up and configure PostgreSQL ODBC drivers for the MySQL Workbench Migration Wizard for more information.

    Known Issues

    Migrating Functions and Procedures

    PostgreSQL's functions and procedures use a language called PL/pgSQL. This language is quite different than the default SQL/PSM language used for MariaDB's stored procedures. PL/pgSQL is more similar to PL/PSQL from Oracle, so you may find it beneficial to try migrate with set.

    See also

    • Set up and configure PostgreSQL ODBC drivers for the MySQL Workbench Migration Wizard

    This page is licensed: CC BY-SA / Gnu FDL

    PostgreSQL
    CONNECT
    Loading the CONNECT Storage Engine
    generated column

    MariaDB Features Not Available in SQL Server

    Highlights features unique to MariaDB, such as pluggable storage engines, dynamic columns, and Flashback, which can offer advantages after migration.

    Some MariaDB features are not available in SQL Server.

    At first glance, it is not important to know about those features to migrate from SQL Server to MariaDB. However, this is not the case. Using MariaDB features that are not in SQL Server allows one to obtain more advantages from the migration, getting the most from MariaDB.

    This page has a list of MariaDB features that are not supported in SQL Server. The list is not exhaustive.

    Plugin Architecture

    • .

    • .

    • .

    • is a columnar storage engine designed to scale horizontally. It runs on a specific edition of MariaDB, so currently it cannot be used in combination with other engines.

    SQL

    • The variable determines in which cases an SQL statement should fail with an error, and in which cases it should succeed with a warning even if it is not entirely correct. For example, when a statement tries to insert a string in a column which is not big enough to contain it, it could fail, or it could insert a truncated string and emit a warning. It is a tradeoff between reliability and flexibility.

      • allows one to use a small subset of SQL Server proprietary syntax.

    • The options are supported for most .

    See also .

    Types

    • don't depend on column type. They can be set globally, or at database, table or column level.

    • Columns may use non-constant expressions as the value. columns may have a DEFAULT value.

    • numeric types.

    • (note that JSON is usually preferred to this feature).

    See also .

    JSON

    For compatibility with some other database systems, MariaDB supports the pseudo-type. However, it is just an alias for:

    LONGTEXT CHECK (JSON_VALID(column_name))

    is the MariaDB equivalent of SQL Server's ISJSON().

    Features

    • functionality allows one to "undo" the changes that happened after a certain point in time.

    • support the following features:

      • Tables can be partitioned based on .

      • Several are available.

    This page is licensed: CC BY-SA / Gnu FDL

    [mysqld]
    # MariaDB settings
    binlog_format=ROW
    default_storage_engine=InnoDB
    innodb_autoinc_lock_mode=2
    bind-address=0.0.0.0
    
    # Galera Provider Configuration
    wsrep_on=ON
    wsrep_provider=/usr/lib/galera/libgalera_smm.so # Adjust path if necessary
    
    # Galera Cluster Configuration
    wsrep_cluster_name="new_mariadb_cluster"
    wsrep_cluster_address="gcomm://node1_ip,node2_ip,node3_ip"
    
    # Node-specific Configuration
    wsrep_node_name="mariadb_node1"
    wsrep_node_address="node1_ip"
    
    # SST Configuration
    wsrep_sst_method=mariadb-backup
    
    mysqldump --user=backup_user --password --all-databases --master-data=2 > /path/to/backup.sql
    sudo galera_new_cluster
    mariadb -u root -p < /path/to/backup.sql
    sudo systemctl start mariadb
    SHOW STATUS LIKE 'wsrep_cluster_size';
    CREATE USER 'repl_user'@'mariadb_node_ip' IDENTIFIED BY 'your_password';
    GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'mariadb_node_ip';
    CHANGE MASTER TO
      MASTER_HOST='mysql_source_ip',
      MASTER_PORT=3306,
      MASTER_USER='repl_user',
      MASTER_PASSWORD='your_password',
      MASTER_USE_GTID=slave_pos;
    
    START SLAVE;
    SHOW SLAVE STATUS\G
    SET GLOBAL innodb_fast_shutdown = 0;
    SELECT user, plugin FROM mysql.user WHERE plugin LIKE "%sha%";
    ALTER USER user_name IDENTIFIED WITH mysql_native_password BY 'new_password';
    SELECT table_schema, table_name FROM information_schema.COLUMNS
    WHERE data_type="JSON";
    ALTER TABLE table_name MODIFY json_column LONGTEXT;
    CREATE TABLE `t1` (
    `c1` int DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMPRESSION='lz4'
    SELECT table_schema, table_name, create_options FROM information_schema.TABLES WHERE
    create_options LIKE "%ENCRYPT%";
    SELECT table_schema, table_name, create_options FROM information_schema.TABLES WHERE
    create_options LIKE "%COMP%";
    -- MySQL: Creating a tablespace in a custom file location
    mysql> CREATE TABLESPACE `ts1` ADD DATAFILE '/home/jan/galeradb/node1/ts1.ibd' Engine=InnoDB;
    
    -- MySQL: Creating a table assigned to that tablespace
    mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1;
    mysql> show create table t1;
    | t1 | CREATE TABLE `t1` (
     `c1` int NOT NULL,
     PRIMARY KEY (`c1`)
    ) /*!50100 TABLESPACE `ts1` */ ENGINE=InnoDB ... |
    XA RECOVER; -- Should return an empty set
    -- Create user compatible with both engines
    CREATE USER 'sst_user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'strong_password';
    GRANT ALL PRIVILEGES ON *.* TO 'sst_user'@'localhost';
    FLUSH PRIVILEGES;
    CREATE TABLE psql_tab (
       id INT,
       str VARCHAR(50)
    ) ENGINE = CONNECT
    table_type=ODBC
    tabname='tab'
    CONNECTION='DSN=psql_server';
    
    CREATE TABLE tab (
       id INT,
       str VARCHAR(50)
    ) ENGINE = InnoDB;
    
    INSERT INTO tab SELECT * FROM psql_tab;
    CREATE TABLE psql_tab (
       id INT,
       str VARCHAR(50)
    ) ENGINE = CONNECT
    table_type=JDBC
    tabname='tab'
    CONNECTION='jdbc:postgresql://psql_server/db1';
    
    CREATE TABLE tab (
       id INT,
       str VARCHAR(50)
    ) ENGINE = InnoDB;
    
    INSERT INTO tab SELECT * FROM psql_tab;
    CREATE TABLE tab (
       id INT,
       str text
    );
    
    INSERT INTO tab VALUES (1, 'str1');
    
    CREATE SERVER mariadb_server
       FOREIGN DATA WRAPPER mysql_fdw
       OPTIONS (host '10.1.1.101', port '3306');
    
    CREATE USER MAPPING FOR postgres
       SERVER mariadb_server
       OPTIONS (username 'foo', password 'bar');
    
    CREATE FOREIGN TABLE mariadb_tab (
       id INT,
       str text
    )
    SERVER mariadb_server
    OPTIONS (dbname 'db1', table_name 'tab');
    
    INSERT INTO mariadb_tab SELECT * FROM tab;
  • Clean Data Directory: One way is to move all files under datadir to a new directory.

  • Install MariaDB: Install mariadb-server and mariadb-backup.

  • for any errors or warnings about unknown variables and adjust your configuration files if needed.

    Required Settings: You must add these specific settings for the first node:

    Manually re-create the sst_user (and other system users) if mariadb-upgrade reports issues, as the mysql.user table structure is not fully compatible.

    SHOW statements.

  • SHOW CREATE statements.

  • SHOW PROCESSLIST and PERFORMANCE_SCHEMA THREAD table provide much richer information, compared to SQL Server sp_who() and sp_who2() procedures.

  • CHECKSUM TABLE statement.

  • (only for stored procedures and stored functions).

  • Row constructors.

  • BEFORE triggers.

  • HANDLER statements, to scroll table rows ordered by an index or in their physical order.

  • DO statement, to call functions without returning a result set.

  • BENCHMARK() function, to measure the speed of an SQL expression.

  • Subpartitions.

  • for some typically expensive statements.

  • Storage engines
    Authentication plugins
    Encryption plugins
    sql_mode
    CREATE ... IF EXISTS, CREATE OR REPLACE, DROP ... IF NOT EXISTS
    DDL statements
    Syntax Differences between MariaDB and SQL Server
    Character sets and collations
    DEFAULT
    TIMESTAMP
    UNSIGNED
    Dynamic columns
    SQL Server and MariaDB Types Comparison
    JSON
    JSON_VALID()
    Flashback
    Partitioned tables
    multiple columns
    partitioning types
    ColumnStore

    Moving Data Between SQL Server and MariaDB

    Provides methods for transferring data from SQL Server to MariaDB, including generating CSV files, using `mariadb-dump`, or leveraging the CONNECT storage engine with ODBC.

    There are several ways to move data between SQL Server and MariaDB. Here we will discuss them and we will highlight some caveats.

    Moving Data Definition from SQL Server to MariaDB

    To copy SQL Server data structures to MariaDB, one has to:

    1. Generate a CSV file from SQL Server data.

    2. Modify the syntax so that it works in MariaDB.

    3. Run the file in MariaDB.

    Variables That Affect DDL Statements

    DDL statements are affected by some server system variables.

    determines the behavior of some SQL statements and expressions, including how strict error checking is, and some details regarding the syntax. Objects like , and , are always executed with the sql_mode that was in effect during their creation. can be used to have MariaDB behaving as close to SQL Server as possible.

    enables the so-called InnoDB strict mode. Normally some errors in the options are ignored. When InnoDB strict mode is enabled, the creation of InnoDB tables will fail with an error when certain mistakes are made.

    determines whether view updates can be made with an or statement with a LIMIT clause if the view does not contain all primary or not null unique key columns from the underlying table.

    Dumps and sys.sql_modules

    SQL Server Management Studio allows one to create a working SQL script to recreate a database - something that MariaDB users refer to as a dump. Several options allow fine-tuning the generated syntax. It could be necessary to adjust some of these options to make the output compatible with MariaDB. It is possible to export schemas, data or both. One can create a single global file, or one file for each exported object. Normally, producing a single file is more practical.

    Alternatively, the procedure returns information about how to recreate a certain object. Similar information is also present in the table (definition column), in the sys schema. Such information, however, is not a ready-to-use set of SQL statements.

    Remember however that . An SQL Server schema is approximately a MariaDB database.

    To execute a dump, we can pass the file to , the MariaDB command-line client.

    Provided that a dump file contains syntax that is valid in MariaDB, it can be executed in this way:

    --show-warnings tells MariaDB to output any warnings produced by the statements contained in the dump. Without this option, warnings will not appear on screen. Warnings don't stop the dump execution.

    Errors will appear on screen. Errors will stop the dump execution, unless the --force option (or just -f) is specified.

    For other mariadb options, see .

    Another way to achieve the same purpose is to start the mariadb client in interactive mode first, and then run the source command. For example:

    In this case, to show warnings we used the \W command, where "w" is uppercase. To hide warnings (which is the default), we can use \w (lowercase).

    For other mariadb commands, see .

    CSV Data

    If the table structures are already in MariaDB, we need only to import table data. While this can still be done as explained above, it may be more practical to export CSV files from SQL Server and import them into MariaDB.

    SQL Server Management Studio and several other Microsoft tools allow one to export CSV files.

    MariaDB allows importing CSV files with the statement, which is essentially the MariaDB equivalent of BULK INSERT.

    It can happen that we don't want to import the whole data, but some filtered or transformed version of it. In that case, we may prefer to use the storage engine to access CSV files and query them. The results of a query can be inserted into a table using .

    Moving Data from MariaDB to SQL Server

    There are several ways to move data from MariaDB to SQL Server:

    • If the tables don't exist at all in SQL Server, we need to generate a dump first. The dump can include data or not.

    • If the tables are already in SQL Server, we can use CSV files instead of dumps to move the rows. CSV files are the most concise format to move data between different technologies.

    • With the tables already in SQL Server, another way to move data is to insert the rows into tables that "point" to remote SQL Server tables.

    Using a Dump (Structure)

    can be used to generate dumps of all databases, a specified database, or a set of tables. It is even possible to only dump a set of rows by specifying the WHERE clause.

    By specifying the --no-data option we can dump the table structures without data.

    --compatible=mssql will produce an output that should be usable in SQL Server.

    Using a Dump (Data)

    mariadb-dump by default produces an output with both data and structure.

    --no-create-info can be used to skip the statements.

    --compatible=mssql will produce an output that should be usable in SQL Server.

    --single-transaction should be specified to select the source data in a single transaction, so that a consistent dump is produced.

    --quick speeds up the dump process when dumping big tables.

    Using a CSV File

    CSV files can also be used to export data to SQL Server. There are several ways to produce CSV files from MariaDB:

    • The statement.

    • The storage engine, with the .

    • The storage engine (note that it doesn't support NULL and indexes).

    Using CONNECT Tables

    The storage engine allows one to access external data, in many forms:

    • (, , , HTML and more).

    • Remote databases, using the or standards, or .

    • Some .

    CONNECT was mentioned previously because it could allow one to read a CSV file and query it in SQL, filtering and transforming the data that we want to move into regular MariaDB tables.

    However, CONNECT can also access remote SQL Server tables. We can read data from it, or even write data.

    To enable CONNECT to work with SQL Server, we need to fulfill these requirements:

    • Install the ODBC driver, downloadable form website. The driver is also available for Linux and MacOS.

    • Install .

    • (unless it is already installed).

    Here is an example of a CONNECT table that points to a SQL Server table:

    The key points here are:

    • ENGINE=CONNECT tells MariaDB that we want to create a CONNECT table.

    • TABLE_TYPE must be 'ODBC', so CONNECT knows what type of data source it has to use.

    • CONNECTION is the connection string to use, including server address, username and password.

    CONNECT is able to query SQL Server to find out the remote table structure. We can use this feature to avoid specifying the column names and types:

    However, we may prefer to manually specify the MariaDB types, sizes and character sets to use.

    Linked Server

    Instead of using MariaDB CONNECT, it is possible to use SQL Server Linked Server functionality. This will allow one to read data from a remote MariaDB database and copy it into local SQL Server tables. However, note that CONNECT allows more control on mapping.

    Refer to section in Microsoft documentation.

    This page is licensed: CC BY-SA / Gnu FDL

    mv /var/lib/mysql /var/lib/mysql_backup_timestamp
    mkdir /var/lib/mysql
    chown mysql:mysql /var/lib/mysql
    Requirement: This is required when upgrading between major versions of both MySQL and MariaDB as the format of the undo or redo files can change between major versions.
    SET GLOBAL innodb_fast_shutdown = 0;
    mysqladmin -u root -p shutdown
    mariadbd --help --verbose > /tmp/log 2>&1
    systemctl start mariadb
    [galera]
    # ... standard galera settings ...
    
    # 1. Point to the MariaDB Donor
    # After the first MariaDB node has successfully joined, this variable 
    # should be set on all other nodes to the value of wsrep_node_name 
    # on the first MariaDB node.
    wsrep_sst_donor=Name_of_First_MariaDB_Node
    
    # 2. Use Binary SST
    # For other joining nodes, mariabackup value should be used.
    wsrep_sst_method=mariabackup
    wsrep_sst_auth=sst_user:strong_password
    
    wsrep_provider_options="gcs.check_appl_proto=0"
    [galera]
    # ... standard galera settings ...
    
    # 1. IGNORE PROTOCOL MISMATCH
    # Required to avoid application protocol mismatch messages during migration.
    wsrep_provider_options="gcs.check_appl_proto=0;gcache.size=2G"
    
    # 2. USE LOGICAL SST (First Node Only)
    # wsrep_sst_method should be set to mysqldump for the first MariaDB node 
    # to join the MySQL cluster.
    wsrep_sst_method=mysqldump
    
    # 3. SST AUTHENTICATION
    # Should contain user and password and this user should exist on both 
    # MySQL and MariaDB databases with sufficient access rights.
    wsrep_sst_auth=sst_user:strong_password
  • TABNAME tells CONNECT what the remote table is called. The local name could be different.

  • sql_mode
    stored procedures
    stored functions
    triggers
    views
    innodb_strict_mode
    CREATE TABLE
    updatable_views_with_limit
    UPDATE
    DELETE
    sp_helptext()
    sql_modules
    MariaDB does not support schemas
    mariadb
    mariadb Command-line Client Options
    mariadb Commands
    LOAD DATA INFILE
    CONNECT
    INSERT SELECT
    CONNECT
    mariadb-dump
    CREATE TABLE
    SELECT INTO OUTFILE
    CONNECT
    CSV table type
    CSV
    CONNECT
    Data files
    CSV
    JSON
    XML
    ODBC
    JDBC
    MariaDB/MySQL native protocol
    special data sources
    Microsoft
    unixODBC
    Install CONNECT
    types and character sets
    Linked Servers
    mariadb --show-warnings < dump.sql
    root@d5a54a082d1b:/# mariadb -uroot -psecret
    Welcome to the MariaDB monitor.  Commands end with ; or \g.
    Your MariaDB connection id is 22
    Server version: 10.4.7-MariaDB-1:10.4.7+maria~bionic mariadb.org binary distribution
    
    Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    MariaDB [(none)]> \W
    Show warnings enabled.
    MariaDB [(none)]> source dump.sql
    CREATE TABLE city (
        id INT PRIMARY KEY,
        city_name VARCHAR(100),
        province_id INT NOT NULL
    )
        ENGINE=CONNECT,
        TABLE_TYPE=ODBC,
        TABNAME='city'
        CONNECTION='Driver=SQL Server Native Client 13.0;Server=sql-server-hostname;Database=world;UID=mariadb_connect;PWD=secret';
    CREATE TABLE city
        ENGINE=CONNECT,
        TABLE_TYPE=ODBC,
        TABNAME='city'
        CONNECTION='Driver=SQL Server Native Client 13.0;Server=sql-server-hostname;Database=world;UID=mariadb_connect;PWD=secret';

    Oracle XE 11.2. and MariaDB 10.1 integration on Ubuntu 14.04 and Debian systems

    Migrate from Oracle to MariaDB Server. This page provides detailed guidance, tools, and best practices for a smooth and efficient transition of your databases and applications.

    Part 1: Installing Oracle Database Express Edition (XE)

    This section covers the installation of Java and the Oracle XE database on a Debian-based system like Ubuntu.

    Step 1: Download Oracle Database XE

    1. Sign up for an Oracle account (if you don't have one) and log in.

    2. Navigate to the download page for legacy versions of the database. A good starting point is the .

    3. Accept the license agreement.

    4. Download Oracle Database Express Edition 11g Release 2 for Linux x64. The file will be named similarly to oracle-xe-11.2.0-1.0.x86_64.rpm.zip.

    Step 2: Install and Configure Java 8

    Oracle XE 11gR2 requires a Java environment.

    A) Add the Java PPA and Install

    B) Verify Java Installation

    After the installation completes, verify the version.

    The output should be similar to:

    C) Set JAVA_HOME Environment Variable

    Edit the system-wide bash configuration file.

    Scroll to the bottom of the file and add the following lines:

    Save the file and exit. Then, source the file to apply the changes and verify the variable is set.

    The output should be:

    Step 3: Install Prerequisite Packages

    Additional packages are required to convert and install the Oracle RPM.

    Step 4: Convert the Oracle RPM to a DEB Package

    The downloaded file is an RPM, which must be converted to a DEB package for Debian-based systems.

    This conversion step might take some time. You can proceed with the following configuration steps in a separate terminal window while it runs.

    Step 5: Create chkconfig and Kernel Configuration

    A) Create a chkconfig Compatibility Script

    The Oracle installer expects the chkconfig utility, which doesn't exist on Debian-based systems. Create a compatibility script.

    Add the following content to the new file:

    Save the file, then make it executable:

    B) Configure Kernel Parameters

    Create a configuration file for Oracle-specific kernel parameters.

    Copy and paste the following into the file. The value for kernel.shmmax should be approximately half of your system's physical RAM, specified in bytes (e.g., 512MB = 536870912 bytes).

    Apply the new kernel parameters and verify the fs.file-max setting.

    The expected output is 6815744.

    Step 6: Final System Adjustments

    A) Create Compatibility Links and Directories

    B) Configure Shared Memory (/dev/shm)

    To avoid a potential ORA-00845: MEMORY_TARGET error, re-mount the /dev/shm directory with a sufficient size. Replace 4096m with the amount of RAM on your machine.

    To make this change persistent across reboots, create a startup script.

    Add the following content, again replacing 4096m with your machine's RAM size.

    Save the file and make it executable:

    Step 7: Install and Configure Oracle XE

    A) Install the Converted Package

    By now, the .deb package should have been created. Install it using \.

    B) Run the Oracle Configuration Script

    Configure the database by running the script and answering the prompts. The default answers are usually acceptable.

    You will be prompted for:

    • HTTP port for Oracle Application Express (default: 8080)

    • Database listener port (default: 1521)

    • A password for the SYS and SYSTEM accounts.

    C) Set Oracle Environment Variables

    Edit /etc/bash.bashrc again to add the Oracle-specific variables.

    Add the following to the end of the file:

    Apply and verify the changes:

    D) Start Oracle

    Part 2: Installing SQL Developer

    Step 1: Download and Install SQL Developer

    1. Go to the Oracle site and download the Linux RPM package for Oracle SQL Developer.

    2. Use alien to convert the package and dpkg to install it.

    1. Create a configuration directory.

    Step 2: Run and Connect to Oracle XE

    1. Launch SQL Developer.

      Bash

    2. If it asks for the Java path, provide it: /usr/lib/jvm/java-8-oracle.

    3. Inside SQL Developer, create a new connection with the following details:

    Part 3: Installing MariaDB and Connecting to Oracle

    Step 1: Install MariaDB

    Follow the official instructions on the MariaDB website for your specific OS version.

    Do NOT copy the commands below. Go to the to generate the correct commands for your system. The following is only an example.

    Step 2: Install MariaDB ODBC Connector

    1. Download the "MariaDB Connector/ODBC" for Linux from the MariaDB website.

    2. Extract the archive and copy the library file.

    Step 3: Install UnixODBC and CONNECT Engine

    Step 4: Configure ODBC Drivers

    A) Configure the Oracle Driver

    Edit /etc/odbcinst.ini and add the following section:

    B) Configure the Oracle DSN

    Edit /etc/odbc.ini and add a Data Source Name (DSN) for your Oracle XE database.

    Step 5: Test the Oracle ODBC Connection

    Use isql to test the connection and create a sample table in Oracle.

    You should see the rows 1, 3, 5, 8 returned.

    Step 6: Configure and Test the MariaDB CONNECT Engine

    A) Set Environment Variables for MariaDB

    For the CONNECT engine to find the Oracle libraries, you must add the Oracle environment variables to MariaDB's startup script. Edit /etc/init.d/mysql.

    Immediately after ### END INIT INFO, add the following block:

    B) Restart MariaDB and Test the Connection

    Once logged into the MariaDB client, run the following SQL commands:

    You should see the values 1, 3, 5, 8 retrieved from the Oracle table.

    Part 4: Connecting to MariaDB via JDBC

    Step 1: Install the MariaDB JDBC Driver

    1. Download the "MySQL Connector/J" from the MySQL or MariaDB website.

    2. Extract the archive and copy the .jar file to a known location.

    Step 2: Configure SQL Developer

    1. Launch SQL Developer: sudo /opt/sqldeveloper/sqldeveloper.sh

    2. Go to Tools -> Preferences.

    3. Expand Database and click on Third Party JDBC Drivers.

    4. Click Add Entry... and navigate to the .jar file you copied: /usr/lib/jvm/java-8-oracle/lib/mariadb/mysql-connector-java-5.0.8-bin.jar

    Step 3: Connect to MariaDB

    1. In SQL Developer, create a new connection.

    2. Switch to the MySQL tab.

    3. Enter the connection details:

      • Connection Name: MariaDB via MySQL Conn


    This page is licensed: CC BY-SA / Gnu FDL

    Whether to start the database on boot (default: y)

    Click: Connections, then Add new connection
  • Connection Name: XE

  • Username: SYSTEM

  • Password: <your-password>

  • Connection Type: Basic, Role: Default

  • Hostname: localhost

  • Port: 1521

  • SID: xe

  • .
  • Click OK to close the preferences.

  • Username: root

  • Password: <your-root-password>

  • Hostname: localhost

  • Port: 3306

  • Click Test Connection. It should report Status: Success.

  • Save and connect. You can now run queries against your MariaDB server in the worksheet.

  • Oracle Database Express Edition (XE) 11gR2 Archive Downloads Page
    MariaDB Repository Configuration Tool
    sudo add-apt-repository ppa:webupd8team/java
    # Press Enter to accept when prompted
    sudo apt-get update
    sudo apt-get install oracle-java8-installer
    java -version
    java version "1.8.0_121"
    sudo nano /etc/bash.bashrc
    export JAVA_HOME=/usr/lib/jvm/java-8-oracle
    export PATH=$JAVA_HOME/bin:$PATH
    source /etc/bash.bashrc
    echo $JAVA_HOME
    /usr/lib/jvm/java-8-oracle
    sudo apt-get install alien libaio1 unixodbc
    unzip oracle-xe-11.2.0-1.0.x86_64.rpm.zip
    cd Disk1/
    sudo alien --scripts -d oracle-xe-11.2.0-1.0.x86_64.rpm
    sudo nano /sbin/chkconfig
    #!/bin/bash
    # Oracle 11gR2 XE installer chkconfig for Ubuntu
    file=/etc/init.d/oracle-xe
    if [[ ! `tail -n1 $file | grep INIT` ]]; then
      echo >> $file
      echo '### BEGIN INIT INFO' >> $file
      echo '# Provides: OracleXE' >> $file
      echo '# Required-Start: $remote_fs $syslog' >> $file
      echo '# Required-Stop: $remote_fs $syslog' >> $file
      echo '# Default-Start: 2 3 4 5' >> $file
      echo '# Default-Stop: 0 1 6' >> $file
      echo '# Short-Description: Oracle 11g Express Edition' >> $file
      echo '### END INIT INFO' >> $file
    fi
    update-rc.d oracle-xe defaults 80 01
    #EOF
    sudo chmod 755 /sbin/chkconfig
    sudo nano /etc/sysctl.d/60-oracle.conf
    # Oracle 11g XE kernel parameters  
    fs.file-max=6815744  
    net.ipv4.ip_local_port_range=9000 65000  
    kernel.sem=250 32000 100 128 
    kernel.shmmax=536870912
    sudo service procps start
    sudo sysctl -q fs.file-max
    sudo ln -s /usr/bin/awk /bin/awk
    sudo mkdir /var/lock/subsys
    sudo touch /var/lock/subsys/listener
    sudo rm -rf /dev/shm
    sudo mkdir /dev/shm
    sudo mount -t tmpfs shmfs -o size=4096m /dev/shm
    sudo nano /etc/rc2.d/S01shm_load
    #!/bin/sh
    case "$1" in
    start)
      mkdir /var/lock/subsys 2>/dev/null
      touch /var/lock/subsys/listener
      rm /dev/shm 2>/dev/null
      mkdir /dev/shm 2>/dev/null
      mount -t tmpfs shmfs -o size=4096m /dev/shm
      ;;
    *)
      echo "Usage: $0 start"
      exit 1
      ;;
    esac
    sudo chmod 755 /etc/rc2.d/S01shm_load
    sudo dpkg --install oracle-xe_11.2.0-2_amd64.deb
    sudo /etc/init.d/oracle-xe configure
    sudo nano /etc/bash.bashrc
    export ORACLE_HOME=/u01/app/oracle/product/11.2.0/xe
    export ORACLE_SID=XE
    export NLS_LANG=`$ORACLE_HOME/bin/nls_lang.sh`
    export ORACLE_BASE=/u01/app/oracle
    export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH
    export PATH=$ORACLE_HOME/bin:$PATH
    source /etc/bash.bashrc
    echo $ORACLE_HOME
    sudo service oracle-xe start
    sudo alien --scripts -d sqldeveloper-4.1.5.21.78-1.noarch.rpm
    sudo dpkg --install sqldeveloper_4.1.5.21.78-2_all.deb
    mkdir ~/.sqldeveloper
    sudo /opt/sqldeveloper/sqldeveloper.sh
    # Example commands for Ubuntu 14.04 Trusty
    sudo apt-get install software-properties-common
    sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xcbcb082a1bb943db
    sudo add-apt-repository 'deb [arch=amd64,i386,ppc64el] http://mirror.netinch.com/pub/mariadb/repo/10.1/ubuntu trusty main'
    sudo apt-get update
    sudo apt-get install mariadb-server
    tar xfz mariadb-connector-odbc-2.0.13-ga-linux-x86_64.tar.gz
    sudo cp -p mariadb-connector-odbc-2.0.13-ga-linux-x86_64/lib/libmaodbc.so /lib
    sudo ldconfig
    sudo apt-get install unixodbc-dev unixodbc-bin unixodbc libodbc1 mariadb-connect-engine-10.1
    [Oracle ODBC driver for Oracle 11.2]
    Description     = Oracle 11.2 ODBC driver
    Driver          = /u01/app/oracle/product/11.2.0/xe/lib/libsqora.so.11.1
    [XE]
    Driver          = Oracle ODBC driver for Oracle 11.2
    ServerName      = //localhost:1521/xe
    DSN             = XE
    UserName        = SYSTEM
    Password        = <your-password>
    isql -v XE SYSTEM <your-password>
    
    CREATE TABLE t1 (i INT);
    INSERT INTO t1 (i) VALUES (1);
    INSERT INTO t1 (i) VALUES (3);
    INSERT INTO t1 (i) VALUES (5);
    INSERT INTO t1 (i) VALUES (8);
    SELECT i FROM t1;
    sudo nano /etc/init.d/mysql
    # Oracle Environment for MariaDB CONNECT Engine
    export JAVA_HOME=/usr/lib/jvm/java-8-oracle 
    export PATH=$JAVA_HOME/bin:$PATH 
    export ORACLE_HOME=/u01/app/oracle/product/11.2.0/xe 
    export CLIENT_HOME=$ORACLE_HOME 
    export ORACLE_SID=XE 
    export NLS_LANG=`$ORACLE_HOME/bin/nls_lang.sh` 
    export ORACLE_BASE=/u01/app/oracle 
    export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH 
    export PATH=$ORACLE_HOME/bin:$PATH
    sudo /etc/init.d/mysql restart
    mysql -uroot -p
    CREATE DATABASE mdb;
    USE mdb;
    INSTALL SONAME 'ha_connect';
    CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC tabname='T1' CONNECTION='DSN=XE;UID=SYSTEM;PWD=<your-password>';
    
    SELECT I FROM t1;
    tar xvfz mysql-connector-java-5.0.8.tar.gz
    cd mysql-connector-java-5.0.8/
    sudo mkdir -p /usr/lib/jvm/java-8-oracle/lib/mariadb/
    sudo cp -p mysql-connector-java-5.0.8-bin.jar /usr/lib/jvm/java-8-oracle/lib/mariadb/

    MariaDB Transactions and Isolation Levels for SQL Server Users

    Discusses transaction handling and isolation levels in MariaDB (READ COMMITTED, REPEATABLE READ) compared to SQL Server, including locking behavior and deadlock handling.

    This page explains how transactions work in MariaDB, and highlights the main differences between MariaDB and SQL Server transactions.

    Note that XA transactions are handled in a completely different way and are not covered in this page. See XA Transactions.

    Missing Features

    These SQL Server features are not available in MariaDB:

    • Autonomous transactions;

    • Distributed transactions.

    Transactions, Storage Engines and the Binary Log

    In MariaDB, transactions are optionally implemented by . The default storage engine, , fully supports transactions. Other transactional storage engines include and . Most storage engines are not transactional, therefore they should not considered general purpose engines.

    Most of the information in this page refers to generic MariaDB server behaviors or InnoDB. For and please check the proper KnowledgeBase sections.

    Writing into a non-transactional table in a transaction can still be useful. The reason is that a is acquired on the table for the duration of the transaction, so that are queued.

    It is possible to write into transactional and non-transactional tables within a single transaction. It is important to remember that non-transactional engines will have the following limitations:

    • In case of rollback, changes to non-transactional engines won't be undone. We will receive a warning 1196 which reminds us of this.

    • Data in transactional tables cannot be changed by other connections in the middle of a transaction, but data in non-transactional tables can.

    • In case of a crash, committed data written into a transactional table can always be recovered, but this is not necessarily true for non-transactional tables.

    If the is enabled, writing into different transactional storage engines in a single transaction, or writing into transactional and non-transactional engines inside the same transaction, implies some extra work for MariaDB. It needs to perform a two-phase commit to be sure that changes to different tables are logged in the correct order. This affects the performance.

    Transaction Syntax

    The first read or write to an InnoDB table starts a transaction. No data access is possible outside a transaction.

    By default is on, which means that the transaction is committed automatically after each SQL statement. We can disable it, and manually commit transactions:

    Whether autocommit is enabled or not, we can start transactions explicitly, and they will not be automatically committed:

    BEGIN can also be used to start a transaction, but does not work in stored procedures.

    Read-only transactions are also available using START TRANSACTION READ ONLY. This is a small performance optimization. MariaDB will issue an error when trying to write data in the middle of a read-only transaction.

    Only DML statements are transactional and can be rolled back. This may change in a future version, see - Atomic DDL and - transactional DDL.

    Changing autocommit and explicitly starting a transaction will implicitly commit the active transaction, if any. DDL statements, and several other statements, implicitly commit the active transaction. See for the complete list of these statements.

    A rollback can also be triggered implicitly, when certain errors occur.

    You can experiment with transactions to check in which cases they implicitly commit or rollback. The system variable can help: it is set to 1 when a transaction is in progress, or 0 when no transaction is in progress.

    This section only covers the basic syntax for transactions. Much more options are available. For more information, see .

    Constraint Checking

    MariaDB supports the following :

    In some databases, constraints can temporarily be violated during a transaction, and their enforcement can be deferred to the commit time. SQL Server does not support this, and always validates data against constraints at the end of each statement.

    MariaDB does something different: it always checks constraints after each row change. There are cases this policy makes some statements fail with an error, even if those statements would work on SQL Server.

    For example, suppose you have an id column that is the primary key, and you need to increase its value for some reason:

    The reason why this happens is that, as the first thing, MariaDB tries to change 1 to 2, but a value of 2 is already present in the primary key.

    A solution is to use this non-standard syntax:

    Changing the ids in reversed order won't duplicate any value.

    Similar problems can happen with CHECK constraints and foreign keys. To solve them, we can use a different approach:

    The last solutions temporarily disable CHECK constraints and foreign keys. Note that, while this may solve practical problems, it is dangerous because:

    • This doesn't disable a single CHECK or foreign key, but also others, that you don't expect to violate.

    • This doesn't defer the constraint checks, but it simply disables them for a while. This means that, if you insert some invalid values, they will not be detected.

    See and system variables.

    Isolation Levels and Locks

    For more information about MariaDB isolation levels see .

    Locking Reads

    In MariaDB, the locks acquired by a read do not depend on the isolation level (with one exception noted below).

    As a general rule:

    • Plain are not locking, they acquire snapshots instead.

    • To force a read to acquire a shared lock, use .

    • To force a read to acquire an exclusive lock, use .

    Changing the Isolation Level

    The default, the isolation level in MariaDB is REPEATABLE READ. This can be changed with the system variable.

    Applications developed for SQL Server and later ported to MariaDB may run with READ COMMITTED without problems. Using a stricter level would reduce scalability. To use READ COMMITTED by default, add the following line to the MariaDB configuration file:

    It is also possible to change the default isolation level for the current session:

    Or just for one transaction, by issuing the following statement before starting a transaction:

    How Isolation Levels are Implemented in MariaDB

    MariaDB supports the following isolation levels:

    • READ UNCOMMITTED

    • READ COMMITTED

    • REPEATABLE READ

    • SERIALIZABLE

    MariaDB isolation levels differ from SQL Server in the following ways:

    • REPEATABLE READ does not acquire share locks on all read rows, nor a range lock on the missing values that match a WHERE clause.

    • It is not possible to change the isolation level in the middle of a transaction.

    • SNAPSHOT isolation level is not supported. Instead, you can use START TRANSACTION WITH CONSISTENT SNAPSHOT to acquire a snapshot at the beginning of the transaction. This is compatible with all isolation levels.

    Here is an example of WITH CONSISTENT SNAPSHOT usage:

    As you can see, session 1 uses WITH CONSISTENT SNAPSHOT, thus it sees all tables as they were when the transaction begun.

    Avoiding Lock Waits

    When we try to read or modify a row that is exclusive-locked by another transaction, our transaction is queued until that lock is released. There could be more queued transactions waiting to acquire the same lock, in which case we will wait even more.

    There is a timeout for such waits, defined by the variable. If it is set to 0, statements that encounter a row lock will fail immediately. When the timeout is exceeded, MariaDB produces the following error:

    It is important to note that this variable has two limitations (by design):

    • It only affects transactional statements, not statements like ALTER TABLE or TRUNCATE TABLE.

    • It only concerns row locks. It does not put a timeout on metadata locks, or table locks acquired - for example - with the statement.

    Note however that can be used for metadata locks.

    There is a special syntax that can be used with SELECT and some non-transactional statements including ALTER TABLE: the clauses. This syntax puts a timeout in seconds for all lock types, including row locks, table locks, and metadata locks. For example:

    InnoDB Transactions

    InnoDB Lock Types

    InnoDB locks are classified based on what exactly they lock, and which operations they lock.

    The first classification is the following:

    • Record Locks lock a row or, more precisely, an index entry.

    • Gap Locks lock an interval between two index entries. Note that indexes have virtual values of -Infinum and Infinum, so a gap lock can cover the gap before the first or after the last index entry.

    • Next-Key Locks lock an index entry and the gap between it and the next entry. They're a combination of record locks and gap locks.

    • Insert Intention Locks are gap locks acquired before inserting a new row.

    Lock modes are the following:

    • Exclusive Locks (X) are generally acquired on writes, e.g. immediately before deleting a row. Only one exclusive lock can be acquired on a resource simultaneously.

    • Shared Locks (S) can be acquired on reads. Multiple shared locks can be acquired at the same time (because the rows are not supposed to change when shared-locked) but are incompatible with exclusive locks.

    • Intention locks (IS, XS) are acquired when it is not possible to acquire an exclusive lock or a shared lock. When a lock on a row or gap is released, the oldest intention lock on that resource (if any) is converted to an X or S lock.

    For more information see .

    Information Schema

    Querying the is the best way to see which transactions have acquired some locks and which transactions are waiting for some locks to be released.

    In particular, check the following tables:

    • : requests for locks not yet fulfilled, or that are blocking another transaction.

    • : queued requests to acquire a lock.

    • : information about all currently executing InnoDB transactions, including SQL queries that are running.

    Here is an example of their usage.

    Deadlocks

    InnoDB detects deadlocks automatically. Since this consumes CPU time, some users prefer to disable this feature by setting the variable to 0. If this is done, locked transactions will wait until the they exceed the . Therefore it is important to set innodb_lock_wait_timeout to a very low value, like 1.

    When InnoDB detects a deadlock, it kills the transaction that modified the least amount of data. The client will receive the following error:

    The latest detected deadlock, and the killed transaction, can be viewed in the output of . Here's an example:

    The latest detected deadlock never disappears from the output of SHOW ENGINE InnoDB STATUS. If you cannot see any, MariaDB hasn't detected any InnoDB deadlocks since the last restart.

    Another way to monitor deadlocks is to set to 1 (0 is the default). InnoDB will log all detected deadlocks into the .

    This page is licensed: CC BY-SA / Gnu FDL

    MariaDB Replication Overview for SQL Server Users

    An introduction to MariaDB's asynchronous replication and Galera Cluster for SQL Server users, explaining concepts like binary logs, relay logs, and group commit.

    MariaDB supports the following types of replication:

    • Asynchronous replication.

    • Semi-synchronous replication.

    • Galera Cluster.

    MariaDB starting with

    Repairing MariaDB Tables for SQL Server Users

    Explains how to check and repair tables in MariaDB using `CHECK TABLE` and `REPAIR TABLE`, noting that InnoDB typically handles corruption by crashing to prevent data loss.

    Repairing tables in MariaDB is not similar to repairing tables in SQL Server.

    The first thing to understand is that every MariaDB table is handled by a . Storage engines are plugins that know how to physically read and write a table, so each storage engine allows one to repair tables in different ways. The default storage engine is .

    MariaDB provides specific SQL statements to deal with corrupted tables:

    • checks if a table is corrupted;

    • repairs a table if it is corrupted.

    Note: in the snippets in this page, several SQL statements use the keyword SLAVE. This word is considered inappropriate by some persons or cultures, so from it is possible to use the REPLICA keyword, as a synonym. Similar synonyms will be created in the future for status variables and system variables. See MDEV-18777 to track the status of these changes.

    Asynchronous Replication

    The original MariaDB replication system is asynchronous primary-replica replication.

    A primary needs to have the binary log enabled. The primary logs all data changes in the binary log. Every event (a binary log entry) is sent to all the replicas.

    For a high-level description of the binary log for SQL Server users, see Understanding MariaDB Architecture.

    The events can be written in two formats: as an SQL statement (statement-based replication, or SBR), or as a binary representation of the change (row-based replication, or RBR). The former is generally slower, because the statement needs to be re-executed by the replicas. It is also less reliable, because some SQL statements are not deterministic, so they could produce different results on the replicas. On the other hand row-based replication could make the binary log much bigger, and require more network traffic. For this reason, DML statements are always logged in statement format.

    For more details on replication formats, see binary log formats.

    The replicas have an I/O thread that receives the binary log events and writes them to the relay log. These events are then read by the SQL thread. This thread could directly apply the changes to the local databases, and this was the only option before . If parallel replication is enabled, the SQL thread hands the events to the worker thread, that apply them to the databases. The latter method is recommended for performance reasons.

    When a replica cannot apply an event to the local data, the SQL thread stops. This happens, for example, if the event is a row deletion but that row doesn't exist on the replica. There can be several reasons for this, for example non-deterministic statements, or a user deleted the row in the replica. To reduce the risk, it is recommended to set read_only to 1 in the replicas.

    SHOW SLAVE STATUS has columns named Slave_SQL_State and Slave_IO_State that show, respectively, if the SQL thread and the IO thread are running. If they are not, the column Last_IO_Errno and Last_IO_Error (for the IO thread) or Last_SQL_Errno and Last_SQL_Error (for the SQL thread) show what the problem is.

    In a replication chain, every server must have a unique server_id.

    For more information on replication, see standard replication.

    Binary Log Coordinates, Relay Log Coordinates and GTID

    The binary log coordinates provide a way to identify a certain data change made by a server. Coordinates consist of a file name and the position of the latest event, expressed as an integer. The last event coordinates can be seen with the SHOW MASTER STATUS columns File and Position. mariadb-dump includes them in a dump if the --master-data option is used.

    A replica uses primary binary log coordinates to identify the last event it read. This can be seen with the SHOW SLAVE STATUS columns Master_Log_File and Read_Master_Log_Pos.

    The columns Relay_Master_Log_File and Exec_Master_Log_Pos identify the primary event that corresponds to the last event applied by the SQL thread.

    The replica relay log also has coordinates. The coordinates of the last applied event can be seen with the SHOW SLAVE STATUS columns Relay_Log_File and Relay_Log_Pos.

    To easily find out how far the replica is lagging behind the primary, we can look at Seconds_Behind_Master.

    Coordinates represented in this way have a problem: they are different on each server. Each server can use files with different (or the same) names, depending on its configuration. And files can be rotated at different times, including when a user runs FLUSH LOGS. By enabling the GTID (global transaction id) an event will have the same id on the primary and on all the replicas.

    When GTID is enabled, SHOW SLAVE STATUS shows two GTIDs: Gtid_IO_Pos is the last event written into the relay log, and Gtid_Slave_Pos is the last event applied by the SQL thread. There is no need for a column identifying the same event in the primary, because the id is the same.

    Provisioning a Replica

    MariaDB does not have an equivalent to SQL Server's snapshot replication.

    To setup a replica, it is necessary to manually provision it. It can be provisioned from the primary in this way:

    • A backup from the primary must be restored on the new replica;

    • The binary log coordinates at the moment of the backup should be set as replication coordinates in the replica, via CHANGE MASTER TO.

    However, if there is at least one existing replica, it is better to use it to provision the new replica:

    • A backup from the existing replica must be restored in the new replica;

    • The backup should include the system tables. In this way it will not be necessary to set the correct coordinates manually.

    For more information see Setting Up Replication and Setting up a Replica with mariadb-backup.

    Replication and Permissions

    A replica connects to a primary using its credentials. See CHANGE MASTER TO.

    The appropriate account must be created in the primary, and it needs to have the REPLICATION SLAVE permission.

    See Setting Up Replication for more information.

    Parallel Replication and Group Commit

    MariaDB uses group commit, which means that a group of events are physically written in the binary log altogether. This reduces the number of IOPS (input/output operations per second). Group commit cannot be disabled, but it can be tuned with variables like binlog_commit_wait_count and binlog_commit_wait_usec.

    Replicas can apply the changes using multiple threads. This is known as parallel replication. Before only one thread was used to apply changes. Since a primary can use many threads to write data, mono-thread replication is a well-known bottleneck. Parallel replication is not enabled by default. To use it, set the slave_parallel_threads variable to a number greater than 1. If replication is running, the replica threads must be stopped in order to change this value:

    There are different parallel replication styles available: in-order and out-of-order. The exact mode in use is determined by the slave_parallel_mode system variable. In parallel replication, the events are not replicated exactly in the same order as they occurred in the primary. But with an in-order replication mode the commit phase is always applied simultaneously. In this way data in the replica always reflect data as they have been in the primary at a certain point in time. Out-of-order replication is faster because there is less queuing, but it's not completely consistent with the primary. If two transactions modified different sets of rows in the primary, they could become visible in the replica in a different order.

    conservative relies on primary group commit: events in different groups are executed in a parallel way.

    optimistic does not try to find out which transaction can be executed in a parallel way - except for transactions that conflicted on the primary. Instead, it always tries to apply many events together, and rolls transactions back when there is a conflict.

    aggressive is similar to optimistic, but it does not take into account which transactions conflicted in the primary.

    minimal applies commits together, but all other events are applied in order.

    Out-of-order replication cannot be enabled automatically by changing a variable in the replica. Instead, it must be enabled by the applications that run transactions in the primary. They can do this if the GTID is enabled. They can set different values for the gtid_domain_id variable in different transactions. This shifts a lot of responsibility to the application layer; however, if the application is aware of which transactions are not going to conflict and this information allows one to sensibly increase the parallelism, and using out-of-order replication can be a good idea.

    Even if out-of-order replication is not normally used, it can be a good idea to use it for long running transactions or ALTER TABLEs, so they can be applied at the same time as normal operations that are not conflicting.

    The impact of the number of threads and mode on performance can be partly seen with SHOW PROCESSLIST, which shows the state of all threads. This includes the replication worker threads, and shows if they are blocking each other.

    Differences Between the Primary and the Replicas

    As a general rule, we want the primary and the replicas to contain exactly the same data. In this way, no conflicts are possible. Conflicts are the most likely cause of replication outages.

    To reduce the possible causes of conflicts, the following best practices are recommended:

    • Users must not change data in the replica directly. Set read_only to 1. Note that this won't prevent root from making changes.

    • Use the same table definitions in the primary and in the replica.

    • Use ROW binary log format on the primary.

    Another cause of inconsistencies include MariaDB bugs and failover in case the primary crashes.

    An open source third party tool is available to check if the primary and a replica are consistent. It is called pt-table-checksum. Another tool, pt-table-sync, can be used to eliminate the differences. Both are part of Percona Toolkit. The advice is to run pt-table-checksum periodically, and use pt-table-sync if inconsistencies are found.

    If a replication outage occurs because an inconsistency is found, sometimes we want to quickly bring the replica up again as quickly as possible, and solve the core problem later. If GTID is not used, a way to do this is to run SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1, which skips the problematic replication event.

    If GTID is used, the gtid_slave_pos variable can be used instead. See the link for an explanation of how it works.

    There are ways to have different data on the replicas. For example:

    • Multi-source replication is possible. In this way, a replica will replicate data from multiple primaries. This feature is described below.

    • Replication filters are supported. This allows one to exclude or include in replication specific tables, entire databases, or tables whose name matches a certain pattern. This allows one to avoid replicating data that is present in the primary but can always be rebuilt.

    • Differences in table definitions are also possible. For example, a replica could have more columns or less columns compared to the primary. In this way we can avoid replicating columns whose values can be rebuilt. Or we can add columns for analytics purposes, without having them in the primary. Be sure to understand the limitations and risks of this technique.

    Delayed Replication

    MariaDB supports delayed replication. This is the equivalent of setting a pollinginterval in SQL Server.

    To delay replication in a MariaDB replica, use CHANGE MASTER TO to specify a delay in seconds.

    For more information, see Delayed Replication.

    Multi-Source Replication

    Multi-source replication is an equivalent to peer-to-peer replication, available in SQL Server Enterprise Edition.

    A MariaDB replica can replicate from any number of primaries. It is very important that different primaries don't have the same tables. Otherwise there could be conflicts between data changes made on different primaries, and this will result in a replication outage.

    In multi-source replication different channels exist, one for each primary.

    This changed the way SQL replication statements work. SHOW PROCESSLIST returns a different row for each channel. Several statements, like CHANGE MASTER TO, START SLAVE or STOP SLAVE. accept a parameter which specifies which replication channel they should affect. For example, to stop a channel called wp1:

    Furthermore, variables that affect parallel replication can be prefixed with a channel name. This allow one to only use parallel replication for certain channels, or to tune it differently for each channel. For example, to enable parallel replication on a channel called wp1:

    Dual Primary

    It is possible to configure two servers in a way that each of them acts as a primary for the other server.

    In this way, data could theoretically be inserted into any of these servers, and will then be replicated to the other server. However, in such a configuration conflicts are very likely. So it is impractical to use this technique to scale writes.

    A dual primary (or primary-primary) configuration however can be useful for failover. In this case we talk about an active primary that receives reads and writes from the clients, and a passive primary that is not used until the active primary crashes.

    Several problems should be considered in this scenario:

    • If the active primary crashes, it is very possible that the passive primary did not receive all events yet, because replication is asynchronous. If the primary data are lost (for example because the disk is damaged), some data are also lost.

    • If data is not lost, when we bring the primary up again, the latest events will be replicated by the other server. There could be conflicts that will break replication.

    • When is the active primary considered down? Even if a server cannot reach it, the active primary could be running and it could be able to communicate with the passive primary. Switching the clients to the passive primary could lead to unnecessary problems. It is a good idea to always check SHOW SLAVE STATUS to be sure that the two primary are not communicating.

    • If we want to have more replicas, we should attach some of them to the active primary, and some of them to the passive primary. The reason is that when a server crashes, its replicas stop receiving any data. Failover is still possible, but it's better to have some servers that will not need any failover.

    A safe primary-primary configuration where both servers accept writes, however, is possible. This is the case is data never conflicts. For example, the two servers could accept writes on different databases. We will have to decide what should happens in case of a server crash:

    • Writes can be stopped until the server is up again. Reads can be sent to the other server, but keep in mind that the most recently written data could be missing.

    • Both writes and reads can failover to the other server. All the problems mentioned above may apply to this situation.

    See Sveta Smirnova's slides at MariaDB Day 2020: "How Safe is Asynchronous Master-Master Setup?".

    Semi-Synchronous Replication

    Semi-synchronous replication was initially implemented as a plugin, in MySQL. Two different plugins needed to be used, one on the primary and the other on the replicas. Starting from it is built-in, which improved its performance.

    The problem with standard replication is that there is no guarantee that it will not lag, even by long amounts of time. Semi-synchronous replication reduces this problem, at the cost of reducing the speed of the primary.

    In semi-synchronous replication, when a transaction is committed on the primary, the primary does not immediately return control to the client. Instead, it sends the event to the replicas. After one replica reported that the commit was executed with success, the primary reports success to the client.

    Semi-synchronous replication is useful for failover, therefore a dual primary setup is not needed in this case. If the primary crashes, the most up-to-date replica can be promoted to primary without losing any data.

    Enabling Semi-Synchronous Replication

    Semi-synchronous replication can be enabled at runtime in this way on the primary:

    Semi-synchronous replication is not used until it has been enabled on the replicas also. If the replicas are already replicating, the io_thread needs to be stopped and restarted. This can be done as follows:

    Tuning the Wait Point and the Primary Timeout

    The most important aspects to tune are the wait point and the primary timeout.

    When the binary log is enabled, transactions must be committed both in the storage engine (usually InnoDB) and in the binary log. Semi-synchronous replication requires that the transaction is also acknowledged by at least one replica before the primary can report success to the client.

    The wait point determines at which point the primary must stop and wait for a confirmation from a replica. This is an important decision from disaster recovery standpoint, in case the primary crashes when a transaction is not fully committed. The rpl_semi_sync_master_wait_point is used to set the wait point, Its allowed values are:

    • AFTER_SYNC: After committing the transaction in the binary log, but before committing it to the storage engine. After a crash, a transaction may be present in the binary log even if it was not committed.

    • AFTER_COMMIT. After committing a transaction both in the binary log and in the storage engine. In case of a crash, a transaction could possibly be committed in the primary but not replicated in the slaves. This is the default.

    Primary timeout is meant to avoid that a primary remains stuck for a long time, or virtually forever, because no replica acknowledges a transaction. If primary timeout is reached, the primary switches to asynchronous replication. Before doing that, the primary writes an error in the error log and increments the Rpl_semi_sync_master_no_times status variable.

    The timeout is set via the rpl_semi_sync_master_timeout variable.

    Galera Cluster

    Galera is a technology that implements virtually synchronous, primary-primary replication for a cluster of MariaDB servers.

    Raft and the Primary Cluster

    Nodes of the cluster communicate using the Raft protocol. In case the cluster is partitioned or some nodes crash, a cluster knows that it's still the primary cluster if it has the quorum: half of the nodes + 1. Only the primary cluster accepts reads and writes.

    For this reason a cluster should consist of an odd number of nodes. Imagine for example that a cluster consists of two nodes: if one of them crashes of the connection between them is interrupted, there will be no primary cluster.

    Transaction Certification

    A transaction can be executed against any node. The node will use a 2-phase commit. After running the transaction locally, the node will ask other nodes to certify it. This means that other nodes will receive it, and will try to apply it, and will report success or a failure. The node that received the transaction will not wait for an answer from all the nodes. Once it succeeded on more than half of the nodes (the quorum) the node will run the final commit and data becomes visible.

    It is desirable to write data on only one node (unless it fails), or write different databases on different nodes. This will minimize the risk of conflicts.

    Galera Cache and SST

    Data changes applied are recorded for some time in the Galera cache. This is an on-disk cache, written in a circularly written file.

    The size of Galera cache can be tuned using the wsrep_provider_options system variable, which contains many flags. We need to tune gcache.size. To tune it, add a line similar to the following to a configuration file:

    If a single transaction is bigger than half of the Galera cache, it needs to be written in a separate file, as on-demand pages. On-demand pages are regularly replaced. Whether a new page replaces an old one depends on another wsrep_provider_options flag: wsrep_provider_options#gcachekeep_pages_size|gcache.keep_pages_size, which limits the total size of on-demand pages.

    When a node is restarted (after a crash or for maintenance reasons), it will need to receive all the changes that were written by other nodes since the moment it was unreachable. A node is therefore chosen as a donor, possibly using the gcssync_donor wsrep_provider_options flag.

    If possible, the donor will send all the recent changes, reading them from the Galera cache and on-demand pages. However, sometimes the Galera cache is not big enough to contain all the needed changes, or the on-demand pages have been overwritten because gcache.keep_pages_size is not big enough. In these cases, a State Snapshot Transfer (SST) needs to be sent. This means that the donor will send the whole dataset to the restarted node. Most commonly, this happens using the mariadb-backup method.

    Flow Control

    While transaction certification is synchronous, certified transactions are applied locally in asynchronous fashion. However, a node should never lag too much behind others. To avoid that, a node may occasionally trigger a mechanism called flow control to ask other nodes to stop replication until its situation improves. Several wsrep_provider_options flags affect flow control.

    gcs.fc_master_slave should normally be set to 1 if all writes are sent to a single node.

    gcs.fc_limit is tuned automatically, unless gcs.fc_master_slave is set to 0. The receive queue (the transactions received and not yet applied) should not exceed this limit. When this happens, flow control is triggered by the node to pause other node's replication.

    Once flow control is activated, gcs.fc_factor determines when it is released. It is a number from 0 to 1, and it represents a fraction. When the receive queue is below this fraction, the flow control is released.

    Flow control and the receive queue can and should be monitored. The most useful metrics are:

    • wsrep_flow_control_paused indicates how many times the replication has been paused as requested by other nodes, since the last FLUSH STATUS.

    • wsrep_flow_control_sent indicates how many times this node requested other nodes to pause replication.

    • wsrep_local_recv_queue is the size of the receive queue.

    Configuration

    Galera is implemented as a plugin. Starting from version 10.1, MariaDB comes with Galera pre-installed, but not in use by default. To enable it one has to set the wsrep_on system variable.

    Like asynchronous replication, Galera uses the binary log. It also requires that data changes are logged in the ROW format.

    For other required settings, see Mandatory Options.

    Galera Limitations

    Galera is not suitable for all databases and workloads.

    • Galera only replicates InnoDB tables. Other storage engines should not be used.

    • For performance reasons, it is highly desirable that all tables have a primary key.

    • Long transactions will damage performance.

    • Some applications use an integer AUTO_INCREMENT primary key. In case of failover from a crashed node to another, Galera does not guarantee that AUTO_INCREMENT follows a chronological order. Therere, applications should use columns for chronological order instead.

    This page is licensed: CC BY-SA / Gnu FDL

    As a general rule, there is no reason why a table that is corrupted on a master should also be corrupted on the slaves. Therefore, REPAIR is generally used with the NO_WRITE_TO_BINLOG option, to avoid replicating it to the slaves.

    Partitioned Tables

    Partitioned tables are normally split into multiple physical files (one per partition). Even if one of the partitions is corrupted, in most cases other partitions are healthy.

    For this reason, CHECK TABLE and REPAIR TABLE don't work on partitioned tables. Instead, use ALTER TABLE to check or repair a single partition.

    For example:

    Indexes

    Indexes can get corrupted. However, as long as data is not corrupted, indexes can always be dropped and rebuilt with ALTER TABLE:

    Checking and Repairing Tables

    Here we discuss how to repair tables, depending on the storage engine.

    InnoDB

    InnoDB follows the "fail fast" philosophy. If table corruption is detected, by default InnoDB deliberately causes MariaDB to crash to avoid corruption propagation, logging an error into the error log. This happens even if the corruption is found with a CHECK TABLE statement. This behavior can be changed with the innodb_corrupt_table_action server variable.

    To repair an InnoDB table after a crash:

    1. Restart MariaDB with the --innodb-force-recovery option set to a low but non-zero value.

    2. If MariaDB fails to start, retry with a higher value. Repeat until you succeed.

    At this point, you can follow two different procedures, depending if you can use a backup or not. Provided that you have a usable backup, it is often the best option to bring the database up quickly. But if you want to reduce the data loss as much as possible, you prefer to follow the second method.

    Restoring a backup:

    1. Drop the whole database with DROP DATABASE.

    2. Restore a backup of the database. The exact procedure depends on the type of backup.

    Recovering existing data:

    1. Dump data from the corrupter table, ordered by primary key. MariaDB could crash when it finds damaged data. Repeat the process skipping damaged data.

    2. Save somewhere the table structure with SHOW CREATE TABLE.

    3. Restart MariaDB.

    4. Drop the table with DROP TABLE.

    5. Recreate the table and restore the dump.

    For more details, see InnoDB Recovery Modes.

    Aria and MyISAM

    MyISAM is not crash-safe. In case of a MariaDB crash, the changes applied to MyISAM tables but not yet flushed to the disk are lost.

    Aria is crash-safe by default, which means that in case of a crash, after repairing any table that is damaged, no changes are lost. However, Aria tables are not crash-safe if created with TRANSACTIONAL=0 or ROW_FORMAT set to FIXED or DYNAMIC.

    System tables use the Aria storage engine and they are crash-safe.

    To check if a MyISAM/Aria table is corrupted, we can use CHECK TABLE. To repair a MyISAM/Aria table, one can use REPAIR TABLE. Before running REPAIR TABLE against big tables, consider increasing myisam_repair_threads or aria_repair_threads.

    MyISAM and Aria tables can also be automatically repaired when corruption is detected. This is particularly useful for Aria, in case corrupted system tables prevent MariaDB from starting. See myisam_recover_options and aria_recover_options. By default Aria runs the quickest repair type. Occasionally, to repair a system table, we may have to start MariaDB in this way:

    It is also possible to stop MariaDB and repair MyISAM tables with myisamchk, and Aria tables with aria_chk. With default values, a repair can be unnecessarily very slow. Before running these tools, be sure to check the Memory and Disk Use With myisamchk page.

    Other Storage Engines

    Notes on the different storage engines:

    • For MyRocks, see MyRocks and CHECK TABLE.

    • With ARCHIVE, REPAIR TABLE also improves the compression rate.

    • For CSV, see Checking and Rpairing CSV Tables.

    • Some special storage engines, like MEMORY or BLACKHOLE, do not support any form of check and repair.

    This page is licensed: CC BY-SA / Gnu FDL

    storage engine
    InnoDB
    CHECK TABLE
    REPAIR TABLE
    storage engines
    InnoDB
    MyRocks
    TokuDB
    MyRocks
    TokuDB
    metadata lock
    ALTER TABLEs
    binary log
    autocommit
    MDEV-17567
    MDEV-4259
    SQL statements That Cause an Implicit Commit
    in_transaction
    Transactions
    constraints
    Primary keys
    UNIQUE
    CHECK
    Foreign keys
    check_constraint_checks
    foreign_key_checks
    SET TRANSACTION
    SELECTs
    SELECT ... LOCK IN SHARED MODE
    SELECT ... FOR UPDATE
    tx_isolation
    innodb_lock_wait_timeout
    LOCK TABLES
    lock_wait_timeout
    WAIT and NOWAIT
    InnoDB Lock Modes
    information_schema
    INNODB_LOCKS
    INNODB_LOCK_WAITS
    INNODB_TRX
    innodb_deadlock_detect
    innodb_lock_wait_timeout
    SHOW ENGINE InnoDB STATUS
    innodb_print_all_deadlocks
    error log

    Migrating from SQL Server?

    Contact our Migration Experts

    Cover
    MariaDB Galera Cluster
    asynchronous replication
    MariaDB version that supports Galera Cluster
    MariaDB Galera Cluster
    Asynchronous replication
    Create a configuration file
    State Snapshot Transfers
    replication process

    SQL Server and MariaDB Types Comparison

    A reference guide mapping SQL Server data types (e.g., `money`, `bit`) to their MariaDB equivalents, highlighting differences in precision and storage.

    This page helps to map each SQL Server type to the matching MariaDB type.

    Numbers

    In MariaDB, numeric types can be declared as SIGNED or UNSIGNED. By default, numeric columns are SIGNED, so not specifying either will not break compatibility with SQL Server.

    When using UNSIGNED

    STOP SLAVE SQL_THREAD;
    SET GLOBAL slave_parallel_threads = 4;
    START SLAVE SQL_THREAD;
    STOP SLAVE "wp1";
    SET GLOBAL wp1.slave_parallel_threads = 4;
    SET GLOBAL rpl_semi_sync_master_enabled = ON;
    SET GLOBAL rpl_semi_sync_slave_enabled = ON;
    STOP SLAVE IO_THREAD;
    START SLAVE IO_THREAD;
    wsrep_provider_options = 'gcache.size=2G';
    ALTER TABLE orders CHECK PARTITION p_2019, p_2020;
    ALTER TABLE orders REPAIR PARTITION p_2019, p_2020;
    ALTER TABLE customer DROP INDEX idx_email;
    ALTER TABLE customer ADD INDEX idx_email (email);
    mysqld --aria-recover-options=BACKUP,FORCE
    SET SESSION autocommit = 0;
    SELECT ... ;
    DELETE ... ;
    COMMIT;
    START TRANSACTION;
    SELECT ... ;
    DELETE ... ;
    COMMIT;
    SELECT id FROM customer;
    +----+
    | id |
    +----+
    |  1 |
    |  2 |
    |  3 |
    |  4 |
    |  5 |
    +----+
    UPDATE customer SET id = id + 1;
    ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'
    UPDATE customer SET id = id + 1 ORDER BY id DESC;
    Query OK, 5 rows affected (0.00 sec)
    Rows matched: 5  Changed: 5  Warnings: 0
    SET SESSION check_constraint_checks = 0;
    -- run some queries
    -- that temporarily violate a CHECK clause
    SET SESSION check_constraint_checks = 1;
    
    SET SESSION foreign_key_checks = 0;
    -- run some queries
    -- that temporarily violate a foreign key
    SET SESSION foreign_key_checks = 1;
    tx_isolation = 'READ COMMITTED'
    SET SESSION tx_isolation = 'read-committed';
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
    -- session 1
    SELECT * FROM t1;
    +----+
    | id |
    +----+
    |  1 |
    +----+
    SELECT * FROM t2;
    +----+
    | id |
    +----+
    |  1 |
    +----+
    START TRANSACTION WITH CONSISTENT SNAPSHOT;
    -- session 2
    INSERT INTO t1 VALUES (2);
    -- session 1
    SELECT * FROM t1;
    +----+
    | id |
    +----+
    |  1 |
    +----+
    -- session 2
    INSERT INTO t2 VALUES (2);
    -- session 1
    SELECT * FROM t2;
    +----+
    | id |
    +----+
    |  1 |
    +----+
    ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
    Session 1:
    START TRANSACTION;
    -- let's acquire a metadata lock
    SELECT id FROM t WHERE 0;
    
    Session 2:
    DROP TABLE t WAIT 0;
    ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
    -- session 1
    START TRANSACTION;
    UPDATE t SET id = 15 WHERE id = 10;
    
    -- session 2
    DELETE FROM t WHERE id = 10;
    
    -- session 1
    USE information_schema;
    SELECT l.*, t.*
        FROM information_schema.INNODB_LOCKS l
        JOIN information_schema.INNODB_TRX t
            ON l.lock_trx_id = t.trx_id
        WHERE trx_state = 'LOCK WAIT' \G
    *************************** 1. row ***************************
                       lock_id: 840:40:3:2
                   lock_trx_id: 840
                     lock_mode: X
                     lock_type: RECORD
                    lock_table: `test`.`t`
                    lock_index: PRIMARY
                    lock_space: 40
                     lock_page: 3
                      lock_rec: 2
                     lock_data: 10
                        trx_id: 840
                     trx_state: LOCK WAIT
                   trx_started: 2019-12-23 18:43:46
         trx_requested_lock_id: 840:40:3:2
              trx_wait_started: 2019-12-23 18:43:46
                    trx_weight: 2
           trx_mysql_thread_id: 46
                     trx_query: DELETE FROM t WHERE id = 10
           trx_operation_state: starting index read
             trx_tables_in_use: 1
             trx_tables_locked: 1
              trx_lock_structs: 2
         trx_lock_memory_bytes: 1136
               trx_rows_locked: 1
             trx_rows_modified: 0
       trx_concurrency_tickets: 0
           trx_isolation_level: REPEATABLE READ
             trx_unique_checks: 1
        trx_foreign_key_checks: 1
    trx_last_foreign_key_error: NULL
              trx_is_read_only: 0
    trx_autocommit_non_locking: 0
    ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
    ------------------------
    LATEST DETECTED DEADLOCK
    ------------------------
    2019-12-23 18:55:18 0x7f51045e3700
    *** (1) TRANSACTION:
    TRANSACTION 847, ACTIVE 10 sec starting index read
    mysql tables in use 1, locked 1
    LOCK WAIT 4 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 1
    MySQL thread id 46, OS thread handle 139985942054656, query id 839 localhost root Updating
    delete from t where id = 10
    *** (1) WAITING FOR THIS LOCK TO BE GRANTED:
    RECORD LOCKS space id 40 page no 3 n bits 80 index PRIMARY of table `test`.`t` trx id 847 lock_mode X locks rec but not gap waiting
    Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 32
     0: len 4; hex 8000000a; asc     ;;
     1: len 6; hex 00000000034e; asc      N;;
     2: len 7; hex 760000019c0495; asc v      ;;
    
    *** (2) TRANSACTION:
    TRANSACTION 846, ACTIVE 25 sec starting index read
    mysql tables in use 1, locked 1
    3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
    MySQL thread id 39, OS thread handle 139985942361856, query id 840 localhost root Updating
    delete from t where id = 11
    *** (2) HOLDS THE LOCK(S):
    RECORD LOCKS space id 40 page no 3 n bits 80 index PRIMARY of table `test`.`t` trx id 846 lock_mode X locks rec but not gap
    Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 32
     0: len 4; hex 8000000a; asc     ;;
     1: len 6; hex 00000000034e; asc      N;;
     2: len 7; hex 760000019c0495; asc v      ;;
    
    *** (2) WAITING FOR THIS LOCK TO BE GRANTED:
    RECORD LOCKS space id 40 page no 3 n bits 80 index PRIMARY of table `test`.`t` trx id 846 lock_mode X locks rec but not gap waiting
    Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 32
     0: len 4; hex 8000000b; asc     ;;
     1: len 6; hex 00000000034f; asc      O;;
     2: len 7; hex 770000019d031d; asc w      ;;
    
    *** WE ROLL BACK TRANSACTION (2)
    values, there is a potential problem with subtractions. When subtracting an
    UNSIGNED
    valued from another, the result is usually of an
    UNSIGNED
    type. But if the result is negative, this will cause an error. To solve this problem, we can enable the
    flag in sql_mode.

    For more information see Numeric Data Type Overview.

    Integer Numbers

    SQL Server Types
    Size (bytes)
    MariaDB Types
    Size (bytes)
    Notes

    tinyint

    1

    1

    smallint

    2

    2

    Real Numbers (approximated)

    SQL Server Types
    Precision
    Size
    MariaDB Types
    Size

    float(1-24)

    7 digits

    4

    4

    float(25-53)

    15 digist

    8

    8

    MariaDB supports an alternative syntax: FLOAT(M, D). M is the total number of digits, and D is the number of digits after the decimal point.

    See also: Floating-point Accuracy.

    Aliases

    In SQL Server real is an alias for float(24).

    In MariaDB DOUBLE, and DOUBLE PRECISION are aliases for FLOAT(24-53).

    Normally, REAL is also a synonym for FLOAT(24-53). However, the sql_mode variable can be set with the REAL_AS_FLOAT flag to make REAL a synonym for FLOAT(0-23).

    Real Numbers (Exact)

    SQL Server Types
    Precision
    Size (bytes)
    MariaDB Types
    Precision
    Size (bytes)

    decimal

    0 - 38

    Up to 17

    0 - 38

    MariaDB supports this syntax: DECIMAL(M, D). M and D are both optional. M is the total number of digits (10 by default), and D is the number of digits after the decimal point (0 by default). In SQL Server, defaults are 18 and 0, respectively. The reason for this difference is that SQL standard imposes a default of 0 for D, but it leaves the implementation free to choose any default for M.

    SQL Server DECIMAL is equivalent to MariaDB DECIMAL(18).

    Aliases

    The following aliases for DECIMAL are recognized in both SQL Server and MariaDB: DEC, NUMERIC. MariaDB also allows one to use FIXED.

    Money

    SQL Server money and smallmoney types represent real numbers guaranteeing a very low level of approximation (five decimal digits are accurate), optionally associated with one of the supported currencies.

    MariaDB doesn't have monetary types. To represent amounts of money:

    • Store the currency in a separate column, if necessary. It's possible to use a foreign key to a currencies table, or the ENUM type.

    • Use a non-approximated type:

      • DECIMAL is very convenient, as it allows one to store the number as-is. But calculations are potentially slower.

      • An integer type is faster for calculations. It is possible to store, for example, the amount of money multiplied by 100.

    There is a small incompatibility that users should be aware about. money and smallmoney are accurate to about 4 decimal digits. This means that, if you use enough decimal digits, operations on these types may produce different results than the results they would produce on MariaDB types.

    Bits

    The BIT type is supported in MariaDB. Its maximum size is BIT(64). The BIT type has a fixed length. If we insert a value which requires less bits than the ones that are allocated, zero-bits are padded on the left.

    In MariaDB, binary values can be written in one of the following ways:

    • b'value'

    • 0value where value is a sequence of 0 and 1 digits. Hexadecimal syntax can also be used. For more details, see Binary Literals and Hexadecimal Literals.

    MariaDB and SQL Server have different sets of bitwise operators. See Bit Functions and Operators.

    BOOLEAN Pseudo-Type

    In SQL Server, it is common to use bit to represent boolean values. In MariaDB it is possible to do the same, but this is not a common practice.

    A column can also be defined as BOOLEAN or BOOL, which is just a synonym for TINYINT. TRUE and FALSE keywords also exist, but they are synonyms for 1 and 0. To understand what this implies, see Boolean Literals.

    In MariaDB 'True' and 'False' are always strings.

    Date and Time

    SQL Server Types
    Range
    Precision
    Size (bytes)
    MariaDB Types
    Range
    Size (bytes)
    Precision
    Notes

    date

    0001-01-01 - 9999-12-31

    3

    /

    0001-01-01 - 9999-12-31

    You may also consider the following MariaDB types:

    • TIMESTAMP has little to do with SQL Server's timestamp. In MariaDB it is the number of seconds elapsed since the beginning of 1970-01-01, with a decimal precision up to 6 digits (0 by default). The maximum allowed value is '2038-01-19 03:14:07'. Values are always stored in UTC. A TIMESTAMP column can optionally be automatically set to the current timestamp on insert, on update, or both. It is not meant to be a unique row identifier. Also, in MariaDB the range of TIMESTAMP values is

    • YEAR is a 1-byte type representing years between 1901 and 2155, as well as 0000.

    Zero Values

    MariaDB allows a special value where all the parts of a date are zeroes: '0000-00-00'. This can be disallowed by setting sql_mode=NO_ZERO_DATE.

    It is also possible to use values where only some date parts are zeroes, for example '1994-01-00' or '1994-00-00'. These values can be disallowed by setting sql_mode=NO_ZERO_IN_DATE. They are not affected by NO_ZERO_DATE.

    Syntax

    Several different date formats are understood. Typically used formats are 'YYYY-MM-DD' and YYYYMMDD. Several separators are accepted.

    The syntax defined in standard SQL and ODBC are understood - for example, DATE '1994-01-01' and {d '1994-01-01'}. Using these eliminates possible ambiguities in contexts where a temporal value could be interpreted as a string or as an integer.

    See Date and Time Literals for the details.

    Precision

    For temporal types that include a day time, MariaDB allows a precision from 0 to 6 (microseconds), 0 being the default. The subsecond part is never approximated. It adds up to 3 bytes. See Data Type Storage Requirements for the details.

    String and Binary

    Binary Strings

    SQL Server Types
    Size (bytes)
    MariaDB Types
    Notes

    binary

    1 to 8000

    or

    See below for BLOB types

    varbinary

    1 to 8000

    or

    See below for BLOB types

    image

    2^31-1

    or

    The VARBINARY type is similar to VARCHAR, but stores binary byte strings, just like SQL Server binary does.

    For large binary strings, MariaDB has four BLOB types, with different sizes. See BLOB and TEXT Data Types for more information.

    Character Strings

    One important difference between SQL Server and MariaDB is that in MariaDB character sets do not depend on types and collations. Character sets can be set at database, table or column level. If this is not done, the default character sets applies, which is specified by the character_set_server system variable.

    To create a MariaDB table that is identical to a SQL Server table, it may be necessary to specify a character set for each string column. However, in many cases using UTF-8 will work.

    SQL Server Types
    Size (bytes)
    MariaDB Types
    Size (bytes)
    Character set

    char

    1 to 8000

    0 to 255

    utf8mb4 (1, 4)

    varchar

    1 to 8000

    0 to 65,532 (2)

    utf8mb4 (1)

    Notes:

    1. If SQL Server uses a non-unicode collation, a subset of UTF-8 is used. So it is possible to use a smaller character set on MariaDB too.

    2. InnoDB has a maximum row length of 65,535 bytes. TEXT columns do not contribute to the row size, because they are stored separately (except for the first 12 bytes).

    3. In SQL Server, UTF-16 is used if data contains Supplementary Characters, otherwise UCS-2 is used. If not sure, use utf16 in MariaDB.

    4. In SQL Server, the value of ANSI_PADDING determines if char values should be padded with spaces to their maximum length. In MariaDB, this depends on the sql_mode flag.

    5. See JSON, below.

    SQL Server Special Types

    rowversion

    MariaDB does not have the rowversion type.

    If the only purpose is to check if a row has been modified since its last read, a TIMESTAMP column can be used instead. Its default value should be ON UPDATE CURRENT_TIMESTAMP. In this way, the timestamp will be updated whenever the column is modified.

    A way to preserve much more information is to use a temporal table. Past versions of the row will be preserved.

    sql_variant

    MariaDB does not support the sql_variant type.

    MariaDB is quite flexible about implicit and explicit type conversions. Therefore, for most cases storing the values as a string should be equivalent to using sql_variant.

    Be aware that the maximum length of an sql_variant value is 8,000 bytes. In MariaDB, you may need to use TINYBLOB.

    uniqueidentifier

    While MariaDB does not support the uniqueidentifier type, the UUID type can typically be used for the same purpose.

    uniqueidentifier columns contain 16-bit GUIDs. MariaDB UUID columns store UUIDv1 values (128 bits).

    The UUID type was implemented in . On older versions, you can generate unique values with the UUID() or UUID_SHORT() functions, and store them in BIT(128) or BIT(64) columns, respectively.

    xml

    MariaDB does not support the xml type.

    XML data can be stored in string columns. MariaDB supports several XML functions.

    JSON

    With SQL Server, typically JSON documents are stored in nvarchar columns in a text form.

    MariaDB has a JSON pseudo-type that maps to LONGTEXT. However, from the JSON pseudo-type also checks that the value is valid a JSON document.

    MariaDB supports different JSON functions than SQL Server. MariaDB currently has more functions, and SQL Server syntax will not work. See JSON functions for more information.

    MariaDB Specific Types

    The following types are supported by MariaDB and don't have a direct equivalent in SQL Server. If you are migrating your database to MariaDB, you can consider using these types.

    • INET6 - IPv6 addresses.

    • INET4 - IPv4 addresses.

    This page is licensed: CC BY-SA / Gnu FDL

    NO_UNSIGNED_SUBTRACTION
    TIMESTAMP

    Understanding MariaDB Architecture

    An architectural overview for SQL Server DBAs, covering MariaDB's storage engines (InnoDB), transaction logs (undo/redo), buffer pool, and system databases.

    MariaDB architecture is partly different from the architecture of traditional DBMSs, like SQL Server. Here we will examine the main components that a new MariaDB DBA needs to know. We will also discuss a bit of history, because this may help understand MariaDB philosophy and certain design choices.

    This section is an overview of the most important components. More information is included in specific sections of this migration guide, or in other pages of the MariaDB documentation (see the links scattered over the text).

    Storage Engines

    MariaDB was born from the source code of MySQL, in 2008. Therefore, its history begins with MySQL.

    MySQL was born at the beginning of the 90s. Back in the days, if compared to its existing competitors, MySQL was lightweight, simple to install, easy to learn. While it had a very limited set of features, it was also fast in certain common operations. And it was open source. These characteristics made it suitable to back the simple websites that existed at that time.

    The web evolved rapidly, and the same happened to MySQL. Being open source helped a lot in this respect, because the community needed functionalities that weren’t supported at that time.

    MySQL was probably the first database system to support a . Basically, this means that MySQL knows very little about creating or populating a table, reading from it, building proper indexes and caches. It just delegated all these operations to a special plugin type called a storage engine.

    One of the first plugins developed by third parties was . It is very fast, and it adds two important features that are not otherwise supported: transactions and .

    Note that when MariaDB asks a storage engine to write or read a row, the storage engine could theoretically do anything. This led to the creation of very interesting alternative engines, like (which doesn’t write or read any data, acting like the /dev/null file in Linux), or (which can read and write to files written in many different formats, or remote DBMSs, or some other special data sources).

    Nowadays InnoDB is the default MariaDB storage engine, and it is the best choice for most use cases. But for particular needs, sometimes using a different storage engine is desirable. In case of doubts about the best storage engine to use for a specific case, check the page.

    When we create a table, we specify its storage engine or use the default one. It is possible to convert an existing table to another storage engine, though this is a blocking operation which requires a complete table copy. Third-party storage engines can also be installed while MariaDB is running.

    Note that it is perfectly possible to use tables with different storage engines in the same transaction (even if some engines are not transactional). It is even possible to use different engines in the same query, for example with JOINs and subqueries.

    The default storage engine can be changed by changing the variable. A different default can be specified for temporary tables by setting . MariaDB uses for system tables and temporary tables created internally to store the intermediate results of a query.

    InnoDB

    It is worth spending some more words here about , the default storage engine.

    Primary Key and Indexes

    InnoDB primary keys are always the equivalent of SQL Server clustered indexes. In other words, an InnoDB table is always ordered by the primary key.

    If an InnoDB table doesn't have a user-defined primary key, the first UNIQUE index whose columns are all NOT NULL is used as a primary key. If there is no such index, the table will have a clustered index. The terminology here can be a bit confusing for SQL Server and other DBMS users. A clustered index in InnoDB is a 6 bytes value that is added to the table. This index and its values are completely invisible to the users. It's important to note that clustered indexes are governed by a global mutex that greatly reduces their scalability.

    Secondary indexes are ordered by the columns that are part of the index, and contain a reference to each entry's corresponding primary key value.

    Some consequences of these design choices are the following:

    • For performance reasons, a primary key value should be inserted in order. In other words, the last inserted value should be the highest. This order is normally followed when inserting values into an AUTO_INCREMENT primary key. The reason is that inserting values in the middle of an ordered data structure is slower, unless they fit into existing holes. If we insert primary key values randomly, InnoDB often has to rearrange pages to make some room for the new data.

    • A big primary keys means that all secondary indexes are also big.

    • A query by primary key will require a single search. A query on a secondary index that also reads columns not contained in the index will require one search on the index, plus one more search for each row that satisfies the index condition.

    Tablespaces

    For InnoDB, a tablespace is a file containing data (not a file group as in SQL Server). The types of tablespaces are:

    • .

    • .

    • .

    The system tablespace is stored in the file ibdata. It contains information used by InnoDB internally, like rollback segments, as well as some system tables. Historically, the system tablespace also contained all tables created by the user. In modern MariaDB versions, a table is created in the system tablespace only if the system variable is set to 0 at the moment of the table creation. By default, innodb_file_per_table is 1.

    Tables created while innodb_file_per_table=1 are written into their own tablespace. These are .ibd files.

    Starting from , temporary tables are written into temporary tablespaces, which means ibtmp* files. Previously, they were created in the system tablespace or in file-per-table tablespaces according to the value of innodb_file_per_table, just like regular tables. Temporary tablespaces, if present, are deleted when MariaDB starts.

    It is important to remember that tablespaces can never shrink. If a file-per-table tablespace grows too much, deleting data won't recover space. Instead, a new table must be created and data needs to be copied. Finally, the old table will be deleted. If the system tablespace grows too much, the only solution is to move data into a new MariaDB installation.

    Transaction Logs

    In SQL Server, the transaction log contains both the undo log and the redo log. Usually we have only one transaction log.

    In MariaDB the undo log and the redo log are stored separately. By default, the is written to two files, called ib_logfile0 and ib_logfile1. The by default is written to the system tablespace, which is in the ibdata1 file. However, it is possible to write it in separate files in a specified directory.

    MariaDB provides no way to inspect the contents of the transaction logs. However, it is possible to inspect the .

    InnoDB transaction logs are written in a circular fashion: their size is normally fixed, and when the end is reached, InnoDB continues to write from the beginning. However, if very long transactions are running, InnoDB cannot overwrite the oldest data, so it has to expand the log size instead.

    InnoDB Buffer Pool

    MariaDB doesn't have a central buffer pool. Each storage engine may or may not have a buffer pool. The is typically assigned a big amount of memory. See .

    MariaDB has no extension like the SQL Server buffer pool extension.

    A part of the buffer pool is called the . It contains dirty pages that have been modified in memory and not yet flushed.

    InnoDB Background Threads

    InnoDB has background threads that take care of flushing dirty pages from the change buffer to the tablespaces. They don't directly affect the latency of queries, but they are very important for performance.

    shows information about them in the BACKGROUND THREAD section. They can also be seen using the table, in the .

    InnoDB flushing is similar to lazy writes and checkpoints in SQL Server. It has no equivalent for eager writing.

    For more information, see and .

    Checksums and Doublewrite Buffer

    InnoDB pages have checksums. After writing pages to disk, InnoDB verifies that the checksums match. The checksum algorithm is determined by . Check the variable documentation for its consequences on performance, backward compatibility and encryption.

    In case of a system crash, hardware failure or power outage, a page could be half-written on disk. For some pages, this causes a disaster. Therefore, InnoDB writes essential pages to disk twice. A backup copy of the new page version is written first. Then, the old page is overwritten. The backup copies are written into a file called the doublewrite buffer.

    • If an event prevents the first page from being written, the old version of the page will still be available.

    • If an event prevents the old page from being completely overwritten by its new version, the page can still be recovered using the doublewrite buffer.

    The doublewrite buffer can disabled using the variable, but this usually doesn't bring big performance benefits. The doublewrite buffer location can be changed with .

    Aria

    Even if we only create InnoDB tables, we use Aria indirectly, in two ways:

    • For system tables.

    • For internal temporary tables.

    Aria is a non-transactional storage engine. By default it is crash-safe, meaning that all changes to data are written and fsynced to a write-ahead log and can always be recovered in case of a crash.

    Aria caches indexes into the pagecache. Data are not directly cached by Aria, so it's important that the underlying filesystem caches reads and writes.

    The pagecache size is determined by the system variable. To know if it is big enough we can check the proportion of free pages (the ratio between and ) and the proportion of cache misses (the ratio between and .

    The proportion of dirty pages is the ratio between and tells us if the log file is big enough.

    The size of Aria log is determined by .

    Databases

    MariaDB does not support the concept of schema. In MariaDB SQL, schema and schemas are synonyms for database and databases.

    When a user connects to MariaDB, they don't connect to a specific database. Instead, they can access any table they have permissions for. There is however a concept of default database, see below.

    A database is a container for database objects like tables and views. A database serves the following purposes:

    • A database is a namespace.

    • A database is a logical container to separate objects.

    • A database has a default and collation, which are inherited by their tables.

    • Permissions can be assigned on a whole database, to make permission maintenance simpler.

    System Databases

    MariaDB has the following system databases:

    • is for internal use only, and should not be read or written directly.

    • contains all information that can be found in SQL Server's information_schema and more. However, while SQL Server's information_schema is a schema containing information about the local database, MariaDB's information_schema is a database that contains information about all databases.

    • contains information about MariaDB runtime. It is disabled by default. Enabling it requires setting the system variable to 1 and restarting MariaDB.

    Default Database

    When a user connects to MariaDB, they can optionally specify a default database. A default database can also be specified or changed later, with the command.

    Having a default database specified allows one to specify tables without specifying the name of the database where they are located. If no default database is specified, all table names must be fully qualified.

    For example, the two following snippets are equivalent:

    Even if a default database is specified, tables from other databases can be accessed by specifying their fully qualified names:

    MariaDB has the function to determine the current database:

    Stored procedures and triggers don't inherit a default database from the session, nor by a caller procedure. In that context, the default database is the database which contains the procedure. USE can be used to change it. The default database will only be valid for the rest of the procedure.

    The Binary Log

    Different tables can be built using different storage engines. It is important to note that not all engines are transactional, and that different engines implement the transaction logs in different ways. For this reason, MariaDB cannot replicate data from a primary to a replica using an equivalent of SQL Server transactional replication.

    Instead, it needs a global mechanism to log the changes that are applied to data. This mechanism is the , often abbreviated to binlog.

    The binary log can be written in the following formats:

    • STATEMENT logs SQL statements that modify data;

    • ROW logs a reference to the rows that have been modified, if any (usually it’s the primary key), and the new values that have been added or modified, in a binary format.

    • MIXED is a combination of the above formats. It means that ROW is used for statements that can safely be logged in this way (see below), and STATEMENT is used in other cases. This is the default format from .

    In most cases, STATEMENT is slower because the SQL statement needs to be re-executed by the replica, and because certain statements may produce a different result in the replica (think about queries that use LIMIT without ORDER BY, or the CURRENT_TIMESTAMP() function). But there are exceptions, and besides, DDL statements are always logged as STATEMENT to avoid flooding the binary log. Therefore, the binary log may well contain both ROW and STATEMENT entries.

    See .

    The binary log allows:

    • replication, if enabled on the primary;

    • promoting a replica to a primary, if enabled on that replica;

    • incremental backups;

    • seeing data as they were in a point of time in the past ();

    If you don't plan to use any of these features on a server, it is possible to the binary log to slightly improve the performance.

    The binary log can be inspected using the utility, which comes with MariaDB. Enabling or disabling the binary log requires restarting MariaDB.

    See also and for a better understanding of how the binary log is used.

    Plugins

    Storage engines are a special type of . But others exist. For example, plugins can add authentication methods, new features, SQL syntax, functions, informative tables, and more.

    A plugin may add some server variables and some status variables. Server variables can be used to configure the plugin, and status variables can be used to monitor its activities and status. These variables generally use the plugin's name as a prefix. For example InnoDB has a server variable called innodb_buffer_pool_size to configure the size of its buffer pool, and a status variable called Innodb_pages_read which indicates the number of memory pages read from the buffer pool. The category of the MariaDB documentation has specific pages for system and status variables associated with various plugins.

    Many plugins are installed by default, or available but not installed by default. They can be installed or uninstalled at runtime with SQL statements, like INSTALL PLUGIN, UNINSTALL PLUGIN and others; see . 3rd party plugins can be made available for installation by simply copying them to the .

    It is important to note that different plugins may have different maturity levels. It is possible to prevent the installation of plugins we don’t consider production-ready by setting the system variable. For plugins that are distributed with MariaDB, the maturity level is determined by the MariaDB team based on the bugs reported and fixed.

    Some plugins are developed by 3rd parties. Even some 3rd party plugins are included in MariaDB official distributions - the ones available on mariadb.org.

    In MariaDB every authorization method (including the default one) is provided by an . A user can be required to use a certain authentication plugin. This gives us much flexibility and control. Windows users may be interested in (which supports Windows authentication, Kerberos and NTLM) and (which uses named pipe impersonation).

    Other plugins that can be very useful include , which includes statistics about resources and table usage, and , which provides information about metadata locks.

    Thread Pool

    MariaDB supports . It works differently on UNIX and on Windows. On Windows, it is enabled by default and its implementation is quite similar to SQL Server. It uses the Windows native CreateThreadpool API.

    If we don't use the thread pool, MariaDB will use its traditional method to handle connections. It consists of using a dedicated thread for each client connection. Creating a new thread has a cost in terms of CPU time. To mitigate this cost, after a client disconnects, the thread may be preserved for a certain time in the .

    Whichever connection method we use, MariaDB has a maximum number of simultaneous connections, which can be changed at runtime. When the limit is reached, if more clients try to connect they will receive an error. This prevents MariaDB from consuming all the server resources and freezing or crashing. See .

    Configuration

    MariaDB has many settings that control the server behavior. These can be set up when starting mysqld (), and the vast majority are also accessible as . These can be classified in these ways:

    • Dynamic or static;

    • Global, session, or both.

    Note that server system variables are not to be confused with . The latter are not used for MariaDB configuration.

    Configuration Files

    MariaDB can use several . Configuration files are searched in several locations, including in the user directory, and if present they all are read and used. They are read in a consistent order. These locations depend on the operating system; see . It is possible to tell MariaDB which files it should read; see .

    On Linux, by default the configuration files are called my.cnf. On Windows, by default the configuration files can be called my.ini or my.cnf. The former is more common.

    If a variable is mentioned multiple times in different files, the occurrence that is read last will overwrite the others. Similarly, if a variable is mentioned several times in a single file, the occurrence that is read last overwrites the others.

    The contents of each configuration file are organized by option groups. MariaDB Server and client programs read different groups. The read groups also depend on the MariaDB version. See for the details. Most commonly, the [server] or [mysqld] groups are used to contain all server configuration. The [client-server] group can be used for options that are shared by the server and the clients (like the port to use), to avoid repeating those variables multiple times.

    Dynamic and Static Variables

    Dynamic variables have a value that can be changed at runtime, using the SQL statement. Static variables have a value that is decided at startup (see below) and cannot be changed without a restart.

    The page states if variables are dynamic or static.

    Scope

    A global system variable is one that affects the general behavior of MariaDB. For example determines the size of the InnoDB buffer pool, which is used by read and write operations, no matter which user issued them. A session system variable is one that affects MariaDB behavior for the current connection; changing it will not affect other connected users, or future connections from the current user.

    A variable could exist in both the global and session scopes. In this case, the session value is what affects the current connection. When a user connects, the current global value is copied to the session scope. Changing the global value afterward will not change existing connections.

    The page states the scope of each variable.

    Global variables and some session variables can only be modified by a user with the privilege (typically root).

    Syntax

    To see the value of a system variable:

    A longer syntax, which is mostly useful to get multiple variables, makes use of the same pattern syntax that is used by the operator:

    To modify the global or session value of a dynamic variable:

    Notice that if we modify a global variable in this way, the new value will be lost at server restart. For this reason we probably want to change the value in the configuration file too.

    For further information see:

    • The statement.

    • The statement.

    Setting System Variables with Startup Parameters

    System variables can be set at server startup without writing their values into a configuration file. This is useful if we want a value to be set once, until we change it or restart MariaDB. Values passed in this way override values written in the configuration files.

    The general rule is that every global variable can be passed as an argument of mysqld by prefixing its name with -- and by replacing every occurrence of _ with - in its name.

    For example, to pass bind_address as a startup argument:

    Debugging Configuration

    Mistyping a variable can prevent MariaDB from starting. We cannot set a variable that doesn't exist in the MariaDB version in use. In these cases, an error is written in the .

    Having several configuration files and configuration groups, as well as being able to pass variables as command-line arguments, brings a lot of flexibility but can sometimes be confusing. When we are unsure about which values will be used, we can run:

    Status Variables

    MariaDB status variables and some system tables allow external tools to monitor a server, building graphs on how they change over time, and allow the user to inspect what is happening inside the server.

    cannot be directly modified by the user. Their values indicate how MariaDB is operating. Their scope can be:

    • Global, meaning that the value is about some MariaDB activity.

    • Session, meaning that the value measures activities taking place in the current session.

    Many status variables exist in both scopes. For example, at global level indicates how much time the CPU was used by the MariaDB process (including all user sessions and all the background threads). At session level, it indicates how much time the CPU was used by the current session.

    The status variables created by a plugin, usually, use the plugin name as a prefix.

    The statement prints the values of the status variables that match a certain pattern.

    Some status variables values are reset when is executed. A possible use:

    This page is licensed: CC BY-SA / Gnu FDL

    We shouldn't explicitly include the primary key in a secondary index. If we do so, the primary key column will be duplicated in the index.

    Physical data files are stored in a directory which has the same name as the database to which they belong.

    restoring a backup and re-appling the binary log, with the exception of a data change which caused problems (human mistake, application bug, SQL injection);

  • Capture Data Changes (CDC), by streaming the binary log to technologies like Apache Kafka.

  • pluggable storage engine architecture
    InnoDB
    foreign keys
    BLACKHOLE
    CONNECT
    Choosing the Right Storage Engine
    default_storage_engine
    default_tmp_storage_engine
    Aria
    InnoDB
    System tablespace
    File-per-table tablespaces
    Temporary tablespaces
    innodb_file_per_table
    redo log
    undo log
    binary log
    InnoDB buffer pool
    MariaDB Memory Allocation
    change buffer
    SHOW ENGINE InnoDB STATUS
    threads
    performance_schema
    InnoDB Page Flushing
    InnoDB Purge
    innodb_checksum_algorithm
    innodb_doublewrite
    innodb_doublewrite_file
    aria_pagecache_buffer_size
    Aria_pagecache_blocks_used
    Aria_pagecache_blocks_unused
    Aria_pagecache_read_requests
    Aria_pagecache_reads
    Aria_pagecache_blocks_used
    Aria_pagecache_blocks_not_flushed
    aria_log_file_size
    character set
    mysql
    information_schema
    performance_schema
    performance_schema
    USE
    DATABASE()
    binary log
    Binary Log Formats
    flashback
    disable
    mariadb-binlog
    MariaDB Replication Overview for SQL Server Users
    MariaDB Backups Overview for SQL Server Users
    plugin
    system variables
    Plugin SQL Statements
    plugin_dir
    plugin_maturity
    authentication plugin
    gsapi
    named_pipe
    userstat
    METADATA_LOCK_INFO
    thread pool
    thread cache
    Handling Too Many Connections
    mysqld options
    server system variables
    user-defined variables
    configuration files
    Default Option File Locations
    Global Options Related to Option Files
    Option Groups
    SET
    Server System Variables
    innodb_buffer_pool_size
    Server System Variables
    SUPER
    LIKE
    SET
    SHOW VARIABLES
    error log
    Status variables
    Cpu_time
    SHOW STATUS
    FLUSH STATUS

    MEDIUMINT

    3

    Takes 3 bytes on disk, but 4 bytes in memory

    int

    1

    INT / INTEGER

    4

    bigint

    8

    BIGINT

    8

    3

    /

    They cover the same range

    datetime

    1753-01-01 - 9999-12-31

    8

    0 to 3, rounded

    DATETIME

    001-01-01 - 9999-12-31

    8

    0 to 6

    MariaDB values are not approximated, see below.

    datetime2

    001-01-01 - 9999-12-31

    8

    6 to 8

    DATETIME

    001-01-01 - 9999-12-31

    8

    0 to 6

    MariaDB values are not approximated, see below.

    smalldatetime

    DATETIME

    datetimeoffset

    DATETIME

    time

    TIME

    See below for BLOB types

    text

    2^31-1

    TEXT

    2^31-1

    ucs2

    nchar

    2 to 8000

    CHAR

    0 to 255

    utf16 or ucs2 (3, 4)

    nvarchar

    2 to 8000

    VARCHAR

    0 to 65,532 (2) (5)

    utf16 or ucs2 (1) (3)

    ntext

    2^30 - 1

    TEXT

    2^31-1

    ucs2

    PAD_CHAR_TO_FULL_LENGTH
    TINYINT
    SMALLINT
    FLOAT(0-23)
    FLOAT(24-53)
    DECIMAL
    See table
    DATE
    VARBINARY
    BLOB
    VARBINARY
    BLOB
    VARBINARY
    BLOB
    CHAR
    VARCHAR

    Migrating from SQL Server?

    Contact our Migration Experts

    Cover

    Migrating from SQL Server?

    Contact our Migration Experts

    Cover
    Cover

    Migrating from SQL Server?

    Cover

    Migrating from PostgreSQL?

    SELECT * FROM my_database.my_table;
    
    -- is equivalent to:
    USE my_database;
    SELECT * FROM my_table;
    -- this query joins my_database.my_table to your_database.your_table
    USE my_database;
    SELECT m.*
        FROM my_table m
        JOIN your_database.your_table y
            ON m.xyz = y.xyz;
    SELECT DATABASE();
    -- global variables:
    SELECT @@global.variable_name;
    -- session variables:
    SELECT @@session.variable_name;
    -- or just use the shortcut:
    SELECT @@variable_name;
    -- global variables whose name starts with 'innodb':
    SHOW GLOBAL VARIABLES LIKE 'innodb%';
    -- session variables whose name starts with 'innodb':
    SHOW SESSION VARIABLES LIKE 'innodb%';
    SHOW VARIABLES LIKE 'innodb%';
    SET @@global.variable_name = 'new 'value';
    SET @@session.variable_name = 'new 'value';
    mysqld --bind-address=127.0.0.1
    mysqld --print-defaults
    -- Show all InnoDB global status variables
    SHOW GLOBAL STATUS LIKE 'innodb%';
    -- Show all InnoDB session status variables
    SHOW SESSION STATUS LIKE 'innodb%';
    SHOW STATUS LIKE 'innodb%';
    -- Show global variables that contain the "size" substring:
    SHOW GLOBAL STATUS LIKE '%size%';
    DELIMITER ||
    BEGIN NOT ATOMIC
    SET @i = 0;
    WHILE @i < 60 DO
        SHOW GLOBAL STATUS LIKE 'Com_select';
        FLUSH STATUS;
        DO SLEEP(1);
        SET @i = @i + 1;
    END WHILE;
    END ||

    Migrating from SQL Server?

    Contact our Migration Experts

    Cover
    Contact our Migration Experts
    Contact our Migration Experts

    MariaDB Authorization and Permissions for SQL Server Users

    Explains the differences in user authorization between SQL Server and MariaDB, noting that MariaDB uses accounts ('user'@'host') rather than users and logins, and detailing privilege levels.

    Understanding Accounts and Users

    MariaDB authorizes access and check permissions on accounts, rather than users. Even if MariaDB supports standard SQL commands like and , it is important to remember that it actually works with accounts.

    An account is specified in the format 'user'@'host'. The quotes are optional and allow one to include special characters, like dots. The host part can actually be a pattern, which follows the same syntax used in LIKE comparisons. Patterns are often convenient because they can match several hostnames.

    Here are some examples.

    Omitting the host part indicates an account that can access from any host. So the following statements are equivalent:

    However, such accounts may be unable to connect from localhost if an anonymous user ''@'%' is present. See localhost and % for the details.

    Accounts are not bound to a specific database. They are global. Once an account is created, it is possible to assign it permissions on any existing or non existing database.

    The sql_mode system variable has a NO_AUTO_CREATE_USER flag. In recent MariaDB versions it is enabled by default. If it is not enabled, a GRANT statement specifying privileges for a non-existent account will automatically create that account.

    For more information: Account Management SQL Commands.

    Setting or Changing Passwords

    Accounts with the same username can have different passwords.

    By default, an account has no password. A password can be set, or changed, in the following way:

    • By specifying it in CREATE USER.

    • By the user, with SET PASSWORD.

    • By root, with SET PASSWORD or ALTER USER.

    With all these statements (CREATE USER, ALTER USER, SET PASSWORD) it is possible to specify the password in plain or as a hash:

    The PASSWORD() function uses the same algorithm used internally by MariaDB to generate hashes. Therefore it can be used to get a hash from a plain password. Note that this function should not be used by applications, as its output may depend on MariaDB version and configuration.

    SET PASSWORD applies to the current account, by default. Superusers can change other accounts passwords in this way:

    Passwords can have an expiry date, set by default_password_lifetime. To set a different date for a particular user:

    To set no expiry date for a particular user:

    For more details, see User Password Expiry.

    It is also possible to lock an account with immediate effect:

    See Account Locking for more details.

    Authentication Plugins

    MariaDB supports authentication plugins. These plugins implement user's login and authorization before they can use MariaDB.

    Each user has one or more authentication plugins assigned. The default one is mysql_native_password. It is the traditional login using the username and password set in MariaDB, as described above.

    On UNIX systems, root is also assigned the unix_socket plugin, which allows a user logged in the operating system to be recognized by MariaDB.

    Windows users may be interested in the named pipe and GSSAPI plugins. GSSAPI also requires the use of a plugin on the client side.

    A plugin can be assigned to a user with CREATE USER, ALTER USER or GRANT, using the IDENTIFIED VIA syntax. For example:

    TLS connections

    A particular user can be required to use TLS connections. Additional requirements can be set:

    • Having a valid X509 certificate.

    • The certificate may be required to be issued by a particular authority.

    • A particular certificate subject can be required.

    • A particular certificate cipher suite can be required.

    These requirements can be set with CREATE USER, ALTER USER or GRANT. For the syntax, see CREATE USER.

    MariaDB can be bundled with several cryptography libraries, depending on its version. For more information about the libraries, see TLS and Cryptography Libraries Used by MariaDB.

    For more information about secure connections, see Secure Connections Overview.

    Permissions

    Permissions can be granted to accounts. As mentioned before, the specified accounts can actually be patterns, and multiple accounts may match a pattern. For example, in this example we are creating three accounts, and we are assigning permissions to all of them:

    The following permission levels exist in MariaDB:

    • Global privileges;

    • Database privileges;

    • Table privileges;

    • Column privileges;

    • and .

    Note that database and schema are synonymous in MariaDB.

    Permissions can be granted for non-existent objects that could exist in the future.

    The list of supported privileges can be found in the GRANT page. Some highlights can be useful for SQL Server users:

    • USAGE privilege has no effect. The GRANT command fails if we don't grant at least one privilege; but sometimes we want to run it for other purposes, for example to require a user to use TLS connections. In such cases, it is useful to grant USAGE.

    • Normally we can obtain a list of all databases for which we have at least one permission. The SHOW DATABASES permission allows getting a list of all databases.

    • There is no SHOWPLAN privilege in MariaDB. Instead, requires the SELECT privilege for each accessed table and the SHOW VIEW privilege for each accessed view.

    • The same permissions are needed to see a table structure (SELECT) or a view definition (SHOW VIEW).

    • REFERENCES has no effect.

    MariaDB does not support negative permissions (the DENY command).

    Some differences concerning the SQL commands:

    • In MariaDB GRANT and REVOKE statements can only assign/revoke permissions to one user at a time.

    • While we can assign/revoke privileges at column level, we have to run a GRANT or REVOKE statement for each column. The table (column_list) syntax is not recognized by MariaDB.

    • In MariaDB it is not needed (or possible) to specify a class type.

    Roles

    MariaDB supports roles. Permissions can be assigned to roles, and roles can be assigned to accounts.

    An account may have zero or one default roles. A default role is a role that is automatically active for a user when they connect. To assign an account or remove a default role, these SQL statements can be used:

    Normally a role is not a default role. If we assign a role in this way:

    ...the user will not have that role automatically enabled. They will have to enable it explicitly:

    MariaDB does not have predefined roles, like public.

    For an introduction to roles, see Roles Overview.

    This page is licensed: CC BY-SA / Gnu FDL

    CREATE USER
    DROP USER
    Cover

    Migrating from SQL Server?

    Syntax Differences between MariaDB and SQL Server

    Details syntax variations between the two systems, such as string quoting, NULL handling, and DDL statement differences, with advice on using `sql_mode='MSSQL'`.

    This article contains a non-exhaustive list of syntax differences between MariaDB and SQL Server and is written for SQL Server users who are unfamiliar with MariaDB.

    Compatibility Features

    Some features are meant to improve syntax and semantics compatibility between MariaDB versions, between MariaDB and MySQL, and between MariaDB and other DBMSs. This section focuses on compatibility between MariaDB and SQL Server.

    CREATE USER viviana;
    CREATE USER viviana@'%';
    -- specifying plain passwords:
    CREATE USER tom@'%.example.com' IDENTIFIED BY 'plain secret';
    ALTER USER tom@'%.example.com' IDENTIFIED BY 'plain secret';
    SET PASSWORD = 'plain secret';
    -- specifying hashes:
    CREATE USER tom@'%.example.com' IDENTIFIED BY PASSWORD 'secret hash';
    ALTER USER tom@'%.example.com' IDENTIFIED BY PASSWORD 'secret hash';
    SET PASSWORD = PASSWORD('secret hash');
    SET PASSWORD FOR tom@'%.example.com' = PASSWORD 'secret hash';
    CREATE USER 'tom'@'%.example.com' PASSWORD EXPIRE INTERVAL 365 DAY;
    CREATE USER 'tom'@'%.example.com' PASSWORD EXPIRE NEVER;
    CREATE USER 'tom'@'%.example.com' ACCOUNT LOCK;
    CREATE USER username@hostname IDENTIFIED VIA gssapi;
    GRANT SELECT ON db.* TO username@hostname IDENTIFIED VIA named_pipe;
    CREATE USER 'tom'@'example.com';
    CREATE USER 'tom'@'123.123.123.123;
    CREATE USER 'tom'@'tomlaptop';
    GRANT USAGE ON *.* TO tom@'%';
    SET DEFAULT ROLE some_role FOR username@hostname;
    SET DEFAULT ROLE NONE FOR username@hostname;
    GRANT some_role TO username@hostname;
    SET ROLE some_role;
    sql_mode and old_mode

    SQL semantics and syntax, in MariaDB, are affected by the sql_mode variable. Its value is a comma-separated list of flags, and each of them, if specified, affects a different aspect of SQL syntax and semantics.

    A particularly important flag for users familiar with SQL Server is .

    sql_mode can be changed locally, in which case it only affects the current session; or globally, in which case it will affect all new connections (but not the connections already established). sql_mode must be assigned a comma-separated list of flags.

    A usage example:

    old_mode is very similar to sql_mode, but its purpose is to provide compatibility with older MariaDB versions. Its flags shouldn't affect compatibility with SQL Server (though it is theoretically possible that some of them do, as a side effect).

    Executable Comments

    MariaDB supports executable comments. These are designed to write generic queries that are only executed by MariaDB, and optionally only certain versions.

    The following examples show how to insert SQL code that will be ignored by SQL Server but executed by MariaDB, or some of its versions.

    • Executed by MariaDB and MySQL (see below):

    • Executed by MariaDB only:

    • Executed by MariaDB starting from version 10.0.5:

    As explained in the Understanding MariaDB Architecture page, MariaDB was initially forked from MySQL. At that time, executable comments were already supported by MySQL. This is why the /*! ... */ syntax is supported by both MariaDB and MySQL. But because MariaDB also supports specific syntax not supported by MySQL, it added the /*M! ... */ syntax.

    Generic Syntax

    Here we discuss some differences between MariaDB and SQL Server syntax that may affect any user, as well as some hints to make queries compatible with a reasonable amount of work.

    Delimiters

    SQL Server uses two different terminators:

    • The batch terminator is the go command. It tells Microsoft clients to send the text we typed to SQL Server.

    • The query terminator is a semicolon (;) and it tells SQL Server where a query ends.

    It is rarely necessary to use ; in SQL Server. It is required for certain common table expressions, for example.

    But the same doesn't apply to MariaDB. Normally, with MariaDB, you only use ;.

    However, MariaDB also has some situations where you want to use a ; but you don't want the mariadb command-line client to send the query yet. This can be done in any situation, but it is particularly useful when creating stored routines or using BEGIN NOT ATOMIC.

    The reason is better explained with an example:

    If we enter this procedure in this way in the mariadb client, as soon as we type the first ; (after the first SELECT) and press enter, the statement will be sent. MariaDB will try to parse it and will return an error.

    To avoid this, mariadb implements the DELIMITER statement. This client statement is never sent to MariaDB. Instead, the client uses it to find out when the typed query should be sent. Let's correct the above example:

    Names

    In MariaDB, most names have a maximum length of 64 characters. When migrating an SQL Server database to MariaDB, check if some names exceed this limit (SQL Server maximum length is 128).

    By default, MariaDB names are case-sensitive if the operating system has case-sensitive file names (Linux), and case-insensitive if the operating system is case-insensitive (Windows). SQL Server is case-insensitive by default on all operating systems.

    When migrating a SQL Server database to MariaDB on Linux, to avoid problems, you may want to set the lower_case_table_names system variable to 1, making table names, database names, and aliases case-insensitive.

    Names can be quoted inside backtick characters (```). This character can be used in names, in which case it should be doubled. By default, this is the only way to quote names.

    To also enable the use of double quotes ("), modify sql_mode by adding the ANSI_QUOTES flag. This is the equivalent of setting QUOTED_IDENTIFIER ON in SQL Server.

    To also enable the use of SQL Server style quotes ([ and ]), modify sql_mode by adding the MSSQL flag.

    The case-sensitivity of stored procedures and functions is never a problem, as they are case-insensitive in SQL Server.

    Quoting Strings

    In SQL Server, by default, strings can only be quoted with single-quotes ('), and to use a double quote in a string, it should be doubled (''). This also works by default in MariaDB.

    SQL Server also allows to use of double quotes (") to quote strings. This works by default in MariaDB, but as mentioned before, it won't work if sql_mode contains the ANSI_QUOTES flag.

    NULL

    The default semantics of NULL in SQL Server and MariaDB are the same, by default.

    However, SQL Server allows one to change it globally with SET ANSI_NULLS OFF, or at the database level with ALTER DATABASE.

    There is no way to achieve exactly the same result in MariaDB. To perform NULL-safe comparisons in MariaDB, one should replace the = operator with the <=> operator.

    Also, note that MariaDB doesn't support the UNKNOWN pseudo-value. An expression like NULL OR 0 returns NULL in MariaDB.

    LIKE

    In MariaDB, LIKE expressions only have two characters with special meanings: % and _. These two characters have the same meanings they have in SQL Server.

    The additional characters recognized by SQL Server ([, ] and ^) are part of regular expressions. MariaDB supports the REGEXP operator that supports the full regular expression syntax.

    Data Definition Language

    Here we discuss some DDL differences that database administrators will want to be aware of.

    While this section is meant to highlight the most noticeable DDL differences between MariaDB and SQL Server, there are many others, both in the syntax and in the semantics. See the ALTER statement documentation.

    Altering Tables Online

    Altering tables online can be a problem, especially when the tables are big and we don't want to cause a disruption.

    MariaDB offers the following solutions to help:

    • The ALTER TABLE ... ALGORITHM clause allows one to specify which algorithm should be used to run a certain operation. For example, INPLACE tells MariaDB not to create a table copy (perhaps because we don't have enough disk space), and INSTANT tells MariaDB to execute the operation instantaneously. Not all algorithms are supported for certain operations. If the algorithm we've chosen cannot be used, the ALTER TABLE statement will fail with an error.

    • The ALTER TABLE ... LOCK clause allows one to specify which lock type should be used. For example, NONE tells MariaDB to avoid any lock on the table and SHARED only allows one to acquire a share lock. If the operation requires a lock that is more strict than the one, we are requesting, the ALTER TABLE statement will fail with an error. Sometimes this happens because the LOCK level we want is not available for the specified ALGORITHM.

    To find out which operations require a table copy and which lock levels are necessary, see InnoDB Online DDL Overview.

    An ALTER TABLE can be queued because a long-running statement (even a SELECT) requires a metadata lock. Since this may cause trouble, sometimes we want the operation to simply fail if the wait is too long. This can be achieved with the WAIT and NOWAIT clauses, whose syntax is a bit different from SQL Server.

    SQL Server WITH ONLINE = ON is equivalent to MariaDB LOCK = NONE. However, note that most ALTER TABLE statements support ALGORITHM = INSTANT, which is non-blocking and much faster (almost instantaneous, as the syntax suggests).

    IF EXISTS, IF NOT EXISTS, OR REPLACE

    Most DDL statements, including ALTER TABLE, support the following syntax:

    • DROP IF EXISTS: A warning (not an error) is produced if the object does not exist.

    • OR REPLACE: If the object exists, it is dropped and recreated; otherwise, it is created. This operation is atomic, so at no point in time does the object not exist.

    • CREATE IF NOT EXISTS: If the object already exists, a warning (not an error) is produced. The object will not be replaced.

    These statements are functionally similar (but less verbose) than SQL Server snippets similar to the following:

    Altering Columns

    With SQL Server, the only syntax to alter a table column is ALTER TABLE ... ALTER COLUMN. MariaDB provides more ALTER TABLE commands to obtain the same result:

    • CHANGE COLUMN allows one to perform any change by specifying a new column definition, including the name.

    • MODIFY COLUMN allows any change, except renaming the column. This is a slightly simpler syntax that we can use when we don't want to change a column name.

    • ALTER COLUMN allows one to change or drop the DEFAULT value.

    • allows one to only change the column name.

    Using a more specific syntax is less error-prone. For example, by using ALTER TABLE ... ALTER COLUMN,we will not accidentally change the data type.

    The word COLUMN is usually optional, except in the case of RENAME COLUMN.

    SHOW Statements

    MariaDB supports SHOW statements to quickly list all objects of a certain type (tables, views, triggers...). Most SHOW statements support a LIKE clause to filter data. For example, to list the tables in the current database whose name begins with 'wp_':

    This is the equivalent of this query, which would work on both MariaDB and SQL Server:

    SHOW CREATE Statements

    In general, for each CREATE statement, MariaDB also supports a SHOW CREATE statement. For example, there is a SHOW CREATE TABLE that returns the CREATE TABLE statement that can be used to recreate a table.

    Though SQL Server has no way to show the DDL statement to recreate an object, SHOW CREATE statements are functionally similar to sp_helptext().

    Database Comments

    MariaDB does not support extended properties. Instead, it supports a COMMENT clause for most CREATE and ALTER statements.

    For example, to create and then change a table comment:

    Comments can be seen with SHOW CREATE statements or by querying information_schema tables. For example:

    Error Handling

    MariaDB SHOW ERRORS and SHOW WARNINGS statements can be used to show errors, or warnings and errors. This is convenient for clients, but stored procedures cannot work with the output of these commands.

    Instead, inside stored procedures, you can:

    • Use the GET DIAGNOSTICS command to assign error properties to variables. This is the equivalent of using SQL Server functions like ERROR_NUMBER() or ERROR_STATE().

    • Add a DECLARE HANDLER block to handle all errors, a class of errors, or a specific error. This is the equivalent of SQL Server TRY ... CATCH.

    • An error or warning can be generated on purpose using SIGNAL. Inside a DECLARE HANDLER block, can be used to issue the error again and interrupt the execution of the block. These are the equivalents of SQL Server RAISERROR().

    Administration

    Administration and maintenance commands in MariaDB use a different syntax from SQL Server.

    • OPTIMIZE TABLE rebuilds table data and indexes. It can be considered as the MariaDB equivalent of SQL Server's ALTER INDEX REBUILD. See Defragmenting InnoDB Tablespaces for more information. This statement is always locked. It supports WAIT and NOWAIT syntax,

    • MariaDB has an ANALYZE TABLE command, which is equivalent to UPDATE STATISTICS.

    BULK INSERT

    MariaDB has no BULK INSERT statement. Instead, it supports:

    • LOAD DATA INFILE to load data from files in CSV or similar formats;

    • LOAD XML INFILE to load data from XML files.

    See also How to Quickly Insert Data Into MariaDB.

    See Also

    • SQL Server and MariaDB Types Comparison

    • MariaDB Transactions and Isolation Levels for SQL Server Users

    This page is licensed: CC BY-SA / Gnu FDL

    Function
    procedure privileges
    EXPLAIN
    Contact our Migration Experts
    # check the current global and local sql_mode values
    SELECT @@global.sql_mode;
    SELECT @@session.sql_mode;
    # empty sql_mode for all users
    SET GLOBAL sql_mode = '';
    # add MSSQL flag to the sql_mode for the current session
    SET SESSION sql_mode = CONCAT(sql_mode, ',MSSQL');
    SELECT * FROM tab /*! FORCE INDEX (idx_a) */ WHERE a = 1 OR b = 2;
    SELECT * /*M! , @in_transaction */ FROM tab;
    DELETE FROM user WHERE id = 100 /*!M100005 RETURNING email */;
    CREATE PROCEDURE p()
    BEGIN
        SELECT * FROM t1;
        SELECT * FROM t2;
    END;
    DELIMITER ||
    
    CREATE PROCEDURE p()
    BEGIN
        SELECT * FROM t1;
        SELECT * FROM t2;
    END;
    
    DELIMITER ;
    IF NOT EXISTS (
            SELECT name
                FROM sysobjects
                WHERE name = 'my_table' AND xtype = 'U'
        )
        CREATE TABLE my_table (
            ...
        )
    go
    SHOW TABLES LIKE 'wp\_%';
    SELECT TABLE_SCHEMA, TABLE_NAME
        FROM INFORMATION_SCHEMA.TABLES
        WHERE TABLE_NAME LIKE 'wp\_';
    CREATE TABLE counter (
        c INT UNSIGNED AUTO_INCREMENT PRIMARY KEY
    )
        COMMENT 'Monotonic counter'
    ;
    ALTER TABLE counter COMMENT
        'Counter. It can contain many values, we only care about the max';
    SELECT TABLE_COMMENT
        FROM information_schema.TABLES
        WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'counter';
    +-----------------------------------------------------------------+
    | TABLE_COMMENT                                                   |
    +-----------------------------------------------------------------+
    | Counter. It can contain many values, we only care about the max |
    +-----------------------------------------------------------------+
    RENAME COLUMN
    RESIGNAL
    Cover

    Migrating from SQL Server?

    Contact our Migration Experts
    Cover

    Migrating from SQL Server?

    Cover

    Migrating from SQL Server?

    Contact our Migration Experts

    Migrating from SQL Server?

    Contact our Migration Experts

    Cover
    Contact our Migration Experts
    Cover

    Migrating from SQL Server?

    Contact our Migration Experts
    Cover

    Migrating from SQL Server?

    Progress reporting
    Contact our Migration Experts
    Cover

    Migrating from SQL Server?

    Contact our Migration Experts
    MariaDB versus MySQL - Features
    MariaDB versus MySQL - Compatibility
    Replication Compatibility Between MariaDB and MySQL
    Function Differences Between MariaDB and MySQL
    System Variable Differences between MariaDB and MySQL
    Incompatibilities and Feature Differences Between MariaDB Rolling and MySQL 8.0
    Incompatibilities and Feature Differences Between MariaDB 11.4 and MySQL 8.0
    Incompatibilities and Feature Differences Between MariaDB 10.11 and MySQL 8.0
    Incompatibilities and Feature Differences Between MariaDB 10.6 and MySQL 8.0
    Incompatibilities and Feature Differences Between MariaDB and MySQL - Unmaintained Series
    MariaDB 5.1
    MariaDB 5.1.50
    latest Generally Available (GA) version
    deprecation policies
    Incompatibilities and Feature Differences Between MariaDB and MySQL.
    MariaDB version compatible
    Incompatibilities and Feature Differences
    MySQL to MariaDB Replication Compatibilit
    MariaDB 10.5
    MariaDB 10.5
    check for incompatibilities and feature differences
    SQL_MODE=ORACLE
    SQL_MODE=MSSQL
    PL/SQL support
    sql_mode='MSSQL'
    10.5.1
    MariaDB 10.5
    MariaDB 10.0.5
    MariaDB 10.0.5
    MariaDB 10.3.3
    MariaDB 10.7
    MariaDB 10.5
    MariaDB 10.2
    MariaDB 10.2
    MSSQL
    SQL_MODE=MSSQL