Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c6e9725

Browse files
authored
pretect concurrent write WAL files to shared network folder
1 parent c8d196f commit c6e9725

File tree

1 file changed

+66
-21
lines changed

1 file changed

+66
-21
lines changed

‎pg_backup/archive_command.sh‎

Lines changed: 66 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,76 @@
11
#!/bin/bash
2-
3-
# заглушка, т.к. для archive_mode = 'on' требуется перезагрузка СУБД
2+
3+
# заглушка, т.к. при изменении значения параметра archive_mode требуется перезагрузка СУБД
44
# exit 0
5-
6-
# проверяем, скрипт должен запускаться с двумя параметрами
5+
6+
function log() {
7+
# echo $(date --rfc-3339=ns) $(hostname -s) $(basename "$SRC_FILE") "1ドル" &>> "$WAL_DIR/archive_wal.log"
8+
return 0
9+
}
10+
11+
WAL_DIR="/mnt/backup_db/archive_wal/cluster"
12+
SRC_FILE="2ドル" # откуда будем читать WAL файл
13+
DST_FILE="$WAL_DIR/1ドル.zst" # куда будем сохранять WAL файл
14+
LOCK_FILE="$WAL_DIR/1ドル.lock" # этот файл создаётся перед архиваций WAL файла и удаляется после
15+
16+
log "check"
17+
18+
# скрипт должен запускаться с двумя параметрами
719
test "$#" -ne 2 && echo "Error: 2 number of parameters expected, $# given" >&2 && exit 2
8-
9-
FILE_SRC="2ドル"
10-
FILE_DST="/mnt/backup_db/archive_wal/cluster/1ドル.zst"
11-
12-
test ! -f "$FILE_SRC" && echo "Error: file '$FILE_SRC' does not exist!" >&2 && exit 1
13-
test -f "$FILE_DST" && exit
14-
20+
test ! -f "$SRC_FILE" && echo "Error: WAL file '$SRC_FILE' does not exist!" >&2 && exit 1
21+
test -f "$DST_FILE" && test ! -f "$LOCK_FILE" && log "exists" && exit 0
22+
23+
log "does not exist"
24+
25+
: <<'COMMENT'
26+
Для надёжности архивирование WAL файлов могут настроить на мастере и репликах через параметр archive_mode=always.
27+
Запрещаем от разных экземпляров СУБД конкурентную запись WAL файлов в общие сетевые папки.
28+
Например, в основном и резервном ЦОДе могут быть разные сетевые папки.
29+
Дополнительные файлы и проверки нужны для решения проблемы переполнения диска или недоступности сетевого соединения,
30+
когда WAL файл может не записаться совсем или записаться только частично.
31+
COMMENT
32+
33+
SRV_FILE="$WAL_DIR/archive_server.$(hostname -s)" # сервер, на котором планируется архивирование WAL файла
34+
touch -m "$SRV_FILE" || exit # создаём файл или обновляем дату модификации файла
35+
36+
# разрешаем архивацию WAL файла только при наличии жёстких связанных ссылок (единый inode) между файлами $SRV_FILE и $LOCK_FILE
37+
# для отладки и просмотра кол-ва жёстких ссылок на файл используйте утилиту stat (не используйте ls, она кеширует информацию)
38+
if ln -T "$SRV_FILE" "$LOCK_FILE" &> /dev/null; then
39+
# если удалось создать файл $LOCK_FILE, то только этот (основной) процесс будет архивировать WAL файл (первая попытка)
40+
log "locked now"
41+
elif test "$SRV_FILE" -ef "$LOCK_FILE"; then
42+
# если файлы имеют одинаковый inode, то только этот (основной) процесс будет архивировать WAL файл (повторная попытка)
43+
log "locked already"
44+
else
45+
# иначе архивировать WAL файл пытается конкурирующий процесс, ждём несколько секунд завершения работы основного процесса
46+
for i in {1..50}; do
47+
log "waiting i=$i"
48+
sleep 0.2
49+
test -f "$DST_FILE" && test ! -f "$LOCK_FILE" && log "appeared" && exit 0
50+
done
51+
# не дождались, значит основной процесс сломался, WAL файл мог сохраниться только частично
52+
# передаём управление другому конкурирующему процессу, который станет основным (при повторном вызове этого скрипта)
53+
rm -f "$DST_FILE" && rm -f "$LOCK_FILE" # очерёдность удаления файлов важна
54+
MESSAGE="waiting timeout, deleted, unlocked"
55+
log "$MESSAGE"
56+
echo "Error: WAL file '$DST_FILE' $MESSAGE" >&2
57+
exit 1
58+
fi
59+
1560
# кол-во потоков сжатия
1661
ZSTD_THREADS=$(echo "$(nproc) / 4 + 1" | bc)
17-
18-
# кол-во файлов в очереди на архивирование
19-
ARCHIVE_STATUS_DIR=$(dirname $FILE_SRC)/archive_status
62+
63+
# подсчитываем кол-во WAL файлов в очереди на архивирование
64+
ARCHIVE_STATUS_DIR=$(dirname "$SRC_FILE")/archive_status
2065
WAL_FILES_QUEUE=$(find "$ARCHIVE_STATUS_DIR" -maxdepth 1 -type f -name "*.ready" -printf "." | wc --bytes)
21-
22-
# чем больше файлов в очереди, тем меньше степень сжатия (но больше скорость сжатия и размер сжатого файла)
23-
STEP=3
66+
67+
STEP=2
68+
# чем больше WAL файлов в очереди, тем меньше степень сжатия (но больше скорость сжатия и размер сжатого файла)
2469
# не ставьте большой уровень компрессии, это приводит к большому потреблению CPU, а экономия на размере файла несущественная
2570
ZSTD_LEVEL=$(echo "(9 * ${STEP} - ${WAL_FILES_QUEUE}) / ${STEP}" | bc)
2671
test "$ZSTD_LEVEL" -lt 1 && ZSTD_LEVEL=1
27-
28-
# архивируем файл
72+
73+
# архивируем WAL файл
2974
# в zstd без флага -B1M используются не все ядра (из-за небольшого размера файла?)
30-
# в zstd флаг -f использовать нельзя, т.к. если файл существует, то должна быть ошибка (защита от дурака от перезаписи нужного файла)
31-
ionice -c2 -n7 nice -n19 zstd -q -${ZSTD_LEVEL} -T${ZSTD_THREADS} -B1M "$FILE_SRC" -o "$FILE_DST"
75+
ionice -c2 -n7 -- nice -n19 -- zstd -q -f -${ZSTD_LEVEL} -T${ZSTD_THREADS} -B1M "$SRC_FILE" -o "$DST_FILE" \
76+
&& rm -f "$LOCK_FILE"&& log "saved, unlocked"

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /