INFOSTART EVENT 2018 EDUCATION

Второй тур голосования за доклады.
Окончание 5 сентября.

Сорокин Сергей | Ведущий программист 1С | МоскоуСофт

«Удаленные сотрудники: учет и систематизация работы»

Многие среди нас имеют возможность самостоятельно выбирать, как работать над проектами. И часто при ограниченных времени и бюджете есть возможность привлечь к сотрудничеству удаленного специалиста высокой квалификации. Без личной встречи, без подробного анализа резюме или даже возможности выдать тестовое задание ­ как можно безопасно привлечь к работе нового человека? Причем сделать это так, чтобы минимизировать свои риски, решить задачу за приемлемый срок и найти себе в команду нового сотрудника. План: ­- Бюджет. Как понять, что удаленный специалист не понимает задачу? Когда фрилансер обойдется дороже штатного специалиста? ­- Поиск и экспресс­проверка квалификации. Незнакомый фрилансер сразу назвал цену и сроки – когда это должно насторожить? ­- Организация контроля. Автоматические способы контроля и «ручные». ­- Системы мотивации. Особенности нематериальных систем мотивации удаленных сотрудников. - Информационная безопасность. Вы уверены, что фрилансер не скопирует себе архив базы клиента? ­- Оценка результатов работы. Простая система оценки удаленных сотрудников. ­- Системы учета. Компетенции, ответственность, культура общения и поведения, интеллект.

1. alexey.karmanov 182 06.08.18 16:00 Сейчас в теме

Резервное копирование и восстановление баз 1С на postgresql

Более опытные в вопросах postgresql коллеги, прошу вашей помощи - сам только осваиваю азы администрирования этой СУБД.

Сам я не администратор, а разработчик и эти основы нужные мне, чтобы добавить работу с postgresql в свою программу администрирования баз 1С.

Текущее окружение: Centos 7, PostgreSQL 9.6.9 (версия с патчами от 1С с сайта postgrespro.ru). Но версия ОС в рамках этой задачи не так важна, проблема повторяется и на Windows.

Сейчас передо мной стоят следующие задачи:

1. Написать скрипт выгрузки дампа базы в формате sql через pg_dump (архивация)
2. Написать скрипт загрузки этого дампа в эту же самую базы, выполнив этот скрипт через psql (восстановление базы из архива)

При этом вариант удаления и создания чистой базы перед восстановлением не подходит, так как эта операция потребовала бы остановки кластера 1с (dr op table не отрабатывает при соединениях с базой). И вообще сам вариант удаления и повторного создания базы для её восстановления кажется мне не совсем подходящим.

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

Скрипт архивации получился такой:
pg_dump.exe --quote-all-identifiers --format=plain --clean --dbname=postgresql://"USER":"PASSWORD"@"HOST:PORT"/"BASE1С_NAME" --file="backup.sql"

Скрипт восстановления такой:
psql.exe --single-transaction --echo-errors --quiet --set="ON_ERROR_STOP=on" --file="backup.sql" --dbname=postgresql://"USER":"PASSWORD"@"HOST:PORT"/"BASE1С_NAME"

Ключик --clean, который мы передали на вход pg_dump как раз и отвечает за генерацию SQL-кода в дампе, который выполняет полную очистку базы перед загрузкой в неё архивной копии.

И проблема возникает именно в этой части sql-дампа. Точная ошибка гласит: тип "public.mvarchar" не существует.

Знаю, что этот тип как раз и был добавлен патчами от 1С.

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

Судя по всему нужно делать постобработку (в части mvarchar) выгруженного дампа перед тем как отдавать его на выполнение pssql.
Вознаграждение за ответ
Показать полностью
Найденные решения
12. alexey.karmanov 182 07.08.18 07:12 Сейчас в теме
Так мне и не удалось научиться корректно очищать существующую базу для загрузки в неё архивной копии. Ничего не остаётся, кроме как загружать копию в новую базу.

Возможно это кому-то пригодится, получилось примерно так:

1. Делаем бэкап:
pg_dump.exe --quote-all-identifiers --format=plain --dbname=postgresql://"USER":"PASSWORD"@"HOST:PORT"/"BASE1C" --file="BACKUP.sql"

2. Создаём новую базу с временным именем (пусть сейчас это будет temp)
createdb.exe --encoding=utf8 --template=template1 --username="USER" --host="HOST" --port=PORT temp

3. Загружаем в temp наш архив:
psql.exe --single-transaction --echo-errors --quiet --set="ON_ERROR_STOP=on" --file="BACKUP.sql" --dbname=postgresql://"USER":"PASSWORD"@"HOST:PORT"/"temp"

4. Далее программно блокируем и выгоняем всех пользователей и фоновые. задания из базы через кластер 1с.

5. Далее программно через кластер очищаем свойство "база данных" у нашей базы. Это нужно, чтобы кластер отпустил базу в СУБД.

6. Далее переименовываем базу BASE1C в BASE1C_TEMP:

psql.exe --single-transaction --echo-errors --quiet --set="ON_ERROR_STOP=on" --dbname=postgresql://"USER":"PASSWORD"@"HOST:PORT"/"template1" --command="ALT ER DATABASE BASE1C RENAME TO BASE1C_TEMP;"

7. Далее переименовываем нашу temp в BASE1C:

psql.exe --single-transaction --echo-errors --quiet --set="ON_ERROR_STOP=on" --dbname=postgresql://"USER":"PASSWORD"@"HOST:PORT"/"template1" --command="ALT ER DATABASE temp RENAME TO BASE1C;"

8. Далее снова программно прописываем в свойства базы в кластере имя BASE1C

9. Наконец, удаляем базу BASE1C_TEMP:
dropdb.exe --username="USER" --host="HOST" --port=PORT BASE1C_TEMP

10. Пускаем всех обратно в базу.

Описанный алгоритм позволяет выполнить загрузку архивной копии в уже существующую базу максимально корректно и безопасно, насколько это возможно в условиях задачи.
KAV2; oldcopy; +2 Ответить
Остальные ответы
Сортировка: Древо
9. Fox-trot 54 06.08.18 22:50 Сейчас в теме +5 $m
(1)
И вообще сам вариант удаления и повторного создания базы для её восстановления кажется мне не совсем подходящим.
а другого варианта и нет
11. alexey.karmanov 182 07.08.18 01:52 Сейчас в теме
(9) я пока надеюсь, что другой вариант всё же найдётся и вернусь к идее с удалением и повторным созданием базы уже в крайнем случае.

Дело в том, что вариант с очисткой и загрузкой можно делать в одной транзакции, в отличие от удаление и пересоздания базы.
2. herfis 257 06.08.18 16:05 Сейчас в теме
Рабочие варианты команд, которые я успешно юзал на базах 1С:
pg_dump -h localhost -U postgres -Fc -Z9 -c -f /backups/WorkBase.bak WorkBase
pg_restore -h localhost -U postgres -c -d WorkBase -v /backups/WorkBase.bak
4. alexey.karmanov 182 06.08.18 17:10 Сейчас в теме
(2) У меня этот вариант также отрабатывает с предупреждениями о mvarchar. То есть база восстанавливается (вроде бы даже рабочая), но наличие этих ошибок при восстановлении не позволяет принять этот вариант за рабочий (иначе как программно контролировать другие типы ошибок, которые могут возникнуть в будущем).

Кроме того хочется бэкап именно в формате sql, а не архивный вариант. Это более гибкий вариант с точки зрения преодоления возможных проблем при восстановлении созданного бэкапа.
6. herfis 257 06.08.18 17:20 Сейчас в теме
(4) У постгри, насколько я знаю, до последнего времени и не было бинарных бэкапов. Т.е. это тоже вроде в формате sql бэкап.
А с ошибкой твоей дело в том, что ключик очистки для pg_dump не выполняет волшебную команду чистки всей базы. Он просто генерит скрипт по предварительному удалению тех объектов, которые он затем создавать будет. Соответственно, если восстановление выполняется в непустую базу, то будет ругаться на попытку удаление всех объектов, которых в этой базе нет. По идее, для твоих целей чистить надо не ключами в pg_dump, а ключами в pg_restore, но я так ни разу не пробовал.
Хм... Курю мануалы, там хитрее. Погоди чуток..
3. Timur.V 15 06.08.18 16:59 Сейчас в теме
5. alexey.karmanov 182 06.08.18 17:11 Сейчас в теме
(3) Всё видел, но проблема специфична именно для баз 1С. В статье также нет подходящего способа применительно к нашему случаю.
7. herfis 257 06.08.18 17:30 Сейчас в теме
Покурил мануалы по pg_dump и pg_restore.
И вроде как там нет опции по предварительной полной очистке целевой базы :)
Опции очистки и там и там просто добавляют команды удаления того объекта, который восстанавливается из бэкапа перед его созданием. И соответственно всегда будет "левая" ошибка, если в целевой базе не было этого объекта перед восстановлением (это явно говорено в мануале).
Хоть сам объекты дропай :)
8. herfis 257 06.08.18 17:48 Сейчас в теме +5 $m
Погуглил. Оказывается что удалить все объекты базы не удаляя саму базу - задача нетривиальная.
Самое простое из предлагаемого - дропнуть схему (большинство объектов принадлежит схеме и тоже дропнутся). Но потом придется ее создать и дефолтные гранты восстановить.
Так что в принципе можно попробовать убрать опцию очистки базы из pg_dump и перед восстановлением бэкапа удалять/восстанавливать схему.
10. alexey.karmanov 182 07.08.18 01:50 Сейчас в теме
(8)
Предварительная очистка базы поддерживается. Ключик --clean для pg_dump генерирует как раз этот код для очистки. Который затем выполняется через psql. Это если мы делаем дамп в plain формате. Как раз в этом коде очистки базы и возникает конфликт с mvarchar (сегодня буду разбираться подробнее).

Если же custom (тот же sql, но пожатый), то восстанавливать надо через pg_restore и там тоже есть ключик --clean. Но проблема та же. Так как pg_restore распаковывает custom в тот же самый plain sql и так же запускает его на выполнение (не знаю только сам или через psql).

Спасибо за помощь, по результатам (если таковые будут) обязательно здесь отпишусь.
12. alexey.karmanov 182 07.08.18 07:12 Сейчас в теме
Так мне и не удалось научиться корректно очищать существующую базу для загрузки в неё архивной копии. Ничего не остаётся, кроме как загружать копию в новую базу.

Возможно это кому-то пригодится, получилось примерно так:

1. Делаем бэкап:
pg_dump.exe --quote-all-identifiers --format=plain --dbname=postgresql://"USER":"PASSWORD"@"HOST:PORT"/"BASE1C" --file="BACKUP.sql"

2. Создаём новую базу с временным именем (пусть сейчас это будет temp)
createdb.exe --encoding=utf8 --template=template1 --username="USER" --host="HOST" --port=PORT temp

3. Загружаем в temp наш архив:
psql.exe --single-transaction --echo-errors --quiet --set="ON_ERROR_STOP=on" --file="BACKUP.sql" --dbname=postgresql://"USER":"PASSWORD"@"HOST:PORT"/"temp"

4. Далее программно блокируем и выгоняем всех пользователей и фоновые. задания из базы через кластер 1с.

5. Далее программно через кластер очищаем свойство "база данных" у нашей базы. Это нужно, чтобы кластер отпустил базу в СУБД.

6. Далее переименовываем базу BASE1C в BASE1C_TEMP:

psql.exe --single-transaction --echo-errors --quiet --set="ON_ERROR_STOP=on" --dbname=postgresql://"USER":"PASSWORD"@"HOST:PORT"/"template1" --command="ALT ER DATABASE BASE1C RENAME TO BASE1C_TEMP;"

7. Далее переименовываем нашу temp в BASE1C:

psql.exe --single-transaction --echo-errors --quiet --set="ON_ERROR_STOP=on" --dbname=postgresql://"USER":"PASSWORD"@"HOST:PORT"/"template1" --command="ALT ER DATABASE temp RENAME TO BASE1C;"

8. Далее снова программно прописываем в свойства базы в кластере имя BASE1C

9. Наконец, удаляем базу BASE1C_TEMP:
dropdb.exe --username="USER" --host="HOST" --port=PORT BASE1C_TEMP

10. Пускаем всех обратно в базу.

Описанный алгоритм позволяет выполнить загрузку архивной копии в уже существующую базу максимально корректно и безопасно, насколько это возможно в условиях задачи.
KAV2; oldcopy; +2 Ответить
13. KAV2 24 08.08.18 07:02 Сейчас в теме
(12) А почему просто не удалить старую базу, перед восстановлением из бэкапа?

То есть:

1) Удаляем базу
dropdb dbname

2) Создаем новую пустую со старым имененм
createdb dbname

3) восстанавливаем в нее бэкап.
gunzip -c filename.gz | psql dbname
14. alexey.karmanov 182 08.08.18 12:27 Сейчас в теме
(13) ну как же...

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

Столько промежуточных шагов исключительно для надежности и отказоустойчивости операции в целом.
Fox-trot; +1 Ответить
15. KAV2 24 08.08.18 15:06 Сейчас в теме
(14) Понял. Ну вы изначально вовсе хотели перезаписать базу, допустим была бы такая специальная команда - перезаписать базу данных при восстановлении бэкапа, тогда в процессе при возникновении ошибки можно было аналогичным образом потерять данные.
17. alexey.karmanov 182 09.08.18 02:25 Сейчас в теме
(15) "тогда в процессе при возникновении ошибки можно было аналогичным образом потерять данные"

Нет, нельзя было бы. Ведь это делалось в рамках одной транзакции (ключик --single-transaction).
19. KAV2 24 09.08.18 05:02 Сейчас в теме
16. oldcopy 64 08.08.18 22:50 Сейчас в теме
(12) В общем и целом - это единственно верное решение. Только вот переименовывать базу SQL туда-сюда-обратно я смысла не вижу. Создали вместо базы Base1, базу Base2, залили в нее дамп и меняем в настройках кластера в свойствах ИБ Base1 на Base2.

В итоге получится 1-5, 8, 10. Пункт 9, удаление базы я бы тоже убрал. Есть она не просит, пусть будет, мало ли что. Тогда можно отказаться от 1, зачем делать бекап, если мы не трогаем исходную базу. При этом нормально так выиграем по времени.
18. alexey.karmanov 182 09.08.18 02:32 Сейчас в теме
(16) Чего-то я не понял несколько... :)

Речь же о том, что мы добавляем эту возможность в универсальный инструмент, позволяющий делать архивные копии (пункт 1) и при необходимости восстанавливать их в базу (остальные пункты). Причём восстанавливать как в ручную, так и автоматически (например, при неудачном обновлении).

При этом в результате этих операций (бэкап и/или восстановление) в СУБД не должны появляться и оставаться новые базы, как и не должно меняться имя самой базы.
20. oldcopy 64 09.08.18 11:45 Сейчас в теме
(18)
При этом в результате этих операций (бэкап и/или восстановление) в СУБД не должны появляться и оставаться новые базы, как и не должно меняться имя самой базы.


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

Если говорить о скрипте для автоматического развертывания бекапов, то на мой взгляд достаточно создать новую базу и перепрописать ее в свойствах ИБ 1С. Если же не хотите менять имя, то лучше отключить старую базу, переименовать, создать новую с тем же именем и залить туда дамп. В этом случае у вас гарантированно останется рабочая база на момент перед восстановлением. Если не нужна - можно всегда удалить потом.
21. alexey.karmanov 182 09.08.18 13:11 Сейчас в теме
Я думаю, что вариант "не удаления старой базы после восстановления" будет опциональным. Это хорошая идея.
23. oldcopy 64 09.08.18 13:21 Сейчас в теме
(21) Подкину еще идею, иногда старую базу (до восстановления) нужно иметь рядом, скажем для "разбора полетов", также опционально ее можно сразу добавлять в кластер 1С.
24. alexey.karmanov 182 09.08.18 14:31 Сейчас в теме
(23) спасибо, записал в список идей :)
22. alexey.karmanov 182 09.08.18 13:13 Сейчас в теме
А по поводу "восстановил не в ту базу". В моём инструменте администрирования при восстановлении из резервной копии (если этот процесс запущен руками) всегда предлагается в начале создать резервную копию текущей базы. Поэтому база до восстановления в любом случае останется.

Если же это происходит при автоматическом обновлении баз (или тестировании), то там тоже перед началом операции создаётся резервная копия базы. Поэтому тоже мы ничего не потеряем даже при самом плохом сценарии.
Оставьте свое сообщение
Новые вопросы с вознаграждением
Автор темы объявил вознаграждение за найденный ответ, его получит тот, кто первый поможет автору.

Вакансии

Программист 1С
Одесса (Украина)
зарплата от 40 000 руб.
Полный день

Программист 1С
Санкт-Петербург
Полный день

Аналитик 1С
Москва
зарплата от 80 000 руб. до 120 000 руб.
Полный день

1С Developer
Одесса (Украина)
зарплата от 60 000 руб. до 120 000 руб.
Полный день

Бизнес-аналитик 1С
Санкт-Петербург
зарплата от 70 000 руб. до 90 000 руб.
Полный день