MySQL使用Model Factories锁定等待超时

Jos*_*ord 23 php mysql laravel eloquent laravel-5.2

我在测试类的方法中生成了一个非常小的数据集,我曾尝试过在setUp()方法中生成数据,但是每次测试都会导致锁定等待超时.将此代码移出setUp()方法并将其放入自己的方法中有所帮助.这意味着不是每个测试都抱怨锁.

我正在使用Laravel 5.2中的DatabaseTransactions特性,以便在每个测试用例运行之前重置数据库.

在我所拥有的每个测试用例中,我都会调用这样的模拟数据.

$data = self::getRandomCommunityWithAssociatedData();
Run Code Online (Sandbox Code Playgroud)

实际方法仅为创建的社区生成一些社区对象和用户对象.

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]];
}
Run Code Online (Sandbox Code Playgroud)

该方法中使用了一些常量,它们用于确定要创建的每个对象的数量.目前,我正在为每个社区实例创建2个社区,3个用户和2个管理员.

锁定等待超时是不可预测的,一次运行可能发生在第一个测试用例上,另一次运行可能发生在第五个测试用例上.

我试图将MySQL等待锁定的时间增加到500秒,我仍然得到超时.增加这个时间确实不是一个选择,因为测试需要能够在所有环境中运行.

在使用Laravel 5.2中的DatabaseTransactions特性和如此小的数据集时,为什么我可能会获得这些锁定等待超时的任何想法?

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

执行的上述查询是社区表上的简单插入,并且没有复杂的子查询或此数据生成中发生的任何类似的查询.

启用查询日志,结果.

       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
Run Code Online (Sandbox Code Playgroud)

小智 2

因此,增加锁等待超时并不是最佳实践;最佳实践是捕获错误并恢复

正式地,这是你应该做的:

死锁和锁等待超时在繁忙的服务器上都是正常的,应用程序有必要意识到它们可能发生并通过重试来处理它们。您可以通过在事务期间第一次更改数据和提交之间执行尽可能少的工作来降低发生这种情况的可能性,从而使锁保持尽可能短的时间和尽可能少的行数。有时,在不同事务之间分配工作可能是实用且有帮助的。