Usando múltiplos núcleos para consultas únicas do MySQL no Debian

10

Estou executando um servidor MySQL para testes em uma VM (VMWare) com o Debian como sistema operacional convidado. O convidado tem quatro núcleos de CPU emulados, então eu defino thread_concurrency para quatro.

Estou fazendo junções caras em tabelas grandes, o que pode levar vários minutos, mas vejo no sistema operacional convidado que apenas um núcleo é usado por vez. Isso acontece independentemente do mecanismo de armazenamento usado para as tabelas envolvidas (testado com MyISAM e InnoDB). Além disso, o banco de dados inteiro parece estar bloqueado ao fazer essas consultas grandes. Não posso fazer nenhuma consulta adicional em paralelo. Estranhamente, o htop mostra que o núcleo usado para a consulta muda durante o tempo de execução da consulta!

Por que isso acontece?

Esta é a entrada relevante de SHOW FULL PROCESSLIST;(não há outras consultas):

| 153 | root       | localhost | pulse_stocks  | Query   |   50 | Copying to tmp table | 
SELECT DISTINCT * FROM 
`pulse_stocks`.`stocks` sto,
`pulse_new`.`security` sec
WHERE
(sto.excntry = sec.excntry AND sto.stock_id = sec.ibtic) OR
( sto.isin = sec.isin AND sto.isin <> "" AND sec.isin <> "" )
ORDER BY
sto.id
LIMIT 0, 30 

Não há outras consultas pendentes. Outra observação interessante é que o MySQL responderá a essa pergunta em um segundo, se eu deixar de fora a ORDER BYparte.

Isto é o que SHOW ENGINE INNODB STATUS;mostra:

=====================================
120316  9:55:56 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 49 seconds
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 47258, signal count 47258
Mutex spin waits 0, rounds 10260, OS waits 39
RW-shared spins 94442, OS waits 47210; RW-excl spins 1, OS waits 1
------------
TRANSACTIONS
------------
Trx id counter 0 5381
Purge done for trx's n:o < 0 1810 undo n:o < 0 0
History list length 2
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0 0, not started, process no 7503, OS thread id 140316748777216
MySQL thread id 154, query id 654 localhost root
SHOW ENGINE INNODB STATUS
---TRANSACTION 0 5380, ACTIVE 105 sec, process no 7503, OS thread id 140316748977920
 fetching rows, thread declared inside InnoDB 429
mysql tables in use 2, locked 0
MySQL thread id 153, query id 623 localhost root Copying to tmp table
SELECT DISTINCT * FROM 
    `pulse_stocks`.`stocks` sto,
    `pulse_new`.`security` sec
WHERE
    (sto.excntry = sec.excntry AND sto.stock_id = sec.ibtic) OR
    ( sto.isin = sec.isin AND sto.isin <> "" AND sec.isin <> "" )
ORDER BY
    sto.id
LIMIT 0, 30

Trx read view will not see trx with id >= 0 5381, sees < 0 5381
--------
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: 0; buffer pool: 0
116089 OS file reads, 7 OS file writes, 7 OS fsyncs
1063.16 reads/s, 117085 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 5, seg size 7,
0 inserts, 0 merged recs, 0 merges
Hash table size 17393, node heap has 1 buffer(s)
0.00 hash searches/s, 14.73 non-hash searches/s
---
LOG
---
Log sequence number 0 38201270
Log flushed up to   0 38201270
Last checkpoint at  0 38201270
0 pending log writes, 0 pending chkp writes
10 log i/o's done, 0.00 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 20638760; in additional pool allocated 994816
Dictionary memory allocated 162680
Buffer pool size   512
Free buffers       0
Database pages     511
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages read 816631, created 0, written 1
7597.72 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 964 / 1000
--------------
ROW OPERATIONS
--------------
1 queries inside InnoDB, 0 queries in queue
2 read views open inside InnoDB
Main thread process no. 7503, id 140316711446272, state: waiting for server activity
Number of rows inserted 0, updated 0, deleted 0, read 160338394
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 1495933.31 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================
Thomas
fonte
Publique a saída de SHOW FULL PROCESSLIST (possivelmente higienizado) e SHOW ENGINE INNODB STATUS para nos ajudar a diagnosticar por que "o banco de dados inteiro" está bloqueado.
Aaron Brown
Obrigado, atualizei a pergunta com as informações solicitadas.
Thomas
11
Se não houver outras consultas em execução, não há evidências de que o banco de dados inteiro esteja bloqueado. Você pode reproduzir essa condição e postar o que acontece quando a consulta de longa duração aparentemente está bloqueando outras pessoas?
Baron Schwartz
Ok, eu verifiquei isso. É possível fazer outras consultas no console do mysql, mesmo quando a consulta grande estiver em execução. No entanto, o phpmyadmin não está respondendo, mesmo a tentativas simples de login, enquanto a consulta está sendo executada. O tempo de execução em si é geralmente menor que 10 segundos, mas a consulta permanece no estado "enviando dados" por vários minutos.
Thomas

Respostas:

10

Você pode achar isso surpreendente, mas defina innodb_thread_concurrency como 0 (que é simultaneidade infinita). Isso permitirá que o InnoDB Storage Engine decida quantos tickets de simultaneidade serão emitidos.

Escrevi um post sobre o envolvimento multicore do InnoDB (MySQL 5.5, também MySQL 5.1.38 InnoDB Plugin) em 26 de maio de 2011 .

De acordo com a documentação do MySQL, a variável thread_concurrency funciona apenas para Solaris .

Tenho mais uma preocupação: seus JOINs envolvem o MyISAM e o InnoDB juntos? O comportamento de bloqueio de tabela completa do MyISAM anula o bloqueio no nível de linha do InnoDB e o MVCC .

Se você não estiver usando o MySQL 5.5, atualize o mais rápido possível para configurar as opções de acoplamento multicore do InnoDB .

UPDATE 2012-03-19 08:30 EDT

A partir do MySQL 5.1.38, você pode instalar o InnoDB Plugin para usar novas configurações para o engajamento multicore. No entanto, você precisa ajustar as configurações corretamente.

De fato, deixou sem configuração

RolandoMySQLDBA
fonte
Muito obrigado. Sua resposta implica que o uso de múltiplos núcleos não está implementado na versão 5.1.X?
Thomas
Sim e não. Eu digo SIM, porque o InnoDB 5.1.x não possui configurações multicore. Eu digo NÃO, porque você pode instalar o plug-in InnoDB para essas novas configurações, mas ele está disponível apenas para o MySQL 5.1.38 e superior.
RolandoMySQLDBA 19/03/12
@RolandoMySQLDBA: Desculpe, eu sei que este post é antigo, mas descobri que o mysql no meu servidor (que tem 24 núcleos) está usando apenas um núcleo. Eu verifiquei o innodb_thread_cuncurrencyque você mencionou e está definido como 0, então eu queria saber por que o mysql não usa mais núcleos?
Monamona
11
@monamona Essa não é a única configuração para brincar. Você também deve definir innodb_read_io_threads e innodb_write_io_threads mais altos (Tente 8, 16, 32 e 64).
RolandoMySQLDBA
@monamona Por favor, leia o meu post antigo dba.stackexchange.com/questions/2918/... para mais detalhes
RolandoMySQLDBA
2

O MySQL, qualquer versão, não possui código para usar múltiplos núcleos em uma única conexão.

A Percona faz um trabalho melhor usando vários núcleos em várias conexões em seu Xtradb. O InnoDB fica sem vapor a cerca de 8 núcleos; O Xtradb fica nivelado aos 32 anos.

Uma "consulta grande" pode estar bloqueando a tabela (ou linhas da tabela) necessária para alguma outra conexão. Vamos dar uma olhada na consulta e na opção SHOW CREATE TABLE.

Rick James
fonte