Cơ sở dữ liệu MySQL InnoDB 'treo' trên các lựa chọn


10

Tôi đang cố gắng sửa cấu hình MySQL trên máy chủ của chúng tôi. Chi tiết cụ thể của ứng dụng của chúng tôi là rất nhiều dữ liệu được lưu trữ trong một bảng (hiện có hơn 300 triệu hàng). Bảng này được sử dụng thường xuyên để chèn (chúng luôn luôn xuất hiện).

Khi tôi chạy một truy vấn chọn trên bảng đó mất nhiều thời gian hơn vài giây thì tất cả các phần chèn (cam kết chính xác) đang chờ truy cập bảng và làm cho ứng dụng của chúng tôi không phản hồi.

Theo như tôi biết thì InnoDB không thực hiện bất kỳ khóa nào trên bàn khi chọn đang chạy. Tại sao bảng chặn chọn sau đó?

Tôi đã cố gắng tìm một lý do với innotop nhưng tôi không chắc làm thế nào để diễn giải đầu ra của nó và nơi để tìm kiếm. Hãy cho tôi biết những gì bạn cần và tôi sẽ đăng nó ở đây.

+-----+---------+-----------+--------+---------+------+----------------+-----------------------------------------------------------------------------------------------------------------------------------+
| Id  | User    | Host      | db     | Command | Time | State          | Info                                                                                                                              |
+-----+---------+-----------+--------+---------+------+----------------+-----------------------------------------------------------------------------------------------------------------------------------+
|   1 | root    | localhost | dbname | Query   |   29 | NULL           | COMMIT                                                                                                                            | 
|   2 | root    | localhost | dbname | Query   |   30 | NULL           | COMMIT                                                                                                                            | 
|   4 | root    | localhost | dbname | Query   |   29 | NULL           | COMMIT                                                                                                                            | 
|   5 | root    | localhost | dbname | Query   |   29 | NULL           | COMMIT                                                                                                                            | 
|   6 | root    | localhost | dbname | Query   |   25 | NULL           | COMMIT                                                                                                                            | 
|   7 | root    | localhost | dbname | Query   |    0 | NULL           | show full processlist                                                                                                             | 
|  13 | user    | localhost | dbname | Query   |   25 | NULL           | COMMIT                                                                                                                            | 
|  38 | user    | localhost | dbname | Sleep   |    0 |                | NULL                                                                                                                              | 
|  39 | user    | localhost | dbname | Sleep   | 9017 |                | NULL                                                                                                                              | 
|  40 | user    | localhost | dbname | Query   |   33 | Sorting result | SELECT * FROM `large_table` WHERE (`large_table`.`hotspot_id` = 3000064)  ORDER BY discovered_at LIMIT 799000, 1000 | 
|  60 | user    | localhost | dbname | Sleep   | 1033 |                | NULL                                                                                                                              | 
|  83 | root    | localhost | dbname | Sleep   | 3728 |                | NULL                                                                                                                              | 
| 112 | root    | localhost | NULL   | Sleep   |    6 |                | NULL                                                                                                                              | 
+-----+---------+-----------+--------+---------+------+----------------+-----------------------------------------------------------------------------------------------------------------------------------+


=====================================
110824 12:24:24 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 19 seconds
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 1521117, signal count 1471216
Mutex spin waits 0, rounds 20647617, OS waits 239914
RW-shared spins 2119697, OS waits 1037149; RW-excl spins 505734, OS waits 218177
------------
TRANSACTIONS
------------
Trx id counter 0 412917332
Purge done for trx's n:o < 0 412917135 undo n:o < 0 0
History list length 48
Total number of lock structs in row lock hash table 5
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0 0, not started, process no 28363, OS thread id 1092766032
MySQL thread id 83, query id 3249941 localhost root
---TRANSACTION 0 412901582, not started, process no 28363, OS thread id 1144449360
MySQL thread id 60, query id 3677008 localhost user
---TRANSACTION 0 412917189, not started, process no 28363, OS thread id 1144314192
MySQL thread id 43, query id 3905773 localhost root
---TRANSACTION 0 412534255, not started, process no 28363, OS thread id 1092630864
MySQL thread id 39, query id 14279 localhost user
---TRANSACTION 0 412917331, not started, process no 28363, OS thread id 1144179024
MySQL thread id 38, query id 3908045 localhost user
---TRANSACTION 0 412917201, not started, process no 28363, OS thread id 1092495696
MySQL thread id 13, query id 3908257 localhost user
---TRANSACTION 0 412538821, not started, process no 28363, OS thread id 1092360528
MySQL thread id 7, query id 3908258 localhost root
show engine innodb status
---TRANSACTION 0 412917330, ACTIVE 6 sec, process no 28363, OS thread id 1144043856
2 lock struct(s), heap size 368, undo log entries 1
MySQL thread id 2, query id 3907373 localhost root
COMMIT
Trx read view will not see trx with id >= 0 412917331, sees < 0 412917131
---TRANSACTION 0 412917328, ACTIVE 6 sec, process no 28363, OS thread id 1092225360
2 lock struct(s), heap size 368, undo log entries 1
MySQL thread id 6, query id 3907345 localhost root
COMMIT
Trx read view will not see trx with id >= 0 412917329, sees < 0 412917131
---TRANSACTION 0 412917326, ACTIVE 6 sec, process no 28363, OS thread id 1091955024
2 lock struct(s), heap size 368, undo log entries 1
MySQL thread id 4, query id 3907335 localhost root
COMMIT
Trx read view will not see trx with id >= 0 412917327, sees < 0 412917131
---TRANSACTION 0 412917324, ACTIVE 6 sec, process no 28363, OS thread id 1092090192
2 lock struct(s), heap size 368, undo log entries 1
MySQL thread id 5, query id 3907328 localhost root
COMMIT
Trx read view will not see trx with id >= 0 412917325, sees < 0 412917131
---TRANSACTION 0 412917321, ACTIVE (PREPARED) 7 sec, process no 28363, OS thread id 1143908688 preparing
2 lock struct(s), heap size 368, undo log entries 1
MySQL thread id 1, query id 3907125 localhost root
COMMIT
Trx read view will not see trx with id >= 0 412917322, sees < 0 412917131
---TRANSACTION 0 412917131, ACTIVE 20 sec, process no 28363, OS thread id 1074075984, thread declared inside InnoDB 111
mysql tables in use 1, locked 0
MySQL thread id 40, query id 3904958 localhost user Sorting result
SELECT * FROM `large_table` WHERE (`large_table`.`hotspot_id` = 3000064)  ORDER BY discovered_at LIMIT 848000, 1000
Trx read view will not see trx with id >= 0 412917132, sees < 0 412917132
--------
FILE I/O
--------
I/O thread 0 state: waiting for i/o request (insert buffer thread)
I/O thread 1 state: waiting for i/o request (log thread)
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (write thread)
Pending normal aio reads: 0, aio writes: 0,
 ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
Pending flushes (fsync) log: 1; buffer pool: 0
3510225 OS file reads, 284998 OS file writes, 202897 OS fsyncs
1.05 reads/s, 21299 avg bytes/read, 8.10 writes/s, 7.58 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 275, free list len 13392, seg size 13668,
489950 inserts, 491830 merged recs, 10986 merges
Hash table size 8850487, used cells 8127172, node heap has 32697 buffer(s)
71914.53 hash searches/s, 8701.91 non-hash searches/s
---
LOG
---
Log sequence number 157 3331524445
Log flushed up to   157 3331521939
Last checkpoint at  157 3326072846
1 pending log writes, 0 pending chkp writes
199025 log i/o's done, 7.53 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 4788954432; in additional pool allocated 1048576
Buffer pool size   262144
Free buffers       0
Database pages     229447
Modified db pages  1439
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages read 7453325, created 14887, written 118658
1.37 reads/s, 0.11 creates/s, 0.53 writes/s
Buffer pool hit rate 1000 / 1000
--------------
ROW OPERATIONS
--------------
1 queries inside InnoDB, 0 queries in queue
7 read views open inside InnoDB
Main thread process no. 28363, id 1091684688, state: flushing log
Number of rows inserted 1093064, updated 249134, deleted 1405, read 1115880534
7.89 inserts/s, 2.47 updates/s, 0.05 deletes/s, 80953.21 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================

BIÊN TẬP:

Cảm ơn đã làm rõ điều này.

Vì vậy, tôi phải chia câu hỏi của tôi thành hai trường hợp bây giờ.

  1. Có phải bình thường rằng khóa trên bảng đơn này khiến toàn bộ ứng dụng của tôi bị 'treo'. DB không nên phản hồi cho các truy vấn đến các bảng khác? Có lẽ một số bộ đệm được đặt quá thấp?

  2. Sẽ chuyển bảng này sang MyISAM giúp đỡ? Tôi không cần giao dịch trên bảng này cả. Sẽ không có khóa nào khác trong tình huống như vậy (chọn lâu + nhiều lần chèn nhanh)?

EDIT2:

Đó là cách các truy vấn chèn trông như thế nào:

INSERT INTO `large_table` (`device_address`, `hotspot_id`, `minute`, `created_at`, `updated_at`, `discovered_with_hci`, `hour`, `rssi`, `day`, `device_class`, `discovered_at`) VALUES('10:40:03:90:10:40', 3000008, 1, '2011-08-22 05:01:08', '2011-08-22 05:01:08', -1, 5, -79, '2011-08-22 05:01:01', '0', '2011-08-22 05:01:01')

Đó là những chỉ số được định nghĩa trên đó:

+-------------+------------+----------------------------------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table       | Non_unique | Key_name                                     | Seq_in_index | Column_name         | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------------+------------+----------------------------------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+
| large_table |          0 | PRIMARY                                      |            1 | id                  | A         |    92396334 |     NULL | NULL   |      | BTREE      |         | 
| large_table |          1 | index_large_table_on_discovered_with_hci     |            1 | discovered_with_hci | A         |          18 |     NULL | NULL   | YES  | BTREE      |         | 
| large_table |          1 | index_large_table_on_hotspot_id              |            1 | hotspot_id          | A         |          18 |     NULL | NULL   | YES  | BTREE      |         | 
| large_table |          1 | index_large_table_on_day_and_hour_and_minute |            1 | day                 | A         |          18 |     NULL | NULL   | YES  | BTREE      |         | 
| large_table |          1 | index_large_table_on_day_and_hour_and_minute |            2 | hour                | A         |          18 |     NULL | NULL   | YES  | BTREE      |         | 
| large_table |          1 | index_large_table_on_day_and_hour_and_minute |            3 | minute              | A         |      537187 |     NULL | NULL   | YES  | BTREE      |         | 
| large_table |          1 | index_large_table_on_created_at              |            1 | created_at          | A         |     8399666 |     NULL | NULL   | YES  | BTREE      |         | 
| large_table |          1 | index_large_table_on_rssi                    |            1 | rssi                | A         |          18 |     NULL | NULL   | YES  | BTREE      |         | 
+-------------+------------+----------------------------------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+

EDIT 3:

Tại sao trong các truy vấn như vậy, toàn bộ ứng dụng của tôi không phản hồi? Nó có nên chỉ ảnh hưởng đến 'Large_table' không?

Có lẽ có gì đó không ổn với cấu hình mysql của tôi? Máy chủ là 4 nhân Xeon 2GHz với 16GB RAM. Nó chạy ứng dụng MySQL + Rails

Thông số cấu hình của tôi:

skip-external-locking
key_buffer              = 64M
max_allowed_packet      = 16M
thread_stack            = 128K
thread_cache_size       = 8
query_cache_size        = 32M
tmp_table_size          = 64M
max_heap_table_size     = 64M
table_cache             = 256
read_rnd_buffer_size    = 512K
sort_buffer_size        = 2M

myisam-recover          = BACKUP
max_connections         = 200

query_cache_limit       = 1M

long_query_time = 200

max_binlog_size         = 100M

innodb_buffer_pool_size = 4G
safe-updates
max_join_size=100000000

Kịch bản Mysqltuner chỉ đề xuất:

long_query_time (<= 10)
innodb_buffer_pool_size (>= 62G)

Vui lòng nối đầu ra của show engine innodb status;.
lượng tử

Trong innotop, bạn có thể nhấn L để có được chế độ xem vào ổ khóa. Làm thế nào để ứng dụng của bạn thiết lập một kết nối? JDBC? Mức độ defaultTransactionIsolation nào bạn đang sử dụng?
HTTP500

Đây là một ứng dụng RoR vì vậy tôi đoán nó là mặc định cho MySQL (tôi có thể kiểm tra bằng cách nào đó bằng truy vấn SQL không?). innotop không hiển thị bất kỳ ổ khóa nào trong khi lựa chọn này chạy.
kaczor1984

@ kaczor1984 Bạn có thể kiểm tra mức cô lập mặc định bằng cách thực hiện: hiển thị các biến như 'tx_isolation'; truy vấn. Mặc định là REPEATABLE READ. Lưu ý rằng MVCC chỉ hoạt động với REPEATABLE READ và READ CAM KẾT. Không chắc giải pháp cho vấn đề của bạn là gì nhưng câu trả lời của RolandoMySQLDBA là thông tin.
HTTP500

Đã cập nhật câu trả lời của tôi với phân tích truy vấn tại Process ID 40
RolandoMySQLDBA

Câu trả lời:


15

Vui lòng xem kỹ danh sách quy trình và 'hiển thị trạng thái innodb'. Bạn thấy gì ???

ID tiến trình 1,2,4,5,6,13 đều đang cố gắng chạy CAM KẾT.

Ai đang giữ tất cả mọi thứ ??? ID tiến trình 40 đang chạy một truy vấn đối với Large_table.

Quá trình ID 40 đã chạy trong 33 giây. ID tiến trình 1,2,4,5,6,13 đã chạy dưới 33 giây. Quá trình ID 40 đang xử lý một cái gì đó. Cái gì giữ lấy ???

Trước hết, truy vấn đang dồn nén vào chỉ mục được nhóm của Large_table thông qua MVCC .

Trong ID tiến trình 1,2,4,5,6,13 là các hàng có Dữ liệu MVCC bảo vệ sự cô lập giao dịch của nó. Process ID 40 có một truy vấn đang di chuyển qua các hàng dữ liệu. Nếu có một chỉ mục trên trường hotspot_id, khóa đó + khóa cho hàng thực tế từ chỉ mục được nhóm phải thực hiện khóa nội bộ. (Lưu ý: Theo thiết kế, tất cả các chỉ mục không duy nhất trong InnoDB đều mang cả khóa của bạn (cột mà bạn muốn lập chỉ mục) + khóa chỉ mục được nhóm). Kịch bản độc đáo này về cơ bản là Lực lượng không thể ngăn cản đáp ứng Đối tượng bất động.

Về bản chất, các CAM KẾT phải đợi cho đến khi an toàn để áp dụng các thay đổi đối với Large_table. Tình huống của bạn không phải là duy nhất, không phải là một lần, không phải là một hiện tượng hiếm gặp.

Tôi thực sự đã trả lời ba câu hỏi như thế này trong DBA StackExchange. Các câu hỏi đã được gửi bởi cùng một người liên quan đến cùng một vấn đề. Câu trả lời của tôi không phải là giải pháp nhưng đã giúp người gửi câu hỏi tự đưa ra kết luận về cách xử lý tình huống của mình.

Ngoài những câu trả lời đó, tôi đã trả lời câu hỏi của người khác về những bế tắc trong InnoDB liên quan đến CHỌN .

Tôi hy vọng bài viết trước đây của tôi về chủ đề này giúp làm rõ những gì đang xảy ra với bạn.

CẬP NHẬT 2011-08-25 08:10 EDT

Đây là truy vấn từ Process ID 40

SELECT * FROM `large_table`
WHERE (`large_table`.`hotspot_id` = 3000064)
ORDER BY discovered_at LIMIT 799000, 1000;

Hai quan sát:

  • Bạn đang làm 'CHỌN *' bạn có cần tìm nạp mọi cột không? Nếu bạn chỉ cần các cột cụ thể, bạn nên gắn nhãn cho chúng vì bảng tạm thời gồm 1000 hàng có thể lớn hơn bạn thực sự cần.

  • Các mệnh đề WHERE và ORDER BY thường đưa ra các vấn đề về hiệu năng hoặc làm cho thiết kế bảng tỏa sáng. Bạn cần tạo một cơ chế giúp tăng tốc độ thu thập các khóa trước khi thu thập dữ liệu.

Theo hai quan sát này, có hai thay đổi lớn bạn phải thực hiện:

THAY ĐỔI CHỦ YẾU # 1: Tái cấu trúc truy vấn

Thiết kế lại truy vấn sao cho

  1. Các khóa được thu thập từ chỉ mục
  2. chỉ 1000 hoặc họ được thu thập
  3. tham gia trở lại bàn chính

Đây là truy vấn mới thực hiện ba điều này

SELECT large_table.* FROM
large_table INNER JOIN
(
    SELECT hotspot_id,discovered_at
    FROM large_table
    WHERE hotspot_id = 3000064
    ORDER BY discovered_at
    LIMIT 799000,1000
) large_table_keys
USING (hotspot_id,discovered_at);

Truy vấn con Large_table_keys thu thập 1000 khóa bạn cần. Kết quả từ truy vấn con sau đó được THAM GIA thành big_table. Cho đến nay, các khóa được lấy thay vì toàn bộ hàng. Đó vẫn là 799.000 hàng để đọc qua. Có một cách tốt hơn để có được những chìa khóa đó, dẫn chúng ta đến ...

THAY ĐỔI CHỦ YẾU # 2: Tạo các Chỉ mục hỗ trợ Truy vấn được cấu trúc lại

Vì truy vấn được cấu trúc lại chỉ có một truy vấn con, nên bạn chỉ cần tạo một chỉ mục. Đây là chỉ số:

ALTER TABLE large_table ADD INDEX hotspot_discovered_ndx (hotspot_id,discovered_at);

Tại sao chỉ số đặc biệt này? Nhìn vào mệnh đề WHERE. Hotspot_id là một giá trị tĩnh. Điều này làm cho tất cả các hotspot_ids tạo thành một danh sách tuần tự trong chỉ mục. Bây giờ, hãy nhìn vào mệnh đề ORDER BY. Cột Discover_at có thể là trường DATETIME hoặc TIMESTAMP.

Thứ tự tự nhiên này thể hiện trong chỉ mục như sau:

  • Chỉ mục có một danh sách các hostpot_ids
  • Mỗi hotspot_id có một danh sách theo thứ tự các trường được khám phá

Tạo chỉ mục này cũng giúp loại bỏ việc sắp xếp nội bộ các bảng tạm thời.

Vui lòng đặt hai thay đổi lớn này và bạn sẽ thấy sự khác biệt về thời gian chạy.

Hãy thử một lần !!!

CẬP NHẬT 2011-08-25 08:15 EDT

Tôi nhìn vào chỉ số của bạn. Bạn vẫn cần tạo chỉ mục tôi đề xuất.


Cảm ơn cho một lời giải thích lớn làm thế nào nó hoạt động. Tôi sợ tôi không thể tìm ra cách tránh những tình huống như thế. Chèn phải sửa đổi chỉ mục và chọn phải sử dụng chỉ mục trên hotspot_id và Discovery_at. Tôi rất vui nếu bạn cũng có thể hiểu được 'ý tưởng' của tôi về việc chuyển sang MyISAM.
kaczor1984

Trên thực tế, việc sử dụng MyISAM có thể khiến mọi thứ trở nên tồi tệ hơn vì mỗi CHERTN, CẬP NHẬT và XÓA trong MyISAM sẽ kích hoạt khóa bảng đầy đủ. Ngay cả khi bạn sử dụng CHỨNG CHỈ THẤP HẤP DẪN hoặc BỊ XÓA, thì vẫn có thể gặp phải khóa toàn bộ bảng. Bạn nên tự khám phá truy vấn vì bất kể công cụ lưu trữ, các truy vấn có thể được điều chỉnh xung quanh các chướng ngại vật đó. Ít nhất, một thuật toán mới hoàn toàn có thể được yêu cầu. Tôi sẽ xem xét truy vấn trong vài phút nữa ...
RolandoMySQLDBA

Tôi đã cập nhật bài viết đầu tiên của mình để bạn có thể thấy các truy vấn và chỉ mục chèn trên bảng này.
kaczor1984

Đã cập nhật câu trả lời của tôi với phân tích truy vấn tại Process ID 40
RolandoMySQLDBA

4
bạn là một anh hùng trong số những người đàn ông vì câu trả lời dài của bạn
Mike

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.