for flooders
:: Главная :: Решения :: Статьи :: Сайт М. Дроздова :: Файловый архив :: Книга по VFP 9 :: Русский Help Online :: OFF-LINE Форум
   Лисоводы   всех   стран,  объединяйтесь !!!  

Список Форумов  :: Visual Foxpro, Foxpro for DOS
  

Транзакции
Божья_коровка
Автор

Сообщений: 24282
Дата: 06.01.21 12:05:53
Всем привет.
Столкнулась со странностью. Отрабатывает процедура на стороне БД Оракл, делает определенные действия по условиям с одной из таблиц, апдейт, инсерт. Форсируется ее запуск с клиента VFP8. По окончании ее действия посылается Sqlcommit. Если потом с клиента послать к этой таблице над которой работала проца простой SELECT, то на клиента возвращаются актуальные обновленные данные, значит коммит отработал. Но если с клиента послать транзакцию инсерт в другую таблицу на основе селекта из обновленной только что таблицы (insert into таблица 2 селект таблица_обновленная), то этих последних обновлений "как будто не видно" идет инсерт старых данных, т.е. предыдущих до обновления. Если захожу PL\SQL Developerom, (но получается что ссеия другая) то вижу, что таблица обновлена и данные корректные.
Почему же при отправке с клиента в одной и той же сессии, простой селект возвращает обновленные данные, а транзакция инсерт на основе этого же селект делает вставку предыдущих до обновления данных?


------------------
Жись, она как зёбра, полоса белая, полоса черная, а мне всегда задница достается...
Ratings: 0 negative/0 positive

Re: Транзакции
PaulWist

Сообщений: 13590
Дата: 06.01.21 13:15:33
Что возвращает Sqlcommit?


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive

Re: Транзакции
Божья_коровка
Автор

Сообщений: 24282
Дата: 06.01.21 13:49:57
PaulWist
Что возвращает Sqlcommit?
Возвращает 1 Т.е. всё должно быть прекрасно, все изменения закомичены в базе...Я второй день бьюсь над этой странностью и понять не могу где собака зарыта.


------------------
Жись, она как зёбра, полоса белая, полоса черная, а мне всегда задница достается...




Исправлено: Божья_коровка, 06.01.21 13:51
Ratings: 0 negative/0 positive

Re: Транзакции
PaulWist

Сообщений: 13590
Дата: 06.01.21 14:11:49
Похоже на вложенные транзакции, посмотри аналог в Оракле, @@trancount - те на каком уровне вложенности транзакции находимся.

Может триггер срабатывает, без генерации ошибки.


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)




Исправлено: PaulWist, 06.01.21 14:13
Ratings: 0 negative/0 positive

Re: Транзакции
Божья_коровка
Автор

Сообщений: 24282
Дата: 06.01.21 15:41:30
PaulWist
Может триггер срабатывает, без генерации ошибки.
Триггер на таблице есть, формирует уникальный айдшник при вставке и при обновлении. Я ведь захожу девелопером и вижу, что данные то обновились, проца отработала корректно, ничто и нигде "не подвисло". Да и простой селект на клиента в той же сессии тоже возвращает обновлённые данные.

PaulWist
посмотри аналог в Оракле, @@trancount
А что это такое? Хотя бы в двух понятных словах, чтобы не перелопачивать всю информацию в хелпе.
вот почитала тут www.sql.ru Выпила вина, потому что нифига не поняла, и что делать? :al:


------------------
Жись, она как зёбра, полоса белая, полоса черная, а мне всегда задница достается...




Исправлено: Божья_коровка, 06.01.21 16:26
Ratings: 0 negative/0 positive

Re: Транзакции
PaulWist

Сообщений: 13590
Дата: 06.01.21 19:37:25
Ммм, без репо-кода трудно.

Ну давай дальше искать.

1. Уровень изоляции какой стоит (TIL)?

2. @@trancount - показывает уровень вложенности транзакции, те фактически количество команд Begin Tran.
Например у тебя такой код:

Begin tran
Begin tran
select @@trancount -- покажет 2
commit tran
select @@trancount -- покажет 1
commit tran
select @@trancount -- покажет 0

т.е. ты читаешь данные из незафиксированной транзакции (первый select), хотя формально выдана команда commit.

3. Какой режим закрытия транзакция стоит в фоксе, sqlgetprop(nConnection, 'Transaction')


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive

Re: Транзакции
Igor Korolyov

Сообщений: 34067
Дата: 06.01.21 21:13:17
В оракле нет никаких вложенных транзакций - есть автономные, но это совсем другое дело. Есть savepoint-ы, но и это не "вложенные транзакции".
Клиентское управление транзакциями (sqlcommit) может некорректно пересекаться с серверным управлением транзакциями (если таковое прописано в ХП) - лучше так НЕ делать. Либо клиент управляет (а на сервере никаких коммитов), либо сервер управляет, но тогда клиент никаких sqlcommit не должен посылать (он то, конечно, может - но смысла в этом будет ровно 0, т.к. ничего фиксировать этот коммит не будет, равно как и sqlrollback ничего не откатит).

Описываемое поведение весьма странное - даже без коммита внутри одной транзакции будут видны все изменения сделанные в некоторой таблице (конечно же изменения сделанные в рамках этой транзакции). Создаётся впечатление, что на самом деле этот insert into ... select ... исполняется в отдельном клиентском процессе (т.е. для него сделано отдельное соединение), при том там включен режим транзакций serializable и сама транзакция стартовала ДО начла изменений таблицы-источника. Но тогда и обычный Select выполненный из этого контекста "не увидит" изменений.


------------------
WBR, Igor
Ratings: 0 negative/1 positive

Re: Транзакции
Божья_коровка
Автор

Сообщений: 24282
Дата: 07.01.21 17:06:27
Igor Korolyov
Описываемое поведение весьма странное - даже без коммита внутри одной транзакции будут видны все изменения сделанные в некоторой таблице (конечно же изменения сделанные в рамках этой транзакции). Создаётся впечатление, что на самом деле этот insert into ... select ... исполняется в отдельном клиентском процессе (т.е. для него сделано отдельное соединение), при том там включен режим транзакций serializable и сама транзакция стартовала ДО начла изменений таблицы-источника. Но тогда и обычный Select выполненный из этого контекста "не увидит" изменений.
Я сама понимаю, что столкнулась с очень странной ситуацией. Нет там никакого отдельного соединения не присутствует, всё выполняется в одной сессии, я эту транзакцию insert into ... select ... посылаю сразу же после того как отработала проца. Два дня ковырялась, так и не поняла в чем дело. Обошла эту странность как раз простым селектом. После проработки процы посылаю с клиента селект, тяну в курсор данные, загоняю в переменные, обрабатываю типы и посылаю инсерт на основе этих переменных. Это получается километр лишнего кода, ну и решение так себе. Ведь куда проще послать транзакцию в три строки и всё четко и понятно.


------------------
Жись, она как зёбра, полоса белая, полоса черная, а мне всегда задница достается...




Исправлено: Божья_коровка, 07.01.21 17:07
Ratings: 0 negative/0 positive

Re: Транзакции
Владимир Максимов

Сообщений: 13874
Откуда: Москва
Дата: 08.01.21 21:15:41
А можно хотя бы в виде псевдокода боле подробно описать, что происходит?

  
 * Настраиваем ручной режим завершения транзакции (иначе смысла в SqlCommit нет)  
  = SQLSETPROP(m.ch, 'Transactions', 2)  
    
 * Со стороны VFP8 запускаем процедуру Oracle  
  =SQLExec(m.ch, 'Call MyProc')  
    
 * Явно завершаем транзакцию  
  isOk = SqlCommit(m.ch)  
    
 * Если делаем явную выборку, то получаем актуальные данные  
  =SQLExec(m.ch, 'select * from MyTab', 'curTest')  
  select curTest  
  BROWSE NOWAIT  
    
 * Если делаем вставку в другую таблицу напрямую  
  =SQLExec(m.ch, 'insert into MyTab2 select * from MyTab')  
    
 * То добавленные данные - это данные до завершения транзакции  
  =SQLExec(m.ch, 'select * from MyTab2', 'curTest2')  
  select curTest2  
  BROWSE NOWAIT

Вот это было сделано?

Те записи, которые просматриваешь в MyTab напрямую - это именно те записи, которые потом вставляешь в MyTab2? Там в команде INSERT нет какого-либо дополнительного WHERE или хитрых триггеров на самой таблице?
Ratings: 0 negative/0 positive

Re: Транзакции
Божья_коровка
Автор

Сообщений: 24282
Дата: 08.01.21 21:45:06
Начало всё как вы и написали -

* Настраиваем ручной режим завершения транзакции (иначе смысла в SqlCommit нет)  
  = SQLSETPROP(m.ch, 'Transactions', 2)  
    
 * Со стороны VFP8 запускаем процедуру Oracle  
  =SQLExec(m.ch, 'Call MyProc')  
    
 * Явно завершаем транзакцию  
  isOk = SqlCommit(m.ch)
После успешного завершения работы процы, т.е. после isOk = SqlCommit(m.ch) посылаю с клиента транзакцию -

=SQLExec(m.ch, 'insert into tabl2 (перечисление полей) select (перечисление полей) from MyTab where id = тут айдишник записи')  
  isOk = SqlCommit(m.ch)

И после этой транзакции заглядываю в tabl2 и вижу, что вставка произошла не последних обновленных данных после процедуры, а предыдущих. Открываю PL\SQL Developrom таблицу MyTab вижу, что данные на самом деле обновлены.

Далее чтобы понять, чтобы убедиться что данные обновились в той же сессии (все таки монитор это другая уже сессия) отрабатываю код -

* Настраиваем ручной режим завершения транзакции (иначе смысла в SqlCommit нет)  
  = SQLSETPROP(m.ch, 'Transactions', 2)  
    
 * Со стороны VFP8 запускаем процедуру Oracle  
  =SQLExec(m.ch, 'Call MyProc')  
    
 * Явно завершаем транзакцию  
  isOk = SqlCommit(m.ch)  
    
 * Если делаем явную выборку, то получаем актуальные данные  
 * ID в where один и тот же послается  
  =SQLExec(m.ch, 'select * from MyTab where id = тут айдишник записи', 'curTest')  
  select curTest  
  BROWSE NOWAIT
Получаю актуальные данные, т.е. они обновились. Но как только посылаю далее транзакцию, то вставка идет предыдущих данных -

* Настраиваем ручной режим завершения транзакции (иначе смысла в SqlCommit нет)  
  = SQLSETPROP(m.ch, 'Transactions', 2)  
    
 * Со стороны VFP8 запускаем процедуру Oracle  
  =SQLExec(m.ch, 'Call MyProc')  
    
 * Явно завершаем транзакцию  
  isOk = SqlCommit(m.ch)  
 *посылаю с клиента транзакцию -  
  =SQLExec(m.ch, 'insert into tabl2 (перечисление полей) select (перечисление полей) from MyTab where id = тут айдишник записи')  
  isOk = SqlCommit(m.ch)


------------------
Жись, она как зёбра, полоса белая, полоса черная, а мне всегда задница достается...




Исправлено: Божья_коровка, 08.01.21 21:59
Ratings: 0 negative/0 positive

Re: Транзакции
Божья_коровка
Автор

Сообщений: 24282
Дата: 08.01.21 21:57:45
В итоге пришлось отказаться от транзакции -

=SQLExec(m.ch, 'insert into tabl2 (перечисление полей) select (перечисление полей) from MyTab where id = тут айдишник записи')
и делать селект
=SQLExec(m.ch, 'select (перечисление полей) from MyTab where id = тут айдишник записи', 'curTest')
обрабатывать типы данных, загонять их в переменные и делать инсерт на основе этих переменных

=SQLExec(m.ch, 'insert into tabl2 (перечисление полей) values (перечисление переменных)')


------------------
Жись, она как зёбра, полоса белая, полоса черная, а мне всегда задница достается...




Исправлено: Божья_коровка, 08.01.21 21:58
Ratings: 0 negative/0 positive

Re: Транзакции
Божья_коровка
Автор

Сообщений: 24282
Дата: 08.01.21 22:03:42
По поводу хитрых триггеров, - их на таблице MyTab нет. Висит один триггер, который при апдейте записи формирует айдишник изменения. Ничего в нем хитрого нет, несколько строчек.

Т.е. я не смогла выяснить почему транзакция инсерт на основе селекта из таблицы, которая была обновлена процедурой вставляет данные предыдущие, а не только что обновленные, тогда как по факту они обновлены и зафиксированы, ведь простой селект на клиента тянет курсор с корректными последними обновлёнными данными.


------------------
Жись, она как зёбра, полоса белая, полоса черная, а мне всегда задница достается...




Исправлено: Божья_коровка, 08.01.21 22:06
Ratings: 0 negative/0 positive

Re: Транзакции
Божья_коровка
Автор

Сообщений: 24282
Дата: 08.01.21 22:15:25
За эти два дня баловалась по всякому даже прописывала такое безобразие -

* Настраиваем ручной режим завершения транзакции (иначе смысла в SqlCommit нет)    
    = SQLSETPROP(m.ch, 'Transactions', 2)    
        
  * Со стороны VFP8 запускаем процедуру Oracle    
    =SQLExec(m.ch, 'Call MyProc')    
        
  * Явно завершаем транзакцию    
    isOk = SqlCommit(m.ch)    
        
  * Если делаем явную выборку, то получаем актуальные данные    
  * ID в where один и тот же послается    
    =SQLExec(m.ch, 'select * from MyTab where id = тут айдишник записи', 'curTest')    
    select curTest   
  IF  curTest.pole1 = 'обновленное значение'  
   * если данные обновились то сделать транзакцию  
    =SQLExec(m.ch, 'insert into tabl2 (перечисление полей) select (перечисление полей) from MyTab where id = тут айдишник записи')    
    isOk = SqlCommit(m.ch)  
  ELSE  
     messagebox ('Всё плохо, ничего не обновилось, транзакцию не посылаю')  
  ENDIF
В общем, селект возвращает обновлённые данные, программа заходит в ветку IF отрабатывает транзакция, которая вставляет предыдущие данные, как будто для нее не существует обновленных данных.


------------------
Жись, она как зёбра, полоса белая, полоса черная, а мне всегда задница достается...




Исправлено: Божья_коровка, 08.01.21 22:18
Ratings: 0 negative/0 positive

Re: Транзакции
PaulWist

Сообщений: 13590
Дата: 08.01.21 23:04:36
Теоретически все правильно, попробуй после первого sqlcommit перевести соединение в автоматический режим и выполнить insert, возможно какие-то косяки с драйвером.

Ну и профайлером посмотреть надо какие команды север выполняет.


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)




Исправлено: PaulWist, 08.01.21 23:06
Ratings: 0 negative/0 positive

Re: Транзакции
leonid

Сообщений: 2919
Откуда: Рига
Дата: 09.01.21 00:16:31
А я бы посоветовал вот это

* Явно завершаем транзакцию    
    isOk = SqlCommit(m.ch)

нафиг выбросить и посмотреть, что будет
Ratings: 0 negative/0 positive

Re: Транзакции
Igor Korolyov

Сообщений: 34067
Дата: 09.01.21 20:30:06
Без вот этого
Божья_коровка
MyProc
вот этого
Божья_коровка
Висит один триггер, который при апдейте записи формирует айдишник изменения.
и вот этого
Божья_коровка
where id = тут айдишник записи
А так же понимания того что такое
Божья_коровка
данные предыдущие, а не только что обновленные
Нереально что либо понять.

Ну можно лишь посоветовать сделать тест - БЕЗ всего этого, без триггера, без условия в insert ... select, без ХП - чисто какой update или insert напрямую послать - и если и тогда будут "чудеса" - ну это значит системная проблема (остаётся лишь серверную трассировку включать и смотреть что происходит). Пока же есть шанс что дело таки в коде.


------------------
WBR, Igor
Ratings: 0 negative/0 positive

Re: Транзакции
of63

Сообщений: 20844
Откуда: Н.Новгород
Дата: 10.01.21 10:53:18
() а если делать операции с Ораклом без указания "начало/конец", т.е. без транзакций, то работает как надо?
Ratings: 0 negative/0 positive

Re: Транзакции
Igor Korolyov

Сообщений: 34067
Дата: 10.01.21 14:43:07
Транзакции там будут по любому, просто в режиме
SQLSETPROP(m.ch, 'Transactions', 1) && Automatic
они будут неявно коммитится после каждого SQLEXEC.


------------------
WBR, Igor
Ratings: 0 negative/0 positive

Re: Транзакции
of63

Сообщений: 20844
Откуда: Н.Новгород
Дата: 10.01.21 17:29:01
Акцент в вопросе был "с автоматическим управлением транзакциями (умолчательными транзакциями), или при полном их отключении (если это возможно) работает так, как надо?"
Ratings: 0 negative/0 positive

Re: Транзакции
Божья_коровка
Автор

Сообщений: 24282
Дата: 10.01.21 18:37:33
of63
Акцент в вопросе был "с автоматическим управлением транзакциями (умолчательными транзакциями), или при полном их отключении (если это возможно) работает так, как надо?"
Я не поняла вопроса, что значит - "умолчательными транзакциями"? И что значит при полном их отключении? В двух словах объясни, что ты имеешь в виду...


------------------
Жись, она как зёбра, полоса белая, полоса черная, а мне всегда задница достается...
Ratings: 0 negative/0 positive



Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 5 PaulWist  (Гостей: 4)


© 2000-2021 Fox Club 
Яндекс.Метрика