mysql & Django 事务隔离级别PostgreSQL

发布于 2024-08-21 16:27:05 字数 84 浏览 9 评论 0原文

你知道Django中使用的事务的默认隔离级别吗? 是否可以以独立于数据库的方式设置隔离级别?

我主要对mysql和postgres感兴趣。

Do you know the default isolation level of the transactions used in Django?
Is it possible to set the isolation level in the database independent way?

I'm mainly interested in mysql and postgres.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

ζ澈沫 2024-08-28 16:27:05

您还可以使用 django 数据库选项更改每个客户端/会话的设置,如下所示:

DATABASE_OPTIONS = { "init_command": "SET storage_engine=INNODB, SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED", }

You can also change this per client / session using the django database options, like this:

DATABASE_OPTIONS = { "init_command": "SET storage_engine=INNODB, SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED", }
画中仙 2024-08-28 16:27:05

隔离级别不会被 mysql 驱动程序更改,因此它取决于服务器的默认隔离级别。

The isolation level isn't changed by mysql drivers so it depends on the server's default isolation level.

夏了南城 2024-08-28 16:27:05

目前 django 没有设置隔离级别。这是一个错误,因为 django 无法在任何高于 READ COMMITTED 的隔离级别下正常工作。但 MySQL 默认使用 REPEATABLE READ。有计划添加一个设置来设置隔离级别 (#14026) 以及关于将 READ COMMITTED 设置为默认值 (#13906)。我还写了一篇关于 MySQL 事务和 django

At the moment django does not set the isolation level. This is a bug, because of django does not work properly with any higher isolation level than READ COMMITTED. But MySQL is using REPEATABLE READ by default. There are plans to add a setting to set the isolation level (#14026) and a discussion about making READ COMMITTED the default (#13906). I have also written a detailed article about MySQL transactions and django.

臻嫒无言 2024-08-28 16:27:05

根据我的测试,Django的默认隔离级别取决于您为数据库设置的隔离级别。换句话说,如果您为 PostgreSQL 或 MySQL 设置SERIALIZABLE,则 Django 的默认隔离级别为SERIALIZABLE

并且,要为 PostgreSQL 设置 SERIALIZABLE,我尝试了 文档Windows 11Django 3.2.16settings.py中进行了解释如下所示,但它不起作用,因此隔离级别仍然是 READ COMMITTED:

# "settings.py"

import psycopg2.extensions

DATABASES = {
    'default':{
        'ENGINE':'django.db.backends.postgresql',
        'NAME':'postgres',
        'USER':'postgres',
        'PASSWORD':'admin',
        'HOST':'localhost',
        'PORT':'5432',
    },
    'OPTIONS': { # ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ Doesn't work ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
        'isolation_level': psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE,
    },
}

但是,我可以通过在 settings 中运行原始查询来设置和检查 SERIALIZABLE .py 用于 PostgreSQL,如下所示。 *在设置中的DATABASES之后运行原始查询。 py:

# "settings.py"

from django.db import connection

# ...

DATABASES = {
    'default':{
        'ENGINE':'django.db.backends.postgresql',
        'NAME':'postgres',
        'USER':'postgres',
        'PASSWORD':'admin',
        'HOST':'localhost',
        'PORT':'5432',
    },
}

# ↓ ↓ ↓ Set isolation level ↓ ↓ ↓

cursor = connection.cursor()
query = """
        ALTER DATABASE postgres 
        SET DEFAULT_TRANSACTION_ISOLATION 
        TO 'SERIALIZABLE';
        """
cursor.execute(query)

# ↓ ↓ ↓ Check isolation level ↓ ↓ ↓

cursor.execute('SHOW default_transaction_isolation;')
print(cursor.fetchone()) # ('serializable',)

*或者,您可以直接使用psql设置SERIALIZABLE,如下所示:

postgres=# ALTER DATABASE postgres SET DEFAULT_TRANSACTION_ISOLATION TO 'SERIALIZABLE';

对于MySQL,您将能够设置和检查SERIALIZABLE 通过在 settings.py 中运行原始查询,如下所示:

# "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 SERIALIZABLE;
        """
cursor.execute(query)

# ↓ ↓ ↓ Check isolation level ↓ ↓ ↓

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

*或者,您可以直接使用 MySQL 客户端SERIALIZABLE 设置为如下图所示:

mysql> SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;

According to my test, Django's default isolation level depends on the isolation level which you set for your database. In other words, if you set SERIALIZABLE for your PostgreSQL or MySQL, Django's default isolation level is SERIALIZABLE.

And, to set SERIALIZABLE for PostgreSQL, I tried what the documentation explains in settings.py in Django 3.2.16 on Windows 11 as shown below but it didn't work so the isolation level is still READ COMMITTED:

# "settings.py"

import psycopg2.extensions

DATABASES = {
    'default':{
        'ENGINE':'django.db.backends.postgresql',
        'NAME':'postgres',
        'USER':'postgres',
        'PASSWORD':'admin',
        'HOST':'localhost',
        'PORT':'5432',
    },
    'OPTIONS': { # ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ Doesn't work ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
        'isolation_level': psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE,
    },
}

But, I could set and check SERIALIZABLE by running the raw queries in settings.py for PostgreSQL as shown below. *Run the raw queries after DATABASES in settings.py:

# "settings.py"

from django.db import connection

# ...

DATABASES = {
    'default':{
        'ENGINE':'django.db.backends.postgresql',
        'NAME':'postgres',
        'USER':'postgres',
        'PASSWORD':'admin',
        'HOST':'localhost',
        'PORT':'5432',
    },
}

# ↓ ↓ ↓ Set isolation level ↓ ↓ ↓

cursor = connection.cursor()
query = """
        ALTER DATABASE postgres 
        SET DEFAULT_TRANSACTION_ISOLATION 
        TO 'SERIALIZABLE';
        """
cursor.execute(query)

# ↓ ↓ ↓ Check isolation level ↓ ↓ ↓

cursor.execute('SHOW default_transaction_isolation;')
print(cursor.fetchone()) # ('serializable',)

*Or, you can directly set SERIALIZABLE with psql as shown below:

postgres=# ALTER DATABASE postgres SET DEFAULT_TRANSACTION_ISOLATION TO 'SERIALIZABLE';

And for MySQL, you will be able to set and check SERIALIZABLE by running the raw queries in settings.py as shown below:

# "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 SERIALIZABLE;
        """
cursor.execute(query)

# ↓ ↓ ↓ Check isolation level ↓ ↓ ↓

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

*Or, you can directly set SERIALIZABLE with MySQL client as shown below:

mysql> SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
煮酒 2024-08-28 16:27:05

(抱歉,我无法对 Danhip 发表评论)
这个解决方案对我来说很有效(mySQL),我在 DATABASE 字段中添加了 Peter 的代码:

DATABASES = {
    'default': {
        (...)
        'OPTIONS': {
            (...),
            "init_command": "SET storage_engine=INNODB, SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"
        },
     }
}

(Sorry, i can't comment for Danhip)
This solution wotked for me (mySQL), I added Peter's code in the DATABASE field:

DATABASES = {
    'default': {
        (...)
        'OPTIONS': {
            (...),
            "init_command": "SET storage_engine=INNODB, SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"
        },
     }
}
樱&纷飞 2024-08-28 16:27:05

如果您想使用读未提交隔离级别。

您在“数据库连接配置选项”中添加“isolation_level”:“读取未提交”。

DATABASES = {
    'read-uncommited': {
        'OPTIONS': {
            'isolation_level': 'read uncommitted'
        },
    },
}

您可以从 https://docs.djangoproject.com/en/2.1/ref 找到/数据库/

if you want to use read uncommited isolation level.

you add the 'isolation_level': 'read uncommitted' in 'OPTIONS on database connection configuration.

DATABASES = {
    'read-uncommited': {
        'OPTIONS': {
            'isolation_level': 'read uncommitted'
        },
    },
}

you can find from https://docs.djangoproject.com/en/2.1/ref/databases/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文