【问题标题】:django loaddata fails because of concurrent database query由于并发数据库查询,django loaddata 失败
【发布时间】:2017-09-27 15:36:26
【问题描述】:

我正在尝试将我的一个 django 项目的数据库从 sqlite 迁移到 mysql。我首先用./manage.py dumpdata > dump.json 转储了整个数据,然后用./manage.py migrate 准备了数据库,并删除了表中所有创建的数据(这是必要的,因为转储包含所有数据)。

当我想用./manage.py loaddata将数据导入新数据库时,我能够解决很多错误,但我找不到这个错误的根源:

Processed 330984 object(s).Traceback (most recent call last):
  File "/app/manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python3.5/site-packages/django/core/management/__init__.py", line 363, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python3.5/site-packages/django/core/management/__init__.py", line 355, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python3.5/site-packages/django/core/management/base.py", line 283, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/usr/local/lib/python3.5/site-packages/django/core/management/base.py", line 330, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python3.5/site-packages/django/core/management/commands/loaddata.py", line 69, in handle
    self.loaddata(fixture_labels)
  File "/usr/local/lib/python3.5/site-packages/django/core/management/commands/loaddata.py", line 109, in loaddata
    self.load_label(fixture_label)
  File "/usr/local/lib/python3.5/site-packages/django/core/management/commands/loaddata.py", line 175, in load_label
    obj.save(using=self.using)
  File "/usr/local/lib/python3.5/site-packages/django/core/serializers/base.py", line 205, in save
    models.Model.save_base(self.object, using=using, raw=True, **kwargs)
  File "/usr/local/lib/python3.5/site-packages/django/db/models/base.py", line 837, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "/usr/local/lib/python3.5/site-packages/django/db/models/base.py", line 904, in _save_table
    forced_update)
  File "/usr/local/lib/python3.5/site-packages/django/db/models/base.py", line 954, in _do_update
    return filtered._update(values) > 0
  File "/usr/local/lib/python3.5/site-packages/django/db/models/query.py", line 664, in _update
    return query.get_compiler(self.db).execute_sql(CURSOR)
  File "/usr/local/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 1199, in execute_sql
    cursor = super(SQLUpdateCompiler, self).execute_sql(result_type)
  File "/usr/local/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 894, in execute_sql
    raise original_exception
  File "/usr/local/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 884, in execute_sql
    cursor.execute(sql, params)
  File "/usr/local/lib/python3.5/site-packages/django/db/backends/utils.py", line 60, in execute
    self.db.validate_no_broken_transaction()
  File "/usr/local/lib/python3.5/site-packages/django/db/backends/base/base.py", line 448, in validate_no_broken_transaction
    "An error occurred in the current transaction. You can't "
django.db.transaction.TransactionManagementError: Problem installing fixture '/path/to/django/dump.json': Could not load auth.User(pk=1): An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.

我已经尝试删除所有的信号接收器,这样在执行 loaddata 时我自己的代码都不会运行。

有没有其他人在使用 django 的 loaddata 时遇到过类似的行为并设法让它工作?

上下文:

  • python v3.5
  • django v1.11.4
  • 仅使用 stdlib django 模型字段

【问题讨论】:

  • 如果你可以使用 Postgresql 代替 Mysql,我认为它可以更优雅地处理并发。
  • 是的,事实上,我可以。我认为这个错误似乎与 django 相关,或者您认为使用 Postgresql 会使其消失?
  • PG 使用 MVCC(多版本并发控制)。我猜现代 Mysql 实例可能会使用 MVCC,但我不知道这是否是默认设置。
  • MySQL 5.7(我正在使用)似乎使用 MVCC(dev.mysql.com/doc/refman/5.7/en/innodb-multi-versioning.html)。这使得对 Postgresql 的更改不太可能解决这个问题 - 如果这是问题的话。
  • 这个 Pg/MySQL 辩论是一个已知的火焰战源。我在 Postgresql 方面,我认为你应该试一试。也就是说,这只是一种意见,为什么这是评论而不是答案。

标签: django


【解决方案1】:

这更像是一种变通方法而不是解决方案,但它确实解决了我的问题。

经过进一步调查,我意识到 auth.user 模型以某种方式触发了查询并破坏了导入。 解决方案是编写一个简单的脚本将转储拆分为多个部分(我无法再访问数据库),然后以正确的顺序导入它们:contenttypesauth 以及其余部分。

您可以找到脚本here
这就是我拆分转储的方式:

./investigate-django-dump.py dump.json extract contenttypes. > contenttypes.json
./investigate-django-dump.py dump.json extract auth. > auth.json
./investigate-django-dump.py dump.json extractnot auth.,contenttypes. > data.json

【讨论】:

    猜你喜欢
    • 2018-11-28
    • 2017-03-04
    • 1970-01-01
    • 2020-01-17
    • 1970-01-01
    • 1970-01-01
    • 2015-11-28
    • 1970-01-01
    • 2018-11-11
    相关资源
    最近更新 更多