Pregunta

¿Cómo revertir una migración rieles fallado? Yo esperaría que rake db:rollback desharía la migración fallado, pero no, deshace la migración anterior (la migración no menos uno). Y rake db:migrate:down VERSION=myfailedmigration no funciona bien. He encontré con esto unas cuantas veces y es muy frustrante. Aquí está una prueba simple que hice para duplicar el problema:

class SimpleTest < ActiveRecord::Migration
  def self.up
    add_column :assets, :test, :integer
    # the following syntax error will cause the migration to fail
    add_column :asset, :test2, :integer
  end

  def self.down
    remove_column :assets, :test
    remove_column :assets, :test2
  end
end

resultado:

==  SimpleTest: migrating =====================================================
-- add_column(:assets, :test, :integer)
   -> 0.0932s
-- add_column(:asset, :error)
rake aborted!
An error has occurred, all later migrations canceled:

wrong number of arguments (2 for 3)

Muy buena opción rollo de nuevo:

$ rake db:rollback
==  AddLevelsToRoles: reverting ===============================================
-- remove_column(:roles, :level)
   -> 0.0778s
==  AddLevelsToRoles: reverted (0.0779s) ======================================

¿eh? que fue mi última migración antes de SimpleTest, no la migración fallado. (Y, oh, sería bueno si la salida de la migración incluido el número de versión.)

Así que vamos a intentar ejecutar el abajo para la migración SimpleTest fallado:

$ rake db:migrate:down VERSION=20090326173033
$

No pasa nada, y no hay salida tampoco. Pero tal vez corrió la migración de todos modos? Por lo que permite solucionar el error de sintaxis en la migración SimpleTest, y tratar de volver a ejecutarlo.

$ rake db:migrate:up VERSION=20090326173033
==  SimpleTest: migrating =====================================================
-- add_column(:assets, :test, :integer)
rake aborted!
Mysql::Error: Duplicate column name 'test': ALTER TABLE `assets` ADD `test` int(11)

Nop. Obviamente, el migran: abajo no funcionaba. No es no, simplemente no está en ejecución.

No hay manera de librarse de esa tabla duplicada otra que ir manualmente en la base de datos y su eliminación, y después de ejecutar la prueba. Tiene que haber una manera mejor que eso.

¿Fue útil?

Solución

Por desgracia, debe limpiar manualmente las migraciones fallidas para MySQL. MySQL no soporta cambios de definición de bases de datos transaccionales.

Barras de 2.2 incluye migraciones transaccionales para PostgreSQL. Carriles 2,3 incluye migraciones transaccionales para SQLite.

Esto en realidad no le ayuda para su problema en este momento, pero si usted tiene una opción de la base de datos sobre proyectos futuros, le recomiendo usar uno con soporte para DDL transaccional, ya que hace migraciones mucho más agradable.

Actualizar - esto sigue siendo cierto en 2017, en los carriles 4.2.7 y MySQL 5.7, reportados por Alejandro Babio en otra respuesta aquí

.

Otros consejos

Para ir a una versión especificada sólo tiene que utilizar:

rake db:migrate VERSION=(the version you want to go to)

Pero si un error en la migración forma parte, tendrá que limpiar primero. Una forma sería la siguiente:

  • editar el método down de la migración a simplemente deshacer la parte de la up que trabajó
  • migrar volver al estado anterior (punto de partida)
  • fijar la migración (incluyendo deshacer los cambios en el down)
  • intentarlo de nuevo

OK, gente, aquí es cómo hacerlo en realidad. No sé lo que las respuestas anteriores están hablando.

  1. Figura saber qué parte de la migración hasta trabajó. Comentar ésos hacia fuera.
  2. También comente / quitar la parte de la migración que se rompió.
  3. Ejecutar de nuevo la migración. Ahora va a completar las partes no roto de la migración, omitiendo las partes que ya se han hecho.
  4. Elimine los bits de la migración Ha comentado a cabo en el paso 1.

Puede migrar hacia abajo y una copia de seguridad de nuevo si desea verificar que lo tienes en este momento.

Estoy de acuerdo que se debe utilizar PostgreSQL cuando sea posible. Sin embargo, cuando le pegan con MySQL, puede evitar la mayoría de estos problemas al tratar la migración de su base de datos de prueba primero:

rake db:migrate RAILS_ENV=test

Puede volver al estado anterior e inténtelo de nuevo con

rake db:schema:load RAILS_ENV=test

En 2015, con Rails 4.2.1 y MySQL 5.7, una migración fallida no se puede solucionar con acciones rastrillo estándar que proporcionan los carriles, como lo fue en 2009.

MySQL no soporta la reversión de statments DDL (en MySQL 5.7 Manual ). Rieles y no pueden hacer nada con eso.

Además, podemos comprobar cómo los carriles está haciendo el trabajo: Una migración es envuelto en una transacción dependiendo de cómo responden adaptador de conexión a :supports_ddl_transactions?. Después de una búsqueda de esta acción en los carriles de la fuente (v 4.2.1), encontré que sólo Sqlite3 y PostgreSql soporta transacciones, y por no se admite por defecto él.

Editar Por lo tanto la respuesta actual a la pregunta original:. Una migración de MySQL no debe fijarse manualmente

La forma más fácil de hacer esto es envolver todas sus acciones en una transacción:

class WhateverMigration < ActiveRecord::Migration

 def self.up
    ActiveRecord::Base.transaction do
...
    end
  end

  def self.down
    ActiveRecord::Base.transaction do
...
    end
  end

end

Como se señaló Lucas Francl, "MySql [ 's tablas MyISAM no] transacciones de apoyo." - que es por qué es posible considerar evitar MySQL en general, o al menos MyISAM, en particular

Si está utilizando InnoDB de MySQL, y luego lo anterior funcionará bien. Cualquier error en arriba o hacia abajo se echarse atrás.

ser conscientes algunos tipos de acciones no pueden ser revertidos a través de transacciones. Generalmente, los cambios de mesa (dejando caer una mesa, la eliminación o la adición de columnas, etc.) no se pueden revertir.

Ejecutar sólo la migración hacia abajo desde la consola:

http: //gilesbowkett.blogspot .com / 2007/07 / cómo-a-uso-migraciones-de-console.html (clic a través de su pastie)

Yo tenía un error tipográfico (en "add_column"):

  

def self.up

add_column :medias, :title, :text
add_colunm :medias, :enctype, :text
     

end

     

def self.down

remove_column :medias, :title
remove_column :medias, :enctype   
     

end

y entonces su problema (no puede deshacer la migración en parte fallado). después de algunos no buscando en Google me encontré esto:

  

def self.up

remove_column :medias, :title
add_column :medias, :title, :text
add_column :medias, :enctype, :text
     

end

     

def self.down

remove_column :medias, :title
remove_column :medias, :enctype
     

end

como se puede ver me acaba de agregar la línea de corrección a mano, y luego se retira de nuevo, antes de que yo lo haya facturado.

La respuesta de Alejandro Babio anterior proporciona la mejor respuesta actual.

Un detalle adicional Quiero añadir:

Cuando la migración myfailedmigration falla, no se considera en su aplicación, y esto puede ser verificada mediante la ejecución de rake db:migrate:status, que mostraría una salida similar a la siguiente:

$  rake db:migrate:status
database: sample_app_dev

 Status   Migration ID    Migration Name
--------------------------------------------------
   up      20130206203115  Create users
   ...
   ...
   down    20150501173156  Test migration

El efecto residual de add_column :assets, :test, :integer siendo ejecutado en la migración no tendrá que ser revertido a nivel de base de datos con una consulta alter table assets drop column test;.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top