2016-04-04 23 views
23

テストクラスのメソッドで生成されるデータセットが非常に小さいため、setUp()メソッドで生成されたデータを試してみましたが、すべてのテストでロック待ちタイムアウトになっていました。このコードをsetUp()メソッドから外して、それを独自のメソッドに入れることは少し助けになりました。すべてのテストがロックについて不平を言うわけではないということを意味します。モデルファクトリを使用したMySQLロック待機タイムアウト

Laravel 5.2のDatabaseTransactions特性を使用しているため、各テストケースを実行する前にデータベースがリセットされます。

私が持っているすべてのテストケースでは、このようなモックデータを取得するための呼び出しを行います。

$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人の管理者を作成しています。

ロック待機タイムアウトは予測できません。最初のテストケースで実行されるロック待機タイムアウトは5番目のテストケースで発生する可能性があります。

私は、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` (` 

実行される上記のクエリは、コミュニティテーブル上の簡単なインサートであると複雑なサブクエリまたはそれは、このデータ生成で起こっているようなものはありません。

クエリログ、結果を有効にしました。

 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 
+0

クエリログを有効にし、どのクエリがデッドロックを引き起こすのかを調べます。タイムアウトを通常のレベルに戻す必要があります。 – DanFromGermany

+0

コミュニティテーブルへの挿入が失敗しています。上記の質問を更新して、mysqlクエリログからデータを表示しました。 –

+1

あなたの質問に答えていない間、私はテストのためだけにsqliteに移動することをお勧めします。テストの実行時間を大幅に短縮します。 – Mysteryos

答えて

2

したがって、ロック待機タイムアウトを増やすことはベストプラクティスではありません。 the best practice is to catch the error and recover

公式には、これはあなたがやるべきことです:

両方デッドロックやロック待ちタイムアウトがビジー状態のサーバー上で正常であると それは彼らが起こると それらを処理することができることを意識するアプリケーションのための必要です再試行します。 トランザクション中の最初のデータ変更とコミットの間でできるだけ少ない作業が行われる可能性があります。したがって、可能な限り最短の行数は で、ロックは最小限に抑えられます。 場合によっては 異なるトランザクション間の分割作業が実用的であり、 が役に立ちます。

関連する問題