문제
InnoDB 테이블이있는 데이터베이스를 실행하는 MySQL 5.6.20 인스턴스 (대부분의 경우)는 1-4 분 동안 모든 업데이트 작업에 대해 가끔씩 중단되어 모든 INSERT, UPDATE 및 DELETE 쿼리가 "쿼리 종료"상태로 남아 있습니다. 이것은 가장 불행한 일입니다. 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
종종 가장 느린 쿼리 스톨은 VARCHAR 기본 키와 전체 텍스트 검색 인덱스가있는 큰 (~ 10 M 행) 테이블에 대한 INSERT라는 것을 mysql 느린 로그에서 자주 발견합니다.
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 STATUS)는 실속을 유발하는 전체 텍스트 인덱스를 사용하는 테이블을 항상 업데이트 하는 것으로 나타났습니다 . "SHOW ENGINE INNODB STATUS"의 각 TRANSACTIONS 섹션에는 가장 오래 실행중인 트랜잭션에 대해 다음과 같은 항목이 있습니다.
---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
따라서 모든 테이블에 대한 모든 SUBSEQUENT 업데이트를 중지 하는 무거운 전체 텍스트 인덱스 작업이 있습니다 ( doing SYNC index
) .
로그에서 그것은 ~ 20,000에 도달 할 때까지 ~ 150 / s로 진행 하는 undo log entries
숫자 처럼 보입니다. doing SYNC index
이 시점에서 작업이 완료됩니다.
이 특정 테이블의 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에서 버그를 열었습니다 .
스톨의 특성으로 인해 로그 플러시 활동 이 범인으로 의심되는 것으로 나타 났 으며 MySQL 5.5의 로그 플러시 성능 문제에 대한이 Percona 기사 는 매우 유사한 증상을 설명하지만 추가 데이터베이스에서 INSERT 작업이이 데이터베이스의 단일 MyISAM 테이블에 표시되는 것으로 나타났습니다 스톨의 영향을 받기 때문에 InnoDB 전용 문제처럼 보이지 않습니다.
그럼에도 불구하고, I의 값을 추적하기로 결정 Log sequence number
하고 Pages flushed up to
로부터 "로그" 의 출력 부 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을 차지해야합니다.
innodb_max_dirty_pages_pct
필 레벨 에서 시작하는 "비동기"플러싱 단계가 선행됩니다.- 중단 동안에도 LSN이 계속 증가하므로 로그 활동이 완전히 중단되지 않습니다
- MyISAM 테이블 INSERT도 영향을받습니다.
- 적응 형 플러싱을위한 page_cleaner 스레드는 DML 쿼리를 중지시키지 않고 작업을 수행하고 로그를 플러시하는 것으로 보입니다.
(번호는 ([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 spin waits"및 "Mutex spin rounds"의 업데이트 작업이 중단 되었기 때문에 대부분의 숫자가 10 배 정도 줄었습니다. 그러나 둘 다 4 배 증가했습니다.
더 자세히 조사하면, 뮤텍스 목록 ( SHOW ENGINE INNODB MUTEX
)에는 정상 작동과 스톨 중 모두 ~ 480 개의 뮤텍스 항목이 나열됩니다. 나는 활성화 innodb_status_output_locks
가 나에게 자세한 내용을 제공 할 것입니다 있는지 확인합니다.
구성 변수
(나는 확실한 성공없이 그들 대부분을 고민했다.)
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