InnoDB の更新は行ロックであり、MyISAM の更新はテーブルロックであることは誰もが知っていますが、これをどのように説明しますか? 問題が発生している最中の SHOW FULL PROCESSLIST の結果を次に示します。
╔═════════╦════════╦═════════╦════════════════════════════════╗
║ Command ║ Time ║ State ║ Info ║
╠═════════╬════════╬═════════╬════════════════════════════════╣
║ Query ║ 0 ║ NULL ║ SHOW FULL PROCESSLIST ║
║ Query ║ 121 ║ end ║ UPDATE [InnoDB table] ║
║ Query ║ 121 ║ update ║ INSERT INTO [MyISAM table] ║
║ Query ║ 121 ║ Locked ║ INSERT INTO [MyISAM table] ║
║ Query ║ 120 ║ Locked ║ INSERT INTO [MyISAM table] ║
║ Query ║ 120 ║ Locked ║ INSERT INTO [MyISAM table] ║
╚═════════╩════════╩═════════╩════════════════════════════════╝
スペースを節約するために、いくつかの列を省略しました。上記はすべて 1 つのデータベースで発生し、単一の InnoDB テーブルと単一の MyISAM テーブルを参照します。この下には、下の 3 つと同様の行が他にもたくさんありましたが、ここでも除外しました。
問題は、MyISAM テーブルをロックしているように見える InnoDB テーブルの UPDATE によって開始されます。毎秒何百もの SELECT クエリが発生し、スタックしていないため、データベース全体はロックされていません。最初の INSERT の状態は「更新」であることに注意してください。これはおそらく、その後の挿入がロックされる原因となっていると思われます。自動インクリメント?テーブルのインデックス? おそらく。しかし、なぜそのような更新が別のテーブルの UPDATE によってブロックされるのでしょうか? 状態の意味の詳細については、こちらを参照してください。
http://dev.mysql.com/doc/refman/5.1/en/general-thread-states.html
これが私がこれまでに理解したものです:
- クエリに問題はありません。UPDATE は適切にインデックス化されており、INSERT クエリと UPDATE クエリの実行には通常 100 ミリ秒未満かかりますが、ご覧のとおり、これは 2 分以上かかっています。
- データベースで実行されるほとんどすべてのクエリは SELECT と INSERT です。UPDATE は例外です。
- 問題を引き起こすのは間違いなくUPDATEであり、半複製可能です-同様のクエリを実行すると、問題が再現される場合があり、通常どおり迅速に実行される場合があります。
- データベース内の他の InnoDB テーブルが問題なく更新されるという点で、問題があると思われるのはこの特定の InnoDB テーブルだけですが、それは最大であり、〜 100 万行を含み、サイズは〜 40 MB です。
- UPDATE は複数のサーバーに複製されますが、長い実行時間は負荷が大きいサーバーでのみ発生するようです。
- 問題が発生している間、サーバーの CPU 負荷と空き RAM を確認しましたが、どちらも問題ありません。
サーバー仕様:
- Debian スクイーズ
- MySQL 5.1
- 8コア
- 32GBのRAM
質問する前に、[mysqld] 構成設定の一部を次に示します。
skip-external-locking
innodb_file_per_table
innodb_flush_method = O_DIRECT
innodb_buffer_pool_size = 512M
key_buffer = 1500M
read_rnd_buffer_size = 512k
table_open_cache = 4096
tmp_table_size = 256M
max_heap_table_size = 256M
concurrent_insert = 2
max_allowed_packet = 16M
thread_stack = 192K
thread_cache_size = 8
max_connections = 2000
open_files_limit = 60000
query_cache_limit = 1M
query_cache_size = 512M
大規模なグーグル検索の後、私はまだ途方に暮れているので、どんな助けも感謝して受け取ります!
追加した
InnoDB テーブルの構文を作成します。
CREATE TABLE `tablename` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`column1` bigint(20) unsigned NOT NULL,
`column2` int(10) unsigned NOT NULL,
`column3` int(10) unsigned NOT NULL,
`column4` int(10) unsigned NOT NULL,
`column5` int(10) unsigned DEFAULT NULL,
`column6` enum('yes','no') NOT NULL DEFAULT 'no',
PRIMARY KEY (`id`),
UNIQUE KEY (`column1`),
KEY (`column2`),
KEY (`column5`)
) ENGINE=InnoDB AUTO_INCREMENT=993266 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;