![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как часть транзакции сделать безоткатной? [D7, MSSQL]
LAMER Pro © (2003-07-09 09:05:00)Уважаемые Мастера!
Наверняка Вам уже приходилось решать проблему аудита системы. Я мало знаком с SQL, а сейчас пишу ТЗ на программу, в которой необходимо фиксировать попытки пользователя произвести определённый набор действий с информацией в БД. В каждой ХП размещаю добавление записи в журнал аудита, но ведь при откате должны "отмениться" ВСЕ измениния в БД? Как быть - мне нужен аудит ВСЕХ действий, даже закончившихся неудачей?
Система ПОКА планируется "клиент-сервер", т.к. пользователй мало (50-70). Или придётся переходить на трёхзвенку?
Планирую использовать Delphi7 + MSSQL2K + ADO2.7 + MS Svr2K, клиенты Win98/Win2K
Буду рад любой идее.
roottim (2003-07-14 10:47:00) [1]я не специалист по мсскл... но мысли выскажу...
на самом деле можно вести лог в базе через хп или триггеры, но только по факту событий... что значит по комиту.
если дейстыия были отменены, значит ничего и небыло.. что тут плохого...
ну если уж действительно необходима такая слежка за пользователем и за его транзакцией, то могу предложить...
но немогу сказать есть ли.... и работает ли такое в мсскл.
в оракле существует, всем известная, посылка сообщений... (в др бд тоже)..
но есть 2 вида сообщений alert и pipe ... отличие в том что 1-й посылается по комиту тразакции а второй асинхронно (как послали так и ушло)...
вот если есть такой мессаг в мсскл... то остается написать некий сервис (прогу).. которая запускается на сервере ловит сообщения и пишет их куда надо.. (хоть в базу, хоть в файл )
вот такое вот кино как мы делали кино :)
АлексейК (2003-07-14 05:11:00) [2]LAMER Pro © (11.07.03 14:22)
to АлексейК (11.07.03 04:58)
>XP в MSSQL не есть одна тразакция, если только она сама не выполняется из XP. Следовательно команды изменения данных в XP будут осуществлтся в разных независимых транзакциях и откат одной не означает отката другой.
Я понимаю работу с ХП следующим образом: при запуске ХП с клиента на сервере АВТОМАТИЧЕСКИ запускается транзакция, следовательно все транзакции, объявленные явно или запуски любых ХП будут вложенными. При ROLLBACK"е происходит откат до самого верхнего уровня транзакции, следовательно ВСЕ транзакции (они ведь вложены в транзакцию верхнего уровня, оформленную как ХП), даже завершившиеся COMMIT"ом должны откатиться. Это приемлемое решение, если мы хотим зафиксировать СВЕРШИВШИЙСЯ ФАКТ, но если мы хотим зафиксировать НАМЕРЕНИЕ (например попытку прочитать документ, к которому доступ запрещён) и транзакция будет прервана, то лог откатится и событие будет потеряно.
По умолчанию в MSSQL стоит автоматический режим тразакций. то есть при выполнении команды тразакция начинается, как команда выполнятся транзакция заканчивается (фиксированием или откатом).
create procedure test
as
/*началасть тразакция*/
insert into....
select .. from .....
/*закончилась*/
/*началасть тразакция*/
update ... set ... where ....
/*закончилась*/
Команды выполнятся в разных тразакциях, если только это ХП не запустить командой exec из другой хранимой процедуры.
Но можно и явно обявлять тразакции (режим явного определения транзакций)
create procedure test
as
declare @er_result int
begin tran /*начали тразакцию*/
insert into....
select .. from .....
set @er_result:=@@ERROR
update ... set ... where ....
set @er_result:=@er_result+@@ERROR
if @er_result=0
commit tran /*закончилась*/
else
rollback tran
Вот в этом случае две комнады выполнятся в одной транзакции.
Есть также режим неявного использования тразакций. С началом нового соединения открывается тразация, но после очередного выполнения команды не происходит фиксирования тразакции. Посльзователь должен сам явно фиксировать или откатывать транзакции, после чего открывается следующая транзакция. Но система пытается атоматически выполнить фиксирование тразакции, при одном из следующих действий (ater table, create, deletem drop, fetch, grant, insert, open, revoke, select, truncate table, update). Хочу заметить что режим неявного использования тразакция и автоматического не одно и тоже.
Dsgnr (2003-07-12 03:41:00) [3]Поделюсь собственным опытом. Достаточно много работал над учетными системами. Для аудита использовал разные варианты. Для себя сделал четкий вывод - результаты аудита НЕ ДОЛЖНЫ БЫТЬ В БД. В сравнении с записью в файл никаких преимуществ это не имеет, кроме спорного вопроса об удобстве анализа. Зато возникает большое количество проблем (о которых много в этом треде сказано), которые, как правило, решаются нездоровыми извращениями.
В свете этого оптимальный подход для сиквела - Extended stored proc с сохранением информации в файл.
SergSuper (2003-07-11 15:04:00) [4]Я понимаю работу с ХП следующим образом: при запуске ХП с клиента на сервере АВТОМАТИЧЕСКИ запускается транзакция
Не правильно. Если установлено SET IMPLICIT_TRANSACTIONS ON, то да, так оно будет. Но обычно это редко устанавливается.
Неявная транзакция запускается когда выполняются команды модификации базы(insert, udpate, delete). Т.е. внутри триггера мывсегда будем в открытой транзакции. При запуске процедуры неявная транзакция не открывается.
Опять же можно проверить скриптом
create table #t(i int)
go
create proc #p as
insert #t select 1
begin tran
insert #t select 2
go
insert #t select 3
exec #p
rollback tran
select * from #t
в таблице останутся 1 и 3, т.е. процедура вставит 1, затем начнет транзакцию, вставит 2, которая откатится после процедуры.
SergSuper (2003-07-11 14:47:00) [5]
> LAMER Pro
Из одной транзакции нельзя запустить другую транзакцию. Пусть кто пишет про параллельные транзакции объяснит что это такое. На то она и транзакция, что если она откатилась никто не должен понять была ли она. В статье кстати всё было грамотно описано.
У Вас 2 пути:
1. Написать Extended Stored Procedures, которая будет брать еще коннект и записывать параллельно.
2. Писать в EventLog с помощью процедуры xp_logevent.
1-й путь требует хорошего знания архитектуры MS SQL и черват возможностями подвешивать сервер напрочь
2-й путь намного проще и безобидней, но сообщения Вы будете видеть не в таблицах, а в стандартном просмоторщике событий.
Я бы советовал вообще отказаться от этой идеи, результат не будет стоит затраченного труда.
И кстати обычно меньше всего хочется объяснять элементарщину.
LAMER Pro (2003-07-11 14:22:00) [6]to АлексейК (11.07.03 04:58)
>XP в MSSQL не есть одна тразакция, если только она сама не выполняется из XP. Следовательно команды изменения данных в XP будут осуществлтся в разных независимых транзакциях и откат одной не означает отката другой.
Я понимаю работу с ХП следующим образом: при запуске ХП с клиента на сервере АВТОМАТИЧЕСКИ запускается транзакция, следовательно все транзакции, объявленные явно или запуски любых ХП будут вложенными. При ROLLBACK"е происходит откат до самого верхнего уровня транзакции, следовательно ВСЕ транзакции (они ведь вложены в транзакцию верхнего уровня, оформленную как ХП), даже завершившиеся COMMIT"ом должны откатиться. Это приемлемое решение, если мы хотим зафиксировать СВЕРШИВШИЙСЯ ФАКТ, но если мы хотим зафиксировать НАМЕРЕНИЕ (например попытку прочитать документ, к которому доступ запрещён) и транзакция будет прервана, то лог откатится и событие будет потеряно.
Вопрос в том как сделать, чтобы при запуске ХП с клиента на сервере автоматически не запускалась транзакция, чтобы транзакции, объявляемые в ХП явным образом были самым верхним уровнем, ясно, что вызовы процедур внутри их будут вложенными, но это уже не важно - здесь бы COMMIT сработал как надо.
Я не вижу такой возможности, а она очччень нужна.
LAMER Pro (2003-07-11 14:03:00) [7]to Smashich © (11.07.03 11:22)
>форум это все таки не курсы повышения квалификации...
Если я спросил элементарщину, то где Ваш ответ?
Кстати, можете пояснить Ваш "ответ" (с учётом моего условия в вопросе - используется только ХП):
>Smashich © (09.07.03 17:38)
если ломиться читать то зачем тебе транзакции? потдтверждение чтения это я пока тока в The Bat! видел;)
вообще то маловато данных о том как ты хочешь логи вести, поэтому посоветовать тебе что то кроме выполнения ПАРАЛЛЕЛЬНЫХ, а не вложенных транзакций не знаю что. тоесть после тада уже выполнения транзакции основной ызывай транзакцию которая в лог запишет чего надо
Особенно попрошу подробно рассказать про ПАРАЛЛЕЛЬНЫЕ транзакции в ХП и какими операторами можно задавать ПОСЛЕДОВАТЕЛЬНОЕ или ПАРАЛЛЕЛЬНОЕ их выполнение в SQL.
jocko (2003-07-11 13:33:00) [8]был не прав :(
SergSuper (2003-07-11 12:32:00) [9]
> jocko
Попробовал
Теперь ты попробуй
В принципе можно написать свою расширенную процедуру(которая xp_ и не на T-SQL), брать там новый коннект и чего-то делать. А так в одном коннекте роллбэк убивает сразу всю транзакцию. Т.к. sp_executesql работает в том же коннекте (иначе было бы не видно временных таблиц) то и его действия тоже убиваются.
> Smashich
Может я чего-то не понял, но в MSSQL User Define Function и Extended Stored Procedures - это совершенно разные вещи, не путайте с InterBase
Smashich (2003-07-11 11:22:00) [10]LAMER Pro © (10.07.03 12:54)
> Но всё равно, хочу разобраться с явным и неявным определением транзакций и действиях при откате. Истина где-то рядом...
почитать бы литературку? форум это все таки не курсы повышения квалификации...
насчет
>UDF-User Define Function - в сиквеле Extended Stored Procedures:) ничего особо сложного в этом нет. и это имхо одно их гудсвенных решений проблемы.
jocko (2003-07-11 10:49:00) [11]2SergSuper
А ты попробуй.
SET @SQLString = N"exec ..."
sp_executesql @SQLString
только для логов ты специально процедурку напиши, я на этом спотыкался уже...
SergSuper (2003-07-11 10:41:00) [12]в MSSQL есть одна тразакция на весь bath, вложенных транзакций нет.
если у вас в bath-е объявлена транзакция, потом вызывается пять процедур, а в 6-й будет rollback - результат выполнения предудыщих 5-ти процедур откатится тоже. Вложенность влияет только будет ли делаться commit или просто уменьшится счетчик вложенности, rollback же делается сразу с любого уровня.
Так что АлексейК не прав, предложение jocko не спасает.
В это легко убедиться на простеньком скрипте
create table #t(i int, c varchar(9))
insert #t select 1,""
union select 2,""
union select 3,""
union select 4,""
union select 5,""
go
create proc #p1 as update #t set c="ss" where i=1
go
create proc #p2 as update #t set c="ww" where i=2
go
create proc #p3 as update #t set c="ww" where i=3 rollback tran
go
create proc #p4 as begin tran update #t set c="ww" where i=4 commit tran
go
begin tran
update #t set c="ww" where i=4
exec ("update #t set c=""ww"" where i=5")
exec #p1
exec #p2
exec #p4
select * from #t
exec #p3
commit tran
--rollback tran
select * from #t
jocko (2003-07-11 10:02:00) [13]По поводу лога неудачных выполнений: я бы написал процедурку ведения логов с параметрами, и вызвал бы ее но не напрямую внутри транзакции, т.е. exec..., а через sp_executesql (см. F1),
в первом случае вложенные процедуры (транзакции) могут откатываться, во втором нет.
АлексейК (2003-07-11 04:58:00) [14]XP в MSSQL не есть одна тразакция, если только она сама не выполняется из XP. Следовательно команды изменения данных в XP будут осуществлтся в разных независимых транзакциях и откат одной не означает отката другой.
DeMoN_Astra (2003-07-10 19:27:00) [15]
> кроме этого можно использовать не текстовый, а структурированный
> файл - меньше места, быстрее анализ
А гнать лог в бд уже нельзя?
LAMER Pro (2003-07-10 13:09:00) [16]to Тих
Сам вижу, что по первому вопросу глупость сморозил ;) - заглянул в BOL.
Следует читать так:
> 1) Через СОМ. sp_OACreate и пр. (см. в Books Online) - создаешь ком-объектик Scripting.FileSystemObject, через него - текстовый файл - и пишешь. При таком раскладе есть грабли с многопроцессорными серверами - не пройдет.
В чём будут проблемы на многопроцессорных серверах?
Где можно ознакомиться с "грабельками"? - может быть при задействовании такой функциональности, которая мне ненужна?
LAMER Pro (2003-07-10 12:54:00) [17]to Тих
> 1) Через СОМ. sp_OACreate и пр. (см. в Books Online) - создаешь ком-объектик Scripting.FileSystemObject, через него - текстовый файл - и пишешь. При таком раскладе есть грабли с многопроцессорными серверами - не пройдет.
Это через MTS делается или внутри SQL-сервера?
В чём будут проблемы на многопроцессорных серверах?
Где можно ознакомиться с "грабельками"? - может быть при задействовании такой функциональности, которая мне ненужна?
> 2) Приделать Linked Server через ODBC-провайдер для текстовых файлов, прилинковать его через вьюшку, навроде create view viewLog as select top 1 * from openquery(LOG_TXT, "select * from log.txt"), инсертить логи в эту вьюшку. Тоже не без граблей - на время инсерта в этот файл он лочится эксклюзивно.
Объясните, пожалуйста, что такое Linked Server, где его "приделывать" на стороне клиента или сервера и как?
Не получится, что при росте лога будет расти время его открытия (ведь текстовый файл - это последовательный доступ)?
Не станет ли критичным ограничение ODBC: "При работе с технологией ODBC пользователь не имеет возможности явно определить начало транзакции, т.к. эта транзакция поддерживает только неявное и автоматическое определение транзакции. При использовании технологий OLE DB и ADO явное определение транзакции разрешено."
3) Немножко изучить API MSSQL и в самом деле написать свою dll, см. add_addextendedproc, Creating Extended Stored Procedures.
Наверное самый надёжный и приемлемый вариант, кроме этого можно использовать не текстовый, а структурированный файл - меньше места, быстрее анализ.
В дальнейшем эти же знания могут помочь решать тривиальные задачи, которые делаются через п%пу в SQL: анализ текстов.
Но всё равно, хочу разобраться с явным и неявным определением транзакций и действиях при откате. Истина где-то рядом...
Спасибо за обстоятельный подход.
KSergey (2003-07-10 08:51:00) [18]К стати, по поводу Extended Stored Procedures - есть пример на дельфи, на sql.ru
Там по поводу нотифицирования клиентских приложений, но во всяком случае каркасик можно стырить.
Тих (2003-07-09 22:14:00) [19]>Можно ли с сервера писать текстовый файл логов?
Можно, например
1) Через СОМ. sp_OACreate и пр. (см. в Books Online) - создаешь ком-объектик Scripting.FileSystemObject, через него - текстовый файл - и пишешь. При таком раскладе есть грабли с многопроцессорными серверами - не пройдет.
2) Приделать Linked Server через ODBC-провайдер для текстовых файлов, прилинковать его через вьюшку, навроде create view viewLog as select top 1 * from openquery(LOG_TXT, "select * from log.txt"), инсертить логи в эту вьюшку. Тоже не без граблей - на время инсерта в этот файл он лочится эксклюзивно.
3) Немножко изучить API MSSQL и в самом деле написать свою dll, см. add_addextendedproc, Creating Extended Stored Procedures.
Fay (2003-07-09 19:12:00) [20]2handra
И чем это лучше?