อินสแตนซ์ MySQL ถ่วงเวลา“ กำลังทำดัชนี SYNC”


12

ปัญหา

อินสแตนซ์ของ MySQL 5.6.20 ที่ทำงานอยู่ (ส่วนใหญ่เป็นเพียง) ฐานข้อมูลที่มีตาราง InnoDB กำลังแสดงแผงลอยเป็นครั้งคราวสำหรับการดำเนินการอัปเดตทั้งหมดเป็นระยะเวลา 1-4 นาทีกับ INSERT, UPDATE และ DELETE ทั้งหมดที่เหลืออยู่ในสถานะ "Query end" เห็นได้ชัดว่าโชคร้ายที่สุด บันทึกการสืบค้นที่ช้าของ MySQL กำลังบันทึกแม้กระทั่งแบบสอบถามที่ไม่สำคัญมากที่สุดด้วยเวลาสอบถามที่ไม่ได้ใช้งานหลายร้อยรายการที่มีการประทับเวลาเดียวกันสอดคล้องกับเวลาที่แผงลอยได้รับการแก้ไข:

# Query_time: 101.743589  Lock_time: 0.000437 Rows_sent: 0  Rows_examined: 0
SET timestamp=1409573952;
INSERT INTO sessions (redirect_login2, data, hostname, fk_users_primary, fk_users, id_sessions, timestamp) VALUES (NULL, NULL, '192.168.10.151', NULL, 'anonymous', '64ef367018099de4d4183ffa3bc0848a', '1409573850');

และสถิติอุปกรณ์แสดงเพิ่มขึ้นแม้ว่าจะไม่มีการโหลด I / O มากเกินไปในกรอบเวลานี้ (ในกรณีนี้การอัปเดตจะหยุดชะงัก 14:17:30 - 14:19:12 ตามเวลาที่บันทึกจากคำสั่งด้านบน):

# sar -d
[...]
02:15:01 PM       DEV       tps  rd_sec/s  wr_sec/s  avgrq-sz  avgqu-sz     await     svctm     %util
02:16:01 PM    dev8-0     41.53    207.43   1227.51     34.55      0.34      8.28      3.89     16.15
02:17:01 PM    dev8-0     59.41    137.71   2240.32     40.02      0.39      6.53      4.04     24.00
02:18:01 PM    dev8-0    122.08   2816.99   1633.44     36.45      3.84     31.46      1.21      2.88
02:19:01 PM    dev8-0    253.29   5559.84   3888.03     37.30      6.61     26.08      1.85      6.73
02:20:01 PM    dev8-0    101.74   1391.92   2786.41     41.07      1.69     16.57      3.55     36.17
[...]
# sar
[...]
02:15:01 PM     CPU     %user     %nice   %system   %iowait    %steal     %idle
02:16:01 PM     all     15.99      0.00     12.49      2.08      0.00     69.44
02:17:01 PM     all     13.67      0.00      9.45      3.15      0.00     73.73
02:18:01 PM     all     10.64      0.00      6.26     11.65      0.00     71.45
02:19:01 PM     all      3.83      0.00      2.42     24.84      0.00     68.91
02:20:01 PM     all     20.95      0.00     15.14      6.83      0.00     57.07

บ่อยกว่านั้นฉันสังเกตเห็นในบันทึกช้า mysql ว่าการสืบค้นที่เก่าแก่ที่สุดคือ INSERT ในตารางใหญ่ - ish (~ 10 M แถว) ตารางด้วยคีย์หลัก VARCHAR และดัชนีการค้นหาข้อความแบบเต็ม:

CREATE TABLE `files` (
  `id_files` varchar(32) NOT NULL DEFAULT '',
  `filename` varchar(100) NOT NULL DEFAULT '',
  `content` text,
  PRIMARY KEY (`id_files`),
  KEY `filename` (`filename`),
  FULLTEXT KEY `content` (`content`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

ตรวจสอบต่อไป (เช่น SHOW ENGINE สถานะ INNODB) ได้แสดงให้เห็นว่ามันแน่นอนเสมอคือการปรับปรุงตารางการใช้ดัชนีข้อความแบบเต็มซึ่งเป็นสาเหตุของคอก ส่วนธุรกรรมที่เกี่ยวข้องของ "SHOW ENGINE INNODB STATUS" มีรายการเช่นสองรายการนี้สำหรับธุรกรรมที่เก่าที่สุดที่กำลังรันอยู่:

---TRANSACTION 162269409, ACTIVE 122 sec doing SYNC index
6 lock struct(s), heap size 1184, 0 row lock(s), undo log entries 19942
TABLE LOCK table "vw"."FTS_000000000000224a_00000000000036b9_INDEX_1" trx id 162269409 lock mode IX
TABLE LOCK table "vw"."FTS_000000000000224a_00000000000036b9_INDEX_2" trx id 162269409 lock mode IX
TABLE LOCK table "vw"."FTS_000000000000224a_00000000000036b9_INDEX_3" trx id 162269409 lock mode IX
TABLE LOCK table "vw"."FTS_000000000000224a_00000000000036b9_INDEX_4" trx id 162269409 lock mode IX
TABLE LOCK table "vw"."FTS_000000000000224a_00000000000036b9_INDEX_5" trx id 162269409 lock mode IX
TABLE LOCK table "vw"."FTS_000000000000224a_00000000000036b9_INDEX_6" trx id 162269409 lock mode IX
---TRANSACTION 162269408, ACTIVE (PREPARED) 122 sec committing
mysql tables in use 1, locked 1
1 lock struct(s), heap size 360, 0 row lock(s), undo log entries 1
MySQL thread id 165998, OS thread handle 0x7fe0e239c700, query id 91208956 192.168.10.153 root query end
INSERT INTO files (id_files, filename, content) VALUES ('f19e63340fad44841580c0371bc51434', '1237716_File_70380a686effd6b66592bb5eeb3d9b06.doc', '[...]
TABLE LOCK table `vw`.`files` trx id 162269408 lock mode IX

ดังนั้นจึงมีการดำเนินการดัชนีข้อความแบบหนักอย่างหนักที่เกิดขึ้นที่นั่น ( doing SYNC index) หยุดการอัปเดตทั้งหมดลงในตารางใด ๆ

จากบันทึกดูเหมือนว่าundo log entriesหมายเลขdoing SYNC indexกำลังจะมาถึง ~ 150 / s จนกว่าจะถึง 20,000 ซึ่งจะมีการดำเนินการ

ขนาด FTS ของตารางเฉพาะนี้ค่อนข้างน่าประทับใจ:

# du -c FTS_000000000000224a_00000000000036b9_*
614404  FTS_000000000000224a_00000000000036b9_INDEX_1.ibd
2478084 FTS_000000000000224a_00000000000036b9_INDEX_2.ibd
1576964 FTS_000000000000224a_00000000000036b9_INDEX_3.ibd
1630212 FTS_000000000000224a_00000000000036b9_INDEX_4.ibd
1978372 FTS_000000000000224a_00000000000036b9_INDEX_5.ibd
1159172 FTS_000000000000224a_00000000000036b9_INDEX_6.ibd
9437208 total

แม้ว่าปัญหานี้จะถูกเรียกใช้โดยตารางที่มีขนาดข้อมูล FTS ขนาดใหญ่น้อยกว่าอย่างมีนัยสำคัญเช่นนี้:

# du -c FTS_0000000000002467_0000000000003a21_INDEX*
49156   FTS_0000000000002467_0000000000003a21_INDEX_1.ibd
225284  FTS_0000000000002467_0000000000003a21_INDEX_2.ibd
147460  FTS_0000000000002467_0000000000003a21_INDEX_3.ibd
135172  FTS_0000000000002467_0000000000003a21_INDEX_4.ibd
155652  FTS_0000000000002467_0000000000003a21_INDEX_5.ibd
106500  FTS_0000000000002467_0000000000003a21_INDEX_6.ibd
819224  total

เวลาของแผงขายในกรณีเหล่านั้นก็เหมือนกันเช่นกัน ผมได้เปิดข้อผิดพลาดใน bugs.mysql.comเพื่อ devs สามารถดูในนี้

ลักษณะของแผงลอยทำให้ฉันสงสัยว่ากิจกรรมการล้างบันทึกการเป็นผู้ร้ายและบทความ Percona นี้เกี่ยวกับปัญหาประสิทธิภาพการล้างบันทึกด้วย MySQL 5.5กำลังอธิบายถึงอาการที่คล้ายกันมาก แต่เหตุการณ์ต่อไปแสดงให้เห็นว่าการดำเนินการ INSERT ในตาราง MyISAM ได้รับผลกระทบจากคอกม้าเช่นกันดังนั้นสิ่งนี้จึงไม่ดูเหมือนเป็นปัญหาของ InnoDB เท่านั้น

อย่างไรก็ตามฉันตัดสินใจที่จะติดตามค่าของLog sequence numberและ Pages flushed up toจากส่วน"LOG"เอาต์พุตของSHOW ENGINE INNODB STATUSทุก ๆ 10 วินาที มันดูเหมือนกิจกรรมการชะล้างอย่างต่อเนื่องระหว่างแผงลอยเนื่องจากการแพร่กระจายระหว่างค่าทั้งสองลดลง:

Mon Sep 1 14:17:08 CEST 2014 LSN: 263992263703, Pages flushed: 263973405075, Difference: 18416 K
Mon Sep 1 14:17:19 CEST 2014 LSN: 263992826715, Pages flushed: 263973811282, Difference: 18569 K
Mon Sep 1 14:17:29 CEST 2014 LSN: 263993160647, Pages flushed: 263974544320, Difference: 18180 K
Mon Sep 1 14:17:39 CEST 2014 LSN: 263993539171, Pages flushed: 263974784191, Difference: 18315 K
Mon Sep 1 14:17:49 CEST 2014 LSN: 263993785507, Pages flushed: 263975990474, Difference: 17377 K
Mon Sep 1 14:17:59 CEST 2014 LSN: 263994298172, Pages flushed: 263976855227, Difference: 17034 K
Mon Sep 1 14:18:09 CEST 2014 LSN: 263994670794, Pages flushed: 263978062309, Difference: 16219 K
Mon Sep 1 14:18:19 CEST 2014 LSN: 263995014722, Pages flushed: 263983319652, Difference: 11420 K
Mon Sep 1 14:18:30 CEST 2014 LSN: 263995404674, Pages flushed: 263986138726, Difference: 9048 K
Mon Sep 1 14:18:40 CEST 2014 LSN: 263995718244, Pages flushed: 263988558036, Difference: 6992 K
Mon Sep 1 14:18:50 CEST 2014 LSN: 263996129424, Pages flushed: 263988808179, Difference: 7149 K
Mon Sep 1 14:19:00 CEST 2014 LSN: 263996517064, Pages flushed: 263992009344, Difference: 4402 K
Mon Sep 1 14:19:11 CEST 2014 LSN: 263996979188, Pages flushed: 263993364509, Difference: 3529 K
Mon Sep 1 14:19:21 CEST 2014 LSN: 263998880477, Pages flushed: 263993558842, Difference: 5196 K
Mon Sep 1 14:19:31 CEST 2014 LSN: 264001013381, Pages flushed: 263993568285, Difference: 7270 K
Mon Sep 1 14:19:41 CEST 2014 LSN: 264001933489, Pages flushed: 263993578961, Difference: 8158 K
Mon Sep 1 14:19:51 CEST 2014 LSN: 264004225438, Pages flushed: 263993585459, Difference: 10390 K

และเมื่อเวลา 14:19:11 การแพร่กระจายได้มาถึงจุดต่ำสุดกิจกรรมการชะล้างจึงดูเหมือนจะหยุดอยู่ที่นี่เพียงแค่ใกล้เคียงกับจุดสิ้นสุดของคอกม้า แต่ประเด็นเหล่านี้ทำให้ฉันยกเลิกการลบบันทึก InnoDB เนื่องจากสาเหตุ:

  • สำหรับการดำเนินการฟลัชชิงเพื่อป้องกันการอัพเดททั้งหมดในฐานข้อมูลจะต้องมี "ซิงโครนัส" ซึ่งหมายความว่าต้องมีการล็อกพื้นที่ 7/8 ของพื้นที่บันทึก
  • มันจะนำหน้าด้วยขั้นตอนการล้าง "asynchronous" เริ่มต้นที่innodb_max_dirty_pages_pctระดับการเติม - ซึ่งฉันไม่เห็น
  • LSN ยังคงเพิ่มขึ้นเรื่อย ๆ แม้ในระหว่างแผงลอยดังนั้นกิจกรรมการบันทึกจึงไม่หยุดอย่างสมบูรณ์
  • ตาราง INISERT ของ MyISAM ก็ได้รับผลกระทบเช่นกัน
  • เธรด page_cleaner สำหรับการล้างข้อมูลแบบปรับตัวดูเหมือนจะทำงานและล้างข้อมูลบันทึกโดยไม่ทำให้แบบสอบถาม DML หยุด:

LSN - หน้าฟลัช

(ตัวเลข([Log Sequence Number] - [Pages flushed up to]) / 1024มาจากSHOW ENGINE INNODB STATUS)

ดูเหมือนว่าปัญหาจะลดลงบ้างโดยการตั้งค่าinnodb_adaptive_flushing_lwm=1บังคับให้ตัวล้างหน้าทำงานมากกว่าเดิม

error.logไม่มีรายการประจวบกับคอกม้า SHOW INNODB STATUSส่วนที่ตัดตอนมาหลังจากการดำเนินการประมาณ 24 ชั่วโมงมีลักษณะดังนี้:

SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 789330
OS WAIT ARRAY INFO: signal count 1424848
Mutex spin waits 269678, rounds 3114657, OS waits 65965
RW-shared spins 941620, rounds 20437223, OS waits 442474
RW-excl spins 451007, rounds 13254440, OS waits 215151
Spin rounds per wait: 11.55 mutex, 21.70 RW-shared, 29.39 RW-excl
------------------------
LATEST DETECTED DEADLOCK
------------------------
2014-09-03 10:33:55 7fe0e2e44700
[...]
--------
FILE I/O
--------
[...]
932635 OS file reads, 2117126 OS file writes, 1193633 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 17.00 writes/s, 1.20 fsyncs/s
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
0 read views open inside InnoDB
Main thread process no. 54745, id 140604272338688, state: sleeping
Number of rows inserted 528904, updated 1596758, deleted 99860, read 3325217158
5.40 inserts/s, 10.40 updates/s, 0.00 deletes/s, 122969.21 reads/s

ใช่ฐานข้อมูลมีการหยุดชะงัก แต่ไม่บ่อยนัก (มีการจัดการ "ล่าสุด" ประมาณ 11 ชั่วโมงก่อนที่จะอ่านสถิติ)

ฉันลองติดตามค่าส่วน "SEMAPHORES" เป็นระยะเวลาหนึ่งโดยเฉพาะอย่างยิ่งในสถานการณ์การทำงานปกติและระหว่างแผงลอย (ฉันเขียนสคริปต์ขนาดเล็กเพื่อตรวจสอบรายการประมวลผลของเซิร์ฟเวอร์ MySQL และเรียกใช้คำสั่งวินิจฉัยสองรายการในกรณีบันทึก ของแผงขายที่ชัดเจน) เนื่องจากตัวเลขถูกยึดไปตามกรอบเวลาที่แตกต่างกันฉันจึงทำให้ผลลัพธ์เป็นปกติ / วินาที:

                          normal   stall
                          1h avg  1m avg
OS WAIT ARRAY INFO: 
    reservation count      5,74    1,00
    signal count          24,43    3,17
Mutex spin waits           1,32    5,67
    rounds                 8,33   25,85
    OS waits               0,16    0,43
RW-shared spins            9,52    0,76
    rounds               140,73    13,39
    OS waits               2,60    0,27
RW-excl spins              6,36    1,08
    rounds               178,42   16,51
    OS waits               2,38    0,20

ฉันไม่แน่ใจเกี่ยวกับสิ่งที่ฉันเห็นที่นี่ ตัวเลขส่วนใหญ่ลดลงตามลำดับความสำคัญ - อาจเป็นเพราะการหยุดดำเนินการอัปเดต "Mutex หมุนรอ" และ "Mutex หมุนรอบ" อย่างไรก็ตามทั้งคู่เพิ่มขึ้นด้วยปัจจัย 4

การตรวจสอบเพิ่มเติมนี้รายการ mutexes ( SHOW ENGINE INNODB MUTEX) มีรายการ mutex ประมาณ 480 รายการทั้งในการดำเนินการปกติและระหว่างแผงลอย ฉันเปิดใช้งานinnodb_status_output_locksเพื่อดูว่ามันจะให้รายละเอียดเพิ่มเติมกับฉัน

ตัวแปรการกำหนดค่า

(ฉัน tinkered กับพวกเขาส่วนใหญ่ไม่ประสบความสำเร็จแน่นอน):

mysql> show global variables where variable_name like 'innodb_adaptive_flush%';
+------------------------------+-------+
| Variable_name                | Value |
+------------------------------+-------+
| innodb_adaptive_flushing     | ON    |
| innodb_adaptive_flushing_lwm | 1     |
+------------------------------+-------+
mysql> show global variables where variable_name like 'innodb_max_dirty_pages_pct%';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_max_dirty_pages_pct     | 50    |
| innodb_max_dirty_pages_pct_lwm | 10    |
+--------------------------------+-------+
mysql> show global variables where variable_name like 'innodb_log_%';
+-----------------------------+-----------+
| Variable_name               | Value     |
+-----------------------------+-----------+
| innodb_log_buffer_size      | 8388608   |
| innodb_log_compressed_pages | ON        |
| innodb_log_file_size        | 268435456 |
| innodb_log_files_in_group   | 2         |
| innodb_log_group_home_dir   | ./        |
+-----------------------------+-----------+
mysql> show global variables where variable_name like 'innodb_double%';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| innodb_doublewrite | ON    |
+--------------------+-------+
mysql> show global variables where variable_name like 'innodb_buffer_pool%';
+-------------------------------------+----------------+
| Variable_name                       | Value          |
+-------------------------------------+----------------+
| innodb_buffer_pool_dump_at_shutdown | OFF            |
| innodb_buffer_pool_dump_now         | OFF            |
| innodb_buffer_pool_filename         | ib_buffer_pool |
| innodb_buffer_pool_instances        | 8              |
| innodb_buffer_pool_load_abort       | OFF            |
| innodb_buffer_pool_load_at_startup  | OFF            |
| innodb_buffer_pool_load_now         | OFF            |
| innodb_buffer_pool_size             | 29360128000    |
+-------------------------------------+----------------+
mysql> show global variables where variable_name like 'innodb_io_capacity%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| innodb_io_capacity     | 200   |
| innodb_io_capacity_max | 2000  |
+------------------------+-------+
mysql> show global variables where variable_name like 'innodb_lru_scan_depth%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_lru_scan_depth | 1024  |
+-----------------------+-------+

สิ่งที่พยายามแล้ว

  • ปิดการใช้งานแคชแบบสอบถามโดย SET GLOBAL query_cache_size=0
  • เพิ่มขึ้นinnodb_log_buffer_sizeถึง 128M
  • เล่นรอบกับinnodb_adaptive_flushing, innodb_max_dirty_pages_pctและตามลำดับ_lwmค่า (พวกเขาถูกกำหนดให้เป็นค่าเริ่มต้นก่อนที่จะมีการเปลี่ยนแปลงของฉัน)
  • เพิ่มขึ้นinnodb_io_capacity(2000) และinnodb_io_capacity_max(4000)
  • การตั้งค่า innodb_flush_log_at_trx_commit = 2
  • ทำงานกับ innodb_flush_method = O_DIRECT (ใช่เราใช้ SAN ที่มีแคชการเขียนถาวร)
  • การตั้งค่า / sys / block / sda / queue / scheduler เป็นnoopหรือdeadline

Innodb_io_capacity, innodb_io_capacity_max และ innodb_lru_scan_depth คืออะไร การตั้งค่าเหล่านี้ให้สูงขึ้น (เหมาะสมกว่า) จะช่วยให้พื้นที่บันทึกว่าง
Morgan Tocker

ค่าเริ่มต้น - 200, 2000 และ 1024 ตอนนี้ฉันเปลี่ยนเป็น 2000, 4000 และ 2000 และค่าสเปรดระหว่างค่า LSN และหน้าแดงล้างได้ลดลงอีกครั้งเป็น <1,000 เค แต่ฉันไม่แน่ใจว่านี่เป็นเรื่องของบันทึกหรือไม่ พื้นที่ในสถานที่แรก
syneticon-dj

แน่นอนมันดูเหมือนจะไม่เป็น ฉันยังคงเห็นแผงลอย - พวกเขาไม่ได้เปลี่ยนแปลงมากในช่วงเวลาหรือความถี่ของการเกิดขึ้น การบันทึก LSN / จุดตรวจสอบของฉันแสดงจำนวนสเปรดสัมบูรณ์ที่ลดลงอย่างมีนัยสำคัญซึ่งค่อนข้างเพิ่มขึ้นระหว่างแผงลอยถึงประมาณ 3 M ใน 1-2 นาที (อาจเป็นธุรกรรมที่ยังไม่เสร็จทำให้เกิดการใช้งานบันทึกที่ไม่เปลี่ยนแปลง) และจุดตรวจสอบเริ่มต้นจากจุดในเวลาที่แผงลอยได้รับการแก้ไข
syneticon-dj

ฉันไม่แน่ใจว่าคุณควรตั้ง innodb_adaptive_flushing_lwm เป็น 1 - เป็นเปอร์เซ็นต์ของพื้นที่บันทึกซึ่งการล้างข้อมูลแบบปรับตัวเริ่มต้น (ค่าเริ่มต้น: 10)
Morgan Tocker

@ MorganTocker ฉันได้ตั้งค่านี้เพื่อให้แน่ใจว่าการล้างข้อมูลแบบปรับตัวจะล้างข้อมูลส่วนใหญ่ในขณะที่ฉันสงสัยว่าการใช้พื้นที่บันทึกเป็นส่วนหนึ่งของปัญหา ปัญหานี้เกิดขึ้นกับค่าเริ่มต้นที่ 10 เช่นกันฉันเปลี่ยนเพื่อแก้ไขปัญหา
syneticon-dj

คำตอบ:


6

เราเห็นปัญหาเดียวกันบนเซิร์ฟเวอร์สองเครื่องในรุ่น 5.6.12 และ 5.6.16 ที่ทำงานบน Windows โดยมีทาสหนึ่งคู่ พวกเรานิ่งงันเช่นคุณเกือบสองเดือน

วิธีแก้ปัญหา :

set global binlog_order_commits = 0;

ดู https://dev.mysql.com/doc/refman/5.6/en/replication-options-binary-log.html#sysvar_binlog_order_commitsเพื่อดูรายละเอียดของตัวแปร

คำอธิบาย :

InnoDB full-text ใช้แคช (ขนาด 8M เริ่มต้น) ที่มีการเปลี่ยนแปลงที่จำเป็นต้องใช้กับดัชนีข้อความจริงบนดิสก์

เมื่อแคชเต็มแล้วจะมีการสร้างธุรกรรมขึ้นสองสามอย่างเพื่อทำการผสานข้อมูลที่มีอยู่ในแคชซึ่งมีแนวโน้มที่จะสุ่ม IO จำนวนมากดังนั้นหากไม่สามารถโหลดดัชนีข้อความแบบเต็มได้ บัฟเฟอร์พูลมันเป็นธุรกรรมที่ยาวและช้า

ด้วยการตั้งค่า binlog_order_commits เป็นจริงธุรกรรมทั้งหมดที่มีการแทรกและการอัพเดตเริ่มต้นหลังจากธุรกรรม fts_sync_index ที่ใช้งานมานานต้องรอจนกว่าจะเสร็จสิ้นก่อนที่จะสามารถกระทำได้

นี่เป็นปัญหาเฉพาะถ้าเปิดใช้งานการบันทึกแบบไบนารี


ดูเหมือนว่าจะเป็นวิธีแก้ไขปัญหาที่ฉันเห็นด้วยเช่นกัน คุณคิดวิธีแก้ปัญหาอย่างไร? นอกจากนี้ในกรณีของฉันดัชนีข้อความแบบเต็มจะมีขนาดพอดีกับบัฟเฟอร์พูล (ซึ่งมีขนาด ~ 30G) แต่การดำเนินการดูเหมือนจะมีความล่าช้าอย่างมาก ฉันรู้สึกว่าสแต็ค I / O ของ MySQL นั้นไม่มีประสิทธิภาพอย่างมากเมื่อต้องจัดการกับเวลาแฝงในการจัดเก็บดังนั้นปัญหานี้อาจเป็นการรวมกันของทั้งสองอย่าง - ความไร้ประสิทธิภาพและค่าเริ่มต้นที่ไม่ดีสำหรับการกำหนดค่าการบันทึกไบนารี
syneticon-dj

ฉันสงสัยว่ามันจะไม่มีใครสังเกตเห็นได้นานขนาดนี้ แน่นอนว่ามีผู้ใช้ InnoDB ที่เปิดใช้งาน FTS และ binlog มากกว่าในที่เก็บข้อมูลที่ไม่ใช่ SSD
syneticon-dj

โชค. ฉันได้มาถึงจุดเดียวกับคุณที่ฉันสามารถจัดการ "สถานะเครื่องยนต์แสดง Innodb" ในระหว่างการล็อก ฉันเขียนโปรแกรมขนาดเล็กที่จะแทรกแถวจำนวนมากลงในตารางด้วยดัชนี FTS และอีกอันหนึ่งที่อัปเดตตารางที่สองและบันทึกเวลาอัปเดต ฉันไม่สามารถหยุดแคชล้าง FTS เพื่อหยุดการอัปเดตได้ชั่วคราวจนกว่าฉันจะผ่านความแตกต่างในการตั้งค่าทีละเครื่องระหว่างเครื่องท้องถิ่นและเซิร์ฟเวอร์ที่ใช้งานจริง การเปิด binlog สร้างปัญหาขึ้นใหม่ดังนั้นฉันเพิ่งอ่านตัวเลือก binlog
Daniel Golding

1
เป็นที่น่าสังเกตว่าทีมงาน MySQL dev ในที่สุด (หลังจาก 15 เดือนในคิว!) ได้กำหนดสถานะของบั๊กที่รายงานเป็น "ตรวจสอบ" และอย่างน้อยบางคนจากทีมงานพัฒนาดูเหมือนว่ากำลังคิดจะแก้ปัญหา ไม่จำเป็นต้องพูดว่าฉันทำกับ MySQL เพื่อความดีฉันหวังว่า
syneticon-dj

4

ให้ฉันลองและอธิบายปัญหาในอดีตด้วยการล้างบันทึกและวิธีการล้างข้อมูลแบบปรับตัว:

  • บันทึกการทำซ้ำเป็นการออกแบบวงแหวนบัฟเฟอร์ พวกเขาเคยเขียนถึง (ไม่เคยอ่านจากการทำงานปกติ) และให้ในการกู้คืนความผิดพลาด ฉันชอบที่จะอธิบายวงแหวนบัฟเฟอร์เช่นเดียวกับดอกยางของรถถัง

  • InnoDB จะไม่สามารถเขียนทับพื้นที่ไฟล์บันทึกได้หากมีการเปลี่ยนแปลงที่ยังไม่ได้แก้ไขบนดิสก์ ดังนั้นในอดีตสิ่งที่จะเกิดขึ้นคือ InnoDB จะพยายามทำงานต่อวินาที (กำหนดค่าโดยinnodb_io_capacity) และถ้านั่นไม่เพียงพอคุณจะไปถึงพื้นที่บันทึกเต็ม แผงลอยจะเกิดขึ้นเมื่อการล้างแบบซิงโครนัสจำเป็นต้องเกิดขึ้นกับพื้นที่ว่างในทันใด

  • เพื่อแก้ไขปัญหานี้ได้มีการแนะนำการล้างข้อมูลแบบปรับตัว เมื่อใช้พื้นที่บันทึก10% (ค่าเริ่มต้น)งานพื้นหลังจะเริ่มรุนแรงขึ้นเรื่อย ๆ จุดประสงค์ของเรื่องนี้มากกว่าที่จะเกิดขึ้นในทันทีคุณมีการแสดงที่สั้นลง

  • เป็นอิสระจากการล้างการปรับตัวก็เป็นสิ่งสำคัญที่จะมีพื้นที่เพียงพอสำหรับการบันทึกภาระงานของคุณ ( innodb_log_file_sizeค่าของ 4G อยู่ในขณะนี้ค่อนข้างปลอดภัย) และให้แน่ใจว่าinnodb_io_capacityและinnodb_lru_scan_depthมีการตั้งค่าให้เป็นค่าที่มีเหตุผล การปรับแบบฟลัชชีท 10% innodb_adaptive_flushing_lwmเป็นสิ่งที่คุณไม่ยืดออกไปมากมันเป็นกลไกการป้องกันมากกว่าพื้นที่


2

เพียงเพื่อนำ InnoDB innodb_purge_threadsบรรเทาความขัดแย้งบางอย่างที่คุณสามารถเล่นกับ

ก่อน MySQL 5.6, Master Threadทำการล้างหน้าทั้งหมด ใน MySQL 5.6 เธรดแยกสามารถจัดการได้ ค่าเริ่มต้นสำหรับinnodb_purge_threadsใน MySQL 5.5 คือ 0โดยมีค่าสูงสุด 1 ใน MySQL 5.6 ค่าเริ่มต้นคือ 1ซึ่งมีค่าสูงสุด 32

การตั้งค่าinnodb_purge_threadsทำอะไรจริง

ค่าที่ไม่เป็นศูนย์จะดำเนินการกวาดล้างในเธรดพื้นหลังอย่างน้อยหนึ่งเธรดซึ่งสามารถลดการช่วงชิงภายในภายใน InnoDB เพื่อปรับปรุงความสามารถในการขยาย การเพิ่มค่าให้มากกว่า 1 สร้างเธรดการล้างที่แยกต่างหากจำนวนมากซึ่งสามารถปรับปรุงประสิทธิภาพบนระบบที่ดำเนินการ DML บนหลายตาราง

ฉันจะเริ่มต้นด้วยการตั้งค่าinnodb_purge_threadsเป็น 4 และดูว่าการล้างหน้าของ InnoDB ลดลงหรือไม่

อัปเดต 2014-09-02 12:33 EDT

มอร์แกน Tocker ชี้ให้เห็นในความคิดเห็นด้านล่างที่ทำความสะอาดหน้าเป็นเหยื่อและ MySQL 5.7 สามารถอยู่มัน อย่างไรก็ตามสถานการณ์ของคุณอยู่ใน MySQL 5.6

ฉันลองดูครั้งที่สองและสังเกตว่าคุณมีinnodb_max_dirty_pages_pctที่ 50

ค่าเริ่มต้นสำหรับinnodb_max_dirty_pages_pctใน MySQL 5.5+ คือ 75 การลดระดับลงจะเพิ่มอุบัติการณ์ของแผงลอยจากการล้าง ฉันจะทำสาม (3) อย่าง

อัปเดต 2014-09-03 11:06 EDT

คุณอาจต้องเปลี่ยนพฤติกรรมการฟลัชชิงของคุณ

ลองตั้งค่าต่อไปนี้แบบไดนามิก

SET GLOBAL flush = 1;
SET GLOBAL flush_time = 10;

ตัวแปรเหล่านี้เปี่ยมและflush_timeจะทำให้การล้างข้อมูลเชิงรุกมากขึ้นโดยการปิดการจัดการไฟล์ที่เปิดอยู่บนตารางทุก ๆ 10 วินาที MyISAM สามารถได้รับประโยชน์อย่างแน่นอนเพราะไม่ได้แคชข้อมูล ทั้งหมดเขียนไปยังตาราง MyISAM ต้องการล็อคเต็มตารางตามด้วยการเขียนของอะตอมและขึ้นอยู่กับระบบปฏิบัติการสำหรับการเปลี่ยนแปลงดิสก์

การล้าง InnoDB ด้วยวิธีนั้นจะต้องมีการรีสตาร์ท mysql ตัวเลือกที่จะเห็นเป็นinnodb_flush_log_at_trx_commitและinnodb_flush_method

ก่อนที่คุณจะรีสตาร์ทโปรดเพิ่มสิ่งเหล่านี้

[mysqld]
flush = 1
flush_time = 10
innodb_flush_log_at_trx_commit = 0
innodb_flush_method = O_DIRECT

ก่อนที่จะไปเส้นทางนี้คุณควรตรวจสอบว่าการบันทึกเป็นปัญหาหรือไม่ ฉันเห็นmysqlperformanceblog โพสต์นี้ใน O_DIRECT กำลังแกล้งเพราะเคอร์เนล โพสต์เดียวกันยังกล่าวถึง MyISAM ที่ได้รับผลกระทบ

ฉันเขียนเกี่ยวกับโพสต์นี้มาก่อน: ib_logfile เปิดด้วย O_SYNC เมื่อ innodb_flush_method = O_DSYNC

ให้มันลอง !!!


1
ในการชี้แจง: ฉันเชื่อว่าเวิร์กโหลดนี้เน้นที่เธรดของตัวล้างหน้ามากกว่าการล้างเธรด ตัวทำความสะอาดหลายหน้าเป็นคุณสมบัติ 5.7 แต่การกำหนดค่าเพิ่มเติมยังคงเป็นไปได้ใน 5.6 ดู: mysqlserverteam.com/mysql-5-7-improves-dml-oriented-workloads
Morgan Tocker

@ MorganTocker @RolandoMySQLDBA สิ่งหนึ่งที่โดดเด่นสำหรับฉันในsar -dผลลัพธ์awaitคือกำลังเพิ่มขึ้นเกือบสิบเท่าในช่วงหนึ่งของร้านขณะที่ปริมาณงานลดลง คุณคิดว่าเป็นไปได้ไหมที่มีปัญหานอก MySQL ที่นี่เช่นกับ I / O scheduler หรือ filesystem journaling?
James L

ฉันผ่านการเปลี่ยนแปลงพารามิเตอร์ส่วนใหญ่ที่คุณแนะนำยกเว้น innodb_purge_threads (ซึ่งต้องรีสตาร์ท) มันไม่ได้ทำอะไรมากสำหรับปัญหานี้ และฉันก็เชื่อว่าเครื่องยนต์ InnoDB ไม่ใช่ปัญหาที่นี่เนื่องจากการแทรกตาราง MyISAM จะหยุดทำงานเช่นกัน
syneticon-dj

โปรดโพสต์การตั้งค่าของคุณสำหรับ innodb_read_io_threads และ innodb_write_io_threads ทำงานSHOW GLOBAL VARIABLES LIKE '%io_threads';
RolandoMySQLDBA

1
@ syneticon-dj วิธีการเขียนไปยังระบบไฟล์เดียวกันจากนอก MySQL - เหล่านั้นถ่วงได้หรือไม่
James L
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.