Подтвердить что ты не робот

Блокировка ожидания блокировки MySQL с использованием фабрик моделей

У меня очень маленький набор данных, сгенерированный в методе тестового класса, я попытался получить данные, сгенерированные в методе setUp(), но это привело к тайм-ауту ожидания блокировки для каждого теста. Перемещение этого кода из метода setUp() и включение его в свой собственный метод помогли немного. Это означает, что не каждый тест жалуется на блокировки.

Я использую свойство DatabaseTransactions, которое находится в Laravel 5.2, так что база данных reset перед запуском каждого тестового примера.

В каждом тестовом случае, который у меня есть, я делаю звонок, чтобы получить данные макета, подобные этому.

$data = self::getRandomCommunityWithAssociatedData();

Фактический метод генерирует только несколько объектов сообщества и пользовательских объектов для созданного сообщества.

public static function getRandomCommunityWithAssociatedData()
{
    self::$communities = factory(\Community::class, self::COMMUNITIES_TO_CREATE)->create()->each(function ($community) {
        self::$users[$community->id] = factory(User::class, self::USERS_TO_CREATE)->create()->each(function (\User $user) use ($community) {
            $user->community()->associate($community);
        });

        self::$admins[$community->id] = factory(User::class, 'superadmin', self::ADMINS_TO_CREATE)->create()->each(function (\User $admin) use ($community) {
            $admin->community()->associate($community);
        });
    });

    $community = self::$communities[mt_rand(0, count(self::$communities) - 1)];

    return ['community' => $community, 'users' => self::$users[$community->id], 'admins' => self::$admins[$community->id]];
}

В этом методе используется несколько констант, и они используются для определения того, сколько из каждого создаваемого объекта. В настоящее время я создаю 2 сообщества и 3 пользователей и 2 администратора для каждого экземпляра сообщества.

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

Я попытался увеличить время, в течение которого MySQL ждет блокировки до 500 секунд, и я все еще получаю таймауты. Увеличение этого времени на самом деле не является вариантом, потому что тесты должны быть доступны во всех средах.

Любые мысли о том, почему я могу получить эти блокировки ожидания ожидания при использовании свойства DatabaseTransactions в Laravel 5.2 с таким небольшим набором данных?

1) UserEmailNotificationsTest::testActiveAdminReceivesNewCommentEmailNotification
Illuminate\Database\QueryException: SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction (SQL: insert into `communities` (`

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

Включен журнал запросов, результаты.

       30 Query START TRANSACTION
       30 Query SAVEPOINT trans2
       30 Prepare   insert into `communities` (`viddler_id`, `domain`, `subdomain`, `active`, `max_seats`, `created_at`, `updated_at`, `assignment_seats`, `general_settings`, `access_settings`, `branding_settings`) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
       30 Execute   insert into `communities` (`viddler_id`, `domain`, `subdomain`, `active`, `max_seats`, `created_at`, `updated_at`, `assignment_seats`, `general_settings`, `access_settings`, `branding_settings`) values ('74', 'gaylord.com', 'qui', '1', '24', '2016-03-30 16:25:45', '2016-04-04 02:27:04', '23', 'a:11:{s:5:\"title\";s:0:\"\";s:11:\"description\";s:0:\"\";s:10:\"meta_title\";s:0:\"\";s:16:\"meta_description\";s:0:\"\";s:13:\"meta_keywords\";s:0:\"\";s:17:\"thumbnail_display\";s:0:\"\";s:18:\"group_nomenclature\";s:8:\"Channels\";s:13:\"home_template\";s:0:\"\";s:11:\"api_version\";s:1:\"2\";s:8:\"language\";s:2:\"en\";s:21:\"use_nested_navigation\";i:0;}', 'a:10:{s:12:\"restrictions\";s:10:\"Restricted\";s:17:\"auto_registration\";i:0;s:14:\"default_active\";i:0;s:12:\"oauth_google\";i:0;s:14:\"oauth_facebook\";i:0;s:14:\"oauth_linkedin\";i:0;s:16:\"oauth_reg_google\";i:0;s:18:\"oauth_reg_facebook\";i:0;s:18:\"oauth_reg_linkedin\";i:0;s:11:\"lti_enabled\";i:0;}', 'a:14:{s:13:\"contact_email\";s:0:\"\";s:17:\"contact_link_text\";s:0:\"\";s:9:\"logo_file\";s:0:\"\";s:14:\"carousel_items\";s:0:\"\";s:11:\"html_header\";s:0:\"\";s:16:\"footer_copyright\";s:45:\"© 2015 Viddler Inc. All Rights Reserved.\";s:19:\"footer_privacy_link\";s:37:\"http://www.viddler.com/privacy-policy\";s:17:\"footer_terms_link\";s:35:\"http://www.viddler.com/terms-of-use\";s:14:\"help_link_text\";s:4:\"Help\";s:9:\"help_link\";s:0:\"\";s:7:\"color_1\";s:7:\"#ffffff\";s:7:\"color_2\";s:7:\"#2C333C\";s:7:\"color_3\";s:7:\"#2C333C\";s:7:\"color_4\";s:7:\"#60a1d7\";}')
160404  9:30:25    30 Close stmt
       21 Query ROLLBACK
       21 Quit
       22 Query ROLLBACK
       22 Quit
       23 Query ROLLBACK
       23 Quit
       24 Query ROLLBACK
       24 Quit
       25 Query ROLLBACK
       25 Quit
       26 Query ROLLBACK
       26 Quit
       27 Query ROLLBACK
       27 Quit
       28 Query ROLLBACK
       28 Quit
       29 Query ROLLBACK
       29 Quit
       30 Query ROLLBACK
       30 Quit
4b9b3361

Ответ 1

Таким образом, увеличение тайм-аута ожидания блокировки не является лучшей практикой; лучшая практика - поймать ошибку и восстановить.

Официально, это то, что вы должны делать:

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