web-dev-qa-db-ja.com

プロセス内でクエリを選択している間は、mysqlデータベースに書き込むことができません

Mysql 5.1.57をInnoDBで実行すると、データベースロックの問題が発生します。

1つのデータベースMySQLに接続された2つの別々のセッションがあります。最初のセッションで、テーブルAに対して長いSELECTクエリ(技術的には遅いクエリ)を実行します。次に、他の接続で、テーブルBに対して小さなUPDATEクエリを実行します。

編集:このトピックの下部で説明したように、この問題は、テーブル/クエリが完全に別のデータベースにあり、同じデータベースにあるテーブル/クエリに限定されない場合にも発生します。

何らかの理由で、テーブルBの更新は、長い選択クエリが終了するまで、同じ接続上にあるかのように完了しません。また、「PROCESS LIST」では、実行待機中に2番目のクエリが「アイテムの解放」として表示されます。

これらのクエリが同時にではなく順次実行される原因となる設定や構成の問題はありますか?

助けてくれてありがとう。

表A

CREATE TABLE `history` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `log` text NOT NULL,
  `created_at` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `user_id_idx` (`user_id`),
  CONSTRAINT `history_user_id_user_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=364398 DEFAULT CHARSET=utf8

表B

CREATE TABLE `client` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `root_id` int(11) DEFAULT NULL,  
  `salesperson_id` int(11) DEFAULT NULL,
  `name` varchar(127) DEFAULT NULL,
  `notes` text,
  `created_at` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `root_id_idx` (`root_id`),
  KEY `salesperson_id_idx` (`salesperson_id`),
  CONSTRAINT `client_root_id_client_id` FOREIGN KEY (`root_id`) REFERENCES `client` (`id`) ON DELETE CASCADE,
  CONSTRAINT `client_salesperson_id_user_id` FOREIGN KEY (`salesperson_id`) REFERENCES `user` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB AUTO_INCREMENT=757 DEFAULT CHARSET=utf8

クエリ1:

SELECT * 
FROM `history` 
WHERE log LIKE '%a%' ORDER BY log ASC LIMIT 0, 20000; // (fictitious query to replicate the issue) 

実行に約10秒かかります

クエリ2:

UPDATE `client` SET name = 'Test Name' WHERE id = 24; // hangs until query 1 is complete

MySQLバージョン情報

 + ------------------------- + ------------------ ------------ + 
 |変数名|値| 
 + ------------------------- + ---------------- -------------- + 
 | innodb_version | 1.0.16 | 
 | protocol_version | 10 | 
 |バージョン| 5.1.57-log | 
 | version_comment | MySQL Community Server(GPL)| 
 | version_compile_machine | x86_64 | 
 | version_compile_os | unknown-linux-gnu | 
 + ------------------------- + ------------ ------------------ + 

注:これはAmazon RDSサーバーです(m1.large)

グローバルInnoDB変数

 + --------------------------------- + ---------- -------------- + 
 |変数名|値| 
 + --------------------------------- + -------- ---------------- + 
 | have_innodb |はい| 
 | ignore_builtin_innodb |オン| 
 | innodb_adaptive_flushing |オン| 
 | innodb_adaptive_hash_index |オン| 
 | innodb_additional_mem_pool_size | 2097152 | 
 | innodb_autoextend_increment | 8 | 
 | innodb_autoinc_lock_mode | 1 | 
 | innodb_buffer_pool_size | 5882511360 | 
 | innodb_change_buffering |挿入| 
 | innodb_checksums |オン| 
 | innodb_commit_concurrency | 0 | 
 | innodb_concurrency_tickets | 500 | 
 | innodb_data_file_path | ibdata1:10M:autoextend | 
 | innodb_data_home_dir |/rdsdbdata/db/innodb | 
 | innodb_doublewrite |オン| 
 | innodb_fast_shutdown | 1 | 
 | innodb_file_format |アンテロープ| 
 | innodb_file_format_check |バラクーダ| 
 | innodb_file_per_table |オン| 
 | innodb_flush_log_at_trx_commit | 1 | 
 | innodb_flush_method | O_DIRECT | 
 | innodb_force_recovery | 0 | 
 | innodb_io_capacity | 200 | 
 | innodb_lock_wait_timeout | 50 | 
 | innodb_locks_unsafe_for_binlog |オフ| 
 | innodb_log_buffer_size | 8388608 | 
 | innodb_log_file_size | 134217728 | 
 | innodb_log_files_in_group | 2 | 
 | innodb_log_group_home_dir |/rdsdbdata/log/innodb | 
 | innodb_max_dirty_pages_pct | 75 | 
 | innodb_max_purge_lag | 0 | 
 | innodb_mirrored_log_groups | 1 | 
 | innodb_old_blocks_pct | 37 | 
 | innodb_old_blocks_time | 0 | 
 | innodb_open_files | 300 | 
 | innodb_read_ahead_threshold | 56 | 
 | innodb_read_io_threads | 4 | 
 | innodb_replication_delay | 0 | 
 | innodb_rollback_on_timeout |オフ| 
 | innodb_spin_wait_delay | 6 | 
 | innodb_stats_method | nulls_equal | 
 | innodb_stats_on_metadata |オン| 
 | innodb_stats_sample_pages | 8 | 
 | innodb_strict_mode |オフ| 
 | innodb_support_xa |オン| 
 | innodb_sync_spin_loops | 30 | 
 | innodb_table_locks |オン| 
 | innodb_thread_concurrency | 0 | 
 | innodb_thread_sleep_delay | 10000 | 
 | innodb_use_sys_malloc |オン| 
 | innodb_version | 1.0.16 | 
 | innodb_write_io_threads | 4 | 
 + --------------------------------- + -------- ---------------- + 

接続変数

 + ---------------------- + ------- + 
 |変数名|値| 
 + ---------------------- + ------- + 
 | max_connections | 623 | 
 | max_user_connections | 0 | 
 + ---------------------- + ------- + 

別のデータベースに問題が残っている

さらなるテストにより、まったく異なるデータベースでこの問題をすべて再現できることが示されました。これにより、テーブルのロックに関する問題がすべて解消されます。これを再現するには、1つのデータベースにテーブルA /クエリ1を設定し、完全に別のデータベース(同じサーバー上)にテーブルB /クエリ2を設定します。クエリ1が実行されている場合、クエリ2は#1が完了するまで待機してから終了します。

これは、この問題を引き起こしているサーバー全体(OSレベルのファイルロック?)があり、1つのデータベースまたはテーブルに関連していないものがあると私に思わせます。何か案は?

ユーザー許可

GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS,
REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES,
LOCK TABLES, EXECUTE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW,
CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.*
TO 'username'@'%' IDENTIFIED BY PASSWORD 'password' WITH GRANT OPTION
5
Slickrick12

AWSサポートに対処し、複数のベンチマークを実行してから1週間後、質問への答えは、RDSにはOS /ファイルシステムを通じてI/Oキャップがあり、大きなクエリがこのタイプのシナリオを適切に処理できないことです。

マイクロインスタンスであっても、この問題を標準のLAMPスタックで再現することはできませんでした。私たちは選択肢がなくなった後、私たちは彼らのサポートをAWSに向けました。

正確なデータセットを提供し、AWSがテストするためのRDSインスタンスをセットアップし、問題を再現するための正確な指示を提供しました。 RDSは問題を再現することができ、彼らのテストの後、彼らはこの答えで戻ってきました:

「RDSはこれを調査し、基本的にディスクI/O(書き込み)を使い果たしているため、2番目のクエリが遅くなります。」 ...「MySQLはこのために一時テーブルを使用するため、SELECTであるにもかかわらず、データベースが多くの書き込みを実行します。」

実際には、これはRDSによって生成されたボトルネックであるため、このシナリオは通常のMySQLインストールではなく、RDSでのみ発生する可能性があります。

結論:この問題が発生した場合は、別のデータベース設定に移動してください。

1
Slickrick12

同じ問題がありました。しかし、私たちのサーバーはクラウド内にありませんでした。

私たちのubuntu osでは、io-schedulerがCFQに設定されていました。これにより、選択元のテーブルの挿入/更新が不足しました。 io-schedulerをDEADLINEオプションに切り替えたところ、ブロッキングの問題はなくなりました。

cat /sys/block/sda/queue/scheduler

noopの予定締め切り[cfq]

echo deadline > /sys/block/sda/queue/scheduler
cat /sys/block/sda/queue/scheduler

noop予想[期限] cfq

0
Nikhil S