Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Как работают транзакции? / 23 сообщений из 23, страница 1 из 1
15.06.2009, 16:01
    #36041708
DavidKats
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работают транзакции?
Будьте любезны могли бы наглядно пояснить работу транзакций?
Вообще мне нужно при работе с рекордсетом, когда я записываю по одному полю, чтобы поля обновились только при успешной записи ВСЕХ полей причем в разных таблицах. А в противном случае - если произошла ошибка, либо отмена, чтобы ни одной новой записи не произошло. Кажется это возможно реализовать как раз при помощи транзакций. Но как они работают толком не знаю.
...
Рейтинг: 0 / 0
15.06.2009, 16:49
    #36041808
Как работают транзакции?
С момента вызова BeginTrans все изменения происходят в буфере.
При CommitTrans - все изменения отражаются в таблицах.
При RollBack - всё откатывается назад (например, при ошибке).

В DAO эти методы применяются к объекту WorkSpace или к DBEngine (ко всем активным WorkSpace), в ADO - к объекту Connection. Всё это есть в справке.

Есть такая тонкость:
Все объекты Recordset, созданные внутри транзакции должны и закрываться до ее завершения, а созданные перед ее началом - после завершения. В первом случае Requery Recordset-a покажет все изменения, во втором - нет.

При отладке кода может случиться, что транзакция не завершена (например, вы прервали выполнение кода). В этом случае нужно обязательно выполнить RollBack (например - в окне отладки).

Применение транзакций требует обязательного обработчика ошибок и контрольного флажка, например:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
On Error GoTo func_err

   Set db = OpenDatabase(...)
   Set rst1 = db.OpenRecordset...
 If db.Transactions Then
   DBEngine.BrginTrans
   fTrans = True
 End If
   Set rst2 = db.OpenRecordset...
...
   rst.Close

func_exit:
   Set rst2 = Nothing
 If fTrans Then
   DBEngine.CommitTrans
   fTrans = False 
 End If
   Set rst1 = Nothing
   Set db = Nothing
   Exit Function

func_err:
 If fTrans Then
   fTrans = False 
   DBEngine.RollBack
 End If
   Resume func_exit
...
Рейтинг: 0 / 0
15.06.2009, 17:14
    #36041878
DavidKats
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работают транзакции?
Анатолий ( Киев ),

Открываются два объекта рекордсет rst1, rst2, а закрывается какой-то один из них rst.. возможно опечатка?
...
Рейтинг: 0 / 0
15.06.2009, 17:20
    #36041893
DavidKats
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работают транзакции?
Анатолий ( Киев ) В первом случае Requery Recordset-a покажет все изменения, во втором - нет.
что за свойство? Что покажет? Кому покажет? Для чего покажет?
...
Рейтинг: 0 / 0
15.06.2009, 17:22
    #36041901
Как работают транзакции?
DavidKatsОткрываются два объекта рекордсет rst1, rst2, а закрывается какой-то один из них rst.. возможно опечатка? Да, rst2.Close. ИМХО, этого можно и не делать, Set rst2 = Nothing - достаточно.
...
Рейтинг: 0 / 0
15.06.2009, 17:35
    #36041936
Как работают транзакции?
DavidKatsАнатолий ( Киев ) В первом случае Requery Recordset-a покажет все изменения, во втором - нет.
что за свойство? Что покажет? Кому покажет? Для чего покажет?
В данном случае, если rst1 и rst2 открыты на одной таблице, то rst1.Requery не отразит изменения записей, выполненные в rst2. Или это приведет к ошибке. А rst2.Requery отразит изменения записей, выполненные в rst1. Может и ошибаюсь...

ЗЫ. Что обидно, при добавлений нескольких записей в таблицу внутри транзакции, а потом - ее откате, счетчик увеличится.
...
Рейтинг: 0 / 0
15.06.2009, 17:42
    #36041951
DavidKats
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работают транзакции?
Анатолий ( Киев ),
Понял.. а можно ли открывать и закрывать одним rst поочередно несколько таблиц в пределах одной и той же транзакции?

Например так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Dim rst as New ADODB.Recordset
With rst
.Open....
.....
.Close

.Open .... 
....
Close
End With
Set rst = Nothing
...
Рейтинг: 0 / 0
15.06.2009, 17:56
    #36041986
Как работают транзакции?
DavidKatsможно ли открывать и закрывать одним rst поочередно несколько таблиц в пределах одной и той же транзакции? Да, можно. Собственно, почему бы вам не попробовать?
Я вот написал, что rst1 нужно закрывать после завершения транзакции, потому, что всегда так делаю, но сейчас не уверен, что его нельзя закрыть когда угодно. Или, что rst2 нельзя закрыть после завершения транзакции, если он не редактировался.
Проведите опыты и расскажите о результатах. Мне - лень.

ЗЫ. Dim rst as New ADODB.Recordset - на заметку, в каком бы месте процедуры вы не вставили объявление переменных, все они создаются при ее вызове.
...
Рейтинг: 0 / 0
15.06.2009, 18:03
    #36042006
DavidKats
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работают транзакции?
Анатолий ( Киев ),
А у меня вот ошибка вылетает при первом же закрытии rst

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
Dim fTrans As Boolean
Dim rst As New ADODB.Recordset
On Error GoTo SubErr
If CurrentDb.Transactions Then
   CurrentProject.Connection.BeginTrans
   fTrans = True
End If

With rst
    .Open "Изделие", CurrentProject.Connection, adOpenDynamic, adLockOptimistic, adCmdTableDirect
    .MoveLast
    .AddNew
    .Fields( 0 ) = Me.№_МСП
    .Fields( 1 ) = Me.Обозначение
    .Close
    
    .Open "ИзделиеИзм", CurrentProject.Connection, adOpenDynamic, adLockOptimistic, adCmdTableDirect
    .MoveLast
    .AddNew
    .Fields( 1 ) = Now
    .Fields( 2 ) = Me.№_МСП
    .Fields( 3 ) = Me.Впроизводстве
    .Fields( 5 ) = Me.НаименовПоЧерт
    .Fields( 6 ) = Me.Завод
    .Fields( 7 ) = Me.Изделие
    .Fields( 8 ) = Me.Признак
    .Fields( 9 ) = Me.Продажа
    .Fields( 10 ) = Me.Примечание
    .Close
End With

Sub_Exit:
   Set rst = Nothing
 If fTrans Then
   CurrentProject.Connection.CommitTrans
   fTrans = False
   MsgBox "Новая запись добавлена", vbInformation, "Успех"
 End If
 Exit Sub
 
SubErr:
 If fTrans Then
   fTrans = False
   CurrentProject.Connection.Rollback
 End If
   Resume Sub_Exit
End Sub
...
Рейтинг: 0 / 0
15.06.2009, 18:20
    #36042037
Как работают транзакции?
Dim rst As ADODB.Recordset
On Error GoTo SubErr
If CurrentDb.Transactions Then
CurrentProject.Connection.BeginTrans
fTrans = True
End If

Set rst = New ADODB.Recordset

Я в ADO с транзакциями не работал, но думаю - дело в этом, т.е. объект создается до ее начала, азакрывается - внутри.
...
Рейтинг: 0 / 0
15.06.2009, 18:34
    #36042066
DavidKats
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работают транзакции?
Анатолий ( Киев ),

Нет.. дело видимо не в этом. Все равно ошибается на закрытии и по ошибке идет в обработчик SubErr и там еще раз спотыкается об строку CurrentProject.Connection.Rollback и выдает ошибку "После EXECUTE ожидается имя запроса."
...
Рейтинг: 0 / 0
15.06.2009, 19:24
    #36042167
Как работают транзакции?
Вероятно нужно создать объектную переменную, присвоить ей:
Set cnn = CurrentProject.Connection
А затем везде указывать ее.

Раз вы работаете с ADO, вместо If CurrentDb.Transactions Then (а это DAO), логично использовать родную для ADO проверку. Поройтесь в справке. Мне некогда, но результат интересует.
...
Рейтинг: 0 / 0
16.06.2009, 14:21
    #36043626
DavidKats
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работают транзакции?
Анатолий ( Киев ),
Это тоже не причина. Я совсем убрал проверку
Код: plaintext
If CurrentDB.Transaction
но затыкается в том же месте на попытке закрытия рекордсета...
...
Рейтинг: 0 / 0
16.06.2009, 14:33
    #36043669
DavidKats
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работают транзакции?
Немножко подправил SubErr. Теперь в нем не спотыкается об cnn.Rollback потому что правильно
Код: plaintext
cnn.RollbackTrans
Но при попытке закрытия рекордсета код по-прежнему лезет в обработчик ошибок. Видимо причина в этом закрытии. Но что именно не так???

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
Dim rst As ADODB.Recordset
Dim fTrans As Boolean
Dim cnn As ADODB.Connection

On Error GoTo SubErr
Set cnn = CurrentProject.Connection
cnn.BeginTrans
fTrans = True

Set rst = New ADODB.Recordset
With rst
    .Open "Изделие", CurrentProject.Connection, adOpenDynamic, adLockOptimistic, adCmdTableDirect
    .MoveLast
    .AddNew
    .Fields( 0 ) = Me.№_МСП
    .Fields( 1 ) = Me.Обозначение
    .Close
    
    .Open "ИзделиеИзм", CurrentProject.Connection, adOpenDynamic, adLockOptimistic, adCmdTableDirect
    .MoveLast
    .AddNew
    .Fields( 1 ) = Now
    .Fields( 2 ) = Me.№_МСП
    .Fields( 3 ) = Me.В_Производстве
    .Close
End With

Sub_Exit:
   Set rst = Nothing
 If fTrans Then
    cnn.CommitTrans
   fTrans = False
   MsgBox "Запись добавлена успешно", vbInformation
 End If
 Exit Sub
 
SubErr:
 If fTrans Then
   fTrans = False
   cnn.RollbackTrans
 End If
   Resume Sub_Exit
End Sub
...
Рейтинг: 0 / 0
16.06.2009, 14:45
    #36043706
вадя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работают транзакции?
зачем такое городить?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Sub_Exit:
   Set rst = Nothing
 If fTrans Then
    cnn.CommitTrans
   fTrans = False
   MsgBox "Запись добавлена успешно", vbInformation
 End If
 Exit Sub
 
SubErr:
 If fTrans Then
   fTrans = False
   cnn.RollbackTrans
 End If
   Resume Sub_Exit
End Sub

достаточно (для проверки тем более)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Sub_Exit:
   Set rst = Nothing
   cnn.CommitTrans
   MsgBox "Запись добавлена успешно", vbInformation
 Exit Sub
 
SubErr:
   cnn.RollbackTrans
   Set rst = Nothing
   Exit  sub
End Sub
...
Рейтинг: 0 / 0
16.06.2009, 15:03
    #36043769
Как работают транзакции?
Вместо:
.Open "Изделие", CurrentProject.Connection, adOpenDynamic,...
надо
.Open "Изделие", cnn, adOpenDynamic,...

и в других местах тоже.

вадязачем такое городить?
достаточно (для проверки тем более)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Sub_Exit:
   Set rst = Nothing
   cnn.CommitTrans
   MsgBox "Запись добавлена успешно", vbInformation
 Exit Sub
 
SubErr:
   cnn.RollbackTrans
   Set rst = Nothing
   Exit  sub
End Sub
Потому, что ошибка может появиться до начала траезакции или после ее завершения. Строка cnn.RollbackTrans, в свою очередь вызовет ошибку и всё зациклится.
...
Рейтинг: 0 / 0
16.06.2009, 15:12
    #36043790
DavidKats
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работают транзакции?
Анатолий ( Киев ),
Я на всякий случай заменил CurrentProject.Connection на cnn. Но это заведомо одно и то же.. поэтому ЕСТЕСТВЕННО проблемы это не сняло. Все так же не закрывает, как и раньше.
...
Рейтинг: 0 / 0
16.06.2009, 15:26
    #36043844
вадя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работают транзакции?
авторПотому, что ошибка может появиться до начала траезакции или после ее завершения. Строка cnn.RollbackTrans, в свою очередь вызовет ошибку и всё зациклится.

если делать всё полностью правильно то надо делать анализ ошибки и производить обработку разных ошибок по разному.

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



авторВместо:
.Open "Изделие", CurrentProject.Connection, adOpenDynamic,...
надо
.Open "Изделие", cnn, adOpenDynamic,...


+1
...
Рейтинг: 0 / 0
16.06.2009, 15:29
    #36043850
DavidKats
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работают транзакции?
авторВместо:
.Open "Изделие", CurrentProject.Connection, adOpenDynamic,...
надо
.Open "Изделие", cnn, adOpenDynamic,...


+1[/quot]

Проблемы не сняло. :(
...
Рейтинг: 0 / 0
16.06.2009, 16:18
    #36044005
Как работают транзакции?
Блин! Десять минут оформлял ответ, а он улетел в никуда...
.Open "Изделие", cnn, adOpenDynamic, adLockOptimistic, adCmdTableDirect
.MoveLast
.AddNew
.Fields(0) = Me.№_МСП
.Fields(1) = Me.Обозначение
.Update
.Close Вы после добавления закрываете RS, не выполнив .Update. Без транзакций у вас это работает?

К слову, в MDB при adOpenDynamic открывается RS типа Static. Вы в курсе? Хотя это вряд ли связано с темой.

Для общего развития - отрывок из статьи "Migrating from DAO to ADO" от MS:авторBoth DAO and ADO have similar methods for beginning, committing, and rolling back a transaction. One difference to note however is that because DAO transactions are tied to the Workspace object, it is possible to use DAO to perform a transaction that spans multiple Microsoft Jet databases. ADO transactions are tied to the Connection object, which limits the transaction to a single data source.
DAO also supports an additional parameter to the CommitTrans method: dbForceOSFlush. This forces the database engine to immediately flush all updates to disk, instead of caching them temporarily. The Microsoft Jet Provider exposes a property, "Jet OLEDB:Transaction Commit Mode", in the Connection object's Properties collection that allows you to specify that transactions within that connection should flush all updates to disk upon commit. Setting this property to 1 is equivalent to using the dbForceOSFlush parameter. В этой статье и примеры есть, но без RS.

ЗЫ. Для Вадя. И у Гетса и в этой статье флажок применяется. И я с ними согласен.
...
Рейтинг: 0 / 0
16.06.2009, 16:50
    #36044129
DavidKats
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работают транзакции?
Анатолий ( Киев ),
Вот что предложил мне один коллега:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Set cnn = CurrentProject.Connection
'Начало транзакции
With cnn
    .BeginTrans
        .Execute _
            "INSERT INTO Изделие ( поле1, поле2 ) " & _
            "SELECT " & Nz(Me!№_МСП,  0 ) & ", " & Nz(Me!Обозначение,  0 )
        .Execute _
            "INSERT INTO ИзделиеИзм ( поле1, поле2 ) " & _
            "SELECT Now(), " & Nz(Me!Me.№_МСП,  0 )
    .CommitTrans
'Конец транзакции
End With

По-моему, гениально... :)
...
Рейтинг: 0 / 0
16.06.2009, 18:28
    #36044470
Как работают транзакции?
DavidKats
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Set cnn = CurrentProject.Connection
'Начало транзакции
With cnn
    .BeginTrans
        .Execute _
            "INSERT INTO Изделие ( поле1, поле2 ) " & _
            "SELECT " & Nz(Me!№_МСП,  0 ) & ", " & Nz(Me!Обозначение,  0 )
        .Execute _
            "INSERT INTO ИзделиеИзм ( поле1, поле2 ) " & _
            "SELECT Now(), " & Nz(Me!Me.№_МСП,  0 )
    .CommitTrans
'Конец транзакции
End With

По-моему, гениально... :) Да, простенько и со вкусом. Но часто этого бывает недостаточно или громоздко. Хотелось бы добить Recordset. Вы Update добаляли?
Кстати, в вашем примере правильнее не SELECT а VALUES, и эта конструкция очень громоздка, когда нужно записать даты, дробные числа, строки с ' или " внутри текста (совпадающие с обрамлением), да еще Null, если какое-то из них Null. Тут аж просится Recordset, особенно если нужно получить ID новой записи.
...
Рейтинг: 0 / 0
16.06.2009, 20:19
    #36044620
вадя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как работают транзакции?
http://sql.ru/forum/actualpost.aspx#7306894
+1

насчет флажка
этот флажок не гарантия.
правильнее перехватить ошибку и по её номеру произвести соответствующую обработку
...
Рейтинг: 0 / 0
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Как работают транзакции? / 23 сообщений из 23, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]