NirIzr
NirIzr

Reputation: 3410

Django default isolation level and db binary log format error

I'm running a set of tests on my django webserver using pytest-django. I'm trying to switch from a MySQL database server to MariaDB in my testing/CI on travis, and for that I also switched from the mysqldb python package to pymysql.

When using MariaDB, I suddenly get a strange exception for all my database related tests:

pymysql.err.InternalError: (1665, 'Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.')

This exception is below in a stack of several exceptions in all tests for that job, but I've identified it as the root cause for the issue.

It's important to note that out of the two jobs that run the test-suite directly on travis, and another that runs it on docker (inside travis), only one fails, the one running on python 3.6.

Although I roughly understand the cause of the problem I could not find a lot of information about the specifics or any reason for it to trigger/manifest all of a sudden. Except this Django documentation issue.

Given it's only triggered for the python3 test job and Django2 dropping support for python2 I assume the issues are related but still I can't seem to figure a reasonable/decent solution. I feel I'm missing at least some of the cause/reasoning behind what's going on in here.

I didn't make any changes to database configuration and all services are running with builtin installations.

For reference, this is a travis job for the PR, in case I missed something important out.

Upvotes: 1

Views: 652

Answers (2)

andyxuq
andyxuq

Reputation: 1

# config as this way, add options
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'xxx',
        'USER': 'xx',
        'PASSWORD': 'xx',
        'HOST': 'xxx',
        'POST': 'xxx',
        'OPTIONS': {
            'isolation_level': "repeatable read"
        },
    },
}

Upvotes: 0

NirIzr
NirIzr

Reputation: 3410

TL;DR: installing a more up-to-date version of MariaDB solved the issue.

Reading some more on the issue, I was able to determine the root cause was indeed due to a collision between two default configurations in my environment:

  1. BINLOG_FORMAT = STATEMENT.

    This was the default in MariaDB until version 10.2.4, according to MariaDB's documentation. Since I was using Travis-CI and because of how using MariaDB on travisCI was documented version 10.0 was hardcoded, thus defaulting to above value.

  2. transaction isolation level is set to READ COMMITTED

    On Python3, Django>=2.0 was installed, in which transaction isolation level is set to READ COMMITTED according to Django's documentation. This configuration seems to be a safer default value.

Replacing the major/minor version string in the example travis mariadb snippet:

addons:
  - mariadb: '10.0'

With a major only version string of '10.3' made travis install a more up-to-date version or MariaDB, which defaulted to the more flexible BINLOG_FORMAT = MIXED configuration.

Upvotes: 0

Related Questions