Posted 4 months ago. Visible to the public. Repeats.

Understanding SQL compatibility modes in MySQL and MariaDB

MySQL and MariaDB have an SQL mode setting which changes how MySQL behaves.

The SQL mode value is comprised of multiple flags like "STRICT_TRANS_TABLES, NO_ZERO_IN_DATE". Each flag activates or disables a particular behavior.

The default SQL mode varies widly between versions of MySQL and MySQL. In general, more recent versions of MySQL and MariaDB have stricter settings than older versions, and MySQL has stricter settings than the more liberal MariaDB.

If your app explodes after changing SQL servers, you might be able to fix it by setting the SQL mode to the value in your previous server version.

Important SQL mode flags

These SQL modes will probably give you the most headaches:

STRICT_TRANS_TABLES, STRICT_ALL_TABLES

Introduced in MySQL 5.7, these enable Strict SQL mode. In SQL Strict mode MySQL is likely to throw an error if an INSERT or UPDATE has invalid or missing values. Without strict mode, MySQL will try more to not throw an error.

For instance, if a STRING exceeds the length of a field, MySQL will throw an error in strict mode. Without strict mode it would truncate the string to the maximum column size.

ONLY_FULL_GROUP_BY

With this enabled (default in MySQL 5.7), you can no longer SELECT values from a group without an aggregate function.

E.g. you will probably find queries like these in old apps:

Copy
SELECT name, address, MAX(age) FROM users GROUP BY name;

With ONLY_FULL_GROUP_BY this now explodes with:

Copy
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'mydb.t.address' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

You need to make sure that any selected value is either (1) the value you group by or (2) passed to an aggregate function like MIN or MAX. If you don't care about the aggregate function, you can use ANY_VALUE:

Copy
SELECT name, ANY_VALUE(address), MAX(age) FROM t GROUP BY name;

TRADITIONAL

This is a shortcut that activates multiple SQL mode flags.

Which SQL mode flags it activates varies between MySQL, MariaDB and their individual versions (see below).

Note that TRADITIONAL does not necessarily make the SQL server behave more liberally in what it accepts. In particular, it enables strict mode, but disables ONLY_FULL_GROUP_BY in all versions we've seen.

Because of this you might want to list individual flags instead of using TRADITIONAL.

Default SQL mode settings

In general, more recent versions of MySQL and MariaDB have stricter settings than older versions, and MySQL has stricter settings than the more liberal MariaDB.

  Maria DB 10 Traditional MariaDB 10.0 default MariaDB 10.2 default MySQL 5.7 Traditional MySQL 5.7 Default MySQL 5.6 Default MySQL 5.6 Traditional
STRICT_TRANS_TABLES yes - yes yes yes - yes
STRICT_ALL_TABLES yes - - yes yes - yes
NO_ZERO_IN_DATE yes - - yes yes - yes
NO_ZERO_DATE yes - - yes yes - yes
ERROR_FOR_DIVISION_BY_ZERO yes - yes yes yes - yes
NO_AUTO_CREATE_USER yes - yes yes yes - yes
NO_ENGINE_SUBSTITUTION - - yes yes yes yes yes
ONLY_FULL_GROUP_BY - - - - yes - -

Changing the SQL mode

Globally

To change the SQL for your entire database server, edit /etc/mysql/my.cnf and add this to the [mysqld] section:

Copy
[mysqld] sql_mode=""

Now restart MySQL:

Copy
sudo service mysql restart

For a single Rails project

If you only want to change the SQL mode for one project, you can add this to your config/database.yml:

Copy
development: adapter: mysql2 database: myproject ... variables: sql_mode: "NO_AUTO_CREATE_USER, STRICT_TRANS_TABLES"

If you make any changes to your database.yml, remember to also change it here:

  • database.sample.yml
  • all colleagues that have a local database.yml (which is in .gitignore)
  • staging servers
  • production servers

Once an application no longer requires constant development, it needs periodic maintenance for stable and secure operation. makandra offers monthly maintenance contracts that let you focus on your business while we make sure the lights stay on.

Owner of this card:

Avatar
Henning Koch
Last edit:
4 months ago
by Henning Koch
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Henning Koch to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more