Laravel Ошибка миграции при откате

mstdmstd

Новичок
Всем привет,
В Laravel5.5 делаю миграцию с 2мя полями и индексом:

PHP:
<?php

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

class ModifyTaskAssignedToUsersIsLeaderStatus extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        try {
            DB::beginTransaction();

            Schema::table('task_assigned_to_users', function (Blueprint $table) {
                $table->enum('status', ['A', 'C', 'N'])->comment(' A=>Accepted, C=>Canceled, N-New(Waiting for acception)')->after('user_id');
                $table->boolean('is_leader')->default(false)->after('status');
                $table->index(['task_id', 'status', 'is_leader'], 'task_assigned_to_users_task_id_status_is_leader_index');
            });

        } catch (Exception $e) {

            DB::rollBack();
            throw $e;
        }
        DB::commit();
      
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        try {
            DB::beginTransaction();

            Schema::table('task_assigned_to_users', function (Blueprint $table) {
                $table->dropIndex('task_assigned_to_users_task_id_status_is_leader_index');
                $table->dropColumn('status');
                $table->dropColumn('is_leader');
            });

        } catch (Exception $e) {

            DB::rollBack();
            throw $e;
        }
        DB::commit();

    }
}
Которая успешно создается, но при выполнении отката ошибка(в мигарциях я стараюсь выполнять и откат для тестирования):

PHP:
$ php artisan migrate:rollback

In Connection.php line 664:
                                                                                                                                                                                                                                          
  SQLSTATE[HY000]: General error: 1553 Cannot drop index 'task_assigned_to_users_task_id_status_is_leader_index': needed in a foreign key constraint (SQL: alter table `tsk_task_assigned_to_users` drop index `task_assigned_to_users_task_id_status_is_leader_index`)                                                                                                                                                                                                             
                                                                                                                                                                                                                                          

In PDOStatement.php line 107:                                                                                                                                                     
  SQLSTATE[HY000]: General error: 1553 Cannot drop index 'task_assigned_to_users_task_id_status_is_leader_index': needed in a foreign key constraint
                                                                                                                                                    

In PDOStatement.php line 105:                                                                                                                                                     
  SQLSTATE[HY000]: General error: 1553 Cannot drop index 'task_assigned_to_users_task_id_status_is_leader_index': needed in a foreign key constraint
В откате индекс указан первым
Поле task_id - это ссылка на tasks таблицу Не пойму почему ошибка и как это сиправить ?


Спасибо !
 

fixxxer

К.О.
Партнер клуба
@mstdmstd, https://laravel.com/docs/5.5/migrations#foreign-key-constraints см. dropForeign. Я, правда, не понял, откуда вообще FK взялся. Если ты ручками его сделал - не делай так, все должно быть в миграциях.

DDL запросы, которые обычно в миграциях, не откатываются во многих СУБД
А где еще, кроме mysql старше 8-й версии? (По сообщению об ошибке, конечно, понятно, что у него мыскль, и вряд ли это бета восьмерки, но все же).
 
Последнее редактирование:

Adelf

Administrator
Команда форума

fixxxer

К.О.
Партнер клуба

mstdmstd

Новичок
У меня mysql 5.7.20-0ubuntu0.17.10.1.
Насчет транзакций, похоже да, не всегда срабатывают.
Я нагуглил такой способ - но часто вижу что, если ошибка то транзакция есть в логе, но отката нет.

И насчет логов : В моем app/Providers/AppServiceProvider.php я прописал трассировку запросов, включая транзакции:

PHP:
public function boot()
{
...
if ($this->app->environment('local')) {

\Event::listen(
[
TransactionBeginning::class,
],
...
\Event::listen(
[
TransactionCommitted::class,
],
function ($event) {
...

\DB::listen(function($query) {

А нет возможности трассировать запросы миграции? Интересно было бы посмотреть ...
 

MiksIr

miksir@home:~$
А где еще, кроме mysql старше 8-й версии? (По сообщению об ошибке, конечно, понятно, что у него мыскль, и вряд ли это бета восьмерки, но все же).
А разве в мускуле 8 откатываются? Они там атомарны стали, это да, но откатываться вроде все еще не умеют.
 

s4devel

Новичок
Всем привет,
В Laravel5.5 делаю миграцию с 2мя полями и индексом:
Всем привет!

На сколько я понял, в предыдущих миграциях на поле task_assigned_to_users.task_id было наложено ограничение внешнего ключа. При этом в MySQL неявно (автоматически) создается индекс по данному полю, который является частью этого ограничения.

В миграции вы создаете новый составной индекс task_assigned_to_users_task_id_status_is_leader_index в котором поле task_id указано первым. При этом MySQL заменит неявно созданный при создании ограничения внешнего ключа индекс по полю task_id на явно создаваемый task_assigned_to_users_task_id_status_is_leader_index и ограничение внешнего ключа будет использовать его.

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

Для корректного отката миграции можно поступить так:
1. Удаляем ограничение внешнего ключа.
2. Удаляем индекс.
3. Восстанавливаем ограничение внешнего ключа.
т.о. полностью возвращаемся к состоянию до миграции.

PHP:
public function down()
{
    Schema::table('task_assigned_to_users', function (Blueprint $table) {
        $table->dropForeign(['task_id']);
    });

    Schema::table('task_assigned_to_users', function (Blueprint $table) {
        $table->dropIndex('task_assigned_to_users_task_id_status_is_leader_index');
    });

    Schema::table('task_assigned_to_users', function (Blueprint $table) {
        $table->foreign('task_id')->references('id')->on('tasks');
    });
}
 
Сверху