Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2010.12.19;
Скачать: [xml.tar.bz2];

Вниз

На этот раз - транзакции   Найти похожие ветки 

 
Юрий Зотов ©   (2010-09-06 22:41) [0]

AS400, DB2, J2SE, двузвенка.
Опуская детали, схема кода выглядит так:

StartTransaction;
try
 DeleteRecord(ID); // ID -первичный ключ
 DoSomething;
 InsertRecord(ID); // Таблица и ID те же, что и в DeleteRecord
 Commit
except
 RollBack;
 WriteLog("Фиг вам")
end;

Коннект к БД единственный и весь этот код работает через него. Казалось бы, все тривиально и железно. Но неожиданно возникают фокусы.

1. При выполнении InsertRecord возникает исключение DuplicateKey. Ради эксперимента выполнил DeleteRecord и InsertRecord в раздельных транзакциях - и все отлично сработало, но в боевом режиме так, конечно, делать нельзя.

Вопрос 1 - какого хрена InsertRecord не видит, что запись удалена?

2. После выполнения этого кода записи c ID в таблице нет (хотя ДО его выполнения она была). В логе есть честное сообщение об ошибке - то есть, исключение было перехвачено и откат состоялся.

Вопрос 2 - какого хрена не откатилось удаление записи?


 
Inovet ©   (2010-09-06 22:55) [1]

> [0] Юрий Зотов ©   (06.09.10 22:41)
> какого хрена InsertRecord не видит, что запись удалена?

Так для других транзакций она живая.


 
Inovet ©   (2010-09-06 22:57) [2]

> [0] Юрий Зотов ©   (06.09.10 22:41)
> Вопрос 2 - какого хрена не откатилось удаление записи?

Может RollBack для транцакции не тот, что надо, настройка транзакции в смысле.


 
Юрий Зотов ©   (2010-09-06 23:07) [3]


> Inovet ©   (06.09.10 22:55) [1]

А другие транзакции тут ни при чем. Delete и Insert выполняются в ОДНОЙ транзакции, поэтому:

1. Insert должна видеть изменения, сделанные в Delete и поэтому не должна давать никаких Duplicate key.
2. А уж если исключение все же возникло, то откатываться должны ВСЕ изменения.


 
Джо ©   (2010-09-06 23:12) [4]

Может, случилась классика жанра и проблема в 13-й строке? :)
Все же чудес не бывает и проблема либо в самой используемой технологии (что маловероятно), либо в неприведенном фрагменте кода. Допустим, в DoSomething транзакция заканчивается, да мало ли что.


 
Petr V. Abramov ©   (2010-09-06 23:12) [5]


> Вопрос 1 - какого хрена InsertRecord не видит, что запись
> удалена?

ээээ, Юр Сергеевич, еврейский InsertRecord или православный sql-ный insert statement??? это две большие разницы в общем случае. хрен его знает, что там жабный метод делает из соображений как получше бы.


 
Юрий Зотов ©   (2010-09-06 23:42) [6]

> Джо ©   (06.09.10 23:12) [4]

Просмотрел весь код раз 100 - ничего не нашел. И потом:

1. Если до вызова Insert транзакция коммитится, то Insert тем более обязан видеть изменения, сделанные в Delete - а ведь не видит.

2. А если до вызова Insert транзакция откатывается, то обязана восстанавливаться удаленная запись - а ведь не восстанавливается.

Странность как раз в том, что происходят две ВЗАИМОИСКЛЮЧАЮЩИЕ ошибки.


 
Inovet ©   (2010-09-07 02:28) [7]

> [6] Юрий Зотов ©   (06.09.10 23:42)
> Странность как раз в том, что происходят две ВЗАИМОИСКЛЮЧАЮЩИЕ ошибки.

Может таки там в этих "AS400, DB2, J2SE, двузвенка" внетранзакционные какие дела с ключами происходят? Действительно, как Пётр выше сказал, попробовать то же, но без обёрток. Это я так предполагаю только, ибо не трогал ДБ2.


 
sniknik ©   (2010-09-07 03:10) [8]

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

в общем попробуй запросами (если там у тебя это возможно).

> ибо не трогал ДБ2.
то же самое, просто по аналогии.


 
Anatoly Podgoretsky ©   (2010-09-07 09:13) [9]

Что такое  DeleteRecord, InsertRecord
Проблема наверно там
Почему не хочешь написать SQL запрос?
DELETE FROM tbl WHERE ID=:ID


 
Polevi ©   (2010-09-07 11:49) [10]

у меня возникает иногда похожая проблема с MS SQL
в транзакции сначала добавляется запись в справочную таблицу, затем в таблицу фактов.
иногда возникает форейн кий констрэйнт, как будто первой операции не было.
используется стандартный SqlCommand


 
Юрий Зотов ©   (2010-09-07 11:54) [11]


> Что такое  DeleteRecord, InsertRecord

Упрощенно, вот что:

private void deleteRecord(Integer iD) throws SQLException {
 String sql = "delete from TABLE where ID = ?";
 Object[] params = new Object[] { iD };
 connection.executeUpdate(sql, params);
}

private void insertRecord(Integer iD) throws SQLException {
 String sql = "insert into TABLE (ID, FLD) values (?, ?) ";
 Object[] params = new Object[] { iD, fldValue };
 connection.executeUpdate(sql, params);
}

Здесь connection и fldValue - приватные поля класса. Транзакция стартует, коммитится и откатывается через этот самый connection. Удаление и вставка, как видно из кода, производятся через него же (то есть, именно в этой транзакции).

Еще из кода видно, что удаление и вставка производятся как раз прямым SQL (точнее, через метод connection.executeUpdate, но поскольку этот метод из стандартного пакета java.sql уже оттестирован миллионы раз сотнями тысяч программеров по всему миру, то подозревать его в неправильности вряд ли можно.


 
12 ©   (2010-09-07 12:04) [12]

а может у connection есть какое св-во, типа AutoCommit, кторое плавает..

зы
может и фигню сказал, зато самому ЮЗ :)


 
Юрий Зотов ©   (2010-09-07 12:11) [13]


> 12 ©   (07.09.10 12:04) [12]

Как раз не фигня - именно такое свойство у него действительно есть. По умолчанию оно - true, и старт транзакции состоит как раз в том, чтобы выставить его в false. После этого начинают работать методы commit и rollback.

Но даже если бы было AutoCommit = true, то Insert тем более был бы обязан видеть изменения, сделанные в Delete - а ведь не видит (поскольку дает Duplicate key).


 
12 ©   (2010-09-07 12:16) [14]


> Юрий Зотов ©   (07.09.10 12:11) [13]

это понятно, но

> кторое плавает..

может сбрасыватся туда-сюда где то по коду выше-ниже?


 
oxffff ©   (2010-09-07 12:17) [15]


> Юрий Зотов ©   (07.09.10 12:11) [13]
>
> > 12 ©   (07.09.10 12:04) [12]
>
> Как раз не фигня - именно такое свойство у него действительно
> есть. По умолчанию оно - true, и старт транзакции состоит
> как раз в том, чтобы выставить его в false. После этого
> начинают работать методы commit и rollback.
>
> Но даже если бы было AutoCommit = true, то Insert тем более
> был бы обязан видеть изменения, сделанные в Delete - а ведь
> не видит (поскольку дает Duplicate key).


Может запускается >1 копии кода в разных транзакциях?
И одна копия коммитится раньше другой успешно. А вторая приводит к subj?


 
Юрий Зотов ©   (2010-09-07 12:34) [16]


> 12 ©   (07.09.10 12:16) [14]

Проверял поиском. Нет такого.


> oxffff ©   (07.09.10 12:17) [15]

Тоже думал, но это исключено. Программа серверная (практически служба, демон) - и в ней предприняты меры для блокировки повторного запуска (да и в списке задач система всегда показывает только 1 экземпляр). Еще программа многопоточная, но данный кусок кода жестко синхронизирован (и синхронизация действительно работает, это много раз проверено).


 
oxffff ©   (2010-09-07 12:45) [17]


> > oxffff ©   (07.09.10 12:17) [15]
>
> Тоже думал, но это исключено. Программа серверная (практически
> служба, демон) - и в ней предприняты меры для блокировки
> повторного запуска (да и в списке задач система всегда показывает
> только 1 экземпляр). Еще программа многопоточная, но данный
> кусок кода жестко синхронизирован (и синхронизация действительно
> работает, это много раз проверено).


Может все же залогировать работу в таблицу и посмотреть логи?


 
Компромисс   (2010-09-07 12:45) [18]

Юрий Зотов

Вы бы оригинальный java код привели, может и помог кто.


 
oxffff ©   (2010-09-07 12:49) [19]


> Может все же залогировать работу в таблицу и посмотреть
> логи?


Очень часто совершенно странные и непонятно как возникающие ошибки случаются банально из-за опечаток, un/комментирования кода, copy paste.


 
Юрий Зотов ©   (2010-09-07 12:50) [20]


> oxffff ©   (07.09.10 12:45) [17]

Сделано с самого начала. Там отладочные сообщения и трасса Exception (включая имена классов, методов и номера строк). Видно, что вылетает именно в Insert из-за Duplicate key, а до этого все хорошо.


> Компромисс   (07.09.10 12:45) [18]

Реальный код слишком большой.


 
oxffff ©   (2010-09-07 12:51) [21]


> oxffff ©   (07.09.10 12:45) [17]
>
> > > oxffff ©   (07.09.10 12:17) [15]
> >
> > Тоже думал, но это исключено. Программа серверная (практически
>
> > служба, демон) - и в ней предприняты меры для блокировки
>
> > повторного запуска (да и в списке задач система всегда
> показывает
> > только 1 экземпляр). Еще программа многопоточная, но данный
>
> > кусок кода жестко синхронизирован (и синхронизация действительно
>
> > работает, это много раз проверено).
>
>
> Может все же залогировать работу в таблицу и посмотреть
> логи?


После удаления проверять select есть запись или нет. Опять же в лог.
И все станет понятно. :)


 
Компромисс   (2010-09-07 13:05) [22]

Похоже на это?

http://www.mail-archive.com/pgsql-general@postgresql.org/msg132161.html


 
sniknik ©   (2010-09-07 13:06) [23]

> По умолчанию оно - true, и старт транзакции состоит как раз в том, чтобы выставить его в false. После этого начинают работать методы commit и rollback.
по описанию больше похоже на кешированные обновления ("батчапдетемоде"), т.е. "транзакция" формируется на клиенте (о чем и говорил).
там также будет (описанный "глюк"), т.к. сервер не знает что запись с таким ключом удалена, и порядок обновлений неизвестен. (вернее если insertRecord именно инсерт, как с некоторыми таблицами раньше BDE могло, а не append, то именно известен, и неправилен... запрос на вставку будет раньше удаления)


 
Anatoly Podgoretsky ©   (2010-09-07 13:32) [24]

> sniknik  (07.09.2010 13:06:23)  [23]

То что кеширование это одназначно.


 
Ega23 ©   (2010-09-07 13:48) [25]

Вложенные транзакции поддерживаются?


 
Ega23 ©   (2010-09-07 13:51) [26]

Что-то типа
Begin Tran1
 Begin Tran2
   Delete(ID)
 Commint Tran2
 Begin Tran3
   Insert
 Commit Tran3
Commit Tran1


 
toto   (2010-09-07 16:51) [27]

Какая версия стоит на АS400? Если не ошибаюсь начиная с V4R5 надо :

Information de journalisation :              
 Actuellement journalisé  . . . . . . :   OUI


 
Юрий Зотов ©   (2010-09-08 17:33) [28]


> Какая версия стоит на АS400? Если не ошибаюсь начиная с
> V4R5 надо :

Если речь идет о журналировании, то оно было включено сразу после создания таблицы.


 
Юрий Зотов ©   (2010-09-08 17:45) [29]

В общем, причину так и не нашел, пришлось искать обходные маневры. По советам Олега и Петра, ничего не удаляя, сделал запись новых данных во временную таблицу - а потом MERGE.

Есть и более простой (но плохой, ИМХО) вариант - тоже ничего не удалять, а перед записью проверять SELECT"ом существовование записи и если она есть - то UPDATE, иначе INSERT. Хотя, учитывая [16] этот вариант, может быть и неплохим вовсе.

Что скажете, гуру БД?


 
Empleado ©   (2010-09-08 17:57) [30]


> а перед записью проверять SELECT"ом существовование записи
> и если она есть - то UPDATE, иначе INSERT

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


 
vrem   (2010-09-08 19:06) [31]

полагается писать транСакции


 
Ega23 ©   (2010-09-08 19:13) [32]


> Есть и более простой (но плохой, ИМХО) вариант - тоже ничего
> не удалять, а перед записью проверять SELECT"ом существовование
> записи и если она есть - то UPDATE, иначе INSERT. Хотя,
> учитывая [16] этот вариант, может быть и неплохим вовсе.


Сильно СУБД-зависимо. Да и структуру таблицы надо смотреть (индексы всякие).
У меня, например, в аналогичной ситуации просто офигенный выигрыш в скорости дала конструкция на T-SQL
TRY
 INSERT ...
CATCH
 UPDATE...
END


Может тут тоже что-то такое нужно, если SQL-диалект позволяет?


 
boriskb ©   (2010-09-08 19:34) [33]

> [29] Юрий Зотов ©   (08.09.10 17:45)
> В общем, причину так и не нашел


Жалко.
Как только ветка появилась, мне вспомнилось, что нечто подобное лет 5-7 назад на MS SQL у меня случалось.
Силился вспомнить - как я выкручивался. Не вспомнилось
Думал - здесь решат и вспомню.

А может и я не "решил", а "выкрутился" ?


 
Ega23 ©   (2010-09-08 19:42) [34]


> Думал - здесь решат и вспомню.


Суррогатный ключ и уникальный индекс - наше всьё!


 
Petr V. Abramov ©   (2010-09-08 20:29) [35]


> Ega23 ©   (08.09.10 19:42) [34]

а какая тут-то разница суррогатный или с акцизной маркой?


 
Anatoly Podgoretsky ©   (2010-09-08 21:31) [36]

> Юрий Зотов  (08.09.2010 17:45:29)  [29]

Я часто использую схему DELETE + Insert, только с прямыми запросами. Все
работает да и транзакция в большинстве случаев лишнее. Обычно нет нужды
откатывать удаленое, кроме редких случаев. А для MSSQL я вообще пишу это как
одну команду.
И делаю это чтобы не узнавать есть запись или нет.
У меня есть посторонняя бухсистема, там последовательно delete+insert
обычная норма, особенно перерасчеты и тоже как правило в рамках одной
команды. Смотрел профайлером.


 
Ega23 ©   (2010-09-08 21:35) [37]


> там последовательно delete+insert обычная норма,


Есть подозрение, что Update в MSSQL это и есть Delete + Insert


 
Игорь Шевченко ©   (2010-09-08 21:36) [38]

Задал бы ты, Юра, свой вопрос в
http://sql.ru/forum/actualtopics.aspx?bid=5

там про DB2 тебе все расскажут, как и почему, а может и про твою беду помогут


 
Игорь Шевченко ©   (2010-09-08 21:37) [39]


> Есть подозрение, что Update в MSSQL это и есть Delete +
> Insert


можешь вклиниться между ? Нет ? Тогда ты неправ


 
Ega23 ©   (2010-09-08 21:43) [40]


> можешь вклиниться между ? Нет ? Тогда ты неправ

Ты меня не так понял.
Впрочем, предлагаю не здесь и не сейчас, а 14-го в соответствующем месте. :)



Страницы: 1 2 вся ветка

Форум: "Прочее";
Текущий архив: 2010.12.19;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.005 c
11-1227142295
arthur
2008-11-20 03:51
2010.12.19
InputBox() function


11-1227267675
Sergey1991
2008-11-21 14:41
2010.12.19
Неправильно отображаются большие числа в TTable


2-1275893023
Крапивин Олег
2010-06-07 10:43
2010.12.19
Видимость колонок в StringGrid


15-1283925708
sniknik
2010-09-08 10:01
2010.12.19
Что за проблема с кнопками?


15-1283804001
Кто б сомневался
2010-09-07 00:13
2010.12.19
Удалить папку System Volume Info навсегда





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский