Есть ли способ увидеть ход выполнения инструкции ALTER TABLE в MySQL? - PullRequest
25 голосов
/ 04 сентября 2008

Например, я выполнил инструкцию ALTER TABLE, чтобы создать индекс для поля MEDIUMTEXT в таблице InnoDB, содержащей 134 тыс. Строк, где размер индекса составлял 255 байт, а средний размер данных в поле - 30 тыс. Эта команда выполнялась в течение последних 15 минут или около того (и это единственное, что выполняется в базе данных). Могу ли я определить, закончится ли он ближе к 5 минутам, 5 часам или 5 дням?

Ответы [ 8 ]

19 голосов
/ 10 октября 2011

Мне удалось выполнить эти 2 запроса и выяснить, сколько строк осталось переместить.

select count(*) from `myoriginalrable`;
select count(*) from `#sql-1e8_11ae5`;

это было бы гораздо полезнее, чем сравнение размера файла на диске, потому что переход от myisam к innodb и т. Д. Изменяет размер строки.

11 голосов
/ 21 августа 2012

В случае таблиц InnoDB можно использовать SHOW ENGINE INNODB STATUS, чтобы найти транзакцию, выполняющую ALTER TABLE, и проверить, сколько блокировок строк содержит TX. Это количество обработанных строк. Подробно объяснил здесь:

http://gabrielcain.com/blog/2009/08/05/mysql-alter-table-and-how-to-observe-progress/

Также MariaDB 5.3 и более поздние версии имеют возможность сообщать о ходе выполнения некоторых операций (включая ALTER TABLE). См:

http://kb.askmonty.org/en/progress-reporting/

3 голосов
/ 20 июля 2013

Я сделал запрос, который оценивает время завершения команды alter в таблице innodb. Вы должны запустить его как минимум дважды в одном сеансе, так как он сравнивает статистику от последовательных прогонов, чтобы сделать оценку. Не забудьте заменить на правильное имя таблицы в четвертой строке. Это дает вам две оценки. Локальная оценка использует только данные между прогонами, в то время как Глобальная оценка использует все время транзакции.

select 
beginsd, now(), qRuns, qTime, tName, trxStarted, trxTime, `rows`, modified, locked, hoursLeftL, estimatedEndL, modifiedPerSecL, avgRows, estimatedEndG, modifiedPerSecG, hoursLeftG
from (
select 
    (@tname:='<table>') tName,
    @beginsd:=sysdate() beginsd,
    @trxStarted:=(select trx_started from information_schema.innodb_trx where trx_query like concat('alter table %', @tname, '%')) trxStarted, 
    @trxTime:=timediff(@beginsd, @trxStarted) trxTime,
    @rows:=(select table_rows from information_schema.tables where table_name like @tname) `rows`,
    @runs:=(ifnull(@runs, 0)+1) qRuns,
    @rowsSum:=(ifnull(@rowsSum, 0)+@rows),
    round(@avgRows:=(@rowsSum / @runs)) avgRows,
    @modified:=(select trx_rows_modified from information_schema.innodb_trx where trx_query like concat('alter table %', @tname, '%')) modified, 
    @rowsLeftL:=(cast(@rows as signed) - cast(@modified as signed)) rowsLeftL,
    round(@rowsLeftG:=(cast(@avgRows as signed) - cast(@modified as signed)), 2) rowsLeftG,
    @locked:=(select trx_rows_locked from information_schema.innodb_trx where trx_query like concat('alter table %', @tname, '%')) locked,
    @endsd:=sysdate() endsd,
    --
    time_to_sec(timediff(@endsd, @beginsd)) qTime,
    @modifiedInc:=(cast(@modified as signed) - cast(@p_modified as signed)) modifiedInc,
    @timeInc:=time_to_sec(timediff(@beginsd, @p_beginsd)) timeInc,
    round(@modifiedPerSecL:=(@modifiedInc/@timeInc)) modifiedPerSecL,
    round(@modifiedPerSecG:=(@modified/time_to_sec(@trxTime))) modifiedPerSecG,
    round(@minutesLeftL := (@rowsLeftL / @modifiedPerSecL / 60)) minutesLeftL,
    round(@minutesLeftG := (@rowsLeftG / @modifiedPerSecG / 60)) minutesLeftG,
    round(@hoursLeftL := (@minutesLeftL / 60), 2) hoursLeftL,
    round(@hoursLeftG := (@minutesLeftG / 60), 2) hoursLeftG,
    (@beginsd + INTERVAL @minutesLeftL MINUTE) estimatedEndL,
    (@beginsd + INTERVAL @minutesLeftG MINUTE) estimatedEndG,
    --
    @p_rows:=@rows,
    @p_modified:=@modified,
    @p_beginsd:=@beginsd
) sq;
3 голосов
/ 04 сентября 2008

Похоже, что это довольно распространенный запрос - он был запрошен еще в 2005 году на bugs.mysql.com . Он уже существует в Oracle и указан как полезный, но "это не простая вещь, поэтому не ожидайте, что она будет скоро будет осуществлено. ". Хотя это был 2005 год :)

Тем не менее, парень, который задал оригинальный вопрос, позже выпустил патч для MySQL 5.0, перенесенный на 4.1, который может помочь вам.

1 голос
/ 29 октября 2012

pt-online-schema-change от Percona показывает оценку оставшегося времени. По умолчанию он выводит оценку оставшегося времени и процент выполнения каждые 30 секунд.

Он также имеет дополнительные функции по сравнению с простым выполнением команды ALTER.

http://www.percona.com/doc/percona-toolkit/2.1/pt-online-schema-change.html

0 голосов
/ 22 февраля 2019

если кто-то хочет решения bash: (sql у меня не работал)

cd /var/lib/mysql/mydb
TABLEFILE="MYTABLE.ibd"
TEMPFILE="\#*ibd"

ls -lah $TABLEFILE;
ls -lah $TEMPFILE; # make sure you have only one temp file or modify the above TEMPFILE

SIZE_TOTAL=$(stat -c %s $TABLEFILE);

# other ways to get 1st size and time
#SIZE1=1550781106; TIME1=1550781106;
#SIZE1=$(stat -c %s $TEMPFILE); TIME1=$(stat -c %Z $TEMPFILE);  sleep 10;
SIZE1=0; TIME1=$(stat -c %X $TEMPFILE); # use file create time

echo "SIZE1=$TIME1; TIME1=$TIME1";

SIZE2=$(stat -c %s $TEMPFILE); TIME2=$(stat -c %Z $TEMPFILE);

DELTA_SIZE=$(( $SIZE2 - $SIZE1 ))
DELTA_TIME=$(( $TIME2 - $TIME1 ))

# debug last numbers should not be zero:

echo $SIZE1  $SIZE2  $SIZE_TOTAL  $DELTA_SIZE;
echo $TIME1  $TIME2  $DELTA_TIME;

SIZE_PER_SECOND=$( awk "BEGIN {print $DELTA_SIZE  / $DELTA_TIME }" );
SIZE_LEFT=$(($SIZE_TOTAL - $SIZE2));
TIME_LEFT_SECONDS=$( awk "BEGIN { print  ( $SIZE_LEFT  / $SIZE_PER_SECOND) }" );
TIME_LEFT_MINUTES=$( awk "BEGIN { print  $TIME_LEFT_SECONDS /60 }" );
TIME_LEFT=$( awk "BEGIN { printf \"%d:%02d:%2d\", int($TIME_LEFT_MINUTES /60), int($TIME_LEFT_MINUTES % 60), int($TIME_LEFT_SECONDS % 60 )  }" );

echo "TIME_LEFT = $TIME_LEFT";
echo "SIZE_LEFT = $SIZE_LEFT" "MB=" $(( $SIZE_LEFT/1024/1024 )) ;
awk "BEGIN { if( $SIZE_TOTAL == $SIZE2 ) print \"mysql finished\" }" ;

free -h # check free memory, sometimes it is full and it makes it slow

выводы: это требует времени, много времени.

просто убедитесь, что баран свободен. и свободное пространство. как 50% памяти не используется mysql.

низкий таран заставляет всю систему работать очень низко

0 голосов
/ 10 февраля 2019

Запустите ls -laShr /var/lib/mysql | sort -h, и вы увидите файлы в папке mysql примерно так: "

-rw-r----- 1 mysql mysql 3.3G Feb  9 13:21 sql-#2088_10fa.ibd
-rw-r----- 1 mysql mysql 10.2G Feb  9 13:21 posts.ibd

Вы можете видеть исходный файл таблицы и файл временной целевой таблицы в том виде, как он создается, с удобочитаемыми размерами. Обычно он будет расти линейно со временем, поэтому, если он вдвое меньше оригинальной таблицы, он будет на полпути. Команда ls отсортирует файлы по размеру, поэтому оба файла будут в нижней части списка файлов, если это большая таблица и вы долго ждали.

0 голосов
/ 20 июля 2013

Percona Server , который является разветвленной версией MySQL с некоторыми улучшениями, имеет эту функцию.

Вы можете наблюдать дополнительные столбцы в SHOW PROCESSLIST для ROWS_SENT и ROWS_EXAMINED. Например, если в вашей таблице 1000000 строк, и вы видите ROWS_EXAMINED, равный 650000, то она завершена на 65%.

См. http://www.percona.com/doc/percona-server/5.6/diagnostics/process_list.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...