Changing MySQL isolation level on Django/Elastic beanstalk/RDS

Question:

I’m trying to change the isolation level of my MySQL instance on RDS through a Django application.
I’ve followed the recommendation here

So, I changed my Django db settings to:

'OPTIONS': {
    'init_command': 'SET default_storage_engine=INNODB; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED'
}

This command works fine when I run directly in the database (MySQL version 8.0.13)
However, when I try to deploy it to Elastic Beanstalk I got the following error:

Command failed on instance. Return code: 1 Output: (TRUNCATED)... manual that corresponds to your MySQL server version for the right syntax to use near 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED' at line 1")

I also tried changing the line to:

SET default_storage_engine=INNODB, SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED

With the same results

Any idea what might be wrong? Or another solution that I can use (maybe I can just run this command and set it to global isolation level instead?)

Asked By: dfranca

||

Answers:

Perhaps that OPTIONS cannot handle 2 commands. So remove the first one — it is useful only when creating a new table. And it may be possible to specify the ENGINE=InnoDB on any CREATE TABLEs you need to do. Anyway, I would expect AWS to default to that. And 8.0 has that engine default.

Answered By: Rick James

Can you try like below, anyone should work.

SET @@SESSION.transaction_isolation = value;
SET SESSION transaction_isolation = value;
SET transaction_isolation = value;
Answered By: asktyagi

For MySQL, you will be able to set and check READ COMMITTED by running the raw queries after database settings in settings.py as shown below. *If running the raw query before database settings, error occurs:

# "settings.py"

from django.db import connection

# ...

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'DB_NAME',
        'USER': 'DB_USER',
        'PASSWORD': 'DB_PASSWORD',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

# ↓ ↓ ↓ Set isolation level ↓ ↓ ↓

cursor = connection.cursor()
query = """
        SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
        """
cursor.execute(query)

# ↓ ↓ ↓ Check isolation level ↓ ↓ ↓

cursor.execute('SELECT @@GLOBAL.transaction_isolation;')
print(cursor.fetchone()) # ('read committed',)

*settings.py is run every time Django Server is run with the command below or every time Django Server is reloaded by writing code so transaction is set every time Django Server is run with the command below or every time Django Server is reloaded by writing code:

python manage.py runserver 0.0.0.0:8000

For me with PostgreSQL, "init_command": ... and "isolation_level" in "OPTIONS": {} below didn’t work so I couldn’t set SERIALIZABLE in settings.py:

# "settings.py"

"OPTIONS": {
    "init_command": "ALTER DATABASE postgres SET DEFAULT_TRANSACTION_ISOLATION TO 'SERIALIZABLE';"
    "isolation_level": psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE,
}
Answered By: Kai – Kazuya Ito