Статьи

Схема производительности: измерение активности многопоточного ведомого устройства

Схема исполнения

Во многих типах рабочих нагрузок базы данных использование многопоточного ведомого устройства с версии 5.6+ помогает повысить производительность репликации. У меня было несколько пользователей, которые включали эту функцию, но никто не спрашивал, как работает каждый поток. Вот быстрый способ с помощью Performance_Schema измерить объем многопоточной активности подчиненного в каждом потоке — после того, как вы уже настроили MTS на своем ведомом, конечно.

Во-первых, нам нужно включить   инструменты заявления :

slave1> UPDATE setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE 'events_statements_%'; 
Query OK, 2 rows affected (0.00 sec) 
Rows matched: 3  Changed: 2  Warnings: 0

Далее, давайте найдем  THREAD_ID  для наших рабовладельцев:

slave1> SELECT THREAD_ID, NAME FROM threads WHERE NAME LIKE '%worker';
+-----------+-------------------------+
| THREAD_ID | NAME                    |
+-----------+-------------------------+ 
|        28 | thread/sql/slave_worker | 
|        29 | thread/sql/slave_worker | 
|        30 | thread/sql/slave_worker | 
|        31 | thread/sql/slave_worker | 
+-----------+-------------------------+ 
4 rows in set (0.00 sec)

И тогда мы фиксируем измерения:

slave1> SELECT THREAD_ID, EVENT_NAME, COUNT_STAR FROM events_statements_summary_by_thread_by_event_name WHERE THREAD_ID IN (28,29,30,31) AND COUNT_STAR > 0; 
+-----------+----------------------+------------+ 
| THREAD_ID | EVENT_NAME           | COUNT_STAR | 
+-----------+----------------------+------------+ 
|        28 | statement/sql/update |         48 | 
|        28 | statement/sql/insert |         24 | 
|        28 | statement/sql/delete |         24 | 
|        28 | statement/sql/begin  |         24 | 
|        29 | statement/sql/update |         68 | 
|        29 | statement/sql/insert |         34 | 
|        29 | statement/sql/delete |         34 | 
|        29 | statement/sql/begin  |         34 | 
|        30 | statement/sql/update |       1864 | 
|        30 | statement/sql/insert |        932 | 
|        30 | statement/sql/delete |        932 | 
|        30 | statement/sql/begin  |        932 | 
|        31 | statement/sql/update |      40320 | 
|        31 | statement/sql/insert |      20160 | 
|        31 | statement/sql/delete |      20160 | 
|        31 | statement/sql/begin  |      20160 | 
+-----------+----------------------+------------+ 
16 rows in set (0.01 sec)

Как вы можете видеть выше, один из многопоточных потоков выполняет больше работы по сравнению с остальными тремя. Это sysbench на ведущем устройстве в базе данных, выполняющее [ —trx-rate = 10] , по сравнению с остальными тремя, которые выполняют только [ —trx-rate = 2 | 5] .

Ниже приведен еще один пример, на этот раз с указанием времени события. С помощью слегка модифицированного теста sysbench я разработал тесты для отправки больших обновлений, но один с низкой скоростью транзакций, другой с высокой скоростью транзакций, а остальные между ними. В потоках 32 и 34 вы можете видеть, что первый выполняет меньшее количество операций [ ОБНОВЛЕНИЯ] , но тратит больше времени на каждое событие.

slave1> SELECT THREAD_ID, EVENT_NAME, COUNT_STAR,
->   SUM_TIMER_WAIT/1000000 AS SUM_TIMER_WAIT_MS,
    ->   (SUM_TIMER_WAIT/COUNT_STAR)/1000000 AS AVG_TIME_MS
    -> FROM events_statements_summary_by_thread_by_event_name
    -> WHERE THREAD_ID IN (31,32,33,34) AND COUNT_STAR > 0; 
+-----------+----------------------+------------+-------------------+--------------+ 
| THREAD_ID | EVENT_NAME           | COUNT_STAR | SUM_TIMER_WAIT_MS | AVG_TIME_MS  | 
+-----------+----------------------+------------+-------------------+--------------+ 
|        31 | statement/sql/update |          3 |          403.9690 | 134.65633333 | 
|        31 | statement/sql/insert |          1 |           91.5340 |  91.53400000 | 
|        31 | statement/sql/delete |          1 |           75.9540 |  75.95400000 | 
|        31 | statement/sql/begin  |          1 |           11.6800 |  11.68000000 | 
|        32 | statement/sql/update |         75 |        25298.5090 | 337.31345333 | 
|        32 | statement/sql/insert |         25 |         2221.1410 |  88.84564000 | 
|        32 | statement/sql/delete |         25 |         2187.8970 |  87.51588000 | 
|        32 | statement/sql/begin  |         25 |          321.0220 |  12.84088000 | 
|        33 | statement/sql/update |       4728 |      1008736.6000 | 213.35376481 | 
|        33 | statement/sql/insert |       1576 |       138815.0570 |  88.08061992 | 
|        33 | statement/sql/delete |       1576 |       136161.9060 |  86.39714848 | 
|        33 | statement/sql/begin  |       1576 |        20498.2300 |  13.00649112 | 
|        34 | statement/sql/update |      70668 |     12304784.2380 | 174.12101995 | 
|        34 | statement/sql/insert |      23556 |      2083454.5350 |  88.44687277 | 
|        34 | statement/sql/delete |      23556 |      2041202.7690 |  86.65319957 | 
|        34 | statement/sql/begin  |      23556 |       303710.4860 |  12.89312642 | 
+-----------+----------------------+------------+-------------------+--------------+ 
16 rows in set (0.00 sec)

Изучая немного дальше, я заметил одну вещь: при использовании [ binlog_format = ROW]  для репликации вы увидите только  события [ BEGIN] с инструментами из [ performance_schema] . Я думаю, что это ошибка, поэтому я сообщил об этом  здесь .

slave1> SELECT THREAD_ID, EVENT_NAME, COUNT_STAR,     
->   SUM_TIMER_WAIT/1000000 AS SUM_TIMER_WAIT_MS,
    ->   (SUM_TIMER_WAIT/COUNT_STAR)/1000000 AS AVG_TIME_MS
    -> FROM events_statements_summary_by_thread_by_event_name
    -> WHERE THREAD_ID IN (40,41,42,43) AND COUNT_STAR > 0; 
+-----------+---------------------+------------+-------------------+-------------+ 
| THREAD_ID | EVENT_NAME          | COUNT_STAR | SUM_TIMER_WAIT_MS | AVG_TIME_MS | 
+-----------+---------------------+------------+-------------------+-------------+ 
|        40 | statement/sql/begin |         16 |          258.6500 | 16.16562500 | 
|        41 | statement/sql/begin |         91 |         1526.4320 | 16.77397802 | 
|        42 | statement/sql/begin |        589 |        10131.4500 | 17.20110357 | 
|        43 | statement/sql/begin |       5022 |        85584.0250 | 17.04182099 | 
+-----------+---------------------+------------+-------------------+-------------+ 
4 rows in set (0.01 sec)

В MySQL 5.7 у MTS есть дополнительное улучшение в том, как применяется параллельная репликация. По умолчанию транзакции применяются параллельно для каждой базы данных. С новым [ slave_parallel_type]  функция, другой вариант называется [ LOGICAL_CLOCK]   вводится , что позволяет распараллеливания внутрисистемных базы данных , а также. Ниже я провел несколько небольших тестов с той же нагрузкой, что и выше. Сначала с  типом [ DATABASE] по умолчанию :

+-----------+----------------------+------------+-------------------+--------------+
| THREAD_ID | EVENT_NAME           | COUNT_STAR | SUM_TIMER_WAIT_MS | AVG_TIME_MS  | 
+-----------+----------------------+------------+-------------------+--------------+ 
|        65 | statement/sql/update |         51 |         9974.1310 | 195.57119608 | 
|        65 | statement/sql/insert |         17 |         2037.7080 | 119.86517647 | 
|        65 | statement/sql/delete |         17 |         2144.4800 | 126.14588235 | 
|        65 | statement/sql/begin  |         17 |          293.0650 |  17.23911765 | 
|        66 | statement/sql/update |        255 |        67131.4980 | 263.26077647 |
|        66 | statement/sql/insert |         85 |         9629.5520 | 113.28884706 |
|        66 | statement/sql/delete |         85 |         9854.2920 | 115.93284706 | 
|        66 | statement/sql/begin  |         85 |         1405.0200 |  16.52964706 | 
|        67 | statement/sql/update |       1215 |       344712.6330 | 283.71410123 | 
|        67 | statement/sql/insert |        405 |        48000.0110 | 118.51854568 | 
|        67 | statement/sql/delete |        405 |        53222.3010 | 131.41308889 | 
|        67 | statement/sql/begin  |        405 |         6836.9070 |  16.88125185 | 
|        68 | statement/sql/update |       5943 |      1820669.3290 | 306.35526317 | 
|        68 | statement/sql/insert |       1981 |       241513.1400 | 121.91476022 | 
|        68 | statement/sql/delete |       1981 |       245022.2450 | 123.68614084 | 
|        68 | statement/sql/begin  |       1981 |        32978.3390 |  16.64731903 | 
+-----------+----------------------+------------+-------------------+--------------+

И затем с [ LOGICAL_CLOCK] :

+-----------+----------------------+------------+-------------------+--------------+
| THREAD_ID | EVENT_NAME           | COUNT_STAR | SUM_TIMER_WAIT_MS | AVG_TIME_MS  |
+-----------+----------------------+------------+-------------------+--------------+
|        59 | statement/sql/update |       9486 |      2667681.7170 | 281.22303574 |
|        59 | statement/sql/insert |       3162 |       376350.1650 | 119.02282258 |
|        59 | statement/sql/delete |       3162 |       388606.5460 | 122.89897090 |
|        59 | statement/sql/begin  |       3162 |        53988.2600 |  17.07408602 |
|        60 | statement/sql/update |        903 |       362853.2080 | 401.83079513 |
|        60 | statement/sql/insert |        301 |        36507.3090 | 121.28674086 |
|        60 | statement/sql/delete |        301 |        37437.2550 | 124.37626246 |
|        60 | statement/sql/begin  |        301 |         5210.4110 |  17.31033555 |
|        61 | statement/sql/update |         42 |        23394.0330 | 557.00078571 |
|        61 | statement/sql/insert |         14 |         1671.5900 | 119.39928571 |
|        61 | statement/sql/delete |         14 |         1720.1230 | 122.86592857 |
|        61 | statement/sql/begin  |         14 |          246.1490 |  17.58207143 |
+-----------+----------------------+------------+-------------------+--------------+

С включенными [ LOGICAL_LOCK]  и [ slave_preserve_commit_order]  :

+-----------+----------------------+------------+-------------------+--------------+
| THREAD_ID | EVENT_NAME           | COUNT_STAR | SUM_TIMER_WAIT_MS | AVG_TIME_MS  |
+-----------+----------------------+------------+-------------------+--------------+
|        71 | statement/sql/update |       8097 |      2216461.7170 | 273.73863369 |
|        71 | statement/sql/insert |       2699 |       322933.1620 | 119.64918933 |
|        71 | statement/sql/delete |       2699 |       326944.2380 | 121.13532345 |
|        71 | statement/sql/begin  |       2699 |        45860.5720 |  16.99169026 |
|        72 | statement/sql/update |        807 |       256668.2730 | 318.05238290 |
|        72 | statement/sql/insert |        269 |        32952.5570 | 122.50021190 |
|        72 | statement/sql/delete |        269 |        33346.3060 | 123.96396283 |
|        72 | statement/sql/begin  |        269 |         4650.1010 |  17.28662082 |
|        73 | statement/sql/update |         33 |         6823.1170 | 206.76112121 |
|        73 | statement/sql/insert |         11 |         1512.5810 | 137.50736364 |
|        73 | statement/sql/delete |         11 |         1593.5790 | 144.87081818 |
|        73 | statement/sql/begin  |         11 |          188.3910 |  17.12645455 |
+-----------+----------------------+------------+-------------------+--------------+

Сочетая значения [ INSERT] , [ UPDATE]  и [ DELETE]  из этих 3 тестов,  вершины [ LOGICAL_CLOCK] получают около 17k событий в течение 120 секунд после той же рабочей нагрузки. Тип [ DATABASE]   был самым медленным, записывая только около 12 000 событий, совершенных на ведомом устройстве.

Наконец, с MySQL 5.7 был добавлен новый инструмент и включен для сбора метрик. Вы также можете измерить скорость за транзакцию вместо класса события.

slave1> UPDATE setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE 'vents_transactions%'; 
Query OK, 0 rows affected (0.00 sec) 
Rows matched: 0  Changed: 0  Warnings: 0   

slave1> UPDATE setup_instruments SET ENABLED = 'YES', TIMED = 'YES' WHERE NAME = 'transaction'; 
Query OK, 1 row affected (0.00 sec) 
Rows matched: 1  Changed: 1  Warnings: 0

И быстрое измерение:

slave1> SELECT THREAD_ID, EVENT_NAME, COUNT_STAR,
->   SUM_TIMER_WAIT/1000000 AS SUM_TIMER_WAIT_MS,     
    ->   (SUM_TIMER_WAIT/COUNT_STAR)/1000000 AS AVG_TIME_MS     
    -> FROM events_transactions_summary_by_thread_by_event_name     
    -> WHERE THREAD_ID IN (     
    ->     SELECT THREAD_ID FROM replication_applier_status_by_worker     
    -> ) AND COUNT_STAR > 0; 
+-----------+-------------+------------+-------------------+----------------+ 
| THREAD_ID | EVENT_NAME  | COUNT_STAR | SUM_TIMER_WAIT_MS | AVG_TIME_MS    | 
+-----------+-------------+------------+-------------------+----------------+ 
|        71 | transaction |       4849 |     50323942.6710 | 10378.21049103 | 
|        72 | transaction |        487 |      6421399.4580 | 13185.62517043 | 
|        73 | transaction |         17 |       319024.9280 | 18766.17223529 | 
+-----------+-------------+------------+-------------------+----------------+ 
3 rows in set (0.00 sec)

Конечно, могут быть измерены не только операторы, события и транзакции; Вы также можете измерить время ожидания и этапы. Удачных инструментов!

Эта статья была написана Джервином Реалом.