带有 MySQL 非事务性更改表的 Django 无法回滚

Posted

技术标签:

【中文标题】带有 MySQL 非事务性更改表的 Django 无法回滚【英文标题】:Django w/ MySQL non-transactional changed tables couldn't be rolled back 【发布时间】:2014-07-19 09:35:59 【问题描述】:

使用 mysql 数据库时不断收到此警告:

Some non-transactional changed tables couldn't be rolled back

我不确定这意味着什么,或者它是否会导致问题,但我希望有人能够让我了解这意味着什么。

我正在获取一个 CSV 文件,逐行读取它并使用 get_or_create 创建 Django 对象。收到消息后,当我尝试重新创建它时,我会在警告发生之前进一步进入 CSV 文件。

我尝试在线阅读有关此错误的信息,但我真的不明白它的含义。找出造成这种情况的原因是理想的,但如果我不能,我想知道是否可以取消警告,因为它可能不会对我的数据库产生负面影响。

【问题讨论】:

您的表使用什么数据库/引擎? MySQL...djando.db.backends.mysql 您知道您的表使用的是什么引擎吗? innodb/myisam?请记住,它是一个表一个表。 我有 MySQL v5.1.61,所以我认为可以肯定地说我有 myisam...如果这不是一个安全的假设,请纠正我 【参考方案1】:

当您混合使用 transactionalnon-transactional 表时会发生这种情况。对非事务表的更改不受ROLLBACK 语句的影响。

由于某些原因,这可能发生在您身上,我们可以求助于docs:

如果您不是故意在事务中混合事务性和非事务性表,则此消息最可能的原因是您认为是事务性的表实际上不是。如果您尝试使用您的 mysqld 服务器不支持的事务存储引擎(或使用启动选项禁用该引擎)创建表,则可能会发生这种情况。如果 mysqld 不支持存储引擎,它会将表创建为 MyISAM 表,这是非事务性的。

如果您说有一个启动事务的HTTP 请求,您进行了一些更改,并且您需要回滚,这将对事情产生负面影响。事务表将回滚,但其他表不会。如果您的软件需要事务性存储引擎,您应该考虑采取措施将所有相关表迁移到 InnoDB 引擎。

【讨论】:

这和使用get_or_create()VS有什么关系吗? try: get()... expect DoesNotExist: ... save() 不,这与 DBMS 中的表引擎有关 我想您的模型有一些将innoDB 连接到myiasm 表的关系,这将导致您看到此错误。它来自DBMS 它是MySQL 错误而不是Django 有没有办法阻止这种情况发生?我的脚本正在使用 get_or_create() 执行大量数据库事务。我可以在脚本中间做些什么来防止发生这种异常吗?把它在try中出现的地方包起来会是不好的做法吗? 您可以通过在您的应用设置中将AUTOCOMMIT 设置为False 来禁用django 的事务行为。然后你必须自己管理事务边界。或者您可以阅读我所说的混合事务/非事务资源。清点您的表并找出问题所在并将其排除在事务操作之外。【参考方案2】:

对我来说,这个错误发生在我从另一个 Django 应用程序导入表之后。源数据库将所有表引擎设置为 MyISAM,目标应用程序将所有引擎设置为 InnoDB。当我导入现有表时,引擎从 InnoBD 更改为 MyISAM 以匹配源。我在命令行上使用 MySQL 解决了这个问题:

$ mysql -uroot -pPASSWORD
> use MY_DB;
> show table status;
> alter table TABLE_WITH_MYISAM engine=innodb;
> quit;

我已经导入了 5 个表,所以我必须为每个表执行 alter 命令。上面的 show 命令将打印出 MY_DB 中所有表的表名和引擎设置。

我希望这有助于解决您的问题!干杯!

【讨论】:

以上是关于带有 MySQL 非事务性更改表的 Django 无法回滚的主要内容,如果未能解决你的问题,请参考以下文章

django中怎么使用mysql数据库的事务

Django提供的mysql事务

MySql存储引擎

mysql事务表和非事务表在binlog日志的不同处理

Mysql数据库表的类型有哪些

2MySQL常见数据库引擎及比较?