Estado Atual do MySQL 5.7
O MySQL 5.7 não é ideal em termos de escalabilidade. O seguinte gráfico ilustra a relação entre a throughput TPC-C e a concorrência no MySQL 5.7.39 sob uma configuração específica. Isso inclui ajustar o nível de isolamento de transação para Read Committed e ajustar o parâmetro innodb_spin_wait_delay
para mitigar a degradação da throughput.
Figura 1: Problemas de escalabilidade no MySQL 5.7.39 durante o teste BenchmarkSQL
A partir do gráfico, é óbvio que os problemas de escalabilidade limitam significativamente aumento na throughput do MySQL. Por exemplo, após 100 concorrências, a throughput começa a decair.
Para addresses os problemas mencionados acima de colapso de desempenho, foi empregado o pool de threads da Percona. O seguinte gráfico ilustra a relação entre a throughput TPC-C e a concorrência após a configuração do pool de threads da Percona.
Figura 2: Pool de threads da Percona mitiga problemas de escalabilidade no MySQL 5.7.39
Embora o pool de threads introduza algum sobrecarga e o pico de desempenho tenha diminuído, ele mitiga o problema de colapso de desempenho sob alta concorrência.
Estado Atual do MySQL 8.0
Vamos olhar para os esforços que o MySQL 8.0 fez em relação à escalabilidade.
Otimização do Log de Redo
A primeira melhoria importante é a otimização do log de redo [3].
commit 6be2fa0bdbbadc52cc8478b52b69db02b0eaff40
Author: Paweł Olchawa <[email protected]>
Date: Wed Feb 14 09:33:42 2018 +0100
WL#10310 Redo log optimization: dedicated threads and concurrent log buffer.
0. Log buffer became a ring buffer, data inside is no longer shifted.
1. User threads are able to write concurrently to log buffer.
2. Relaxed order of dirty pages in flush lists - no need to synchronize
the order in which dirty pages are added to flush lists.
3. Concurrent MTR commits can interleave on different stages of commits.
4. Introduced dedicated log threads which keep writing log buffer:
* log_writer: writes log buffer to system buffers,
* log_flusher: flushes system buffers to disk.
As soon as they finished writing (flushing) and there is new data to
write (flush), they start next write (flush).
5. User threads no longer write / flush log buffer to disk, they only
wait by spinning or on event for notification. They do not have to
compete for the responsibility of writing / flushing.
6. Introduced a ring buffer of events (one per log-block) which are used
by user threads to wait for written/flushed redo log to avoid:
* contention on single event
* false wake-ups of all waiting threads whenever some write/flush
has finished (we can wake-up only those waiting in related blocks)
7. Introduced dedicated notifier threads not to delay next writes/fsyncs:
* log_write_notifier: notifies user threads about written redo,
* log_flush_notifier: notifies user threads about flushed redo.
8. Master thread no longer has to flush log buffer.
...
30. Mysql test runner received a new feature (thanks to Marcin):
--exec_in_background.
Review: RB#15134
Reviewers:
- Marcin Babij <[email protected]>,
- Debarun Banerjee <[email protected]>.
Performance tests:
- Dimitri Kravtchuk <[email protected]>,
- Daniel Blanchard <[email protected]>,
- Amrendra Kumar <[email protected]>.
QA and MTR tests:
- Vinay Fisrekar <[email protected]>.
Um teste comparando a throughput TPC-C com diferentes níveis de concorrência antes e depois da otimização foi realizado. Detalhes específicos são mostrados no seguinte gráfico:
Figura 3: Impacto da otimização do log de redo em diferentes níveis de concorrência
Os resultados na figura mostram uma melhoria significativa na throughput em níveis de concorrência baixos.
Otimizando Lock-Sys por meio de divisão de latches
A segunda melhoria importante é a otimização de Lock-Sys [5].
commit 1d259b87a63defa814e19a7534380cb43ee23c48
Author: Jakub Łopuszański <[email protected]>
Date: Wed Feb 5 14:12:22 2020 +0100
WL#10314 - InnoDB: Lock-sys optimization: sharded lock_sys mutex
The Lock-sys orchestrates access to tables and rows. Each table, and each row,
can be thought of as a resource, and a transaction may request access right for
a resource. As two transactions operating on a single resource can lead to
problems if the two operations conflict with each other, Lock-sys remembers
lists of already GRANTED lock requests and checks new requests for conflicts in
which case they have to start WAITING for their turn.
Lock-sys stores both GRANTED and WAITING lock requests in lists known as queues.
To allow concurrent operations on these queues, we need a mechanism to latch
these queues in safe and quick fashion.
In the past a single latch protected access to all of these queues.
This scaled poorly, and the managment of queues become a bottleneck.
In this WL, we introduce a more granular approach to latching.
Reviewed-by: Pawel Olchawa <[email protected]>
Reviewed-by: Debarun Banerjee <[email protected]>
RB:23836
Baseado no programa antes e depois da otimização com Lock-Sys, usando BenchmarkSQL para comparar a throughput TPC-C com a concorrência, os resultados específicos são mostrados na figura seguinte:
Figura 4: Impacto da otimização de Lock-Sys em diferentes níveis de concorrência
A partir da figura, é possível ver que a otimização de Lock-Sys melhora significativamente a throughput em condições de alta concorrência, enquanto o efeito é menos pronunciado em níveis de concorrência baixos devido a menos conflitos.
Divisão de latches para trx-sys
A terceira melhoria importante é a divisão de latches para trx-sys.
commit bc95476c0156070fd5cedcfd354fa68ce3c95bdb
Author: Paweł Olchawa <[email protected]>
Date: Tue May 25 18:12:20 2021 +0200
BUG#32832196 SINGLE RW_TRX_SET LEADS TO CONTENTION ON TRX_SYS MUTEX
1. Introduced shards, each with rw_trx_set and dedicated mutex.
2. Extracted modifications to rw_trx_set outside its original critical sections
(removal had to be extracted outside trx_erase_lists).
3. Eliminated allocation on heap inside TrxUndoRsegs.
4. [BUG-FIX] The trx->state and trx->start_time became converted to std::atomic<>
fields to avoid risk of torn reads on egzotic platforms.
5. Added assertions which ensure that thread operating on transaction has rights
to do so (to show there is no possible race condition).
RB: 26314
Reviewed-by: Jakub Łopuszański [email protected]
Baseado nestas otimizações antes e depois, usando BenchmarkSQL para comparar a throughput TPC-C com a concorrência, os resultados específicos são mostrados na figura seguinte:
Figura 5: Impacto da divisão de latches em trx-sys em diferentes níveis de concorrência
A partir da figura, é possível ver que esta melhoria aumenta significativamente a throughput TPC-C, alcançando seu pico em 200 concorrências. Note-se que o impacto diminui em 300 concorrências, principalmente devido a problemas de escalabilidade em subsistema trx-sys relacionados a MVCC ReadView.
Refinando o MySQL 8.0
As melhorias restantes são nossas melhorias independentes.
Melhorias no Data Structure de Leitura MVCC ReadView
A primeira melhoria importante é a melhoria no data structure de leitura MVCC ReadView [1].
Foi realizada uma comparação de desempenho para avaliar a eficácia da otimização do MVCC ReadView. A figura abaixo mostra a comparação do throughput TPC-C com diferentes níveis de concorrência, antes e depois da modificação do data structure de leitura MVCC ReadView.
Figure 6: Performance comparison before and after adopting the new hybrid data structure in NUMA
A partir da figura, é evidente que essa transformação principalmente otimizou a escalabilidade e melhorou a throughput máxima do MySQL em ambientes NUMA.
Evitar problemas de Duplo Latch
A segunda melhoria importante que fizemos é resolver o problema de duplo latch, onde “duplo latch” se refira à necessidade do latch global trx-sys por ambos view_open
e view_close
[1].
Usando a versão optimizada do MVCC ReadView, compare o throughput TPC-C antes e depois das modificações. Detalhes são mostrados na figura abaixo:
Figure 7: Performance improvement after eliminating the double latch bottleneck
A partir da figura, é evidente que as modificações melhoraram significativamente a escalabilidade sob condições de alta concorrência.
Mechanism of Transaction Throttling
A última melhoria é a implementação de um mecanismo de limitação de transações para proteger contra a quebra de desempenho sob concorrência extrema [1] [2] [4].
O seguinte gráfico representa a prova de stress de escalabilidade TPC-C realizada após a implementação de mecanismos de limitação de transações. O teste foi executado em um cenário com o NUMA BIOS desabilitado, limitando a entrada de até 512 threads de usuário no sistema de transações.
Figura 8: Throughput máximo TPC-C em BenchmarkSQL com mecanismos de limitação de transações
Ao olhar para o gráfico, é evidente que a implementação de mecanismos de limitação de transações melhora significativamente a escalabilidade do MySQL.
Resumo
Geralmente, é inteiramente possível para o MySQL manter o desempenho sem colapso em dezenas de milhares de conexões concorrentes em cenários de baixo conflito de testes TPC-C do BenchmarkSQL.
Referências
- Bin Wang (2024). O Artigo da Solução de Problemas em Engenharia de Software: Como tornar o MySQL melhor.
- O Novo Piscina de Threads do MySQL
- Paweł Olchawa. 2018. MySQL 8.0: Novo design de WAL sem mutex. Arquivo de Blog do MySQL.
- Xiangyao Yu. Uma avaliação do controle de concorrência com mil núcleos. Tese de Doutorado, Instituto de Tecnologia de Massachusetts, 2015.
- Manual de Referência do MySQL 8.0
Source:
https://dzone.com/articles/mysql-scalability-improvement-for-benchmarksql