Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Журналирование операций работы с БД 
:(
    Опции темы
santilaas
Дата 21.1.2007, 07:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 322
Регистрация: 28.8.2005
Где: Блага

Репутация: нет
Всего: нет



Привет всем! Это снова я.
Вопрос такой: хочу реализовать логирование операций по работе с моей БД (написана с исп-ем Firebird1.5.1), притом хочу хранить все сведения, начиная от попыток подключения к БД до изменения любого поля. При этом хочу для LOG-а создать отдельный файл БД (Log.fdb) - вопрос - насколько это рационально - стоит или нет такое делать (т.е. создавать 2 БД)??? 
Желательно услышать мнение профессионалов или по крайней мере тех, у кого логирование работает и не тормозит работу всей БД.
Может кто предложит свой вариант - и, если можно, поподробнее.


--------------------
[
PM MAIL   Вверх
Alex
Дата 22.1.2007, 01:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 17
Всего: 162





--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
Akella
Дата 22.1.2007, 10:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 29
Всего: 329



Я всё делаю в одной БД.
И не средствами триггеров. Делаю всё в клиентском приложении. Т.к. триггеры не могут зафиксировать доступ, например к форме репликации или доступ к форме настроек программы. Мало того, у меня фсе пользователи работают "для сервера" под одним именем. Опять же, потому что сервер не может контролировать доступ к форме справочников или к форме настроек. Поэтому у меня отдельная своя таблица пользователей, отдельная своя таблица групп и прав доступа.
PM MAIL   Вверх
Alex
Дата 22.1.2007, 11:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 17
Всего: 162



Цитата(Akella @  22.1.2007,  11:58 Найти цитируемый пост)
Я всё делаю в одной БД.
И не средствами триггеров. Делаю всё в клиентском приложении. Т.к. триггеры не могут зафиксировать доступ, например к форме репликации или доступ к форме настроек программы. Мало того, у меня фсе пользователи работают "для сервера" под одним именем. Опять же, потому что сервер не может контролировать доступ к форме справочников или к форме настроек. Поэтому у меня отдельная своя таблица пользователей, отдельная своя таблица групп и прав доступа. 

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


--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
Akella
Дата 22.1.2007, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 29
Всего: 329



если у такого горе-пользователя есть доступ к БД, я имею ввиду пароль SYSDBA, то это проблемы админа БД, я предупредил своих.


Alex, где-то я с тобой согласен, но я видел уже в нескольких программах такой подход, как у меня, и даже в достаточно серьезных программах! Везде есть свои плюсы и минусы!

Это сообщение отредактировал(а) Akella - 22.1.2007, 16:16
PM MAIL   Вверх
santilaas
Дата 28.1.2007, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 322
Регистрация: 28.8.2005
Где: Блага

Репутация: нет
Всего: нет




Alex, эту классную статейку я уже читал, просто думал спросить, как это реализуют другие люди.
А вообще, так как мне нужен вариант, где журналируются все изменения, я сделал "Логирование в базе данных с сохранением информации", - кстати, сразу вопрос - сильно ли это "ударит" по размеру моей БД или нет (при 15 таблицах)??? 
И потом в любом случае придется еще дополнительно вести лог (текстовый файл- внешнюю таблицу) операций, не связанных с непосредственной вставкой, изменением или удалением данных. - получается так?  



--------------------
[
PM MAIL   Вверх
Alex
Дата 28.1.2007, 11:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 17
Всего: 162



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


--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
santilaas
Дата 28.1.2007, 15:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 322
Регистрация: 28.8.2005
Где: Блага

Репутация: нет
Всего: нет



Цитата

каждая копия программы ведет отдельно лог файл своей работы 

этот файл - текстовый?


--------------------
[
PM MAIL   Вверх
Alex
Дата 28.1.2007, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 17
Всего: 162



Цитата(santilaas @  28.1.2007,  16:41 Найти цитируемый пост)
этот файл - текстовый? 

разумеется, т.к. в него должна попасть даже информация, о не возможности подключения к серверу БД.
Вот как примерно он выглядит:
Цитата

-----------Старт-----------
24.01.2007 16:12:43    >> Старт 'sks.exe' 1.0.0.1929.
                       Компьютер: 'NATASHA', Базовая папка: D:\SKS_BASE\, ОС: 'Windows XP v5.01.2600 Service Pack 2'
24.01.2007 16:12:43    >> Настройки:
                         База: 'General:sks_new'
                         Путь по умолчанию для картинок: '\\General\sks_base\db\img\'
                         Путь по умолчанию для данных: '\\General\sks_base\db\data\'
24.01.2007 16:12:43    Создание папки для временных файлов "C:\DOCUME~1\9335~1\LOCALS~1\Temp\SKS\"
24.01.2007 16:12:43    Папка для временных файлов создана
24.01.2007 16:12:43    Распаковка клиентской DLL в "C:\DOCUME~1\9335~1\LOCALS~1\Temp\SKS\fbclient.dll"
24.01.2007 16:12:50    Попытка подключения к базе "General:sks"
24.01.2007 16:12:52    Попытка подключения к базе удалась
24.01.2007 16:12:52    Получение данных из БД
24.01.2007 16:12:52    Проверка минимальной версии программы для работы.
24.01.2007 16:12:52    Проверка минимальной версии БД для работы.
24.01.2007 16:12:52    Проверка возможности работы программы, закончена.
24.01.2007 16:12:52    Загрузка настроек из БД
24.01.2007 16:12:53    Считывание дополнительных параметров
24.01.2007 16:12:53    Запуск процедуры коррекции резервов
24.01.2007 16:12:53    Резервы скорректированы
24.01.2007 16:12:53    Запуск процедуры коррекции статуса проформ
24.01.2007 16:12:53    Статусы проформ скорректированы
24.01.2007 16:12:53    Запуск процедуры коррекции статуса партии
24.01.2007 16:12:53    Статусы партий скорректированы
24.01.2007 16:12:53    Создание необходимых генераторов
24.01.2007 16:12:53    Генераторы созданы
24.01.2007 16:12:53    Программная настройка отображения полей
...
24.01.2007 18:14:24    Попытка дисконнекта от базы
24.01.2007 18:14:24    Попытка дисконнекта от базы удалась



--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
Akella
Дата 1.2.2007, 16:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 29
Всего: 329



Цитата(santilaas @  28.1.2007,  11:15 Найти цитируемый пост)
кстати, сразу вопрос - сильно ли это "ударит" по размеру моей БД или нет

делай отдельную БД, я не сделал, а теперь жалею, нужно переделывать
PM MAIL   Вверх
Akella
Дата 2.2.2007, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 29
Всего: 329



цитата из Firebird Release Notes 2.0
Цитата

Afixednumberofpre-definednamespacesisavailable:
USER_SESSION
Offers access to session-specific user-defined variables. You can define and set values for variables
withanynameinthiscontext.
USER_TRANSACTION
Offerssimilar possibilitiesforindividualtransactions.
SYSTEM
Providesread-onlyaccesstothefollowingvariables:
• NETWORK_PROTOCOL :: The network protocol used by client to connect. Currently used val-
ues:“TCPv4”,“WNET”,“XNET”andNULL.
• CLIENT_ADDRESS :: The wire protocol address of the remote client, represented as a string. The
value is an IP address in form "xxx.xxx.xxx.xxx" for TCPv4 protocol; the local process ID for
XNETprotocol;andNULLforanyotherprotocol.
• DB_NAME :: Canonical name of the current database. It is either the alias name (if connection via
file names is disallowed DatabaseAccess = NONE) or, otherwise, the fully expanded database file
name.
• ISOLATION_LEVEL :: The isolation level of the current transaction. The returned value will be
oneof"READCOMMITTED","SNAPSHOT","CONSISTENCY".
• TRANSACTION_ID :: The numeric ID of the current transaction. The returned value is the same
aswouldbereturnedbytheCURRENT_TRANSACTIONpseudo-variable.
• SESSION_ID :: The numeric ID of the current session. The returned value is the same as would be
returnedbytheCURRENT_CONNECTIONpseudo-variable.
33

DataManipulationLanguage(DML)
• CURRENT_USER :: The current user. The returned value is the same as would be returned by the
CURRENT_USERpseudo-variableorthepredefinedvariableUSER.
• CURRENT_ROLE :: Current role for the connection. Returns the same value as the CUR-
RENT_ROLEpseudo-variable.
Notes
To avoid DoS attacks against the Firebird Server, the number of variables stored for each transaction
orsessioncontextislimitedto1000.
Exampleof Use
set term ^;
create procedure set_context(User_ID varchar(40), Trn_ID integer) as
begin
RDB$SET_CONTEXT('USER_TRANSACTION', 'Trn_ID', Trn_ID);
RDB$SET_CONTEXT('USER_TRANSACTION', 'User_ID', User_ID);
end ^
create table journal (
jrn_id integer not null primary key,
jrn_lastuser varchar(40),
jrn_lastaddr varchar(255),
jrn_lasttransaction integer
)^
CREATE TRIGGER UI_JOURNAL FOR JOURNAL AFTER INSERT OR UPDATE
as
begin
new.jrn_lastuser = rdb$get_context('USER_TRANSACTION', 'User_ID');
new.jrn_lastaddr = rdb$get_context('SYSTEM', 'CLIENT_ADDRESS');
new.jrn_lasttransaction = rdb$get_context('USER_TRANSACTION', 'Trn_ID');
end ^
commit ^
execute procedure set_context('skidder', 1) ^
insert into journal(jrn_id) values(0) ^
set term ;^
Sincerdb$set_contextreturns1orzero,itcanbemadetoworkwithasimpleSELECTstatement.
Example
SQL> select rdb$set_context('USER_SESSION', 'Nickolay', 'ru')
CNT> from rdb$database;
RDB$SET_CONTEXT
===============
0
0meansnotdefinedalready; wehavesetitto'ru'
SQL> select rdb$set_context('USER_SESSION', 'Nickolay', 'ca')
CNT> from rdb$database;
RDB$SET_CONTEXT
===============
34

DataManipulationLanguage(DML)
1
1meansitwasdefinedalready;wehavechangeditto'ca'
SQL> select rdb$set_context('USER_SESSION', 'Nickolay', NULL)
CNT> from rdb$database;
RDB$SET_CONTEXT
===============
1
1saysitexistedbefore;wehavechangedittoNULL,i.e.undefinedit.
SQL> select rdb$set_context('USER_SESSION', 'Nickolay', NULL)
CNT> from rdb$database;
RDB$SET_CONTEXT
===============
0
0,sincenothingactuallyhappenedthistime:itwasalreadyundefined.


Добавлено @ 15:38 
обрати внимание на 
Цитата

• CLIENT_ADDRESS :: The wire protocol address of the remote client, represented as a string. The
value is an IP address in form "xxx.xxx.xxx.xxx" for TCPv4 protocol; the local process ID for
XNETprotocol;andNULLforanyotherprotocol.

PM MAIL   Вверх
santilaas
Дата 4.2.2007, 16:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 322
Регистрация: 28.8.2005
Где: Блага

Репутация: нет
Всего: нет



Alex, Akella, спасибо Вам за советы и примеры - все, что касается БД буду делать в самой базе (с исп-ем IBExpert-а), а что касается программы - буду писать в текстовый файл 


--------------------
[
PM MAIL   Вверх
Akella
Дата 5.2.2007, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 29
Всего: 329



1. Вначале создаем две функции для чтения и записи контекстных переменных
Код

DECLARE EXTERNAL FUNCTION RDB$GET_CONTEXT
    VARCHAR(80) CHARACTER SET NONE NULL,
    VARCHAR(80) CHARACTER SET NONE NULL
RETURNS VARCHAR(255) FREE_IT
ENTRY_POINT 'get_context' MODULE_NAME 'system_module'


Код

DECLARE EXTERNAL FUNCTION RDB$SET_CONTEXT
    VARCHAR(80) CHARACTER SET NONE NULL,
    VARCHAR(80) CHARACTER SET NONE NULL,
    VARCHAR(255) CHARACTER SET NONE NULL
RETURNS INTEGER BY VALUE
ENTRY_POINT 'set_context' MODULE_NAME 'system_module'


2. Создаем 2 хранимки, для сохранения и чтения соответственно
Код

CREATE PROCEDURE SP_SET_GLOBAL_VAR (
    var_name varchar(110),
    var_value varchar(110))
as
begin
  RDB$SET_CONTEXT('USER_SESSION', :var_name, :var_value);
end^

Код

CREATE PROCEDURE SP_GET_GLOBAL_VAR (
    var_name varchar(110))
returns (
    var_value varchar(110))
as
begin
  VAR_VALUE = RDB$GET_CONTEXT('USER_SESSION', :VAR_NAME);
  suspend;
end^

Т.К. у нас USER_SESSION (контекст сессии), то при отключении от базы переменная самоуничтожится.


Далее. При подключении юзера к базе:
вызываем окно авторизации, где узнаем, какой пользователь залогинился и 
сразу вызываем из приложения хранимку
execute procedure sp_set_global_var('USER_ID', :ID_USER);

Добавлено @ 13:19 
создаем таблицу журнал
Код

CREATE TABLE JOURNAL (
    ID         BIGINT NOT NULL,
    UID        INTEGER NOT NULL,
    DATE_TIME  DATETIME NOT NULL /* DATETIME = TIMESTAMP */,
    "TABLE"    STRING100 NOT NULL /* STRING100 = CHAR(100) */,
    ACT        STRING100 NOT NULL /* STRING100 = CHAR(100) */,
    CLIENT_IP  STRING100 NOT NULL /* STRING100 = CHAR(100) */
);
не забываем про перв. ключ, индексы и т.д.

PM MAIL   Вверх
Akella
Дата 5.2.2007, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 29
Всего: 329



теперь делаем такой триггер для каждой таблицы

Код

CREATE TRIGGER APART_BI0 FOR APART
ACTIVE BEFORE INSERT OR UPDATE OR DELETE POSITION 1
AS
  declare variable Table_name varchar(100);
begin
  Table_name = 'APART';
  if (inserting) then begin
    insert into journal (uid, date_time, TABLE_NAME, ACT, client_ip)
    select VAR_VALUE, current_timestamp, :Table_name, 'ДОБАВЛЕНИЕ',rdb$get_context('SYSTEM', 'CLIENT_ADDRESS') from sp_get_global_var('USER_ID');
  end

  if (updating) then begin
    insert into journal (uid, date_time, TABLE_NAME, ACT, client_ip)
    select VAR_VALUE, current_timestamp, :Table_name, 'ОБНОВЛЕНИЕ',rdb$get_context('SYSTEM', 'CLIENT_ADDRESS') from sp_get_global_var('USER_ID');
  end

  if (deleting) then begin
    insert into journal (uid, date_time, TABLE_NAME, ACT, client_ip)
    select VAR_VALUE, current_timestamp, :Table_name, 'УДАЛЕНИЕ',rdb$get_context('SYSTEM', 'CLIENT_ADDRESS') from sp_get_global_var('USER_ID');
  end
end



Добавлено @ 14:17 
если бы в контексте триггера ещё можно было бы узнать имя таблицы....

Добавлено @ 14:30 
А МОЖНО НЕМНОГО ПО ДРУГОМУ РЕАЛИЗОВАТЬ.
Создаем хранимую процедуру:

Код

CREATE PROCEDURE SP_JOURNALING (
    table_name varchar(100) character set win1251,
    act varchar(100) character set win1251)
as
declare variable user_id integer;
begin
  select coalesce(VAR_VALUE, -1) from sp_get_global_var('USER_ID') into :USER_ID;

  if (:act = 'ДОБАВЛЕНИЕ') then begin
    insert into journal
      (UID,     date_time,         TABLE_NAME, ACT,   client_ip)
    values
      (:USER_ID, current_timestamp, :Table_name, :act, rdb$get_context('SYSTEM', 'CLIENT_ADDRESS'));
  end

  if (:act = 'ОБНОВЛЕНИЕ') then begin
    insert into journal (UID, date_time, TABLE_NAME, ACT, client_ip)
    select VAR_VALUE, current_timestamp, :Table_name, :act,rdb$get_context('SYSTEM', 'CLIENT_ADDRESS') from sp_get_global_var('USER_ID');
  end

  if (:act = 'УДАЛЕНИЕ') then begin
    insert into journal (UID, date_time, TABLE_NAME, ACT, client_ip)
    select VAR_VALUE, current_timestamp, :Table_name, :act,rdb$get_context('SYSTEM', 'CLIENT_ADDRESS') from sp_get_global_var('USER_ID');
  end

end^


создаем триггер
Код

CREATE TRIGGER ARENDA_BIUD0 FOR ARENDA
ACTIVE BEFORE INSERT OR UPDATE OR DELETE POSITION 0
AS
begin
  if (inserting) then execute procedure sp_journaling('ARENDA','ДОБАВЛЕНИЕ');
  if (updating) then execute procedure sp_journaling('ARENDA','обновление');
  if (deleting) then execute procedure sp_journaling('ARENDA','удаление');
end



Это сообщение отредактировал(а) Akella - 5.2.2007, 15:27
PM MAIL   Вверх
Akella
Дата 5.2.2007, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 29
Всего: 329



я пишу для FB 2.0
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Базы данных и репортинг"
Vit
Петрович

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами


Обязательно указание:

1. Базы данных (Paradox, Oracle и т.п.)

2. Способа доступа (ADO, BDE и т.д.)


  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • Вопросы по SQL и вопросы по базам данных не связанные с Дельфи задавать здесь

FAQ раздела лежит здесь!


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Vit, Петрович.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Базы данных и репортинг | Следующая тема »


 




[ Время генерации скрипта: 0.1436 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.