Глобальный контекст.УстановитьМонопольныйРежим

Методы · SetExclusiveMode

Устанавливает и отключает использование монопольного режима.

Синтаксис

УстановитьМонопольныйРежим(<МонопольныйРежим>, <Параметры>)

Примеры платформы

Попытка
    УстановитьМонопольныйРежим(Истина);
Исключение
    Предупреждение(НСтр("ru = 'С информационной базой работают другие пользователи.
        |В данный момент невозможно установить монопольный режим!';
        |en = 'Other users are working with infobase.
        |It is impossible to set the Exclusive mode at the moment!'"), 10);
КонецПопытки;
Полное описание, параметры и ограничения

Глобальный контекст.УстановитьМонопольныйРежим (Global context.SetExclusiveMode)

Глобальный контекст (Global context)

УстановитьМонопольныйРежим (SetExclusiveMode)

Доступен, начиная с версии 8.0.

Синтаксис:
УстановитьМонопольныйРежим(<МонопольныйРежим>, <Параметры>)
Параметры:

<МонопольныйРежим> (обязательный)
Тип: Булево.
Истина - устанавливает монопольную блокировку текущей области данных от имени сеанса;
Ложь - если установлена монопольная блокировка текущей области от имени текущего сеанса, то удаляет монопольную блокировку текущей области. Снимает монопольный режим только текущей области, т.е. области, определяемой значениями установленных в сеансе разделитей. Не затрагивает монопольные блокировки подобластей;

<Параметры> (необязательный)
Тип: ПараметрыМонопольногоРежима.
Используется только, если МонопольныйРежим установлен в значение Истина.
Если не указан, то считается, что Сообщение – Неопределено и РазрешитьЗавершатьПриНачалеСеанса – Ложь.
Если при запуске клиентского приложения база или область находится в монопольном режиме, то значение свойства Сообщение отображается пользователю в диалоге сообщения.
Если Сообщение – Неопределено, то отображается текст сообщения об ошибке по умолчанию, например, "Ошибка разделенного доступа к базе данных. База данных заблокирована: сеанс 555, начат 20.06.2019 в 12:31:23, приложение Фоновое задание. Выполняется ожидание возможности запуска. При появлении возможности, запуск будет выполнен автоматически. Нажмите «Выполнить запуск» для немедленной попытки запуска. Нажмите «Отмена» для отказа от запуска. Нажмите «Завершить сеансы и выполнить запуск» для завершения блокирующих сеансов и немедленной попытки запуска."
Иначе частью текста в диалоге сообщения об ошибке будет заданная строки или форматированная строка, например, "<Значение свойства Сообщение> Выполняется ожидание возможности запуска. При появлении возможности, запуск будет выполнен автоматически. Нажмите «Выполнить запуск» для немедленной попытки запуска. Нажмите «Отмена» для отказа от запуска. Нажмите «Завершить сеансы и выполнить запуск» для завершения блокирующих сеансов и немедленной попытки запуска."
Значение по умолчанию: Неопределено.
Описание:

Устанавливает и отключает использование монопольного режима.

Доступность:

Сервер, толстый клиент, внешнее соединение, мобильное приложение (сервер), мобильный автономный сервер.

Примечание:
Монопольный режим может быть установлен при одновременном выполнении следующих условий:
если в данный момент в режиме 1С:Предприятие с данной информационной базой работает только один пользователь;

текущий пользователь имеет право на установку монопольного режима.
Если в текущем сеансе установлены разделители, то будет установлен монопольный режим области данных, определяемой их значениями.
Если установить монопольный режим не удалось, то будет вызвано исключение.
Пример:

Попытка
УстановитьМонопольныйРежим(Истина);
Исключение
Предупреждение(НСтр("ru = 'С информационной базой работают другие пользователи.
|В данный момент невозможно установить монопольный режим!';
|en = 'Other users are working with infobase.
|It is impossible to set the Exclusive mode at the moment!'"), 10);
КонецПопытки;

См. также:
Глобальный контекст, метод МонопольныйРежим

Использование в версии:

Доступен, начиная с версии 8.0.

Методическая информация

Практические примеры

Свой встроенный binary-store: шесть фаз политики, реальные own пакеты и проверка содержимого

Не формальные setters: полностью собственная новая client-server IB, единственный каталог и шесть собственных4..16KiB payload. Настройки native manager отдельно от ХранилищеЗначения, четыре placement enum, ReadOnly сохраняет IB writes и scoped native database+storage size. Никаких S3/upload/backup/restore/очисток.

Где и как запускать

Полный серверный server-call общий модуль УчебныеДвоичные85. Только own new client-server localhost:1541/ref UUID IB на8.5.1.1343, один actual administrator, one catalog/three exact fields, manual optimized-storage prerequisite;6real own records. CLIENT отдельно full managed form module.

Подготовка

  1. Сначала вручную подготовьте отдельную новую client-server учебную базу на своей локальной VM/своем localhost:1541 cluster, не копию production и не общий сервер. Выберите вариант установленной8.5.1.1343, где native GetBinaryDataStorageAvailability=True. Если он False, урок честно отказывает; не обходите edition/license ограничения.

  2. Сами создайте новый canonical nonzero UUID marker и зарегистрируйте только собственную IB с Ref=Уч85Двоичные_<UUID>. В списке баз задайте строку строго Srvr="localhost:1541";Ref="Уч85Двоичные_<UUID>";. Метод ConnectionString возвращает как зарегистрировано: другой порядок/порт/пробелы/дополнительные параметры даже своего адреса безопасно отвергаются. UUID-marker имени не является realIBUUID; строка соединения никогда не выводится.

  3. Конфигуратор → новая конфигурация → имя УчебныеДвоичные85. Никаких типовых справочников/документов/регистров/внешних источников/подписок/регламентных заданий/общих реквизитов/расширений. Встроенное storage изначально Запретить, native состав пуст, внешних storage0. Код не приспосабливает существующую рабочую базу.

  4. Конфигуратор → Справочники → Добавить → УчебныеПакеты85, Иерархический=Нет, код строковый36, Автонумерация=Нет, наименование100. Добавьте ровно три реквизита: КлючОпыта Строка36, Фаза Число(2,0) неотрицательное, Данные ХранилищеЗначения единственного типа. Табличных частей0, модуль объекта/обработчики записи пустые. Это вручную создаваемая собственная учебная metadata schema, не реально внесенные автором изменения.

  5. Создайте ровно одного собственного реального пользователя IB Уч85Двоичные_<тот жеUUIDmarker>, с уникальным actualIBUUID, административными правами и правом монопольного режима только в этой учебной базе. CurrentUser и списокactualIBUsers проверяются. Никакого privileged impersonation/сервисных пользователей/установленных разделителей нет; права контролирует native платформа.

  6. Обязательная отдельная ручная подготовка администратора: предварительно включите оптимизированное хранение двоичных данных в БД способом, документированным именно для вашей установленной поставки8.5.1.1343/ее средства администрирования. Native SetDataCopiesPlacementMode прямо требует его и иначе выдает ОшибкаСоединенияСБазойДанных. В экспортированной native справке не найден BSLsetter этой настройки; здесь не выдумывается его имя, CLIflag или меню. Если эта prerequisite не подтверждена владельцем стенда по документации своей поставки — не запускайте опыт. Данная предварительная настройка не заменяет включение встроенного storage менеджером.

  7. Конфигуратор → Общие → Общие модули → УчебныеДвоичные85: Сервер/Вызов сервера=Да, Клиент/Привилегированный/Глобальный=Нет. Вставьте SERVER целиком. Storage manager только сервер; наличие глобального size-метода на клиенте не переносит native setters в client context.

  8. Создайте свою внешнюю обработку с управляемой формой, строковыми реквизитами МеткаСвоейБазы36 и Подтверждение100 и командой ВыполнитьОпыт. Вставьте supporting CLIENT целиком. Никакого автостарта/HTTP/UI upload/file dialogs или фонового расписания нет.

  9. Войдите под единственным своим администратором, закройте прочие свои сеансы, конфигуратор и фоновые задания. Native exclusive lock устанавливается только если возможно; чужие сеансы не завершаются и блокировки не снимаются принудительно. Общих реквизитов нет, поэтому области разделения не заданы.

  10. Перед запуском каталог пуст, режим storage Запретить, состав0, external storage0. Введите свой marker и сначала неправильное подтверждение: данные не должны создаться. Затем сознательно введите СВОЙ ПУСТОЙ СТЕНД ДВОИЧНЫЕ85 и нажмите один раз. После ошибки/обрыва не повторяйте: собственные настройки/записи могли сохраниться частично.

  11. Опыт создаст новый ownnonce и six real own catalog objects. Payload формируется только из nonce/номерафазы/256строк книги3×250=750 в памяти, UTF8 безBOM, bounded4..16KiB, ValueStorage безcompression. Ни чужие файлы, ни произвольный client payload/metadataID/SQL не принимаются.

  12. Фазы1..4 последовательно устанавливают четыре native placement mode и проверяют getter, затем реально записывают новый own object и читают отдельно через real saved ref.GetObject/ValueStorage.Get. Проверяются own passport/тип/размер/SHA256. РежимCopyOnRead может копировать при чтении: такой read не обещан физически read-only; созданные свои storage copies не являются backup files.

  13. Фаза5 устанавливает storage.ТолькоЧтение и все равно пишет еще один actual IBobject: native это разрешает и направляет новые binary values в БД. Фаза6 снова ReadAndWrite, но composition.DontUse только для own attribute, и еще одна real IBwrite/read. Состав берет actual metadata реквизита, не каталог целиком, не string и не runtime ValueStorage.

  14. Все шесть сохраненных own objects затем повторно читаются/хешируются. Size API вызывается с пустым search-area array и include=[actual own catalog metadata], exclude=[]: не вся база и не все разделители. Результат — совокупные table+storage bytes, не суммаpayload/размерbackup/списокblob location; величина после не обязана равняться6×payload или строго возрастать.

  15. На успешном завершении настройки сознательно остаются enabled/ReadAndWrite/default=false/threshold2048/composition.Use own attribute/CopyOnWrite, а свои шесть записей сохраняются. Не выключайте storage/не удаляйте его физические файлы: это не миграция оставшихся blobs обратно в БД. Exclusive0→1→0 принадлежит только этому сеансу; при ошибке снимается лишь собственная блокировка, если native снятие завершилось, без автоматического rollback policy/data.

  16. Нельзя проверять failover остановкой production/локального storage process, менять внешние storage, делать backup/restore/ClearUnusedSpace или удалять файлы. Авторские проверки статические/native; реальная 1С/cluster/SQL/storage/UI/files/network не запускались и никаких backups не создано.

Функция ВыполнитьСвойОпытДвоичных85(МеткаСвоейБазы, Подтверждение) Экспорт
    ПроверитьСвоюБазуДвоичных85(МеткаСвоейБазы);
    Если Подтверждение <> "СВОЙ ПУСТОЙ СТЕНД ДВОИЧНЫЕ85" Тогда
        ВызватьИсключение "Настройки собственного хранилища и данные не изменены";
    КонецЕсли;
    Если МонопольныйРежим() Или ПривилегированныйРежим() Тогда
        ВызватьИсключение "Чужой монопольный/привилегированный контекст не принимается";
    КонецЕсли;
    Выборка = Справочники.УчебныеПакеты85.Выбрать();
    Если Выборка.Следующий() Тогда
        ВызватьИсключение "Свой новый каталог уже содержит данные; повтор запрещен";
    КонецЕсли;
    Если Не ХранилищеДвоичныхДанных.ПолучитьДоступностьХранилищаДвоичныхДанных() Тогда
        ВызватьИсключение "Этот вариант платформы не поддерживает встроенное binary-store. Опыт не запускается";
    КонецЕсли;
    Если ХранилищеДвоичныхДанных.ПолучитьРежимИспользованияХранилищаДвоичныхДанных() <> РежимИспользованияХранилищаДвоичныхДанных.Запретить
        Или ХранилищеДвоичныхДанных.ПолучитьСоставХранимыхДанных().Количество() <> 0
        Или ВнешниеХранилищаДвоичныхДанных.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен новый own стенд с выключенным встроенным storage, пустым составом и без внешних storage";
    КонецЕсли;
    КлючОпыта = Строка(Новый УникальныйИдентификатор);
    Протокол = Новый Массив;
    РазмерДо = ПолучитьРазмерТолькоСвоегоКаталога85();
    Попытка
        УстановитьМонопольныйРежим(Истина);
        Если Не МонопольныйРежим() Тогда
            ВызватьИсключение "Монопольный доступ собственного сеанса не подтвержден";
        КонецЕсли;
        ПроверитьСвоюБазуДвоичных85(МеткаСвоейБазы);
        Выборка = Справочники.УчебныеПакеты85.Выбрать();
        Если Выборка.Следующий() Или ВнешниеХранилищаДвоичныхДанных.Количество() <> 0
            Или ХранилищеДвоичныхДанных.ПолучитьРежимИспользованияХранилищаДвоичныхДанных() <> РежимИспользованияХранилищаДвоичныхДанных.Запретить
            Или ХранилищеДвоичныхДанных.ПолучитьСоставХранимыхДанных().Количество() <> 0 Тогда
            ВызватьИсключение "После own exclusive получения начальное пустое состояние изменилось; ничего не перенастраиваем";
        КонецЕсли;
        ХранилищеДвоичныхДанных.УстановитьРежимИспользованияХранилищаДвоичныхДанных(РежимИспользованияХранилищаДвоичныхДанных.Разрешить);
        Если ХранилищеДвоичныхДанных.ПолучитьРежимИспользованияХранилищаДвоичныхДанных() <> РежимИспользованияХранилищаДвоичныхДанных.Разрешить Тогда
            ВызватьИсключение "Own enabled mode не подтвержден";
        КонецЕсли;
        ХранилищеДвоичныхДанных.УстановитьМинимальныйРазмерЗаписываемыхДанных(1024);
        Если ХранилищеДвоичныхДанных.ПолучитьМинимальныйРазмерЗаписываемыхДанных() <> 2048 Тогда
            ВызватьИсключение "Native clamp минимального порога1024→2048 не подтвердился";
        КонецЕсли;
        ХранилищеДвоичныхДанных.УстановитьМинимальныйРазмерЗаписываемыхДанных(2048);
        ХранилищеДвоичныхДанных.УстановитьРежимЧтенияЗаписиХранилищаДвоичныхДанных(РежимЧтенияЗаписиХранилищаДвоичныхДанных.ЧтениеИЗапись);
        Если ХранилищеДвоичныхДанных.ПолучитьРежимЧтенияЗаписиХранилищаДвоичныхДанных() <> РежимЧтенияЗаписиХранилищаДвоичныхДанных.ЧтениеИЗапись Тогда
            ВызватьИсключение "Own storage read/write не подтвержден";
        КонецЕсли;
        ХранилищеДвоичныхДанных.УстановитьИспользованиеКакХранилищаПоУмолчанию(Истина);
        Если Не ХранилищеДвоичныхДанных.ПолучитьИспользованиеКакХранилищаПоУмолчанию() Тогда
            ВызватьИсключение "Own default=true не подтвержден";
        КонецЕсли;
        ХранилищеДвоичныхДанных.УстановитьИспользованиеКакХранилищаПоУмолчанию(Ложь);
        Если ХранилищеДвоичныхДанных.ПолучитьИспользованиеКакХранилищаПоУмолчанию() Тогда
            ВызватьИсключение "Own default=false не подтвержден";
        КонецЕсли;
        УстановитьТолькоСвойСостав85(ИспользованиеХраненияВХранилищеДвоичныхДанных.Использовать);
        Режимы = Новый Массив;
        Режимы.Добавить(РежимРазмещенияКопийДанныхВХранилищеДвоичныхДанных.РазмещениеКопийДанныхВХранилищеПриЗаписиВБазуДанных);
        Режимы.Добавить(РежимРазмещенияКопийДанныхВХранилищеДвоичныхДанных.РазмещениеКопийДанныхВХранилищеПриЧтенииИзБазыДанных);
        Режимы.Добавить(РежимРазмещенияКопийДанныхВХранилищеДвоичныхДанных.РазмещениеДанныхТолькоВХранилище);
        Режимы.Добавить(РежимРазмещенияКопийДанныхВХранилищеДвоичныхДанных.РазмещениеДанныхВХранилищеИВБазеДанныхПриНедоступностиХранилища);
        Для Номер = 0 По Режимы.Количество() - 1 Цикл
            Режим = Режимы[Номер];
            Если ТипЗнч(Режим) <> Тип("РежимРазмещенияКопийДанныхВХранилищеДвоичныхДанных") Тогда
                ВызватьИсключение "Нужен настоящий native enum placement mode";
            КонецЕсли;
            ХранилищеДвоичныхДанных.УстановитьРежимРазмещенияКопийДанныхВХранилищеДвоичныхДанных(Режим);
            Если ХранилищеДвоичныхДанных.ПолучитьРежимРазмещенияКопийДанныхВХранилищеДвоичныхДанных() <> Режим Тогда
                ВызватьИсключение "Placement-mode own roundtrip не совпал. Проверьте ручную предварительную optimized-storage настройку своей базы";
            КонецЕсли;
            Протокол.Добавить(ЗаписатьИПрочитатьСвойПакет85(КлючОпыта, Номер + 1, Строка(Режим)));
        КонецЦикла;
        ХранилищеДвоичныхДанных.УстановитьРежимРазмещенияКопийДанныхВХранилищеДвоичныхДанных(
            РежимРазмещенияКопийДанныхВХранилищеДвоичныхДанных.РазмещениеКопийДанныхВХранилищеПриЗаписиВБазуДанных);
        ХранилищеДвоичныхДанных.УстановитьРежимЧтенияЗаписиХранилищаДвоичныхДанных(РежимЧтенияЗаписиХранилищаДвоичныхДанных.ТолькоЧтение);
        Если ХранилищеДвоичныхДанных.ПолучитьРежимЧтенияЗаписиХранилищаДвоичныхДанных() <> РежимЧтенияЗаписиХранилищаДвоичныхДанных.ТолькоЧтение Тогда
            ВызватьИсключение "Storage read-only mode отдельно не подтвержден";
        КонецЕсли;
        Протокол.Добавить(ЗаписатьИПрочитатьСвойПакет85(КлючОпыта, 5, "StorageReadOnly: IB write permitted"));
        ХранилищеДвоичныхДанных.УстановитьРежимЧтенияЗаписиХранилищаДвоичныхДанных(РежимЧтенияЗаписиХранилищаДвоичныхДанных.ЧтениеИЗапись);
        УстановитьТолькоСвойСостав85(ИспользованиеХраненияВХранилищеДвоичныхДанных.НеИспользовать);
        Протокол.Добавить(ЗаписатьИПрочитатьСвойПакет85(КлючОпыта, 6, "Own metadata attribute: DontUse"));
        УстановитьТолькоСвойСостав85(ИспользованиеХраненияВХранилищеДвоичныхДанных.Использовать);
        Если ХранилищеДвоичныхДанных.ПолучитьРежимИспользованияХранилищаДвоичныхДанных() <> РежимИспользованияХранилищаДвоичныхДанных.Разрешить
            Или ХранилищеДвоичныхДанных.ПолучитьМинимальныйРазмерЗаписываемыхДанных() <> 2048
            Или ХранилищеДвоичныхДанных.ПолучитьИспользованиеКакХранилищаПоУмолчанию()
            Или ХранилищеДвоичныхДанных.ПолучитьРежимЧтенияЗаписиХранилищаДвоичныхДанных() <> РежимЧтенияЗаписиХранилищаДвоичныхДанных.ЧтениеИЗапись
            Или ХранилищеДвоичныхДанных.ПолучитьРежимРазмещенияКопийДанныхВХранилищеДвоичныхДанных()
                <> РежимРазмещенияКопийДанныхВХранилищеДвоичныхДанных.РазмещениеКопийДанныхВХранилищеПриЗаписиВБазуДанных Тогда
            ВызватьИсключение "Согласованная own final policy отдельно не подтверждена";
        КонецЕсли;
        ПроверитьВсеСвоиШестьПакетов85(КлючОпыта);
        РазмерПосле = ПолучитьРазмерТолькоСвоегоКаталога85();
        Если Протокол.Количество() <> 6 Или РазмерПосле < 0 Тогда
            ВызватьИсключение "Own report ограничен шестью фазами и неотрицательным native size";
        КонецЕсли;
    Исключение
        Если МонопольныйРежим() Тогда
            УстановитьМонопольныйРежим(Ложь);
        КонецЕсли;
        ВызватьИсключение "Own опыт мог оставить настройки/данные частично. Монопольная блокировка снята, если native снятие завершилось; режимов/данных автоматически не откатываем, запуск не повторять";
    КонецПопытки;
    УстановитьМонопольныйРежим(Ложь);
    Если МонопольныйРежим() Тогда
        ВызватьИсключение "Own exclusive lock не снята; не объявляем завершение";
    КонецЕсли;
    Возврат Новый Структура("Ключ,Фазы,РазмерДо,РазмерПосле", КлючОпыта, Протокол, РазмерДо, РазмерПосле);
КонецФункции

Процедура УстановитьТолькоСвойСостав85(Хранение)
    Если Не МонопольныйРежим() Или ВнешниеХранилищаДвоичныхДанных.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен собственный exclusive-сеанс без других storage";
    КонецЕсли;
    Состав = Новый СоставХранимыхДанныхХранилищаДвоичныхДанных;
    Состав.Добавить(Метаданные.Справочники.УчебныеПакеты85.Реквизиты.Данные, Хранение);
    ХранилищеДвоичныхДанных.УстановитьСоставХранимыхДанных(Состав);
    СвежийСостав = ХранилищеДвоичныхДанных.ПолучитьСоставХранимыхДанных();
    Если СвежийСостав.Количество() <> 1 Тогда
        ВызватьИсключение "Own состав должен содержать ровно один собственный attribute";
    КонецЕсли;
    Элемент = СвежийСостав.Получить(0);
    Если Элемент.Метаданные <> Метаданные.Справочники.УчебныеПакеты85.Реквизиты.Данные Или Элемент.Хранение <> Хранение Тогда
        ВызватьИсключение "Состав вернулся с чужим metadata или неправильным location flag";
    КонецЕсли;
КонецПроцедуры

Функция ЗаписатьИПрочитатьСвойПакет85(КлючОпыта, Фаза, Режим)
    Если Не МонопольныйРежим() Или Фаза < 1 Или Фаза > 6 Тогда
        ВызватьИсключение "Own payload создается только в шести фазах одного своего exclusive опыта";
    КонецЕсли;
    Данные = ПолучитьСвойPayload85(КлючОпыта, Фаза);
    Элемент = Справочники.УчебныеПакеты85.СоздатьЭлемент();
    Элемент.Код = Строка(Новый УникальныйИдентификатор);
    Элемент.Наименование = КлючОпыта + "|" + Строка(Фаза);
    Элемент.КлючОпыта = КлючОпыта;
    Элемент.Фаза = Фаза;
    Элемент.Данные = Новый ХранилищеЗначения(Данные);
    Элемент.Записать();
    Свежий = Элемент.Ссылка.ПолучитьОбъект();
    ПроверитьСвойПакет85(Свежий, КлючОпыта, Фаза);
    Возврат Новый Структура("Фаза,Режим,БайтовPayload,ХешPayload,Ссылка", Фаза, Режим, Данные.Размер(),
        Base64Строка(ХешироватьСвойPayload85(Данные)), Строка(Свежий.Ссылка));
КонецФункции

Функция ПолучитьСвойPayload85(КлючОпыта, Фаза)
    UUIDКлюча = Новый УникальныйИдентификатор(КлючОпыта);
    Если КлючОпыта <> Строка(UUIDКлюча) Или UUIDКлюча = Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000")
        Или Фаза < 1 Или Фаза > 6 Тогда
        ВызватьИсключение "Нужен собственный canonical nonzero nonce и phase1..6";
    КонецЕсли;
    Текст = КлючОпыта + "|" + Строка(Фаза) + "|";
    Для Номер = 1 По 256 Цикл
        Текст = Текст + Строка(Номер) + ":Книга3×250=750;";
    КонецЦикла;
    Данные = ПолучитьДвоичныеДанныеИзСтроки(Текст, КодировкаТекста.UTF8, Ложь);
    Если Данные.Размер() < 4096 Или Данные.Размер() > 16384 Тогда
        ВызватьИсключение "Own bounded binary payload должен быть4..16KiB без чтения файлов";
    КонецЕсли;
    Возврат Данные;
КонецФункции

Функция ХешироватьСвойPayload85(Данные)
    Хеширование = Новый ХешированиеДанных(ХешФункция.SHA256);
    Хеширование.Добавить(Данные);
    Возврат Хеширование.ХешСумма;
КонецФункции

Процедура ПроверитьСвойПакет85(Свежий, КлючОпыта, Фаза)
    Если Свежий = Неопределено Или Свежий.КлючОпыта <> КлючОпыта Или Свежий.Фаза <> Фаза
        Или Свежий.Наименование <> КлючОпыта + "|" + Строка(Фаза) Или Свежий.ПометкаУдаления
        Или ТипЗнч(Свежий.Данные) <> Тип("ХранилищеЗначения") Тогда
        ВызватьИсключение "Actual own object passport не совпал";
    КонецЕсли;
    Прочитанные = Свежий.Данные.Получить();
    Ожидаемые = ПолучитьСвойPayload85(КлючОпыта, Фаза);
    Если ТипЗнч(Прочитанные) <> Тип("ДвоичныеДанные") Или Прочитанные.Размер() <> Ожидаемые.Размер()
        Или Base64Строка(ХешироватьСвойPayload85(Прочитанные)) <> Base64Строка(ХешироватьСвойPayload85(Ожидаемые)) Тогда
        ВызватьИсключение "Actual own fresh payload length/SHA256 не совпал";
    КонецЕсли;
КонецПроцедуры

Процедура ПроверитьВсеСвоиШестьПакетов85(КлючОпыта)
    Выборка = Справочники.УчебныеПакеты85.Выбрать();
    Фазы = Новый Массив;
    Пока Выборка.Следующий() Цикл
        Если Фазы.Количество() >= 6 Или Выборка.КлючОпыта <> КлючОпыта Или Фазы.Найти(Выборка.Фаза) <> Неопределено Тогда
            ВызватьИсключение "В своем sole catalog есть чужие/дублированные/лишние данные";
        КонецЕсли;
        ПроверитьСвойПакет85(Выборка.Ссылка.ПолучитьОбъект(), КлючОпыта, Выборка.Фаза);
        Фазы.Добавить(Выборка.Фаза);
    КонецЦикла;
    Если Фазы.Количество() <> 6 Тогда
        ВызватьИсключение "Own six phases после финальной настройки не подтвердились";
    КонецЕсли;
КонецПроцедуры

Функция ПолучитьРазмерТолькоСвоегоКаталога85()
    Включить = Новый Массив;
    Включить.Добавить(Метаданные.Справочники.УчебныеПакеты85);
    Размер = ПолучитьРазмерДанныхБазыДанныхИХранилищаДвоичныхДанных(Новый Массив, Включить, Новый Массив);
    Если ТипЗнч(Размер) <> Тип("Число") Или Размер < 0 Тогда
        ВызватьИсключение "Native size собственных таблиц+storage должен быть неотрицательным числом байтов";
    КонецЕсли;
    Возврат Размер;
КонецФункции

Процедура ПроверитьСвоюБазуДвоичных85(МеткаСвоейБазы)
    ПроверитьСвойПустойСтенд();
    UUIDМетки = Новый УникальныйИдентификатор(МеткаСвоейБазы);
    Если МеткаСвоейБазы <> Строка(UUIDМетки) Или UUIDМетки = Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000") Тогда
        ВызватьИсключение "Own ref marker должен быть каноническим ненулевым UUID, не realIBUUID";
    КонецЕсли;
    ОжидаемоеСоединение = "Srvr=""localhost:1541"";Ref=""Уч85Двоичные_" + МеткаСвоейБазы + """;";
    Если СтрокаСоединенияИнформационнойБазы() <> ОжидаемоеСоединение Тогда
        ВызватьИсключение "Допускается только exact own localhost:1541/ref connection, без file/prod/других параметров. Строка соединения не выводится";
    КонецЕсли;
    Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
    Текущий = ПользователиИнформационнойБазы.ТекущийПользователь();
    Если Пользователи.Количество() <> 1 Или Текущий = Неопределено Тогда
        ВызватьИсключение "Нужен единственный real собственный IBUser";
    КонецЕсли;
    Если Пользователи[0].УникальныйИдентификатор <> Текущий.УникальныйИдентификатор
        Или Текущий.Имя <> "Уч85Двоичные_" + МеткаСвоейБазы Тогда
        ВызватьИсключение "Real current own IBUser не подтвержден";
    КонецЕсли;
    Мета = Метаданные.Справочники.УчебныеПакеты85;
    Если Мета.Имя <> "УчебныеПакеты85" Или Мета.Иерархический Или Мета.ТабличныеЧасти.Количество() <> 0
        Или Мета.Реквизиты.Количество() <> 3 Или Метаданные.Боты.Количество() <> 0
        Или Метаданные.Константы.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0
        Или Мета.Реквизиты.Данные.Тип.Типы().Количество() <> 1
        Или Мета.Реквизиты.КлючОпыта.Тип.Типы().Количество() <> 1 Или Мета.Реквизиты.Фаза.Тип.Типы().Количество() <> 1
        Или Не Мета.Реквизиты.Данные.Тип.СодержитТип(Тип("ХранилищеЗначения"))
        Или Не Мета.Реквизиты.КлючОпыта.Тип.СодержитТип(Тип("Строка"))
        Или Не Мета.Реквизиты.Фаза.Тип.СодержитТип(Тип("Число")) Тогда
        ВызватьИсключение "Нужна только own exact catalog schema с тремя реквизитами и без разделителей/служебных данных опыта";
    КонецЕсли;
КонецПроцедуры

Процедура ПроверитьСвойПустойСтенд()
    Если Метаданные.Справочники.Количество() <> 1 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
    КонецЕсли;
    Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
        ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
    КонецЕсли;
    Источники = Новый Массив;
    Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
    Для Каждого Источник Из Источники Цикл
        Расширения = РасширенияКонфигурации.Получить(, Источник);
        Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
            ВызватьИсключение "Native список расширений должен иметь тип Массив";
        КонецЕсли;
        Если Расширения.Количество() <> 0 Тогда
            ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
        КонецЕсли;
    КонецЦикла;
    Если ТранзакцияАктивна() Тогда
        ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
    КонецЕсли;
КонецПроцедуры
Полный модуль собственной управляемой формы: one-shot запуск и bounded отчет

Собственная внешняя обработка → Управляемая форма → Модуль формы.

Модуль управляемой формы, клиент только выводит own отчет; native storage setters и ValueStorage ctor остаются серверными.

Перем ОпытНачат85;

&НаКлиенте
Процедура ВыполнитьОпыт(Команда)
    Если ОпытНачат85 = Истина Тогда
        ВызватьИсключение "Повтор запрещен: storage policy/свои записи могли уже измениться";
    КонецЕсли;
    ОпытНачат85 = Истина;
    Протокол = ВыполнитьНаСервере85();
    Сообщить("Own nonce: " + Протокол.Ключ + "; шесть фаз проверены чтением/SHA256. Это не physical-placement proof");
    Для Каждого Фаза Из Протокол.Фазы Цикл
        Сообщить("Фаза " + Строка(Фаза.Фаза) + ": " + Фаза.Режим + "; own payload " + Строка(Фаза.БайтовPayload) + "байт; SHA256(base64)=" + Фаза.ХешPayload);
    КонецЦикла;
    Сообщить("Размер только своего каталога, native tables+storage bytes: до=" + Строка(Протокол.РазмерДо) + ", после=" + Строка(Протокол.РазмерПосле));
    Сообщить("Это не размер отдельных физически размещенных blobs/backup и не тест отказоустойчивости. Own записи сохранены, storage оставлен включенным; exclusive lock снята");
КонецПроцедуры

&НаСервере
Функция ВыполнитьНаСервере85()
    Возврат УчебныеДвоичные85.ВыполнитьСвойОпытДвоичных85(МеткаСвоейБазы, Подтверждение);
КонецФункции

Разбор по шагам

  1. До изменений guard проверяет exactCF/version, one local client-server Ref/marker, one actualIBUser, three typed own catalog fields, отсутствие других данных/разделителей/расширений и externalstores0.

  2. Административные действия отличаются от ValueStorage constructor: только native глобальный ХранилищеДвоичныхДанных manager изменяет настройки всей собственной базы. ValueStorage хранит значение и сам не выбирает физический сервер/путь.

  3. Exclusive context первоначально0, затем native1 внутри Try и последовательно0 success/catch. Native невозможность установки не обходится termination чужих сеансов.

  4. Enable создает storage при отсутствии, threshold1024 clamps2048 и это подтверждается getter; default true/false переключается только пока свой каталог пуст, затем own attribute composition explicitly controls записи.

  5. Placement enum четырех фаз readonly/native, свойства не присваиваются. Каждый setter имеет настоящий аргумент нужного типа и отдельный getter; missing optimized prerequisite не подменяется invented setter.

  6. Six own records имеют реальные сохраненные ссылки, own nonce/phase/name, binary data4..16KiB и свежие проверенныеSHA256. StandardCode новый UUID — собственный код, не fake reference identity.

  7. Native ReadOnly не приводит к учебному ожиданию исключения при IBwrite: пятая запись успешно читается в собственномpreparedruntime. Это native-described behavior, не измеренная нами запись физическихDB страниц.

  8. Composition содержит actual own Данные attribute и useflag. Возвращаемые Item.Metadata/Location readonly только сверяются. Objects already mapped другим storage native rejects; ownfixtureexternal0/emptycomposition это исключает в подготовке, не подменяет migration.

  9. Scoped size uses3native arguments and onlyownmetadata include. Не заявляется равенствоphysicalbytes=payloadbytes, storegrowth, отказоустойчивость или runtime вашего сервера.

Как проверить результат

  1. Actual own six saved refs после записи читаются отдельно; паспорта,4..16KiB размеры иSHA256 совпадают для всех фаз, включая ReadOnly/DontUse.

  2. После native exclusive acquisition заново проверяется пустой own каталог/disabled storage/emptycomposition/external0 до первой мутации, чтобы предварительное чтение не стало ошибочной защитой от изменения состояния.

  3. SetMinWrite1024 подтвердил native2048 clamp. Все четыре placement getter совпали с заданными native enum, финальный storage enabled/ReadAndWrite/defaultfalse/owncomposition.Use.

  4. Фаза5 IBwrite не ожидает исключения: exact native ReadOnly page прямо разрешает сохранение новыхbinarydata вБД независимо от включенияstore.

  5. Scope размера явно own catalog через include metadata, search=[]/exclude=[]; возвращены числабайтов, не полныетаблицы чужойбазы или обещанное равенствоpayloadbytes.

  6. Exclusive lock принадлежит только своему сеансу и снимаетсяsuccess/catch, еслиnative release успешен; policy/данные не объявляются откатившимися при ошибке.

Ожидаемый результат

При самостоятельном успешном запуске полностью подготовленного собственного стенда отчет содержит6фаз, реальные ownpayload размеры/SHA256 и scoped native table+storage bytes до/после. Все6own records сохранены, финальная policy оставленаenabled, exclusive снята. Проверка содержимого не доказывает физическое размещение каждого байта/failover. Здесь runtime0, не живой результат вашей базы.

На что обратить внимание

  1. У менеджера нет native constructor: он доступен через readonly глобальное свойство ХранилищеДвоичныхДанных, только на сервере. Не присваивайте глобальное свойство и не создавайте Новый МенеджерХранилищаДвоичныхДанных.

  2. Client-server/local/address marker иmetadata guard — страховки, не доказательство ownership чужого server instance. Новый собственный выделенный кластер/IB по подготовке обязателен.

  3. SupportAvailability говорит о поддержке варианта платформы, не successful storage connectivity/current mode/optimizedDB. Ее True не доказывает все prerequisites.

  4. Native placement setter требует optimized DB binary storage, которое готовит владелец по точной своей документации. Здесь BSLsetter/CLIflag отсутствует честно; при неподтвержденной prerequisite опыт не готов к запуску.

  5. MinSize1024 не является допустимым физическим порогом: native clamps к2048. Payload bound и ValueStorage безcompression позволяют не ошибиться на меньшемcompressed value, но точный serialized overhead не измерялся.

  6. ReadOnly storage не делает IB/каталог readonly: writes идут в БД. Не превращайте режим в access-control или защиту документов от записи.

  7. CopyOnWrite хранит данные в storage и служебной таблице; CopyOnRead пишет в служебную таблицу и синхронно копирует при первом read. DataPlacementToStorageOnly поnative чтению также имеет попыткуfallback из служебной таблицы при ошибке, но само имя не обещает существование полнойDBкопии.

  8. DataPlacementToStorageAndDatabaseOnInaccessibleStorage при невозможностиstore-write пишетвDB; это не гарантия всех старыхblobs вDB и не проведенный failover test. Недоступность специально не создается.

  9. Один metadata attribute нельзя одновременно включить в состав разныхstore. Не копируйте состав из чужой production или не переименовывайте существующий storage: здесь они отсутствуют заранее.

  10. Policy setters/DB writes не обещаны одной общей транзакцией. Отмена собственного exclusive lock не откатывает policy, сохраненныеobjects или storagecopies; никаких автоматических реставраций/повторов.

  11. Size API может быть дорогим, не учитывает историюданных ирасширения, учитывает только доступныечтению данные. Свой малыйcatalog нужен для ограниченного учебного scope; результат не является physical-location/backup proof.

  12. Финальное enabled оставлено сознательно: отключениеstorage после StorageOnly не равно миграцииpayloadвDB. Delete files/cleanup/backups не входят в код и не выполнялись при подготовкеурока.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Пометка, найденная ссылка и контролируемое удаление: почему один объект останется

На собственных трёх сохранённых записях увидеть разницу между пометкой и удалением, проверить настоящую зависимость USE85→BLOCK85 и отдельно согласовать удаление только свободного FREE85.

Где и как запускать

Полный общий client-only модуль новой собственной Windows FileCF8.5.1.1343, только толстый обычный клиент. Реальные записи/монополия/удаление лишь будущие ручные этапы со своим явным согласием.

Подготовка

  1. Только совершенно новая собственная пустая File ИБ C:\1c-labs\OwnDeleteRefs85_3a8e7d41-9216-4bba-86ac-610c70f427d9\IB на отдельном учебном Windows стенде8.5.1.1343. Если путь/регистрация уже существуют — не переиспользуйте и не очищайте, остановитесь. Exact File="путь"; проверяется буквально; UUID в пути — лабораторная метка, не измеренный UUIDИБ. Здесь VM/каталог/CF/ИБ/данные не создавались и1С не запускалась.

  2. Конфигурация УчебноеУдалениеСсылок85: РежимСовместимостиНеИспользовать, ОсновнойРежимЗапускаОбычноеПриложение. Сервис→Параметры→Общие→вид редактирования конфигурации для режима запуска «Управляемое приложение и обычное приложение». Это параметр редактора, не metadataSupportedRunModes. Два справочника, одна обработка, один общий модуль и одна роль. Остальные прикладные объекты/разделители/расширения/параметрысеанса/подписки/задания/источники/хранилища отсутствуют; модули объектов/менеджеров пустые.

  3. Справочник Кандидаты85: неиерархический, без владельцев/табличных частей/предопределённых. КодСтрока12, Наименование80, автонумерацияНет, контрольуникальностиДа. Реквизиты Маркер85 единственныйтипСтрока36, Сумма85 единственныйтипЧисло10,0. Справочник Использования85: те же стандартные настройки, реквизиты Маркер85Строка36, Сумма85Число10,0, Кандидат85 единственныйтипСправочникСсылка.Кандидаты85. Никаких иных реквизитов или связей.

  4. Роль Уборка85Администратор только своей новойCF: Администрирование для списка пользователей, АктивныеПользователи, право установки монопольного режима; все права чтения/добавления/изменения/пометки/удаления обоих собственных справочников и использования обработки. Без RLS/ограничений чтения/разделителей. Единственный пользователь Уборка85Ученик с этой ролью; подключается только он. Это полная учебная роль, не рекомендации производственных прав.

  5. ДО вставки startup вручную сохраните ровно3записи обычными стандартными формами: Кандидаты85 BLOCK85/Сохранить/Сумма85=100 и FREE85/Удалить/200; Использования85 USE85/Связь/100, Кандидат85=реально сохранённый BLOCK85, не UUID-литерал. Маркер85 у всех3a8e7d41-9216-4bba-86ac-610c70f427d9; ПредопределенныйFalse. Обе записи кандидатов вручную пометьте на удаление, USE85 НЕ помечайте. Пометка не равна физическому удалению: USE85 сохраняет настоящую ссылку на BLOCK85.

  6. ОбщийМодуль УборкаПамять85: ГлобальныйНет, КлиентОбычноеПриложениеДа, КлиентУправляемоеПриложениеНет, СерверНет, ВнешнееСоединениеНет, ПривилегированныйНет, повторноеиспользованиеНеИспользовать. MAIN CODE полностью в этот модуль. Обработка Уборка85: единственная основная ОБЫЧНАЯ форма Пульт85, форма сама ничего не записывает при открытии. Реквизиты формы Подтверждаю85Булево начальноеFalse, Статус85Строка2000readonly. Кнопки Монопольно85/Удалить85: обе nativeНажатие→Этап85(Кнопка); формаПриОткрытии0→ПриОткрытии. FORM целиком в модуль; APPLICATION целиком в МодульОбычногоПриложения. Ни событие, ни кнопку вручную не вызывают.

  7. Сохраните/обновите вручную исключительно новуюCF. Закройте Конфигуратор и любые другие подключения своего стенда; не открывайте второе окно/фоновые сеансы/консоль запросов. Запустите толстый обычный клиент. Открытие читает полный объём обоих собственных справочников безГДЕ, сверяет все поля и actualGetObject; записей и блокировки пока нет.

  8. Первое отдельное согласие: поставьте флажок и нажмите Монопольно85. До установки блокировки код заново проверяет exactFile/схему/пользователя/единственное подключение/полный fixture. NativeУстановитьМонопольныйРежимTrue применяется только к своей новойИБ без разделителей; нет завершения чужих сеансов/параметров bypass. Затем getter и полный readback. Неудача запрещает продолжение, блокировка может уже существовать: код не снимает её blindfinally.

  9. В ownОбласть85 все три scope аргумента заданы: пустой массив комбинаций разделителей, Включить именно два собственных metadata каталога, явный пустой Исключить. NativeFindMarked иначе при Неопределено вИсключить может игнорировать include/exclude; старый compatibility≤8.3.4 тоже меняет семантику, поэтому запрещён. Мобильная платформа игнорирует scope — не поддерживается. Найденные2refs обязаны быть только BLOCK/FREE, без дубликатов. NativeFindByRefs возвращает actual USE→BLOCK; проверены каждая positional колонка0/1/2 и metadataИспользования85.

  10. Второе НОВОЕ согласие: прочитайте статус, снова поставьте флажок и нажмите Удалить85. Список refs получен заново, полный source/зависимость сверены перед процедурой. Проверять всегдаИстина: native defaultЛожь опасен и не используется. Процедура УдалитьОбъекты не возвращает значение: Оставшиеся — native выходной параметр. Ожидаемый будущий outcome: FREE85 физически исчезнет, BLOCK85 не удалится из-заUSE85, обе сохранённые ссылки/все поля останутся. Полные запросы подтверждают кандидатов300→100 и объектов3→2, новое marked-search1 и прежнюю собственную зависимость.

  11. Любое исключение/лишняя зависимость/чужая ссылка/неожиданная структура выходнойTV означает stickyСТОП, даже если часть операции уже выполнена. Повторов/rollback/автоочистки/снятия монополии кодом нет. Проверьте вручную только свой стенд, затем закройте только этот учебный клиент. Не обходите блокировку и не выполняйте упражнение на production или реальной копии. Отмена/отсутствие согласия не вызывает deletion; открытие формы повторно после выполненного удаления тоже откажет исходному fullfixture.

#Если ТолстыйКлиентОбычноеПриложение Тогда

Процедура ПроверитьСтенд85()
    Если СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1c-labs\OwnDeleteRefs85_3a8e7d41-9216-4bba-86ac-610c70f427d9\IB"";" Или Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Или Метаданные.ОсновнойРежимЗапуска <> РежимЗапускаКлиентскогоПриложения.ОбычноеПриложение Или ТранзакцияАктивна() Тогда
        ВызватьИсключение "Только собственный exact File стенд без совместимости и активной транзакции";
    КонецЕсли;
    Если Метаданные.Справочники.Количество() <> 2 Или Метаданные.Обработки.Количество() <> 1
        Или Метаданные.ОбщиеМодули.Количество() <> 1 Или Метаданные.Роли.Количество() <> 1
        Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Константы.Количество() <> 0
        Или Метаданные.Отчеты.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.ОбщиеФормы.Количество() <> 0
        Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0
        Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0
        Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0
        Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0
        Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0
        Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПараметрыСеанса.Количество() <> 0
        Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0
        Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Или Метаданные.ХранилищаНастроек.Количество() <> 0 Тогда
        ВызватьИсключение "Чужие метаданные/данные/разделители/дополнительные зависимости запрещены";
    КонецЕсли;
    Если РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.БазаДанных).Количество() <> 0
        Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансАктивные).Количество() <> 0
        Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансОтключенные).Количество() <> 0 Тогда
        ВызватьИсключение "Расширения не допускаются";
    КонецЕсли;
    Если Метаданные.Справочники.Найти("Кандидаты85") = Неопределено Или Метаданные.Справочники.Найти("Использования85") = Неопределено
        Или Метаданные.Обработки.Найти("Уборка85") = Неопределено Или Метаданные.ОбщиеМодули.Найти("УборкаПамять85") = Неопределено
        Или Не РольДоступна("Уборка85Администратор") Тогда
        ВызватьИсключение "Собственная схема/роль не найдена";
    КонецЕсли;
    Для Каждого Имя Из СтрРазделить("Кандидаты85,Использования85", ",") Цикл
        МД = Метаданные.Справочники.Найти(Имя);
        Если МД.Иерархический Или МД.Владельцы.Количество() <> 0 Или МД.ТабличныеЧасти.Количество() <> 0
            Или МД.Реквизиты.Количество() <> ?(Имя = "Кандидаты85", 2, 3) Тогда
            ВызватьИсключение "Каталоги без иерархии/владельцев/табличных частей, только объявленные собственные поля";
        КонецЕсли;
    КонецЦикла;
    Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
    Текущий = ПользователиИнформационнойБазы.ТекущийПользователь();
    Если ТипЗнч(Пользователи) <> Тип("Массив") Или Пользователи.Количество() <> 1 Или Текущий = Неопределено Тогда
        ВызватьИсключение "Нужен единственный свой пользователь";
    КонецЕсли;
    Если Пользователи[0].Имя <> "Уборка85Ученик" Или Текущий.УникальныйИдентификатор <> Пользователи[0].УникальныйИдентификатор Тогда
        ВызватьИсключение "Не подтвержден собственный текущий пользователь";
    КонецЕсли;
    Соединения = ПолучитьСоединенияИнформационнойБазы();
    Если ТипЗнч(Соединения) <> Тип("Массив") Или Соединения.Количество() <> 1 Тогда
        ВызватьИсключение "Закройте остальные подключения только своего стенда";
    КонецЕсли;
    Если Соединения[0].НомерСоединения <> НомерСоединенияИнформационнойБазы()
        Или Соединения[0].Пользователь.УникальныйИдентификатор <> Текущий.УникальныйИдентификатор Тогда
        ВызватьИсключение "Единственное подключение должно быть текущим и собственным";
    КонецЕсли;
КонецПроцедуры

Функция ПрочитатьИсточник85(СвободныйУдален) Экспорт
    ПроверитьСтенд85();
    Если ТипЗнч(СвободныйУдален) <> Тип("Булево") Тогда
        ВызватьИсключение "Неизвестная стадия учебного источника";
    КонецЕсли;
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ Ссылка,Код,Наименование,ПометкаУдаления,Предопределенный,Маркер85,Сумма85 ИЗ Справочник.Кандидаты85";
    Кандидаты = Запрос.Выполнить().Выгрузить();
    Если ТипЗнч(Кандидаты) <> Тип("ТаблицаЗначений") Или Кандидаты.Колонки.Количество() <> 7
        Или Кандидаты.Количество() <> ?(СвободныйУдален, 1, 2) Тогда
        ВызватьИсключение "Полный объём кандидатов не совпал";
    КонецЕсли;
    Блокированный = Неопределено;
    Свободный = Неопределено;
    Сумма = 0;
    Для Каждого Строка Из Кандидаты Цикл
        Если ТипЗнч(Строка.Ссылка) <> Тип("СправочникСсылка.Кандидаты85") Или Строка.Ссылка.Пустая()
            Или ТипЗнч(Строка.ПометкаУдаления) <> Тип("Булево") Или Не Строка.ПометкаУдаления
            Или Строка.Предопределенный Или Строка.Маркер85 <> "3a8e7d41-9216-4bba-86ac-610c70f427d9"
            Или ТипЗнч(Строка.Сумма85) <> Тип("Число") Тогда
            ВызватьИсключение "Не подтверждены собственные типы/пометки/маркер кандидатов";
        КонецЕсли;
        Если Строка.Код = "BLOCK85" И Строка.Наименование = "Сохранить" И Строка.Сумма85 = 100 И Блокированный = Неопределено Тогда
            Блокированный = Строка.Ссылка;
        ИначеЕсли Не СвободныйУдален И Строка.Код = "FREE85" И Строка.Наименование = "Удалить" И Строка.Сумма85 = 200 И Свободный = Неопределено Тогда
            Свободный = Строка.Ссылка;
        Иначе
            ВызватьИсключение "Лишняя/изменённая собственная запись кандидата";
        КонецЕсли;
        Объект = Строка.Ссылка.ПолучитьОбъект();
        Если ТипЗнч(Объект) <> Тип("СправочникОбъект.Кандидаты85") Или Объект.Метаданные() <> Метаданные.Справочники.Кандидаты85
            Или Объект.Ссылка <> Строка.Ссылка Или Объект.Код <> Строка.Код Или Объект.Наименование <> Строка.Наименование
            Или Объект.ПометкаУдаления <> Строка.ПометкаУдаления Или Объект.Предопределенный <> Строка.Предопределенный
            Или Объект.Маркер85 <> Строка.Маркер85 Или Объект.Сумма85 <> Строка.Сумма85 Тогда
            ВызватьИсключение "Actual объект кандидата не совпал со всем query source";
        КонецЕсли;
        Сумма = Сумма + Строка.Сумма85;
    КонецЦикла;
    Если Блокированный = Неопределено Или Не СвободныйУдален И (Свободный = Неопределено Или Свободный = Блокированный)
        Или Сумма <> ?(СвободныйУдален, 100, 300) Тогда
        ВызватьИсключение "Полные actual refs/числа кандидатов не подтверждены";
    КонецЕсли;
    Запрос.Текст = "ВЫБРАТЬ Ссылка,Код,Наименование,ПометкаУдаления,Предопределенный,Маркер85,Кандидат85,Сумма85 ИЗ Справочник.Использования85";
    Использования = Запрос.Выполнить().Выгрузить();
    Если ТипЗнч(Использования) <> Тип("ТаблицаЗначений") Или Использования.Количество() <> 1 Или Использования.Колонки.Количество() <> 8 Тогда
        ВызватьИсключение "Нужно единственное actual собственное использование";
    КонецЕсли;
    Строка = Использования[0];
    Если ТипЗнч(Строка.Ссылка) <> Тип("СправочникСсылка.Использования85") Или Строка.Ссылка.Пустая()
        Или Строка.Код <> "USE85" Или Строка.Наименование <> "Связь" Или Строка.ПометкаУдаления Или Строка.Предопределенный
        Или Строка.Маркер85 <> "3a8e7d41-9216-4bba-86ac-610c70f427d9" Или ТипЗнч(Строка.Кандидат85) <> Тип("СправочникСсылка.Кандидаты85")
        Или Строка.Кандидат85 <> Блокированный Или ТипЗнч(Строка.Сумма85) <> Тип("Число") Или Строка.Сумма85 <> 100 Тогда
        ВызватьИсключение "Изменено/чужое использование кандидата";
    КонецЕсли;
    Объект = Строка.Ссылка.ПолучитьОбъект();
    Если ТипЗнч(Объект) <> Тип("СправочникОбъект.Использования85") Или Объект.Метаданные() <> Метаданные.Справочники.Использования85
        Или Объект.Ссылка <> Строка.Ссылка Или Объект.Код <> Строка.Код Или Объект.Наименование <> Строка.Наименование
        Или Объект.ПометкаУдаления <> Строка.ПометкаУдаления Или Объект.Предопределенный <> Строка.Предопределенный
        Или Объект.Маркер85 <> Строка.Маркер85 Или Объект.Кандидат85 <> Строка.Кандидат85 Или Объект.Сумма85 <> Строка.Сумма85 Тогда
        ВызватьИсключение "Actual объект использования не совпал со всем query source";
    КонецЕсли;
    Возврат Новый Структура("Блокированный,Свободный,Использование,Сумма,Объекты", Блокированный, Свободный, Строка.Ссылка, Сумма, Кандидаты.Количество() + Использования.Количество());
КонецФункции

Функция Область85()
    Включить = Новый Массив;
    Включить.Добавить(Метаданные.Справочники.Кандидаты85);
    Включить.Добавить(Метаданные.Справочники.Использования85);
    Возврат Новый Структура("Разделители,Включить,Исключить", Новый Массив, Включить, Новый Массив);
КонецФункции

Функция Помеченные85(Паспорт, Область, После)
    Найденные = НайтиПомеченныеНаУдаление(Область.Разделители, Область.Включить, Область.Исключить);
    Если ТипЗнч(Найденные) <> Тип("Массив") Или Найденные.Количество() <> ?(После, 1, 2) Тогда
        ВызватьИсключение "Native marked-search не подтвердил собственный объём";
    КонецЕсли;
    Проверенные = Новый Массив;
    Для Каждого Ссылка Из Найденные Цикл
        Если ТипЗнч(Ссылка) <> Тип("СправочникСсылка.Кандидаты85") Или Ссылка.Пустая() Или Проверенные.Найти(Ссылка) <> Неопределено
            Или Ссылка <> Паспорт.Блокированный И (После Или Ссылка <> Паспорт.Свободный) Тогда
            ВызватьИсключение "Native marked-search содержит чужую/дублированную ссылку";
        КонецЕсли;
        Проверенные.Добавить(Ссылка);
    КонецЦикла;
    Возврат Найденные;
КонецФункции

Процедура ПроверитьЗависимость85(Таблица, Паспорт)
    Если ТипЗнч(Таблица) <> Тип("ТаблицаЗначений") Или Таблица.Колонки.Количество() <> 3 Или Таблица.Количество() <> 1 Тогда
        ВызватьИсключение "Только3 documented positional columns/1своя зависимость; иной return-shape требует ручной сверки, не обрезания";
    КонецЕсли;
    Если ТипЗнч(Таблица[0][0]) <> Тип("СправочникСсылка.Кандидаты85") Или Таблица[0][0] <> Паспорт.Блокированный
        Или ТипЗнч(Таблица[0][1]) <> Тип("СправочникСсылка.Использования85") Или Таблица[0][1] <> Паспорт.Использование
        Или Таблица[0][2] <> Метаданные.Справочники.Использования85 Тогда
        ВызватьИсключение "Не подтверждены ВСЕ actual ссылки и metadata источника зависимости";
    КонецЕсли;
КонецПроцедуры

Процедура ПроверитьПаспорт85(Паспорт, После)
    Если ТипЗнч(Паспорт) <> Тип("Структура") Или Паспорт.Количество() <> 5 Тогда
        ВызватьИсключение "Неизвестный собственный паспорт";
    КонецЕсли;
    Если ТипЗнч(Паспорт.Блокированный) <> Тип("СправочникСсылка.Кандидаты85") Или Паспорт.Блокированный.Пустая()
        Или ТипЗнч(Паспорт.Свободный) <> Тип("СправочникСсылка.Кандидаты85") Или Паспорт.Свободный.Пустая()
        Или Паспорт.Свободный = Паспорт.Блокированный Или ТипЗнч(Паспорт.Использование) <> Тип("СправочникСсылка.Использования85")
        Или Паспорт.Использование.Пустая() Или ТипЗнч(Паспорт.Сумма) <> Тип("Число") Или Паспорт.Сумма <> 300
        Или ТипЗнч(Паспорт.Объекты) <> Тип("Число") Или Паспорт.Объекты <> 3 Тогда
        ВызватьИсключение "Не подтверждён полный первоначальный own паспорт3refs/300/3";
    КонецЕсли;
    Факт = ПрочитатьИсточник85(После);
    Если Факт.Блокированный <> Паспорт.Блокированный Или Факт.Использование <> Паспорт.Использование
        Или Не После И Факт.Свободный <> Паспорт.Свободный Тогда
        ВызватьИсключение "Полный свежий source не подтвердил whitelist actual refs";
    КонецЕсли;
КонецПроцедуры

Функция ПодготовитьМонопольно85(Подтверждение) Экспорт
    Если ТипЗнч(Подтверждение) <> Тип("Булево") Или Не Подтверждение Тогда
        ВызватьИсключение "Отдельно подтвердите монопольный режим только своего стенда";
    КонецЕсли;
    Паспорт = ПрочитатьИсточник85(Ложь);
    Если МонопольныйРежим() Тогда
        ВызватьИсключение "Уже существующий монопольный этап не переиспользуется";
    КонецЕсли;
    ПроверитьПаспорт85(Паспорт, Ложь);
    УстановитьМонопольныйРежим(Истина);
    Если Не МонопольныйРежим() Тогда
        ВызватьИсключение "Actual монопольная блокировка не подтверждена";
    КонецЕсли;
    Область = Область85();
    Ссылки = Помеченные85(Паспорт, Область, Ложь);
    ПроверитьЗависимость85(НайтиПоСсылкам(Ссылки, Область.Разделители, Область.Включить, Область.Исключить), Паспорт);
    ПроверитьПаспорт85(Паспорт, Ложь);
    Возврат Паспорт;
КонецФункции

Функция ПопытатьсяУдалить85(Паспорт, Подтверждение) Экспорт
    Если ТипЗнч(Подтверждение) <> Тип("Булево") Или Не Подтверждение Тогда
        ВызватьИсключение "Заново подтвердите проверяемую попытку удаления своих BLOCK85/FREE85";
    КонецЕсли;
    ПроверитьПаспорт85(Паспорт, Ложь);
    Если Не МонопольныйРежим() Тогда
        ВызватьИсключение "Удаление без actual монопольного режима запрещено";
    КонецЕсли;
    Область = Область85();
    Ссылки = Помеченные85(Паспорт, Область, Ложь);
    ПроверитьЗависимость85(НайтиПоСсылкам(Ссылки, Область.Разделители, Область.Включить, Область.Исключить), Паспорт);
    ПроверитьПаспорт85(Паспорт, Ложь);
    Оставшиеся = Новый ТаблицаЗначений;
    УдалитьОбъекты(Ссылки, Истина, Оставшиеся, Область.Разделители, Область.Включить, Область.Исключить);
    ПроверитьЗависимость85(Оставшиеся, Паспорт);
    ПроверитьПаспорт85(Паспорт, Истина);
    После = ПрочитатьИсточник85(Истина);
    СсылкиПосле = Помеченные85(Паспорт, Область, Истина);
    ПроверитьЗависимость85(НайтиПоСсылкам(СсылкиПосле, Область.Разделители, Область.Включить, Область.Исключить), Паспорт);
    ПроверитьПаспорт85(Паспорт, Истина);
    Возврат После;
КонецФункции

#КонецЕсли
Полный пульт двух отдельно согласованных этапов

Обработки → Уборка85 → Формы → Пульт85 → Модуль, целиком

Толстый обычный клиент; actual own ButtonClick1/OnOpen0. StickyUnknown до каждого изменяемого этапа.

Перем Паспорт85, НеизвестныйИсход85, Завершено85;

Процедура ПриОткрытии()
    НеизвестныйИсход85 = Истина;
    Подтверждаю85 = Ложь;
    УборкаПамять85.ПрочитатьИсточник85(Ложь);
    Паспорт85 = Неопределено;
    Завершено85 = Ложь;
    НеизвестныйИсход85 = Ложь;
    Статус85 = "Подготовлено3своих объекта. Отдельно подтвердите монопольный этап; затем новое согласие перед удалением.";
КонецПроцедуры

Процедура Этап85(Кнопка)
    Если Кнопка <> ЭлементыФормы.Монопольно85 И Кнопка <> ЭлементыФормы.Удалить85 Тогда
        ВызватьИсключение "Нужна actual собственная кнопка";
    КонецЕсли;
    Если Кнопка.Имя <> ?(Кнопка = ЭлементыФормы.Монопольно85, "Монопольно85", "Удалить85")
        Или НеизвестныйИсход85 <> Ложь Или Завершено85 <> Ложь Тогда
        ВызватьИсключение "Неверный source-control/предыдущая ошибка/завершённый опыт";
    КонецЕсли;
    Если ТипЗнч(Подтверждаю85) <> Тип("Булево") Или Не Подтверждаю85 Тогда
        ВызватьИсключение "Поставьте своё согласие на один следующий этап";
    КонецЕсли;
    Подтверждаю85 = Ложь;
    НеизвестныйИсход85 = Истина;
    Попытка
        Если Кнопка = ЭлементыФормы.Монопольно85 Тогда
            Если Паспорт85 <> Неопределено Тогда
                ВызватьИсключение "Монопольный этап нельзя повторять";
            КонецЕсли;
            Паспорт85 = УборкаПамять85.ПодготовитьМонопольно85(Истина);
            Статус85 = "Actual2marked/однаUSE85→BLOCK85 проверены, source300/3неизменен. Теперь отдельное согласие: FREE85 исчезнет, BLOCK85 должен остаться.";
        Иначе
            Если Паспорт85 = Неопределено Тогда
                ВызватьИсключение "Нет собственного завершённого монопольного этапа";
            КонецЕсли;
            После = УборкаПамять85.ПопытатьсяУдалить85(Паспорт85, Истина);
            Статус85 = "Actual сумма кандидатов: " + Формат(Паспорт85.Сумма, "ЧГ=0;ЧДЦ=0") + "→" + Формат(После.Сумма, "ЧГ=0;ЧДЦ=0")
                + "; объектов: " + Формат(Паспорт85.Объекты, "ЧГ=0") + "→" + Формат(После.Объекты, "ЧГ=0") + ". BLOCK85 и USE85 сохранены. Закройте только этот учебный клиент; повторов нет.";
            Завершено85 = Истина;
        КонецЕсли;
        НеизвестныйИсход85 = Ложь;
    Исключение
        НеизвестныйИсход85 = Истина;
        Статус85 = "СТОП: исход блокировки/удаления неизвестен, возможно частичное изменение. Не повторять и не снимать блокировку кодом. " + ОписаниеОшибки();
        ВызватьИсключение;
    КонецПопытки;
КонецПроцедуры
Полный startup собственной формы

Конфигурация → Модуль обычного приложения, целиком ПОСЛЕ ручного fixture

NativeOnStart0, ordinarythick; own ProcessingManager.GetForm/freshkey→actualOpen; никакого ручного eventcall.

Процедура ПриНачалеРаботыСистемы()
#Если ТолстыйКлиентОбычноеПриложение Тогда
    СвойКлюч85 = Новый УникальныйИдентификатор;
    Форма85 = Обработки.Уборка85.ПолучитьФорму("Пульт85",, СвойКлюч85);
    Если Форма85 = Неопределено Или ТипЗнч(Форма85) <> Тип("Форма") Или Форма85.Открыта() Или Форма85.КлючУникальности <> СвойКлюч85 Тогда
        ВызватьИсключение "Не подтверждена новая собственная ordinary форма";
    КонецЕсли;
    Форма85.Открыть();
#Иначе
    ВызватьИсключение "Только собственный толстый обычный клиент";
#КонецЕсли
КонецПроцедуры

Разбор по шагам

  1. Вручную подготовить собственную новуюCF и actual2marked кандидата100/200 плюс одну непомеченную actualUsage100.

  2. Полным query/GetObject подтвердить каждую собственную ссылку/поле и единственный сеанс, затем отдельно согласовать собственную монополию.

  3. FindMarked с тремя явными scope массивами даёт только2actualref; FindByRefs с четырьмя аргументами даёт собственную dependency, не придуманную ссылку.

  4. Новое согласие → свежий полный whitelist → DeleteObjects(6args, CheckTrue, actualoutputTable) без назначения return.

  5. Проверить actualremaining dependency и оба полных sources: только свободная запись исчезла, blocked и usage полностью сохранены, actual numeric300→100/objects3→2.

Как проверить результат

  1. Проверяются обе ссылки кандидатных объектов, собственная ссылка использования и все3 positional поля dependency, не только число строк.

  2. У неизвестного/дублированного refs или несоответствующего metadata/ref/marker/amount fullguard отказывает доdelete.

  3. Статические native/callback/readonly/arity/consent/owner/scope mutations; реальных запусков и удаления0.

Ожидаемый результат

Будущий ручной результат: FREE85 удалён, BLOCK85 и USE85 сохранены; сумма кандидатов300→100, объекты3→2, oneactualremaining dependency. Здесь только полный authored код/подготовка и статические проверки;1С/ИБ/БД/UI/runtime0.

На что обратить внимание

  1. DeleteObjects может удалить и непомеченный объект, если его ref передан: список здесь берётся изactual marked-search и строгого own whitelist, не из unknowninput.

  2. Один сеанс и монопольная блокировка не оправдывают удаление production. Поиск ограничен доступностью/разделением/правами; отсутствие чужих источников задаётся именно новой собственной минимальнойCF, не выводится из одной таблицы зависимостей.

  3. NativeDelete parameter описывает3 positional columns, notes также упоминают4-е поле комбинаций разделителей. Для своейNoSplit fixture принимается только реальный3-column return; иной shape — стоп, не угадывание default четвёртого поля/не обрезание. Поля/порядок nativecolumnnames не выдумываются.

  4. Remaining показывает только непосредственно препятствующие объекты, не рекурсивный граф. Этот урок имеет ровноодну заранее подготовленную непосредственную связь и не обещает обработки произвольной конфигурации.

  5. Никакой обещанной атомарности нескольких этапов/rollback. Исключение после setter/delete оставляет неизвестный исход; штатный native результат и полный readback проверяются отдельно от статических тестов.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.