Потеря данных — одна из самых неприятных ситуаций в работе с корпоративными информационными системами. Особенно остро стоит вопрос, когда документ исчезает бесследно, а стандартные средства вроде "Корзины" в интерфейсе не помогают, так как удаление произошло программно — например, с помощью внешней обработки или прямого SQL-запроса. В этой статье мы подробно разберем, как провести расследование инцидента, используя инструменты платформы 1С:Предприятие и возможности MS SQL Server.
Давайте представим ситуацию: из базы данных пропал важный документ. Известно, что это могло быть сделано случайно запущенной внешней обработкой. Наша задача — выяснить, с какого компьютера и под каким пользователем была запущена эта процедура.
Первое место, куда мы должны заглянуть, — это стандартный Журнал регистрации. Существует распространенное заблуждение, что программное удаление объектов (методом Удалить()) не фиксируется в журнале, если разработчик явно не прописал туда запись. Однако в современных версиях платформы это не совсем так.
Если уровень журналирования в конфигураторе установлен в значение "Информация" или "Ошибки", платформа автоматически фиксирует факт физического удаления данных.
Давайте выполним следующие действия для поиска следов:
Если нам повезет и запись найдется, мы увидим всю необходимую информацию:
Важный нюанс: Если удаление происходило в транзакции, которая была отменена, записи в журнале регистрации о самом удалении не останется. Однако, если документ действительно исчез из базы, значит транзакция была зафиксирована (committed).
Если в Журнале регистрации пусто (например, журнал был отключен, очищен или удаление произошло прямым SQL-запросом мимо сервера 1С), нам придется спуститься на уровень ниже — к системе управления базами данных MS SQL Server.
MS SQL Server ведет Журнал транзакций (Transaction Log). В нем фиксируются все изменения данных. Даже если данные удалены из таблицы, запись об этой операции хранится в логе до тех пор, пока не будет сделан бэкап журнала транзакций (в модели восстановления Full) или пока чекпоинт не очистит его (в модели Simple). Если с момента удаления прошло немного времени и бэкап лога еще не делался, у нас есть шансы.
Прежде чем искать удаление, нужно понять, как называется таблица, в которой хранился документ. 1С не называет таблицы человеческими именами вроде "Document.Накладная". Имена имеют вид _Document123, _InfoRg456 и т.д.
Чтобы узнать соответствие, мы воспользуемся встроенной функцией языка 1С ПолучитьСтруктуруХраненияБазыДанных(). Создадим простую внешнюю обработку и выполним следующий код:
МассивИмен = Новый Массив;
МассивИмен.Добавить("Документ.РеализацияТоваровУслуг"); // Укажите имя вашего документа
СтруктураХранения = ПолучитьСтруктуруХраненияБазыДанных(МассивИмен);
Для Каждого СтрокаТаблицы Из СтруктураХранения Цикл
Сообщить("Имя таблицы SQL: " + СтрокаТаблицы.ИмяТаблицыХранения);
КонецЦикла;
Запишите полученное имя таблицы (например, _Document345). Оно понадобится нам для поиска в логах.
Ранее для этих целей использовали сторонние утилиты, такие как Log Explorer от Lumigent. Сейчас мы можем воспользоваться недокументированной, но широко известной системной функцией MS SQL — sys.fn_dblog.
Запустим SQL Server Management Studio (SSMS) и выполним запрос к базе данных. Нам нужно найти операции удаления (LOP_DELETE_ROWS) по нашей таблице (AllocUnitName). Обратите внимание, что имя таблицы в логе будет содержать имя схемы, обычно dbo..
Пример запроса:
USE [ИмяВашейБазы1С];
SELECT
[Current LSN],
[Operation],
[Context],
[Transaction ID],
[Begin Time],
[AllocUnitName]
FROM
sys.fn_dblog(NULL, NULL)
WHERE
[Operation] = 'LOP_DELETE_ROWS'
AND [AllocUnitName] LIKE '%_Document345%' -- Подставьте имя таблицы, полученное из 1С
Этот запрос покажет нам все факты удаления строк из таблицы документа. По колонке [Begin Time] мы сможем определить точное время удаления.
Здесь мы сталкиваемся с главной сложностью трехзвенной архитектуры (Клиент — Сервер 1С — SQL Server). Если мы посмотрим в логи SQL Server (или даже настроим SQL Audit), в графе "Пользователь" мы, скорее всего, увидим имя служебной учетной записи, под которой запущен процесс rphost сервера 1С (например, USR1CV8). А в графе "Компьютер" (HostName) будет указано имя сервера приложений 1С, а не компьютера пользователя.
Это происходит потому, что для SQL Server "клиентом" является сервер 1С, а не конечный пользователь Вася Пупкин.
Как же тогда найти виновника?
Единственный надежный метод в данном случае — это сопоставление времени.
sys.fn_dblog берем точное время транзакции удаления (с точностью до секунд или миллисекунд).Мы будем искать любые события: "Транзакция.Начало", "Данные.Изменение", выполнение фоновых заданий или запуск обработок. Если в эту секунду активность проявлял только один пользователь — с высокой долей вероятности это и есть наш "автор" удаления.
Чтобы в будущем облегчить расследование подобных инцидентов, рассмотрим несколько превентивных мер:
1. Ограничение прав на внешние обработки
Как верно заметили участники обсуждения, нужно четко понимать, у кого есть право Интерактивное открытие внешних обработок. Оставьте это право только администраторам или ответственным лицам.
2. Версионирование объектов
В типовых конфигурациях (БП, УТ, ERP) есть подсистема "Версионирование объектов". Включите ее для критически важных справочников и документов. Она позволяет хранить историю изменений. Хотя при полном физическом удалении версия тоже может стать недоступной, часто версионирование помогает понять, что происходило с объектом до удаления.
3. Технология Change Data Capture (CDC) в MS SQL
Для опытных администраторов баз данных. Включение CDC позволяет автоматически логировать все изменения (INSERT, UPDATE, DELETE) в специальных системных таблицах. Это даст вам полную историю изменений данных на уровне SQL без необходимости парсить логи транзакций вручную.
Резюме: Если документ удален "бесследно", начните с Журнала регистрации. Если там пусто, используйте sys.fn_dblog в SQL Server для поиска времени удаления, а затем сопоставьте это время с активностью пользователей в 1С. Это кропотливая работа, но она дает наиболее точный результат.