powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Как работают транзакции?
23 сообщений из 23, страница 1 из 1
Как работают транзакции?
    #36041708
DavidKats
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Будьте любезны могли бы наглядно пояснить работу транзакций?
Вообще мне нужно при работе с рекордсетом, когда я записываю по одному полю, чтобы поля обновились только при успешной записи ВСЕХ полей причем в разных таблицах. А в противном случае - если произошла ошибка, либо отмена, чтобы ни одной новой записи не произошло. Кажется это возможно реализовать как раз при помощи транзакций. Но как они работают толком не знаю.
...
Рейтинг: 0 / 0
Как работают транзакции?
    #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
Как работают транзакции?
    #36041878
DavidKats
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Анатолий ( Киев ),

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

ЗЫ. Что обидно, при добавлений нескольких записей в таблицу внутри транзакции, а потом - ее откате, счетчик увеличится.
...
Рейтинг: 0 / 0
Как работают транзакции?
    #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
Как работают транзакции?
    #36041986
DavidKatsможно ли открывать и закрывать одним rst поочередно несколько таблиц в пределах одной и той же транзакции? Да, можно. Собственно, почему бы вам не попробовать?
Я вот написал, что rst1 нужно закрывать после завершения транзакции, потому, что всегда так делаю, но сейчас не уверен, что его нельзя закрыть когда угодно. Или, что rst2 нельзя закрыть после завершения транзакции, если он не редактировался.
Проведите опыты и расскажите о результатах. Мне - лень.

ЗЫ. Dim rst as New ADODB.Recordset - на заметку, в каком бы месте процедуры вы не вставили объявление переменных, все они создаются при ее вызове.
...
Рейтинг: 0 / 0
Как работают транзакции?
    #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
Как работают транзакции?
    #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
Как работают транзакции?
    #36042066
DavidKats
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Анатолий ( Киев ),

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

Раз вы работаете с ADO, вместо If CurrentDb.Transactions Then (а это DAO), логично использовать родную для ADO проверку. Поройтесь в справке. Мне некогда, но результат интересует.
...
Рейтинг: 0 / 0
Как работают транзакции?
    #36043626
DavidKats
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Анатолий ( Киев ),
Это тоже не причина. Я совсем убрал проверку
Код: plaintext
If CurrentDB.Transaction
но затыкается в том же месте на попытке закрытия рекордсета...
...
Рейтинг: 0 / 0
Как работают транзакции?
    #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
Как работают транзакции?
    #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
Как работают транзакции?
    #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
Как работают транзакции?
    #36043790
DavidKats
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Анатолий ( Киев ),
Я на всякий случай заменил CurrentProject.Connection на cnn. Но это заведомо одно и то же.. поэтому ЕСТЕСТВЕННО проблемы это не сняло. Все так же не закрывает, как и раньше.
...
Рейтинг: 0 / 0
Как работают транзакции?
    #36043844
вадя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторПотому, что ошибка может появиться до начала траезакции или после ее завершения. Строка cnn.RollbackTrans, в свою очередь вызовет ошибку и всё зациклится.

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

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



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


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


+1[/quot]

Проблемы не сняло. :(
...
Рейтинг: 0 / 0
Как работают транзакции?
    #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
Как работают транзакции?
    #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
Как работают транзакции?
    #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
Как работают транзакции?
    #36044620
вадя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
http://sql.ru/forum/actualpost.aspx#7306894
+1

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


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