Блокировка базы 1С — запрет начала новых сеансов: пока он действует, в программу не войдут ни пользователи, ни внешние соединения без кода разрешения. Базу закрывают перед обновлением конфигурации, выгрузкой в .dt и работами в монопольном режиме. Ниже — три способа закрыть и открыть вход, как войти в заблокированную базу с ключом /UC и как снять блокировку, оставшуюся после неудачного обновления.
Платформа запрещает только новые сеансы. Кто уже в базе, работает дальше, пока его не отключат: обработка БСП делает это сама, в консоли кластера сеансы удаляют вручную.
Такой текст видит пользователь при входе в базу trade на сервере srv01, закрытую через БСП:
Начало сеанса с информационной базой запрещено.
Плановое обслуживание, вход откроется в 23:00
Для администратора:
Для того чтобы разрешить работу пользователей, воспользуйтесь консолью кластера серверов или запустите "1С:Предприятие" с параметрами:
ENTERPRISE /S"srv01\trade" /CРазрешитьРаботуПользователей /UC<код разрешения>
Первую строку добавляет платформа, вторая — ваше сообщение, блок «Для администратора» дописывает БСП (СоединенияИБ.СформироватьСообщениеБлокировки). Выходов два:
<код разрешения>. Сеанс войдёт вопреки блокировке, а БСП выполнит РазрешитьРаботуПользователей: снимет блокировку и закроет программу. У файловой базы в подсказке будет /F с путём к каталогу, кластера у неё нет.Работает в любой клиент-серверной базе, даже без БСП. В оснастке раскройте «Центральные серверы 1С:Предприятия 8.3 → srv01 → Кластеры → Локальный кластер → Информационные базы», щёлкните правой кнопкой по базе trade и выберите «Свойства». Консоль спросит «Администратор информационной базы» — пользователя этой базы с административными правами.
Запрет включает флажок «Блокировка начала сеансов включена». Рядом поля «Начало» и «Конец» (формат yyyy-mm-dd hh:mm:ss, пустой конец — до снятия вручную), «Сообщение» и «Код разрешения» для /UC. Флажок «Блокировка регламентных заданий включена» отдельный: блокировка сеансов задания не останавливает.
Тех, кто уже в базе, удалите в узле «Сеансы». Чтобы открыть вход, снимите флажок. Без консоли то же делает rac srv01:1545 infobase update с ключами --sessions-deny=on|off и --permission-code — готовый скрипт есть в статье про консоль кластера серверов.
Есть во всех конфигурациях на БСП и работает с файловой и клиент-серверной базой. В УТ 11.4 путь такой: «НСИ и администрирование → Администрирование → Обслуживание → Блокировка работы пользователей». В любой конфигурации на БСП обработку открывают через «Все функции → Обработки» или командой «Перейти по ссылке...» с адресом e1cib/app/Обработка.БлокировкаРаботыПользователей.
Заполните «Сообщение для пользователей», период «с … по …» (пустое «по» — бессрочно), «Код для разблокировки», а в клиент-серверной базе при необходимости — «Также запретить работу регламентных заданий». После «Установить блокировку» форма показывает, сколько сеансов осталось, и кнопку «Остановить» для отмены, а при следующем открытии на месте основной кнопки будет «Снять блокировку». Дальше БСП 3.1.5 (сверено по УТ 11.4) действует так:
Из кода типовой то же делают СоединенияИБ.УстановитьБлокировкуСоединений(ТекстСообщения, КодРазрешения, ОжиданиеНачалаБлокировки, ДлительностьБлокировки) (два последних параметра — в минутах) и СоединенияИБ.РазрешитьРаботуПользователей(); без полных прав обе вернут Ложь.
Тот же механизм запускается параметрами — удобно для ночного обслуживания из планировщика Windows. В /C передают ЗавершитьРаботуПользователей и через запятую Код=, Сообщение=, Ожидание= и Длительность= в минутах, а при администраторах кластера — Имя= и Пароль=. Без Код= БСП подставит код КодРазрешения.
@echo off
rem Ночное обслуживание базы на БСП: закрыть вход -> выгрузить копию -> открыть вход.
rem Файл сохраните в UTF-8: в параметрах /C кириллица.
chcp 65001 > nul
set "V8=C:\Program Files\1cv8\<версия платформы>\bin\1cv8.exe"
set "IB=srv01\trade"
rem IB_USER, IB_PWD (администратор базы) и UC_CODE (код разрешения) задайте
rem в переменных окружения задачи планировщика, а не в этом файле.
rem 1. Через 5 минут закрыть вход на 3 часа, дождаться выхода всех и закрыть сеанс
start "" /wait "%V8%" ENTERPRISE /S"%IB%" /N"%IB_USER%" /P"%IB_PWD%" /UC"%UC_CODE%" /DisableStartupDialogs ^
/C"ЗавершитьРаботуПользователей,Код=%UC_CODE%,Ожидание=5,Длительность=180,Сообщение=Плановое обслуживание"
rem 2. Работа в закрытой базе: конфигуратор тоже входит только с кодом разрешения
start "" /wait "%V8%" DESIGNER /S"%IB%" /N"%IB_USER%" /P"%IB_PWD%" /UC"%UC_CODE%" /DisableStartupDialogs ^
/DumpIB "D:\backup\trade.dt" /Out "D:\backup\trade-dump.log"
rem 3. Открыть вход: БСП снимет блокировку и сама закроет сеанс
start "" /wait "%V8%" ENTERPRISE /S"%IB%" /N"%IB_USER%" /P"%IB_PWD%" /UC"%UC_CODE%" /DisableStartupDialogs ^
/C"РазрешитьРаботуПользователей"
Первый сеанс ставит блокировку, ждёт выхода всех и закрывается последним. Если к началу кто-то остался (часто это фоновое задание), сеанс администратора попробует удалить его через кластер. Не выйдет — сам останется открытым с сообщением «Завершение сеансов не выполнено. Подробности см. в Журнале регистрации.», и скрипт будет ждать на первом шаге.
На встроенном языке блокировкой управляют объект БлокировкаСеансов и функции ПолучитьБлокировкуСеансов() и УстановитьБлокировкуСеансов(). Они доступны на сервере, в толстом клиенте и во внешнем соединении, работают в файловой и клиент-серверной базе, БСП не нужна. В клиент-серверной базе это та же блокировка, что в свойствах базы в консоли. Общий модуль закрывает и открывает вход и показывает, кто ещё в базе:
// Общий модуль ОбслуживаниеБазы, флажки «Сервер» и «Вызов сервера».
// Работает в файловой и клиент-серверной базе, БСП не нужна.
// Управлять блокировкой может пользователь с правом «Администрирование».
// Закрывает вход. ЧерезМинут - отсрочка начала, НаМинут - длительность (0 - до снятия вручную).
// Кто уже в базе, продолжит работать: платформа запрещает только новые сеансы.
Функция ЗакрытьВходВБазу(Знач ТекстСообщения, Знач КодРазрешения, Знач ЧерезМинут = 0, Знач НаМинут = 0) Экспорт
ПроверитьПравоАдминистрирования();
Если ПустаяСтрока(КодРазрешения) Тогда
ВызватьИсключение "Укажите код разрешения: с ним администратор войдет в закрытую базу (ключ /UC)";
КонецЕсли;
Текущая = ПолучитьБлокировкуСеансов();
Если БлокировкаЕщеДействует(Текущая) И Текущая.КодРазрешения <> КодРазрешения Тогда
// Например, идет обновление: не перезаписываем, иначе его код разрешения потеряется
ВызватьИсключение СтрШаблон("Вход уже закрыт другой блокировкой (начало: %1) с другим кодом разрешения",
Формат(Текущая.Начало, "ДЛФ=DT; ДП='не задано'"));
КонецЕсли;
Блокировка = Новый БлокировкаСеансов;
Блокировка.Начало = ТекущаяДата() + ЧерезМинут * 60; // время сервера, а не сеанса
Если НаМинут > 0 Тогда
Блокировка.Конец = Блокировка.Начало + НаМинут * 60; // забытая блокировка снимется сама
КонецЕсли;
Блокировка.КодРазрешения = КодРазрешения;
Блокировка.Сообщение = ТекстСообщения;
Блокировка.Установлена = Истина;
УстановитьБлокировкуСеансов(Блокировка);
Возврат ОписаниеБлокировкиБазы(Блокировка);
КонецФункции
// Открывает вход. Код разрешения для этого не нужен, нужны права.
Функция ОткрытьВходВБазу() Экспорт
ПроверитьПравоАдминистрирования();
Блокировка = ПолучитьБлокировкуСеансов();
Если Блокировка.Установлена Тогда
Блокировка.Установлена = Ложь;
УстановитьБлокировкуСеансов(Блокировка);
КонецЕсли;
Возврат ОписаниеБлокировкиБазы(Блокировка);
КонецФункции
// Состояние блокировки и список тех, кто еще в базе. Результат можно вернуть на клиент.
Функция СостояниеВходаВБазу() Экспорт
ПроверитьПравоАдминистрирования();
Описание = ОписаниеБлокировкиБазы(ПолучитьБлокировкуСеансов());
НомерСвоегоСеанса = НомерСеансаИнформационнойБазы();
Для Каждого Сеанс Из ПолучитьСеансыИнформационнойБазы() Цикл
// Консоль кластера не мешает ни блокировке, ни монопольному режиму
Если Сеанс.НомерСеанса = НомерСвоегоСеанса Или Сеанс.ИмяПриложения = "SrvrConsole" Тогда
Продолжить;
КонецЕсли;
Кто = ?(Сеанс.Пользователь = Неопределено, "<не вошел>", Сеанс.Пользователь.Имя);
Описание.ВБазе.Добавить(СтрШаблон("%1. %2, %3, с %4", Формат(Сеанс.НомерСеанса, "ЧГ=0"),
Кто, ПредставлениеПриложения(Сеанс.ИмяПриложения), Формат(Сеанс.НачалоСеанса, "ДФ='дд.ММ ЧЧ:мм'")));
КонецЦикла;
Возврат Описание;
КонецФункции
Функция ОписаниеБлокировкиБазы(Блокировка)
Описание = Новый Структура("Установлена, Действует, Начало, Конец, Сообщение, ВБазе");
Описание.Установлена = Блокировка.Установлена;
Описание.Действует = БлокировкаЕщеДействует(Блокировка) И Блокировка.Начало <= ТекущаяДата();
Описание.Начало = Блокировка.Начало;
Описание.Конец = Блокировка.Конец;
Описание.Сообщение = Строка(Блокировка.Сообщение); // бывает и ФорматированнаяСтрока
Описание.ВБазе = Новый Массив;
Возврат Описание;
КонецФункции
// Включена и срок не истек. Начало при этом может быть еще впереди.
Функция БлокировкаЕщеДействует(Блокировка)
Возврат Блокировка.Установлена
И (Не ЗначениеЗаполнено(Блокировка.Конец) Или Блокировка.Конец > ТекущаяДата());
КонецФункции
Процедура ПроверитьПравоАдминистрирования()
Если Не ПравоДоступа("Администрирование", Метаданные) Тогда
ВызватьИсключение "Управлять блокировкой базы может только пользователь с правом ""Администрирование""";
КонецЕсли;
КонецПроцедуры
Вызов ОбслуживаниеБазы.ЗакрытьВходВБазу("Плановое обслуживание", Код, 5, 120) закроет вход через 5 минут на два часа. Код разрешения запишите туда, где его найдёт коллега.
/UC<код>. После работы строку уберите.1cv8.exe ENTERPRISE /S"srv01\trade" /UC<код>, для конфигуратора — DESIGNER с тем же ключом.Srvr="srv01";Ref="trade";UC=<код>.Через веб-сервер ключ /UC не работает — так сказано в справке платформы. Подключайтесь тонким клиентом напрямую к серверу 1С или снимайте блокировку в консоли.
Блокировка сеансов не останавливает регламентные задания: в кластере для них отдельный флажок, а в файловой базе их выполняет один из запущенных клиентов. Чтобы ночная выгрузка не началась посреди обслуживания, долгое задание проверяет блокировку само:
// Общий модуль с флажком «Сервер». Блокировка сеансов не останавливает регламентные
// задания, поэтому долгое задание само проверяет, не закрыт ли вход на обслуживание.
Функция ИдетОбслуживаниеБазы(Знач ЗапасМинут = 15) Экспорт
УстановитьПривилегированныйРежим(Истина); // задание часто работает не под администратором
Блокировка = ПолучитьБлокировкуСеансов();
УстановитьПривилегированныйРежим(Ложь);
Если Не Блокировка.Установлена Тогда
Возврат Ложь;
КонецЕсли;
Сейчас = ТекущаяДата();
Если ЗначениеЗаполнено(Блокировка.Конец) И Блокировка.Конец <= Сейчас Тогда
Возврат Ложь; // срок истек, вход снова открыт
КонецЕсли;
// Уже действует или начнется в ближайшие ЗапасМинут - долгую работу не начинаем
Возврат Блокировка.Начало <= Сейчас + ЗапасМинут * 60;
КонецФункции
// Обработчик регламентного задания «Выгрузка остатков на сайт»
Процедура ВыгрузкаОстатковНаСайтРегламент() Экспорт
Если ИдетОбслуживаниеБазы() Тогда
ЗаписьЖурналаРегистрации("Выгрузка остатков на сайт", УровеньЖурналаРегистрации.Предупреждение, , ,
"Пропущено: вход в базу закрыт на обслуживание");
Возврат;
КонецЕсли;
// Дальше обычный код выгрузки
КонецПроцедуры
В конфигурации на БСП ответ на вопрос «действует ли блокировка сейчас» даёт СоединенияИБ.УстановленаБлокировкаСоединений() — она сама читает блокировку в привилегированном режиме.
Зависшая блокировка пережила своё обслуживание: обновление упало, скрипт прервали, блокировку поставили без срока и забыли. Что делать:
ПакетноеОбновлениеКонфигурацииИБ, а параметр ЗавершитьРаботуПользователей без Код= — с кодом КодРазрешения. Войдите с /UC и нажмите «Снять блокировку» в обработке или запустите программу с /CРазрешитьРаботуПользователей.1Cv8.cdn в каталоге базы рядом с 1Cv8.1CD. Скопируйте каталог и переименуйте этот файл — вход откроется.// Модуль формы внешней обработки «Блокировка в кластере». Платформа 8.3.14 и новее,
// на сервере srv01 запущен ras. Реквизиты обработки: ИмяБазы (имя в кластере, как Ref=),
// АдминистраторБазы и ПарольАдминистратораБазы (у поля в форме включен режим пароля).
&НаКлиенте
Процедура ПоказатьБлокировкуВКластере(Команда)
Описание = БлокировкаВКластере(ПодключениеККластеру(), Ложь);
ПоказатьПредупреждение(, ТекстОписанияБлокировки(Описание));
КонецПроцедуры
&НаКлиенте
Процедура СнятьБлокировкуВКластере(Команда)
Описание = БлокировкаВКластере(ПодключениеККластеру(), Истина);
ПоказатьПредупреждение(, "Вход открыт. Было: " + ТекстОписанияБлокировки(Описание));
КонецПроцедуры
&НаКлиенте
Функция ПодключениеККластеру()
Подключение = Новый Структура;
Подключение.Вставить("АдресRAS", "srv01");
Подключение.Вставить("ПортRAS", 1545);
Подключение.Вставить("ПортКластера", 1541);
Подключение.Вставить("АдминистраторКластера", ""); // пусто, если администраторы кластера не заведены
Подключение.Вставить("ПарольКластера", "");
Подключение.Вставить("ИмяБазы", Объект.ИмяБазы);
Подключение.Вставить("АдминистраторБазы", Объект.АдминистраторБазы);
Подключение.Вставить("ПарольБазы", Объект.ПарольАдминистратораБазы);
Возврат Подключение;
КонецФункции
// Читает блокировку базы в кластере вместе с кодом разрешения, при Снять = Истина снимает ее.
// Возвращает состояние до изменения.
&НаСервереБезКонтекста
Функция БлокировкаВКластере(Знач Подключение, Знач Снять)
База = НайтиБазуВКластере(Подключение);
Описание = Новый Структура;
Описание.Вставить("Включена", База.ВключенаБлокировкаНачалаСеансов);
Описание.Вставить("Начало", База.ВремяНачалаБлокировки);
Описание.Вставить("Конец", База.ВремяОкончанияБлокировки);
Описание.Вставить("Сообщение", Строка(База.СообщениеБлокировки));
Описание.Вставить("КодРазрешения", База.КодРазрешенияНачалаСеансов);
Описание.Вставить("РегламентныеЗапрещены", База.БлокировкаРегламентныхЗаданий);
Если Снять И База.ВключенаБлокировкаНачалаСеансов Тогда
База.ВключенаБлокировкаНачалаСеансов = Ложь;
База.Записать();
КонецЕсли;
Возврат Описание;
КонецФункции
&НаСервереБезКонтекста
Функция НайтиБазуВКластере(Знач Подключение)
Агент = Новый АдминистрированиеСервера(Подключение.АдресRAS, Подключение.ПортRAS);
Для Каждого Кластер Из Агент.ПолучитьКластеры() Цикл
Если Кластер.Порт <> Подключение.ПортКластера Тогда
Продолжить;
КонецЕсли;
Кластер.ВыполнитьАутентификацию(Подключение.АдминистраторКластера, Подключение.ПарольКластера);
Для Каждого База Из Кластер.ПолучитьИнформационныеБазы() Цикл
Если НРег(База.Имя) = НРег(Подключение.ИмяБазы) Тогда
// Как и в консоли, свойства блокировки меняют от имени администратора этой базы
База.ВыполнитьАутентификацию(Подключение.АдминистраторБазы, Подключение.ПарольБазы);
Возврат База;
КонецЕсли;
КонецЦикла;
КонецЦикла;
ВызватьИсключение СтрШаблон("На %1 нет кластера с портом %2 или в нем нет базы ""%3""",
Подключение.АдресRAS, Формат(Подключение.ПортКластера, "ЧГ=0"), Подключение.ИмяБазы);
КонецФункции
&НаКлиентеНаСервереБезКонтекста
Функция ТекстОписанияБлокировки(Описание)
Если Не Описание.Включена Тогда
Текст = "блокировка начала сеансов выключена";
Иначе
Текст = СтрШаблон("вход закрыт с %1 по %2, код разрешения: %3, сообщение: %4",
Формат(Описание.Начало, "ДЛФ=DT"), Формат(Описание.Конец, "ДЛФ=DT; ДП=бессрочно"),
Описание.КодРазрешения, Описание.Сообщение);
КонецЕсли;
Если Описание.РегламентныеЗапрещены Тогда
Текст = Текст + Символы.ПС + "Регламентные задания тоже запрещены - проверьте, нужно ли это сейчас";
КонецЕсли;
Возврат Текст;
КонецФункции
Команда «Показать» только читает блокировку вместе с кодом, «Снять» выключает её. Флажок регламентных заданий обработка не трогает, но предупредит о нём: после обслуживания его легко забыть, и тогда обмены молча стоят.
Каждое изменение блокировки платформа пишет в журнал регистрации событием «Информационная база. Изменение блокировки начала сеансов» (_$InfoBase$_.SessionLockChange). В данных события есть и код разрешения, так что выгрузку журнала посторонним не отдавайте. Функция собирает историю за последние дни:
// Кто и когда закрывал и открывал вход. Платформа пишет событие «Информационная база.
// Изменение блокировки начала сеансов». Нужно право «Журнал регистрации».
Функция ИсторияБлокировокБазы(Знач ЗаДней = 7) Экспорт
Отбор = Новый Структура;
Отбор.Вставить("ДатаНачала", НачалоДня(ТекущаяДата()) - (ЗаДней - 1) * 86400);
Отбор.Вставить("Событие", "_$InfoBase$_.SessionLockChange");
Записи = Новый ТаблицаЗначений;
ВыгрузитьЖурналРегистрации(Записи, Отбор, "Дата,ИмяПользователя,Компьютер,ИмяПриложения,Данные");
Записи.Сортировать("Дата Убыв");
История = Новый Массив;
Для Каждого Запись Из Записи Цикл
Текст = СтрШаблон("%1 %2 (%3, %4): ", Формат(Запись.Дата, "ДФ='дд.ММ.гг ЧЧ:мм'"),
?(ПустаяСтрока(Запись.ИмяПользователя), "<без пользователя>", Запись.ИмяПользователя),
ПредставлениеПриложения(Запись.ИмяПриложения), Запись.Компьютер);
// В Данных структура: Установлена, Начало, Конец, Сообщение, Параметр и КодРазрешения.
// Код разрешения в историю не выводим.
Данные = Запись.Данные;
Если ТипЗнч(Данные) <> Тип("Структура") Или Не Данные.Свойство("Установлена") Тогда
Текст = Текст + "изменил блокировку";
ИначеЕсли Данные.Установлена Тогда
Текст = Текст + СтрШаблон("закрыл вход с %1 по %2", ДатаИзДанныхЖурнала(Данные, "Начало", "сейчас"),
ДатаИзДанныхЖурнала(Данные, "Конец", "бессрочно"));
Иначе
Текст = Текст + "открыл вход";
КонецЕсли;
История.Добавить(Текст);
КонецЦикла;
Возврат История;
КонецФункции
Функция ДатаИзДанныхЖурнала(Данные, ИмяСвойства, ЕслиПусто)
Значение = Неопределено;
Если Данные.Свойство(ИмяСвойства, Значение) И ЗначениеЗаполнено(Значение) Тогда
Возврат Формат(Значение, "ДФ='дд.ММ.гг ЧЧ:мм'");
КонецЕсли;
Возврат ЕслиПусто;
КонецФункции
ТекущаяДата() + ЧерезМинут * 60 — время сервера: в БСП отмечено, что блокировка задаётся в часовом поясе сервера, а ТекущаяДатаСеанса() сдвинула бы начало у пользователя из другого пояса.Блокировка.Конец — страховка: после этого момента блокировка не действует, даже если её не сняли.Текущая.КодРазрешения <> КодРазрешения — не перезаписываем чужую блокировку, иначе скрипт обновления потеряет свой код.УстановитьПривилегированныйРежим(Истина) — задание часто работает под пользователем без административных прав, а без них блокировку не прочитать.База.ВыполнитьАутентификацию(...) — как и в консоли, свойства блокировки меняют от имени администратора этой базы.ТипЗнч(Данные) <> Тип("Структура") — защита от записи журнала с другим составом данных.Нет, платформа запрещает только новые сеансы. Обработка БСП отключает пользователей сама, а после консоли или своего кода сеансы удаляют вручную в узле «Сеансы».
Блокировка будет действовать, пока её не снимут. Задавайте конец с запасом: если обслуживание сорвётся, вход откроется сам.
Каждое подключение — новый сеанс, и без кода разрешения оно получит ту же ошибку. Внешнему соединению код передают параметром UC строки соединения, а обмены через веб-сервер на время работ лучше остановить.
Нет. Здесь речь о запрете входа в базу целиком, а «Конфликт блокировок при выполнении транзакции» — про блокировки данных, когда два сеанса меняют одни и те же записи. Об этом — в статье «Конфликт блокировок 1С».
Если базу нужно закрывать по расписанию, обновлять ночью и открывать без ручной работы, с письмом администратору при сбое, — это задача для программиста 1С. Разместите задачу на площадке бесплатно: оценка тоже бесплатная, ответ — в течение рабочего дня. Другие направления — на странице услуг.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.