Elixir Ecto使用索引回滚迁移

时间:2018-05-24 23:37:18

标签: elixir phoenix-framework ecto

我目前正在进行一系列迁移,这些迁移会创建一些带有引用和一些唯一索引的表。当我想用mix ecto.migrate迁移表时,这似乎工作得很好但是如果我想回滚mix ecto.rollback咳嗽以下错误。我是否需要更改迁移以在回滚期间添加处理索引的内容?

迁移步骤:

defmodule App.Repo.Migrations.CreateTokens do
  use Ecto.Migration

  def change do
    create table(:tokens) do
      add :token, :string
      add :user_id, references(:users, on_delete: :delete_all, on_update: :update_all)

      timestamps()
    end

    create index(:tokens, [:user_id])
    create unique_index(:tokens, [:token], unique: true, name: :unique_tokens_index)
  end
end

错误日志:

[info] == Running App.Repo.Migrations.CreateTokens.change/0 backward
[info] drop index unique_tokens_index
[info] drop index tokens_user_id_index
** (Mariaex.Error) (1553): Cannot drop index 'tokens_user_id_index': needed in a foreign key constraint
    (ecto) lib/ecto/adapters/sql.ex:200: Ecto.Adapters.SQL.query!/5
    (ecto) lib/ecto/adapters/mysql.ex:118: anonymous fn/4 in Ecto.Adapters.MySQL.execute_ddl/3
    (elixir) lib/enum.ex:1899: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ecto) lib/ecto/adapters/mysql.ex:118: Ecto.Adapters.MySQL.execute_ddl/3
    (ecto) lib/ecto/migration/runner.ex:104: anonymous fn/2 in Ecto.Migration.Runner.flush/0
    (elixir) lib/enum.ex:1899: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ecto) lib/ecto/migration/runner.ex:102: Ecto.Migration.Runner.flush/0
    (stdlib) timer.erl:181: :timer.tc/2
    (ecto) lib/ecto/migration/runner.ex:26: Ecto.Migration.Runner.run/6
    (ecto) lib/ecto/migrator.ex:128: Ecto.Migrator.attempt/6
    (ecto) lib/ecto/migrator.ex:106: anonymous fn/4 in Ecto.Migrator.do_down/4
    (ecto) lib/ecto/adapters/sql.ex:576: anonymous fn/3 in Ecto.Adapters.SQL.do_transaction/3
    (db_connection) lib/db_connection.ex:1283: DBConnection.transaction_run/4
    (db_connection) lib/db_connection.ex:1207: DBConnection.run_begin/3
    (db_connection) lib/db_connection.ex:798: DBConnection.transaction/3
    (ecto) lib/ecto/migrator.ex:262: anonymous fn/4 in Ecto.Migrator.migrate/4
    (elixir) lib/enum.ex:1294: Enum."-map/2-lists^map/1-0-"/2
    (ecto) lib/mix/tasks/ecto.rollback.ex:79: anonymous fn/4 in Mix.Tasks.Ecto.Rollback.run/2
    (elixir) lib/enum.ex:737: Enum."-each/2-lists^foreach/1-0-"/2
    (elixir) lib/enum.ex:737: Enum.each/2

1 个答案:

答案 0 :(得分:0)

即使您有索引等,

ecto.rollback通常也能正常工作。通过阅读错误消息,似乎问题是ecto正在尝试回滚一个具有其他表使用的密钥作为外键的表。这可能是您的迁移订单的问题。

例如,如果您有此迁移

defmodule App.Repo.Migrations.CreateTokens do
  use Ecto.Migration

  def change do
    create table(:tokens) do
      add :token, :string
      add :user_id, references(:users, on_delete: :delete_all, on_update: :update_all)

      timestamps()
    end

    create index(:tokens, [:user_id])
    create unique_index(:tokens, [:token], unique: true, name: :unique_tokens_index)
  end
end

应首先创建CreateUsers迁移(这意味着首先在文件名上设置较低的时间戳),因为CreateTokens依赖于CreateUsers来建立其foreign_keys。

此错误可能是由于您生成迁移并尝试自己随后更改它。请记住,迁移对时间敏感/对订单敏感,因此如果您还没有创建用户表,则无法创建引用用户的令牌表

您可以尝试运行mix ecto.reset,但由于在尝试回滚时遇到错误,因此在运行mix ecto.migrate

时很可能会出错

解决方案是修复迁移订单甚至拆分为更多迁移...例如:CreateUsers,CreateTokens,CreateForeignKeys