2013-12-06 2 views
14

При разработке у меня так много проблем с миграциями в laravel.Laravel migration transaction

Я создаю миграцию. Когда я заканчиваю его создание, на середине миграции возникает небольшая ошибка (скажем, ограничение внешнего ключа), которая приводит к сбою «php artisan migrate». Он говорит мне, где ошибка, действительно, но затем миграция переходит в несовместимое состояние, где сделаны все изменения в базе данных, сделанные до ошибки, а не следующие.

Это делает это, когда я исправляю ошибку и перезапускаю migrate, первый оператор терпит неудачу, поскольку столбец/таблица уже создан/изменен. Тогда единственное решение, которое я знаю, - это перейти в мою базу данных и «откат» вручную, что намного дольше.

migrate: rollback пытается откат предыдущих миграций, так как ток не был применен успешно.

Я также попытался обернуть весь свой код в DB :: transaction(), но он все еще не работает.

Есть ли решение для этого? Или мне просто нужно постоянно перекатывать вещи?



редактировать, добавив пример (не писать код схемы строителя, просто какое-то псевдо-код):
Migration1:

Create Table users (id, name, last_name, email) 

Migration1 выполняется OK. Через несколько дней мы делаем миграция 2:

Create Table items (id, user_id references users.id) 
Alter Table users make_some_error_here 

Теперь то, что будет происходить в том, что мигрирует будут называть первое заявление и создать элементы таблицы с его внешним ключом для пользователей. Затем, когда он попытается применить следующее утверждение, это не удастся.

Если мы исправим make_some_error_here, мы не сможем выполнить миграцию, потому что созданная таблица «элементы». Мы не можем откатываться (ни обновлять, ни перезагружать), потому что мы не можем удалить пользователей таблицы, поскольку из элементов таблицы есть ограничение внешнего ключа.

Тогда единственный способ продолжения - перейти в базу данных и удалить элементы таблицы вручную, чтобы перейти в согласованное состояние.

+3

Действительно, это очень раздражает. Я также не нашел способ сделать запуск в транзакции MySQL. Кажется, он игнорирует его полностью, когда я пытаюсь. –

+1

@Blossoming_Flower, операторы DDL в MYSQL нельзя отменить. Прочтите мой ответ для получения более подробной информации и ссылок. Благодарю. –

ответ

0

Просто удалите неудавшийся код из файла миграции и создайте новую миграцию для отказавшего оператора. Теперь, когда он терпит неудачу, создание базы данных по-прежнему неповреждено, поскольку оно живет в другом файле миграции.

Другим преимуществом использования этого подхода является то, что при обращении с БД у вас больше контроля и меньших шагов.

Надежда, что помогает: D

+0

Это сработало так? Решила проблему по-другому? – DaGardner

+8

Это был рабочий стол. Но наличие миграций, которые делают несколько вещей, также полезно, я не хочу иметь 10 файлов для одного изменения базы данных. То, что я делаю сейчас, вдохновленное вашим ответом, - это когда я получаю сообщение об ошибке в середине миграции, просто закомментируйте все части, которые были выполнены правильно. Как только я исправлю ошибку, я раскомментирую ее, откат и миграцию снова, чтобы проверить, что все работает правильно. Это своего рода эффект, который вы сказали, но без создания большего количества файлов. Все еще рабочий стол. – olivarra1

+0

olivarra1, я думал, что вы правы на первом месте, но позже выясняется, что MYSQL не поддерживает транзакции в DDL. И это изменило мое мнение. Я написал отдельный ответ, чтобы объяснить свое видение. Благодарю. –

1

UPDATE: мое решение ниже фактически не работает (если вы используете Mysql, скорее всего), см комментарии. Он работает только для операторов delete/insert/update. Мой совет, как говорили другие, разделить ваши миграции на несколько миграций, которые не оставляют ничего позади, когда один не удается.


Я часто сталкивался с этой проблемой раньше.Решение состоит в том, чтобы начать транзакцию в начале вашей миграции, а также совершать все-таки работа сделана:

<?php 

use Illuminate\Database\Schema\Blueprint; 
use Illuminate\Database\Migrations\Migration; 

class UpdateUserTableAddColumnName extends Migration { 

    public function up() 
    { 
    DB::beginTransaction(); 

    Schema::table('user', function(Blueprint $table) { 
     // update your table here 
     $table->string('name') 
    }); 

    DB::commit(); 
    } 
} 

Если миграция не удается, база данных по-прежнему, как и до миграции. Даже таблица миграции не обновляется.

+0

На самом деле я все еще сталкиваюсь с нарушенными миграциями. Я не уверен, что это решение имеет значение. –

+1

Этот подход не поможет вам предотвратить неработающие транзакции, если вы используете MYSQL. Поскольку инструкции DDL в MYSQL нельзя отменить. Прочтите мой ответ для получения более подробной информации и ссылок. Благодарю. –

+0

А, я этого никогда не знал. Я был настолько смущен, почему некоторые транзакции действительно работали, а другие - нет. Иногда у меня есть ОБНОВЛЕНИЯ или ВСТАВКИ в миграции, и я думаю, что они работали. Спасибо за это, поддержал ваш ответ. –

5

Это не ограничение Laravel, я уверен, вы используете MYSQL, верно?

В MYSQL документации говорит here

Некоторые операторы не могут быть свернуты. В общем, это включают в себя данные операторов определения языка (DDL), такие как те, которые создают или сбрасывают базы данных, те, которые создают, удаляют или изменяют таблицы или сохраняют процедуры .

И у нас есть рекомендации самого Тейлора Otwell here говоря:

Мой лучший совет, чтобы сделать одну операцию за миграции, так что ваши миграции оставаться очень зернистая.

1

Как Евгений Афанасьев подчеркнул Тейлор Otwell, как говорят (но подход, который я уже взял себя): ваши миграции работают только на определенных таблиц или выполнить конкретную операцию, как добавление/удаление столбца или ключа. Таким образом, когда вы получаете неудачные миграции, которые вызывают несогласованные состояния, подобные этому, вы можете просто отбросить таблицу и снова выполнить миграцию.

Я испытал именно то, что вы описали, но пока не нашел пути вокруг него.

+0

Я так счастлив найти свое имя в том же предложении, где Тейлор Отуэлл упоминался. Спасибо, Мартин. –

3

Я использую MySql, и у меня есть эта проблема.

Мое решение зависит от того, что ваш метод down() делает именно то, что вы делаете в up(), но в обратном направлении.

Это то, что я хожу:

try{ 
    Schema::create('table1', function (Blueprint $table) { 
     //... 
    }); 
    Schema::create('tabla2', function (Blueprint $table) { 
     //... 
    }); 
}catch(PDOException $ex){ 
    $this->down(); 
    throw $ex; 
} 

Так вот, если что-то не автоматически вызывает метод down() и снова бросает исключение.

Вместо того, чтобы использовать миграцию между transaction() сделать это между этим попробовать

Смежные вопросы