Spec-Zone.ru › MySQL 5.7

5.8.4.1 Справочник по зондам mysqld DTrace

  • 5.8.4.1.1 Зонды подключений
  • 5.8.4.1.2 Зонды команд
  • 5.8.4.1.3 Зонды запросов
  • 5.8.4.1.4 Зонды разбора запросов
  • 5.8.4.1.5 Зонды кэша запросов
  • 5.8.4.1.6 Зонды выполнения запросов
  • 5.8.4.1.7 Зонды уровня строк
  • 5.8.4.1.8 Зонды чтения строк
  • 5.8.4.1.9 Зонды индексов
  • 5.8.4.1.10 Зонды блокировок
  • 5.8.4.1.11 Зонды сортировки файлов
  • 5.8.4.1.12 Зонды инструкций
  • 5.8.4.1.13 Зонды сети
  • 5.8.4.1.14 Зонды кэша ключей

MySQL поддерживает следующие статические зонды, организованные по группам функциональности.

Таблица 5.5 Зонды DTrace MySQL

Таблица 5.5 Зонды DTrace MySQL
Группа Зонды
Подключение connection-start, connection-done
Команда command-start, command-done
Запрос query-start, query-done
Разбор запроса query-parse-start, query-parse-done
Кэш запросов query-cache-hit, query-cache-miss
Выполнение запроса query-exec-start, query-exec-done
Уровень строк insert-row-start, insert-row-done
update-row-start, update-row-done
delete-row-start, delete-row-done
Чтение строк read-row-start, read-row-done
Чтение индексов index-read-row-start, index-read-row-done
Блокировка handler-rdlock-start, handler-rdlock-done
handler-wrlock-start, handler-wrlock-done
handler-unlock-start, handler-unlock-done
Сортировка файлов filesort-start, filesort-done
Инструкция select-start, select-done
insert-start, insert-done
insert-select-start, insert-select-done
update-start, update-done
multi-update-start, multi-update-done
delete-start, delete-done
multi-delete-start, multi-delete-done
Сеть net-read-start, net-read-done, net-write-start, net-write-done
Кэш ключей keycache-read-start, keycache-read-block, keycache-read-done, keycache-read-hit, keycache-read-miss, keycache-write-start, keycache-write-block, keycache-write-done

Примечание

При извлечении данных аргументов из зондов каждый аргумент доступен как argN, начиная с arg0. Для идентификации каждого аргумента в определениях используются описательные имена, но доступ к информации необходимо осуществлять с помощью соответствующего параметра argN.

5.8.4.1.1 Зонды подключений

Зонды connection-start и connection-done охватывают подключение от клиента, независимо от того, осуществляется ли подключение через сокет или сетевое соединение.

connection-start(connectionid, user, host)
connection-done(status, connectionid)
  • connection-start: Срабатывает после успешного подключения и аутентификации клиента. Аргументы содержат информацию о подключении:

    • connectionid: Объект unsigned long, содержащий идентификатор подключения. Он совпадает с идентификатором процесса, показанным как значение Id в выводе SHOW PROCESSLIST.

    • user: Имя пользователя, использованное при аутентификации. Значение пустое для анонимного пользователя.

    • host: Хост клиента при подключении. Для подключения через Unix-сокеты значение пустое.

  • connection-done: Срабатывает при закрытии подключения к клиенту. Аргументы:

    • status: Статус подключения при закрытии. Для выхода значение 0; для любого другого завершения подключения — ненулевое значение.

    • connectionid: Идентификатор подключения, которое было закрыто.

Следующий скрипт D оценивает и суммирует среднюю продолжительность индивидуальных подключений, а также предоставляет подсчёт, выгружая информацию каждые 60 секунд:

#!/usr/sbin/dtrace -s


mysql*:::connection-start
{
  self->start = timestamp;
}

mysql*:::connection-done
/self->start/
{
  @ = quantize(((timestamp - self->start)/1000000));
  self->start = 0;
}

tick-60s
{
  printa(@);
}

При выполнении на сервере с большим количеством клиентов, возможно получение вывода подобного:

  1  57413                        :tick-60s

           value  ------------- Distribution ------------- count
              -1 |                                         0
               0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 30011
               1 |                                         59
               2 |                                         5
               4 |                                         20
               8 |                                         29
              16 |                                         18
              32 |                                         27
              64 |                                         30
             128 |                                         11
             256 |                                         10
             512 |                                         1
            1024 |                                         6
            2048 |                                         8
            4096 |                                         9
            8192 |                                         8
           16384 |                                         2
           32768 |                                         1
           65536 |                                         1
          131072 |                                         0
          262144 |                                         1
          524288 |                                         0        
END_OF_DOCUMENT_MARKER
5.8.4.1.2 Запросы команд

Запросы команд выполняются до и после выполнения клиентской команды, включая любое SQL-выражение, которое может быть выполнено в этот период. Команды включают операции, такие как инициализация базы данных, использование операции COM_CHANGE_USER (поддерживаемой протоколом MySQL) и манипулирование подготовленными запросами. Многие из этих команд используются только API MySQL-клиента из различных коннекторов, таких как PHP и Java.

command-start(connectionid, command, user, host)
command-done(status)
  • command-start: Срабатывает при отправке команды на сервер.

    • connectionid: Идентификатор подключения клиента, выполняющего команду.

    • command: Целое число, представляющее команду, которая была выполнена. Возможные значения показаны в следующей таблице.

      Значение Имя Описание
      00 COM_SLEEP Внутреннее состояние потока
      01 COM_QUIT Закрыть соединение
      02 COM_INIT_DB Выбор базы данных (USE ...)
      03 COM_QUERY Выполнение запроса
      04 COM_FIELD_LIST Получение списка полей
      05 COM_CREATE_DB Создание базы данных (устарело)
      06 COM_DROP_DB Удаление базы данных (устарело)
      07 COM_REFRESH Обновить соединение
      08 COM_SHUTDOWN Выключение сервера
      09 COM_STATISTICS Получить статистику
      10 COM_PROCESS_INFO Получить процессы (SHOW PROCESSLIST)
      11 COM_CONNECT Инициализация соединения
      12 COM_PROCESS_KILL Убить процесс
      13 COM_DEBUG Получить отладочную информацию
      14 COM_PING Ping
      15 COM_TIME Внутреннее состояние потока
      16 COM_DELAYED_INSERT Внутреннее состояние потока
      17 COM_CHANGE_USER Изменить пользователя
      18 COM_BINLOG_DUMP Используется репликой или mysqlbinlog для запуска чтения двоичного лога
      19 COM_TABLE_DUMP Используется репликой для получения информации о таблице источника
      20 COM_CONNECT_OUT Используется репликой для протоколирования соединения с сервером
      21 COM_REGISTER_SLAVE Используется репликой во время регистрации
      22 COM_STMT_PREPARE Подготовить оператор
      23 COM_STMT_EXECUTE Выполнить оператор
      24 COM_STMT_SEND_LONG_DATA Используется клиентом при запросе расширенных данных
      25 COM_STMT_CLOSE Закрыть подготовленный оператор
      26 COM_STMT_RESET Сбросить подготовленный оператор
      27 COM_SET_OPTION Установить опцию сервера
      28 COM_STMT_FETCH Извлечь подготовленный оператор
    • user: Пользователь, выполняющий команду.

    • host: Хост клиента.

  • command-done: Срабатывает при завершении выполнения команды. Аргумент status содержит 0, если команда выполнена успешно, или 1, если оператор был прерван до нормального завершения.

Запросы command-start и command-done лучше всего использовать в сочетании с запросами операторов, чтобы получить представление о времени выполнения в целом.

5.8.4.1.3 Запросы операторов

Запросы query-start и query-done срабатывают при получении сервером определенного запроса и после завершения запроса и успешной отправки информации клиенту.

query-start(query, connectionid, database, user, host)
query-done(status)
  • query-start: Срабатывает после получения строки запроса от клиента. Аргументы:

    • query: Полный текст отправленного запроса.

    • connectionid: Идентификатор подключения клиента, который отправил запрос. Идентификатор подключения равен идентификатору подключения, возвращённому при первом подключении клиента, и значению Id в выводе из SHOW PROCESSLIST.

    • database: Имя базы данных, в которой выполняется запрос.

    • user: Имя пользователя, используемого для подключения к серверу.

    • host: Имя хоста клиента.

  • query-done: Срабатывает после выполнения запроса и возвращения информации клиенту. Запрос содержит один аргумент, status, который возвращает 0 при успешном выполнении запроса и 1, если произошла ошибка.

Вы можете получить простой отчёт о времени выполнения каждого запроса, используя следующий скрипт D:

#!/usr/sbin/dtrace -s

#pragma D option quiet

dtrace:::BEGIN
{
   printf("%-20s %-20s %-40s %-9s\n", "Who", "Database", "Query", "Time(ms)");
}

mysql*:::query-start
{
   self->query = copyinstr(arg0);
   self->connid = arg1;
   self->db    = copyinstr(arg2);
   self->who   = strjoin(copyinstr(arg3),strjoin("@",copyinstr(arg4)));
   self->querystart = timestamp;
}

mysql*:::query-done
{
   printf("%-20s %-20s %-40s %-9d\n",self->who,self->db,self->query,
          (timestamp - self->querystart) / 1000000);
}

При выполнении вышеуказанного скрипта вы получите общее представление о времени выполнения запросов:

$> ./query.d
Who                  Database             Query                                    Time(ms)
root@localhost       test                 select * from t1 order by i limit 10     0
root@localhost       test                 set global query_cache_size=0            0
root@localhost       test                 select * from t1 order by i limit 10     776
root@localhost       test                 select * from t1 order by i limit 10     773
root@localhost       test                 select * from t1 order by i desc limit 10 795 
5.8.4.1.4 Запросы разбора операторов

Запросы разбора операторов срабатывают перед разбором исходного SQL-оператора и после завершения разбора оператора и определения модели выполнения, необходимой для обработки оператора:

query-parse-start(query)
query-parse-done(status)
  • query-parse-start: Срабатывает непосредственно перед разбором оператора парсером MySQL. Единственный аргумент, query, — строка, содержащая полный текст исходного запроса.

  • query-parse-done: Срабатывает по завершении разбора исходного оператора. status — целое число, описывающее состояние операции. 0 указывает, что запрос был успешно разобран. 1 указывает, что разбор запроса не удался.

Например, вы можете отслеживать время выполнения разбора определённого запроса, используя следующий скрипт D:

#!/usr/sbin/dtrace -s

#pragma D option quiet

mysql*:::query-parse-start
{
   self->parsestart = timestamp;
   self->parsequery = copyinstr(arg0);
}

mysql*:::query-parse-done
/arg0 == 0/
{
   printf("Parsing %s: %d microseconds\n", self->parsequery,((timestamp - self->parsestart)/1000));
}

mysql*:::query-parse-done
/arg0 != 0/
{
   printf("Error parsing %s: %d microseconds\n", self->parsequery,((timestamp - self->parsestart)/1000));
}

В вышеприведённом скрипте используется предикат на query-parse-done, чтобы генерировать различный вывод в зависимости от значения состояния запроса.

При запуске скрипта и отслеживании выполнения:

$> ./query-parsing.d
Error parsing select from t1 join (t2) on (t1.i = t2.i) order by t1.s,t1.i limit 10: 36 ms
Parsing select * from t1 join (t2) on (t1.i = t2.i) order by t1.s,t1.i limit 10: 176 ms
5.8.4.1.5 Запросы к кэшу запросов

Запросы к кэшу запросов запускаются при выполнении любого запроса. Запрос query-cache-hit срабатывает, когда запрос присутствует в кэше запросов, и может быть использован для возвращения информации о кэше запросов. Аргументы содержат исходный текст запроса и количество строк, возвращённых из кэша запросов для запроса. Если запрос не находится в кэше запросов или кэш запросов отключён, то вместо этого срабатывает запрос query-cache-miss.

query-cache-hit(query, rows)
query-cache-miss(query)
  • query-cache-hit: Срабатывает, когда запрос найден в кэше запросов. Первый аргумент, query, содержит исходный текст запроса. Второй аргумент, rows, — целое число, содержащее количество строк в кэшированном запросе.

  • query-cache-miss: Срабатывает, когда запрос не найден в кэше запросов. Первый аргумент, query, содержит исходный текст запроса.

Запросы к кэшу запросов лучше всего комбинировать с запросом на основной запрос, чтобы определить разницу во времени между использованием или неиспользованием кэша запросов для определенных запросов. Например, в следующем скрипте D информация о запросе и кэше запросов объединяется в вывод информации во время мониторинга:

#!/usr/sbin/dtrace -s

#pragma D option quiet

dtrace:::BEGIN
{
   printf("%-20s %-20s %-40s %2s %-9s\n", "Who", "Database", "Query", "QC", "Time(ms)");
}

mysql*:::query-start
{
   self->query = copyinstr(arg0);
   self->connid = arg1;
   self->db    = copyinstr(arg2);
   self->who   = strjoin(copyinstr(arg3),strjoin("@",copyinstr(arg4)));
   self->querystart = timestamp;
   self->qc = 0;
}

mysql*:::query-cache-hit
{
   self->qc = 1;
}

mysql*:::query-cache-miss
{
   self->qc = 0;
}

mysql*:::query-done
{
   printf("%-20s %-20s %-40s %-2s %-9d\n",self->who,self->db,self->query,(self->qc ? "Y" : "N"),
          (timestamp - self->querystart) / 1000000);
}

При выполнении скрипта вы можете увидеть влияние кэша запросов. Изначально кэш запросов отключён. Если вы установите размер кэша запросов и затем выполните запрос несколько раз, вы должны увидеть, что кэш запросов используется для возвращения данных запроса:

$> ./query-cache.d
root@localhost       test                 select * from t1 order by i limit 10     N  1072
root@localhost                            set global query_cache_size=262144       N  0
root@localhost       test                 select * from t1 order by i limit 10     N  781
root@localhost       test                 select * from t1 order by i limit 10     Y  0 
5.8.4.1.6 Пробы выполнения запросов

Проба выполнения запроса срабатывает, когда начинается фактическое выполнение запроса после анализа и проверки кэша запросов, но перед проверкой привилегий или оптимизацией. Сравнивая разницу между началом и завершением пробы, можно отслеживать фактическое время, затраченное на обработку запроса (вместо просто обработки синтаксического анализа и других элементов запроса).

query-exec-start(query, connectionid, database, user, host, exec_type)
query-exec-done(status)
Примечание

Информация, предоставленная в аргументах для query-start и query-exec-start, почти идентична и предназначена для того, чтобы вы могли выбрать мониторинг всего процесса запроса (используя query-start) или только выполнения (используя query-exec-start), одновременно предоставляя основную информацию о пользователе, клиенте и выполняемом запросе.

  • query-exec-start: Срабатывает при запуске выполнения отдельного запроса. Аргументы:

    • query: Полный текст отправленного запроса.

    • connectionid: Идентификатор соединения клиента, который отправил запрос. Идентификатор соединения равен идентификатору соединения, возвращенному при первом подключении клиента, и значению Id в выводе из SHOW PROCESSLIST.

    • database: Имя базы данных, в которой выполняется запрос.

    • user: Имя пользователя, используемого для подключения к серверу.

    • host: Имя хоста клиента.

    • exec_type: Тип выполнения. Типы выполнения определяются на основе содержимого запроса и места его отправки. Значения для каждого типа показаны в следующей таблице.

      Значение Описание
      0 Выполненный запрос из sql_parse, запрос верхнего уровня.
      1 Выполнение подготовленного оператора
      2 Выполнение оператора курсора
      3 Выполнение запроса в хранимой процедуре
  • query-exec-done: Срабатывает, когда выполнение запроса завершено. Проба включает один аргумент, status, который возвращает 0 при успешном выполнении запроса и 1, если произошла ошибка.

5.8.4.1.7 Пробы на уровне строк

Пробы на уровне строк срабатывают каждый раз, когда операция над строкой передается в движок хранения. Например, если вы выполняете оператор INSERT с 100 строками данных, то пробы insert-row-start и insert-row-done срабатывают по 100 раз для каждой вставки строки.

insert-row-start(database, table)
insert-row-done(status)

update-row-start(database, table)
update-row-done(status)

delete-row-start(database, table)
delete-row-done(status)
  • insert-row-start: Срабатывает перед вставкой строки в таблицу.

  • insert-row-done: Срабатывает после вставки строки в таблицу.

  • update-row-start: Срабатывает перед обновлением строки в таблице.

  • update-row-done: Срабатывает после обновления строки в таблице.

  • delete-row-start: Срабатывает перед удалением строки из таблицы.

  • delete-row-done: Срабатывает после удаления строки из таблицы.

Аргументы, поддерживаемые пробами, согласованы для соответствующих start и done проб в каждом случае:

  • database: Имя базы данных.

  • table: Имя таблицы.

  • status: Статус; 0 для успеха или 1 для неудачи.

Поскольку пробы на уровне строк срабатывают для каждого отдельного доступа к строке, эти пробы могут срабатывать много тысяч раз в секунду, что может негативно повлиять на скрипт мониторинга и MySQL. Окружение DTrace должно ограничивать срабатывание этих проб, чтобы предотвратить негативное влияние на производительность. Используйте эти пробы экономно или используйте счетчики или агрегационные функции для отчетности по этим пробам, а затем предоставьте сводку при завершении скрипта или в рамках query-done или query-exec-done проб.

Следующий пример скрипта суммирует продолжительность каждой операции со строкой в пределах более крупного запроса:

#!/usr/sbin/dtrace -s

#pragma D option quiet

dtrace:::BEGIN
{
   printf("%-2s %-10s %-10s %9s %9s %-s \n",
          "St", "Who", "DB", "ConnID", "Dur ms", "Query");
}

mysql*:::query-start
{
   self->query = copyinstr(arg0);
   self->who   = strjoin(copyinstr(arg3),strjoin("@",copyinstr(arg4)));
   self->db    = copyinstr(arg2);
   self->connid = arg1;
   self->querystart = timestamp;
   self->rowdur = 0;
}

mysql*:::query-done
{
   this->elapsed = (timestamp - self->querystart) /1000000;
   printf("%2d %-10s %-10s %9d %9d %s\n",
          arg0, self->who, self->db,
          self->connid, this->elapsed, self->query);
}

mysql*:::query-done
/ self->rowdur /
{
   printf("%34s %9d %s\n", "", (self->rowdur/1000000), "-> Row ops");
}

mysql*:::insert-row-start
{
   self->rowstart = timestamp;
}

mysql*:::delete-row-start
{
   self->rowstart = timestamp;
}

mysql*:::update-row-start
{
   self->rowstart = timestamp;
}

mysql*:::insert-row-done
{
   self->rowdur += (timestamp-self->rowstart);
}

mysql*:::delete-row-done
{
   self->rowdur += (timestamp-self->rowstart);
}

mysql*:::update-row-done
{
   self->rowdur += (timestamp-self->rowstart);
}

Выполняя вышеуказанный скрипт с запросом, который вставляет данные в таблицу, вы можете отслеживать точное время, затраченное на выполнение фактической вставки строк:

St Who        DB            ConnID    Dur ms Query
 0 @localhost test              13     20767 insert into t1(select * from t2)
                                        4827 -> Row ops
5.8.4.1.8 Пробы чтения строк

Пробы чтения строк срабатывают на уровне движка хранения каждый раз, когда происходит операция чтения строки. Эти пробы определяются внутри каждого движка хранения (в отличие от проб *row-start, которые находятся в интерфейсе движка хранения). Таким образом, эти пробы можно использовать для отслеживания отдельных операций и производительности чтения строк на уровне движка хранения. Поскольку эти пробы срабатывают вокруг интерфейса чтения строк движка хранения, они могут вызываться значительное количество раз во время простого запроса.

read-row-start(database, table, scan_flag)
read-row-done(status)
  • read-row-start: Срабатывает, когда строка считывается движком хранения из указанного database и table. scan_flag устанавливается в 1 (истина), когда чтение является частью сканирования таблицы (то есть последовательного чтения), или в 0 (ложь), когда считывается конкретная запись.

  • read-row-done: Срабатывает, когда операция чтения строки внутри движка хранения завершается. status возвращает 0 при успехе или положительное значение при ошибке.

5.8.4.1.9 Пробы индексов

Пробы индексов срабатывают каждый раз, когда строка считывается с использованием одного из индексов для указанной таблицы. Проба срабатывает внутри соответствующего движка хранения для таблицы.

index-read-row-start(database, table)
index-read-row-done(status)
  • index-read-row-start: Срабатывает, когда строка считывается движком хранения из указанного database и table.

  • index-read-row-done: Срабатывает, когда операция чтения индексированной строки внутри движка хранения завершается. status возвращает 0 при успехе или положительное значение при ошибке.

5.8.4.1.10 Пробы блокировок

Пробы блокировок вызываются всякий раз, когда MySQL запрашивает внешнюю блокировку таблицы с использованием соответствующего механизма блокировки таблицы, определенного типом движка таблицы. Существует три различных типа блокировок: чтение, запись и разблокировка. Используя пробы, можно определить продолжительность внешней процедуры блокировки (то есть время, затраченное движком хранения на реализацию блокировки, включая время ожидания, пока другая блокировка не освободится), и общее время процесса блокировки/разблокировки.

handler-rdlock-start(database, table)
handler-rdlock-done(status)

handler-wrlock-start(database, table)
handler-wrlock-done(status)

handler-unlock-start(database, table)
handler-unlock-done(status)
  • handler-rdlock-start: Срабатывает при запросе блокировки чтения на указанном database и table.

  • handler-wrlock-start: Срабатывает при запросе блокировки записи на указанном database и table.

  • handler-unlock-start: Срабатывает при запросе разблокировки на указанном database и table.

  • handler-rdlock-done: Срабатывает при завершении запроса блокировки чтения. status равно 0, если операция блокировки выполнена успешно, или >0 при ошибке.

  • handler-wrlock-done: Срабатывает при завершении запроса блокировки записи. status равно 0, если операция блокировки выполнена успешно, или >0 при ошибке.

  • handler-unlock-done: Срабатывает при завершении запроса разблокировки. status равно 0, если операция разблокировки выполнена успешно, или >0 при ошибке.

Для мониторинга блокировки и разблокировки отдельных таблиц можно использовать массивы, а затем вычислять продолжительность всей блокировки таблицы с помощью следующего скрипта:

#!/usr/sbin/dtrace -s

#pragma D option quiet

mysql*:::handler-rdlock-start
{
   self->rdlockstart = timestamp;
   this->lockref = strjoin(copyinstr(arg0),strjoin("@",copyinstr(arg1)));
   self->lockmap[this->lockref] = self->rdlockstart;
   printf("Start: Lock->Read   %s.%s\n",copyinstr(arg0),copyinstr(arg1));
}

mysql*:::handler-wrlock-start
{
   self->wrlockstart = timestamp;
   this->lockref = strjoin(copyinstr(arg0),strjoin("@",copyinstr(arg1)));
   self->lockmap[this->lockref] = self->rdlockstart;
   printf("Start: Lock->Write  %s.%s\n",copyinstr(arg0),copyinstr(arg1));
}

mysql*:::handler-unlock-start
{
   self->unlockstart = timestamp;
   this->lockref = strjoin(copyinstr(arg0),strjoin("@",copyinstr(arg1)));
   printf("Start: Lock->Unlock %s.%s (%d ms lock duration)\n",
          copyinstr(arg0),copyinstr(arg1),
          (timestamp - self->lockmap[this->lockref])/1000000);
}

mysql*:::handler-rdlock-done
{
   printf("End:   Lock->Read   %d ms\n",
          (timestamp - self->rdlockstart)/1000000);
}

mysql*:::handler-wrlock-done
{
   printf("End:   Lock->Write  %d ms\n",
          (timestamp - self->wrlockstart)/1000000);
}

mysql*:::handler-unlock-done
{
   printf("End:   Lock->Unlock %d ms\n",
          (timestamp - self->unlockstart)/1000000);
}

При выполнении вы получите информацию как о продолжительности процесса блокировки, так и о блокировках на конкретной таблице:

Start: Lock->Read   test.t2
End:   Lock->Read   0 ms
Start: Lock->Unlock test.t2 (25743 ms lock duration)
End:   Lock->Unlock 0 ms
Start: Lock->Read   test.t2
End:   Lock->Read   0 ms
Start: Lock->Unlock test.t2 (1 ms lock duration)
End:   Lock->Unlock 0 ms
Start: Lock->Read   test.t2
End:   Lock->Read   0 ms
Start: Lock->Unlock test.t2 (1 ms lock duration)
End:   Lock->Unlock 0 ms
Start: Lock->Read   test.t2
End:   Lock->Read   0 ms
5.8.4.1.11 Пробы Filesort

Пробы filesort срабатывают всякий раз, когда операция filesort применяется к таблице. Более подробную информацию о filesort и условиях, при которых она возникает, см. в разделе 8.2.1.14 «Оптимизация ORDER BY».

filesort-start(database, table)
filesort-done(status, rows)
  • filesort-start: Срабатывает при запуске операции filesort для таблицы. Два аргумента пробы, database и table, идентифицируют таблицу, которая сортируется.

  • filesort-done: Срабатывает при завершении операции filesort. Предоставляются два аргумента: status (0 для успеха, 1 для неудачи) и количество отсортированных строк во время процесса filesort.

Пример этого показан в следующем скрипте, который отслеживает продолжительность процесса filesort в дополнение к продолжительности основного запроса:

#!/usr/sbin/dtrace -s

#pragma D option quiet

dtrace:::BEGIN
{
   printf("%-2s %-10s %-10s %9s %18s %-s \n",
          "St", "Who", "DB", "ConnID", "Dur microsec", "Query");
}

mysql*:::query-start
{
   self->query = copyinstr(arg0);
   self->who   = strjoin(copyinstr(arg3),strjoin("@",copyinstr(arg4)));
   self->db    = copyinstr(arg2);
   self->connid = arg1;
   self->querystart = timestamp;
   self->filesort = 0;
   self->fsdb = "";
   self->fstable = "";
}

mysql*:::filesort-start
{
  self->filesort = timestamp;
  self->fsdb = copyinstr(arg0);
  self->fstable = copyinstr(arg1);
}

mysql*:::filesort-done
{
   this->elapsed = (timestamp - self->filesort) /1000;
   printf("%2d %-10s %-10s %9d %18d Filesort on %s\n",
          arg0, self->who, self->fsdb,
          self->connid, this->elapsed, self->fstable);
}

mysql*:::query-done
{
   this->elapsed = (timestamp - self->querystart) /1000;
   printf("%2d %-10s %-10s %9d %18d %s\n",
          arg0, self->who, self->db,
          self->connid, this->elapsed, self->query);
}

Выполнение запроса к большой таблице с условием ORDER BY, которое инициирует filesort, а затем создание индекса в таблице и повторное выполнение того же запроса, позволяют увидеть разницу в скорости выполнения:

St Who        DB            ConnID       Dur microsec Query
 0 @localhost test              14           11335469 Filesort on t1
 0 @localhost test              14           11335787 select * from t1 order by i limit 100
 0 @localhost test              14          466734378 create index t1a on t1 (i)
 0 @localhost test              14              26472 select * from t1 order by i limit 100
5.8.4.1.12 Пробы операторов

Индивидуальные пробы операторов предназначены для предоставления конкретной информации о различных типах операторов. Для проб начала предоставляется строка запроса в качестве единственного аргумента. В зависимости от типа оператора, информация, предоставляемая соответствующей пробой завершения, может отличаться. Для всех проб завершения предоставляется статус операции (0 для успеха, >0 для неудачи). Для операций SELECT, INSERT, INSERT ... (SELECT FROM ...), DELETE и DELETE FROM t1,t2 возвращается количество изменённых строк.

Для операторов UPDATE и UPDATE t1,t2 ... предоставляется количество сопоставленных строк и количество фактически изменённых строк. Это обусловлено тем, что количество строк, фактически сопоставленных соответствующим WHERE условием, и количество изменённых строк могут отличаться. MySQL не обновляет значение строки, если оно уже соответствует новому значению.

select-start(query)
select-done(status,rows)

insert-start(query)
insert-done(status,rows)

insert-select-start(query)
insert-select-done(status,rows)

update-start(query)
update-done(status,rowsmatched,rowschanged)

multi-update-start(query)
multi-update-done(status,rowsmatched,rowschanged)

delete-start(query)
delete-done(status,rows)

multi-delete-start(query)
multi-delete-done(status,rows)
  • select-start: Срабатывает перед оператором SELECT.

  • select-done: Срабатывает в конце оператора SELECT.

  • insert-start: Срабатывает перед оператором INSERT.

  • insert-done: Срабатывает в конце оператора INSERT.

  • insert-select-start: Срабатывает перед оператором INSERT ... SELECT.

  • insert-select-done: Срабатывает в конце оператора INSERT ... SELECT.

  • update-start: Срабатывает перед оператором UPDATE.

  • update-done: Срабатывает в конце оператора UPDATE.

  • multi-update-start: Срабатывает перед оператором UPDATE с участием нескольких таблиц.

  • multi-update-done: Срабатывает в конце оператора UPDATE с участием нескольких таблиц.

  • delete-start: Срабатывает перед оператором DELETE.

  • delete-done: Срабатывает в конце оператора DELETE.

  • multi-delete-start: Срабатывает перед оператором DELETE с участием нескольких таблиц.

  • multi-delete-done: Срабатывает в конце оператора DELETE с участием нескольких таблиц.

Аргументы для проб операторов:

  • query: Строка запроса.

  • status: Статус запроса. 0 для успеха и >0 для неудачи.

  • rows: Количество строк, затронутых оператором. Возвращает количество найденных строк для SELECT, количество удалённых строк для DELETE и количество успешно вставленных строк для INSERT.

  • rowsmatched: Количество строк, сопоставленных с WHERE-условием оператора UPDATE.

  • rowschanged: Количество фактически изменённых строк во время оператора UPDATE.

Используйте эти пробы для отслеживания выполнения этих типов операторов без необходимости мониторинга пользователя или клиента, выполняющего эти операторы. Простой пример - отслеживание времени выполнения:

#!/usr/sbin/dtrace -s

#pragma D option quiet

dtrace:::BEGIN
{
   printf("%-60s %-8s %-8s %-8s\n", "Query", "RowsU", "RowsM", "Dur (ms)");
}

mysql*:::update-start, mysql*:::insert-start,
mysql*:::delete-start, mysql*:::multi-delete-start,
mysql*:::multi-delete-done, mysql*:::select-start,
mysql*:::insert-select-start, mysql*:::multi-update-start
{
    self->query = copyinstr(arg0);
    self->querystart = timestamp;
}

mysql*:::insert-done, mysql*:::select-done,
mysql*:::delete-done, mysql*:::multi-delete-done, mysql*:::insert-select-done
/ self->querystart /
{
    this->elapsed = ((timestamp - self->querystart)/1000000);
    printf("%-60s %-8d %-8d %d\n",
           self->query,
           0,
           arg1,
           this->elapsed);
    self->querystart = 0;
}

mysql*:::update-done, mysql*:::multi-update-done
/ self->querystart /
{
    this->elapsed = ((timestamp - self->querystart)/1000000);
    printf("%-60s %-8d %-8d %d\n",
           self->query,
           arg1,
           arg2,
           this->elapsed);
    self->querystart = 0;
}

При выполнении можно увидеть основные временные затраты и количество сопоставленных строк:

Query                                                        RowsU    RowsM    Dur (ms)
select * from t2                                             0        275      0
insert into t2 (select * from t2)                            0        275      9
update t2 set i=5 where i > 75                               110      110      8
update t2 set i=5 where i < 25                               254      134      12
delete from t2 where i < 5                                   0        0        0

Другой вариант — использование агрегирующих функций в DTrace для агрегации времени выполнения отдельных операторов:

#!/usr/sbin/dtrace -s

#pragma D option quiet


mysql*:::update-start, mysql*:::insert-start,
mysql*:::delete-start, mysql*:::multi-delete-start,
mysql*:::multi-delete-done, mysql*:::select-start,
mysql*:::insert-select-start, mysql*:::multi-update-start
{
    self->querystart = timestamp;
}

mysql*:::select-done
{
        @statements["select"] = sum(((timestamp - self->querystart)/1000000));
}

mysql*:::insert-done, mysql*:::insert-select-done
{
        @statements["insert"] = sum(((timestamp - self->querystart)/1000000));
}

mysql*:::update-done, mysql*:::multi-update-done
{
        @statements["update"] = sum(((timestamp - self->querystart)/1000000));
}

mysql*:::delete-done, mysql*:::multi-delete-done
{
        @statements["delete"] = sum(((timestamp - self->querystart)/1000000));
}

tick-30s
{
        printa(@statements);
}

Приведенный скрипт агрегирует затраченное время на каждую операцию, что может использоваться для тестирования нагрузок.

 delete                                                            0
  update                                                            0
  insert                                                           23
  select                                                         2484

  delete                                                            0
  update                                                            0
  insert                                                           39
  select                                                        10744

  delete                                                            0
  update                                                           26
  insert                                                           56
  select                                                        10944

  delete                                                            0
  update                                                           26
  insert                                                         2287
  select                                                        15985
5.8.4.1.13 Пробы сети

Пробы сети отслеживают передачу информации между сервером MySQL и клиентами всех типов по сети. Пробы определяются следующим образом:

net-read-start()
net-read-done(status, bytes)
net-write-start(bytes)
net-write-done(status)
  • net-read-start: Срабатывает при запуске сетевой операции чтения.

  • net-read-done: Срабатывает при завершении операции сетевого чтения. status — это integer, представляющий статус возврата операции, 0 для успеха и 1 для неудачи. Аргумент bytes — целое число, указывающее количество считанных байтов в процессе.

  • net-start-bytes: Срабатывает при записи данных в сетевой сокет. Единственный аргумент, bytes, задаёт количество байтов, записанных в сетевой сокет.

  • net-write-done: Срабатывает при завершении операции сетевой записи. Единственный аргумент, status, — целое число, представляющее статус возврата операции, 0 для успеха и 1 для неудачи.

Пробы сети можно использовать для мониторинга времени, затраченного на чтение и запись данных от и к сетевым клиентам во время выполнения. Следующий скрипт D предоставляет пример этого. Вычисляется как кумулятивное время для чтения/записи, так и количество байтов. Обратите внимание, что размер динамической переменной увеличен (с помощью опции dynvarsize) для обработки быстрого срабатывания отдельных проб для сетевых чтений/записей.

#!/usr/sbin/dtrace -s

#pragma D option quiet
#pragma D option dynvarsize=4m

dtrace:::BEGIN
{
   printf("%-2s %-30s %-10s %9s %18s %-s \n",
          "St", "Who", "DB", "ConnID", "Dur microsec", "Query");
}

mysql*:::query-start
{
   self->query = copyinstr(arg0);
   self->who   = strjoin(copyinstr(arg3),strjoin("@",copyinstr(arg4)));
   self->db    = copyinstr(arg2);
   self->connid = arg1;
   self->querystart = timestamp;
   self->netwrite = 0;
   self->netwritecum = 0;
   self->netwritebase = 0;
   self->netread = 0;
   self->netreadcum = 0;
   self->netreadbase = 0;
}

mysql*:::net-write-start
{
   self->netwrite += arg0;
   self->netwritebase = timestamp;
}

mysql*:::net-write-done
{
   self->netwritecum += (timestamp - self->netwritebase);
   self->netwritebase = 0;
}

mysql*:::net-read-start
{
   self->netreadbase = timestamp;
}

mysql*:::net-read-done
{
   self->netread += arg1;
   self->netreadcum += (timestamp - self->netreadbase);
   self->netreadbase = 0;
}

mysql*:::query-done
{
   this->elapsed = (timestamp - self->querystart) /1000000;
   printf("%2d %-30s %-10s %9d %18d %s\n",
          arg0, self->who, self->db,
          self->connid, this->elapsed, self->query);
   printf("Net read: %d bytes (%d ms) write: %d bytes (%d ms)\n",
               self->netread, (self->netreadcum/1000000),
               self->netwrite, (self->netwritecum/1000000));
}

При выполнении вышеуказанного скрипта на машине с удалённым клиентом можно увидеть, что примерно треть времени, затрачиваемого на выполнение запроса, связана с отправкой результатов запроса обратно клиенту.

St Who                            DB            ConnID       Dur microsec Query
 0 root@::ffff:198.51.100.108      test              31               3495 select * from t1 limit 1000000
Net read: 0 bytes (0 ms) write: 10000075 bytes (1220 ms)
5.8.4.1.14 Пробы кэша ключей

Пробы кэша ключей срабатывают при использовании кэша индексных ключей с движком хранения MyISAM. Пробы предназначены для мониторинга момента, когда данные считываются в кэш ключей, кэшированные данные ключей записываются из кэша в кэшированный файл или при доступе к кэшу ключей.

Использование кэша ключей показывает, когда данные считываются или записываются из файлов индексов в кэш, и может использоваться для мониторинга эффективности использования памяти, выделенной для кэша ключей. Большое количество чтений из кэша ключей в различных запросах может указывать на то, что кэш ключей слишком мал для размера данных, к которым осуществляется доступ.

keycache-read-start(filepath, bytes, mem_used, mem_free)
keycache-read-block(bytes)
keycache-read-hit()
keycache-read-miss()
keycache-read-done(mem_used, mem_free)
keycache-write-start(filepath, bytes, mem_used, mem_free)
keycache-write-block(bytes)
keycache-write-done(mem_used, mem_free)

При чтении данных из файлов индексов в кэш ключей, процесс сначала инициализирует операцию чтения (указано keycache-read-start), затем загружает блоки данных (keycache-read-block), а затем считанный блок либо соответствует искомым данным (keycache-read-hit), либо требуется чтение дополнительных данных (keycache-read-miss). После завершения операции чтения, чтение останавливается с keycache-read-done.

Данные могут быть считаны из файла индекса в кэш ключей только тогда, когда указанный ключ ещё не находится в кэше ключей.

  • keycache-read-start: Срабатывает при запуске операции чтения из кэша ключей. Данные считываются из указанного filepath, читая указанное количество bytes. mem_used и mem_avail указывают на память, в настоящее время используемую кэшем ключей, и количество доступной памяти в кэше ключей.

  • keycache-read-block: Срабатывает, когда кэш ключей считывает блок данных, содержащий указанное количество bytes, из файла индекса в кэш ключей.

  • keycache-read-hit: Срабатывает, когда блок данных, считанный из файла индекса, соответствует запрошенным данным ключа.

  • keycache-read-miss: Срабатывает, когда блок данных, считанный из файла индекса, не соответствует необходимым данным ключа.

  • keycache-read-done: Срабатывает по завершении операции чтения из кэша ключей. mem_used и mem_avail указывают на память, в настоящее время используемую кэшем ключей, и количество доступной памяти в кэше ключей.

Запись в кэш ключей происходит, когда информация индекса обновляется во время операции INSERT, UPDATE или DELETE, и кэшированная информация ключа записывается обратно в файл индекса.

  • keycache-write-start: Срабатывает при запуске операции записи в кэш ключей. Данные записываются в указанный filepath, читая указанное количество bytes. mem_used и mem_avail указывают на память, в настоящее время используемую кэшем ключей, и количество доступной памяти в кэше ключей.

  • keycache-write-block: Срабатывает, когда кэш ключей записывает блок данных, содержащий указанное количество bytes, в файл индекса из кэша ключей.

  • keycache-write-done: Срабатывает по завершении операции записи в кэш ключей. mem_used и mem_avail указывают на память, в настоящее время используемую кэшем ключей, и количество доступной памяти в кэше ключей.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/dba-dtrace-mysqld-ref.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API