LINUX.ORG.RU

Специалистам по awk


0

1

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

Тест 1:

root@server1:~/test/21# cat /etc/fstab | awk 'BEGIN {n=0}; /sda/{n+=1}; {print > n}'
root@server1:~/test/21# ls -lA
итого 16
-rw-r----- 1 root root 306 Фев 22 03:19 0
-rw-r----- 1 root root  34 Фев 22 03:19 1
-rw-r----- 1 root root  33 Фев 22 03:19 2
-rw-r----- 1 root root  64 Фев 22 03:19 3

Файл нарезался нормально. Результат одинаковый для gawk и mawk.

Теперь берем дамп, проделываем то же самое с ним:

root@server1:~/test/21# pbunzip2 -c ../../file.sql.bz2 | gawk 'BEGIN {n=0}; /DROP TABLE IF EXIST/{n+=1}; {print > n}'

 *Control-C or similar caught, quitting...
pbzip2:  *WARNING: Deletion of output file (apparently) failed.

root@server1:~/test/21# ls -l
итого 542268
-rw-r----- 1 root root         0 Фев 22 03:21 0
-rw-r----- 1 root root      4096 Фев 22 03:21 1
-rw-r----- 1 root root         0 Фев 22 03:21 10
-rw-r----- 1 root root         0 Фев 22 03:21 11
-rw-r----- 1 root root         0 Фев 22 03:21 12
-rw-r----- 1 root root         0 Фев 22 03:21 13
-rw-r----- 1 root root      4096 Фев 22 03:21 14
-rw-r----- 1 root root     20480 Фев 22 03:21 15
-rw-r----- 1 root root  10956800 Фев 22 03:21 16
******

Часть файлов получается нулевого размера. Ок, посмотрим, что происходит в awk'e:

root@server1:~/test/21# bunzip2 -c ../../file.sql.bz2 | gawk 'BEGIN {n=0}; /DROP TABLE IF EXIST/{n+=1}; {print n, $0}' | head
0 -- MySQL dump 10.13  Distrib 5.5.20, for Linux (x86_64)
0 --
0 -- Host: localhost    Database: database
0 -- ------------------------------------------------------

и так далее

т.е., вроде как все ок должно быть во 2-м тесте, но не работает. Ок, сделаем костыль:

root@server1:~/test/21# bunzip2 -c ../../file.sql.bz2 | gawk 'BEGIN {n=0}; /DROP TABLE IF EXIST/{n+=1}; {print | "cat >"n}'

root@server1:~/test/21# ls -l
итого 51760
-rw-r----- 1 root root      784 Фев 22 03:26 0
-rw-r----- 1 root root     4111 Фев 22 03:26 1
-rw-r----- 1 root root      972 Фев 22 03:26 10
-rw-r----- 1 root root      737 Фев 22 03:26 11
-rw-r----- 1 root root     2320 Фев 22 03:26 12

*********

Так работает, в «0» получаем заголовок таблицы, в остальных файлах - сами таблицы. Такой вариант пока и использую, но хотелось бы mawk.

Пробую любой вариант с mawk - получаю некоторые пустые файлы на выходе как во 2-м тесте.

Почему так происходит?

И да, зачем mawk:

pbunzip2 -c ../../file.sql.bz2 | pv -cN pregawk | gawk '{print}' | pv -cN out > file
  pregawk: 1,38GB 0:00:11 [ 183MB/s]
pbunzip2 -c ../../file.sql.bz2 | pv -cN pregawk | gawk '//{print}' | pv -cN out > file
  pregawk: 61,3MB 0:00:06 [24,5MB/s]

А вот mawk в любом варианте:

pbunzip2 -c ../../file.sql.bz2 | pv -cN pregawk | mawk '//{print}' | pv -cN out > file
  pregawk:  782MB 0:00:11 [ 237MB/s]

★★★★★

Последнее исправление: YAR (всего исправлений: 1)

Часть файлов получается нулевого размера.

Ты же pbunzip убиваешь по Ctrl+C, awk не успевает скинуть буферизированные данные. Те что превышают 4К скидываются автоматом. Добавь после { print > n; fflush() }

sdio ★★★★★
()
Ответ на: комментарий от sdio

Я его в любом случае убиваю по Ctrl+c и в любом случае после того, как обработаются несколько десятков таблиц размером несколько сотен Мб. В любом случае:

root@server1:~/test/21# bunzip2 -c ../../file.sql.bz2 | mawk 'BEGIN {n=0}; /DROP TABLE IF EXIST/{n+=1}; {print > n; fflush()}'

root@server1:~/test/21# ls -lh 
итого 246M
-rw-r----- 1 root root    0 Фев 22 03:50 0
-rw-r----- 1 root root 4,0K Фев 22 03:50 1
-rw-r----- 1 root root    0 Фев 22 03:50 10
-rw-r----- 1 root root    0 Фев 22 03:50 11
-rw-r----- 1 root root    0 Фев 22 03:50 12
-rw-r----- 1 root root    0 Фев 22 03:50 13
-rw-r----- 1 root root 4,0K Фев 22 03:50 14
-rw-r----- 1 root root  20K Фев 22 03:50 15
-rw-r----- 1 root root  11M Фев 22 03:50 16
-rw-r----- 1 root root 4,0K Фев 22 03:50 17
-rw-r----- 1 root root  20K Фев 22 03:50 18

*******
YAR ★★★★★
() автор топика
Ответ на: комментарий от sdio

О! Похоже, таки ты прав, просто буферизируется сильно много. Добавил fflush(n) - заработало. Ну и после обработки всего файла без этой функции тоже работало.

YAR ★★★★★
() автор топика

А тебе случайно не {print >> n} нужно?

В крайнем случае, если память не жалко:

/DROP TABLE IF EXIST/{print s > n; n++; s=$0} {s=s"\n"$0}

baka-kun ★★★★★
()
Ответ на: комментарий от baka-kun

Как ни странно, но мой вариант тоже работает. Вот, только что нарезал дамп:

root@server1:~/test/21# pbunzip2 -c ../../file.sql.bz2 | pv | mawk 'BEGIN {n=0}; /DROP TABLE IF EXIST/{n+=1}; {print > n ; fflush(n)}'
15,7GB 0:04:20 [61,9MB/s] [ <=>       ]
root@server1:~/test/21# ls -lh
итого 16G
-rw-r----- 1 root root  784 Фев 22 03:59 0
-rw-r----- 1 root root 4,1K Фев 22 03:59 1
-rw-r----- 1 root root  972 Фев 22 03:59 10
-rw-r----- 1 root root  791 Фев 22 03:59 100
-rw-r----- 1 root root  12K Фев 22 03:59 101
-rw-r----- 1 root root  725 Фев 22 03:59 102
-rw-r----- 1 root root  781 Фев 22 03:59 103
-rw-r----- 1 root root 2,7G Фев 22 04:01 104
-rw-r----- 1 root root 1,9M Фев 22 04:01 105
********
YAR ★★★★★
() автор топика
Ответ на: комментарий от baka-kun

А тебе случайно не {print >> n} нужно?

Это awk, а не шел, файл не закрывается после первого print и остается открытым до конца жизни awk.

TC: перед n+=1 принудительно закрой файл командой close(n), тогда и fflush не понадобится.

sdio ★★★★★
()
Ответ на: комментарий от sdio

Ага, спасибо, тоже работает

YAR ★★★★★
() автор топика

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

Lavos ★★★★★
()
Ответ на: комментарий от Lavos
sqlpar-restore() { type="$(file "${1}" | grep -oE 'gzip|bzip')" ; case "${type}" in gzip) cmd='unpigz -c' ;; bzip) cmd='pbunzip2 -c' ;; *) cmd='cat' ;; esac ; ${cmd} "${1}" | pv -N 'Total' | mawk 'BEGIN {f="_-_database_-_header_-_.sql"}; /DROP TABLE IF EXIST/{close(f) ; print f ; f=$5".sql" ; gsub(/`|;/, "", f)}; {print >> f} END {print f}' | while read table ; do { sleep .1 ; pv -N "${table}" | mysql -h"${2}" -u"${3}" -p"${4}" "${5}" < "${table}" 2>>/tmp/parrestore.log && rm "${table}" ; } &: ; done ; }
YAR ★★★★★
() автор топика
Ответ на: комментарий от YAR

Работает, спасибо.

cat fulldump.sql | mawk 'BEGIN {f="_-_database_-_header_-_.sql"}; /DROP TABLE IF EXIST/{close(f) ; print f ; f=$5".sql" ; gsub(/`|;/, "", f)}; {print >> f} END {print f}'

Lavos ★★★★★
()
Ответ на: комментарий от YAR

А, да, там ошибочка, если что :)

YAR ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.