Кто удалил запись из таблицы?
В качестве дополнительного аргумента в пользу использования механизма After-Imaging, рассмотрим ситуацию, когда в системе не используется OpenEdge Auditing и приложение не создаёт собственные журналы аудита. В таком случае, как можно определить, кто и когда удалил конкретную запись из таблицы?
В этом случае помогут архивы AI-экстентов, если в базе данных реализован механизм After-Imaging. Методика поиска виновного будет рассмотрена на примере базы данных sports.
Для этого необходимо скопировать базу sports из каталога DLC, включить механизмы After-Imaging и AI File Management, запустить базу данных и сформировать резервную копию базы sports в онлайн.
Как это сделать, подробно описано в предыдущих статьях и книгах на данном сайте.
Для поиска необходимой информации требуется выполнить следующие действия:
- Получить доступ к архивам AI-экстентов, созданных в период, когда предположительно произошло удаление записи.
- Определить имя таблицы, из которой была удалена запись.
- Определить область хранения, в которой находится таблица.
- Определить RECID удаленной записи или номер блока, в котором она хранилась.
Для демонстрации процесса поиска информации необходимо удалить запись из базы данных. В качестве примера возьмем запись с номером 54 из таблицы Family.
Подключитесь к базе sports в режиме редактора:
mpro sports
Выполните следующий ABL-код:
find last family where empnum = 54 exclusive-lock. delete family.
Отключитесь от базы данных и дождитесь формирования очередного архива AI-экстента. Время формирования зависит от установленного интервала архивирования AI-экстентов в механизме AI File Management.
В данный момент необходимо определить RECID данной записи.
Восстановите базу данных sports в отдельный каталог из ранее созданной резервной копии.
prorest ./db1/sports ./backup/sports.bkp
Подключитесь к восстановленной базе данных в режиме редактора и выполните следующий ABL-код:
find last family where empnum = 54 no-lock. displ recid(family).
В результате работы данной программы на экран монитора будет выведено значение RECID, равное 510.
Для определения области хранения данной таблицы можно использовать команду PROUTIL TABANALYS или Data Dictionary.
PROUTIL TABANALYS
Выполните команду:
proutil sports -C tabanalys > tabanalys.txt
Откройте файл tabanalys.txt и найдите информацию о таблице Family. В качестве примера рассмотрим базу данных sports.
RECORD BLOCK SUMMARY FOR AREA "Employee" : 7 ------------------------------------------------------- -Record Size (B)- ---Fragments--- Scatter Table Records Size Min Max Mean Count Factor Factor PUB.Benefits 21 848.0B 39 41 40 21 1.0 1.0 PUB.Department 7 211.0B 26 35 30 7 1.0 2.0 PUB.Employee 55 6.2K 99 135 115 55 1.0 1.0 PUB.Family 70 3.0K 38 51 44 70 1.0 1.0
Здесь мы видим, что таблица Family находится в области Employee с порядковым номером 7.
Data Dictionary
Подключитесь к базе данных sports в режиме редактора и перейдите в меню Tools -> Data Dictionary -> Database -> Reports -> Detailed Table. В появившемся диалоговом окне выберите название таблицы Family и нажмите клавишу Enter. Откроется диалоговое окно Report Options, которое позволяет настраивать параметры отчета. Ничего не меняйте, нажмите клавишу F1. На экран будет выведен отчет с информацией по таблице Family.
Найдите в отчете строку Storage Area, которая будет указывать на имя области, в которой хранится таблица. В нашем случае это область хранения Employee.
После того как было найдено имя области хранения, необходимо найти значение RPB для этой области. Воспользуйтесь структурным файлом базы данных (sports.st), предварительно обновив его следующей командой:
prostrct list sports
Откройте файл sports.st и найдите в нем описание области «Employee». В ее описании значение RPB равно 32 :
d "Employee":7,32;1
Получив значения RECID и RPB, необходимо рассчитать значение DBKEY. Для этого следует выполнить следующие действия:
- Разделить RECID на RPB.
- Отбросить дробную часть полученного результата.
- Умножить полученное целое число на RPB.
Полученное произведение и будет значением DBKEY.
510 / 32 = 15,9375 DBKEY = 15 х 32 = 480
Теперь вам известно значение DBKEY. Вы можете приступить к его поиску в сформированных архивах AI-экстентов. Для этого перейдите в каталог с архивами AI-экстентов и выделите те из них, которые, по вашему мнению, были сформированы в период существования записи и после её удаления.
После этого выгрузите AI-заметки из выбранных AI-экстентов в отдельный файл следующей командой:
rfutil sports -C aimage scan verbose -a ai-file-name >> scanai.txt
Для того чтобы избежать необходимости выполнять данную команду вручную для каждого AI-экстента, можно автоматизировать этот процесс с помощью следующей команды:
for ai in `ls -1 ./*.sports.a*`; do rfutil sports -C aimage scan verbose -a $ai >> AIscan.txt ; done
После этого необходимо найти в файле AIscan.txt все данные, связанные с DBKEY и номером области хранения. В нашем случае ищем значение 480 (DBKEY) и отсекаем по номеру области 7.
cat AIscan.txt | grep 480 | grep 7 Trid: 3942 area = 7 dbkey = 480 update counter = 35 (12529) Trid: 3942 area = 7 dbkey = 480 update counter = 36 (12529) Trid: 3942 area = 7 dbkey = 480 update counter = 37 (12529)
Необходимо найти все AI-заметки транзакции, в рамках которой было выполнено удаление. В данном случае это Trid: 3942.
cat AIscan.txt | grep "Trid: 3942"
Результат будет выглядеть следующим образом:
Trid: 3942 Thu May 27 14:42:48 2010. (2598) Trid: 3942 User Id: val (12531) Trid: 3942 code = RL_TBGN version = 1 (12528) Trid: 3942 dbkey = 0 update counter = 0 (12530) Trid: 3942 code = RL_IXDEL version = 2 (12528) Trid: 3942 dbkey = 0 update counter = 0 (12530) Trid: 3942 code = RL_BKREPL version = 1 (12528) Trid: 3942 area = 7 dbkey = 192 update counter = 209 (12529) Trid: 3942 code = RL_RMDEL version = 2 (12528) Trid: 3942 area = 7 dbkey = 480 update counter = 35 (12529) Trid: 3942 code = RL_RMCR version = 2 (12528) Trid: 3942 area = 7 dbkey = 480 update counter = 36 (12529) Trid: 3942 code = RL_BKBBOT version = 1 (12528) Trid: 3942 area = 7 dbkey = 480 update counter = 37 (12529) Trid: 3942 code = RL_BKMBOT version = 2 (12528) Trid: 3942 area = 7 dbkey = 64 update counter = 62 (12529) Trid: 3942 code = RL_BK2EB version = 2 (12528) Trid: 3942 area = 7 dbkey = 512 update counter = 38 (12529) Trid: 3942 Thu May 27 14:42:48 2010. (2598) Trid: 3942 code = RL_TEND version = 1 (12528) Trid: 3942 dbkey = 0 update counter = 0 (12530)
Выделенная жирным шрифтом информация представляет для нас интерес.
Согласно данным, запись была удалена пользователем val в 14:42:48 27 мая 2010 года.
Строка с RL_RMDEL указывает на выполнение операции удаления.
Следующая строка содержит информацию о номере области хранения (area = 7) и номере DBKEY (dbkey = 480).
Приведенный пример наглядно показывает, что механизм After-Imaging может быть полезен не только для дополнительного резервного копирования базы данных, но и для помощи в разрешении инцидентов, таких как несанкционированное удаление данных из базы.
Метка:After-Imaging