|
|
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
Добрый день, коллеги. Переезжаем с Аccess на PostgreSQL. Вроде бы всё работает на первый взгляд удовлетворительно, но в одном месте наткнулся на опасную ошибку. При использовании транзакции код отрабатывает без ошибок, но запись в таблице не появляется! Поскольку транзакции используются в коде повсеместно, очень опасная тенденция. Код VBA такой Код: vbnet 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. В этом месте транзакция не критична, но в большинстве других мест это не так. Не понятно, почему пропадает часть изменений и как отследить, что записи не пропадают? Потому как в некоторых местах без специального исследования и не поймёшь, что что-то пошло не так и часть данных пропала по дороге. В другом месте нормально отрабатывали гораздо более длинные транзакции, но там были только рекордсеты, я так понимаю всё портит CurrentDb.Execute... Возможно, там не такой коннект как у СurrentDb.OpenRecordset, но я не уверен Переписать под ADO единовременно не представляется возможным, ибо данные переносятся по кускам и некоторых таблиц на сервере ещё долго не будет... К тому же никто не гарантирует, что там это не будет работать точно так же. В общем, мистика и жёпа - на дебаг всех форм и всех транзакции уйдут остатки молодости, нужно искать корень и системное решение. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.10.2015, 14:49 |
|
||
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
Шыфл, перепишите все работы с рекордсетами типа tb1.FindFirst на прямые [pass-through] запросы к серверу. (то же DAO). по крайней мер -- где можете. за планы отрезать хвост по частям -- убивать на месте. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.10.2015, 15:43 |
|
||
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
qwwqШыфл, перепишите все работы с рекордсетами типа tb1.FindFirst на прямые [pass-through] запросы к серверу. (то же DAO). по крайней мер -- где можете. за планы отрезать хвост по частям -- убивать на месте. Не везде удобно работать с прямыми запросами, хочется понять причину - почему теряется часть транзакции, а часть - проходит как ни бывало. Если оба изменения провести рекордсетом, всё работает. Если CurrentDb.Execute запустить раньше, чем tb1.Update, всё прекрасно срабатывает, значит дело не в разных коннектах, а в чём-то ещё. Хотелось бы понять, куда деваются изменения и как это можно победить с наименьшими потерями - потому что баг на лицо: тихая, не заметная потеря данных в рамках легальной транзакции. П.с. Зажарить слона на вертеле целиком - очень нетривиальная и бессмысленная задача, приходится свежевать на порционные куски. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.10.2015, 17:11 |
|
||
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
ШыфлqwwqШыфл, перепишите все работы с рекордсетами типа tb1.FindFirst на прямые [pass-through] запросы к серверу. (то же DAO). по крайней мер -- где можете. за планы отрезать хвост по частям -- убивать на месте. Не везде удобно работать с прямыми запросами, хочется понять причину - почему теряется часть транзакции, а часть - проходит как ни бывало. Если оба изменения провести рекордсетом, всё работает. Если CurrentDb.Execute запустить раньше, чем tb1.Update, всё прекрасно срабатывает, значит дело не в разных коннектах, а в чём-то ещё. Хотелось бы понять, куда деваются изменения и как это можно победить с наименьшими потерями - потому что баг на лицо: тихая, не заметная потеря данных в рамках легальной транзакции. П.с. Зажарить слона на вертеле целиком - очень нетривиальная и бессмысленная задача, приходится свежевать на порционные куски. Включите лог запросов на стороне базы и смотрите что реально вызывается от приложения. Какие запросы, какие последовательности транзакций и тд. И сразу все станет ясно (скорее всего ;) ). -- Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.10.2015, 18:01 |
|
||
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
для лога обратите внимание на формат. вам будет важен http://www.postgresql.org/docs/9.4/static/runtime-config-logging.html log_line_prefix %v Virtual transaction ID (backendID/localXID) %x Transaction ID (0 if none is assigned) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.10.2015, 18:18 |
|
||
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
Похоже, что без tb1.Close теряется транзакция. Попробуйте закрыть перед выполнением запроса. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.10.2015, 18:31 |
|
||
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
ChA, tb1.close не помогает, включил лог вот операция в оригинальной последовательности, т.е. сначала tbl1.update, потом Execute: <[н/д]%2015-11-02 11:04:28.022 EET%00000%2/8111%0>ОТМЕТКА: оператор: BEGIN;SELECT "public"."СчетаДанные"."Id" FROM "public"."СчетаДанные" <[н/д]%2015-11-02 11:04:33.017 EET%00000%2/8111%0>ОТМЕТКА: оператор: SELECT MAX("Id" ) FROM "public"."СчетаДанные" WHERE ("Id" BETWEEN 0 AND 99999999 ) <[н/д]%2015-11-02 11:04:44.573 EET%00000%2/8111%0>ОТМЕТКА: выполнение <unnamed>: INSERT INTO "public"."СчетаДанные" ("Id","IdСчета","КодМЦ","КодЦвет","Количество","Цена","Сумма","НДСПроцент","НДССумма","СуммаВсего","ВозвратПроцент","Упаковка","ЦенаПрайс","СрокПоставки3","ЦенаПрайс2","ЦенаПрайс3") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16) <[н/д]%2015-11-02 11:04:44.573 EET%00000%2/8111%0>ПОДРОБНОСТИ: параметры: $1 = '187024', $2 = '38903', $3 = '40001028', $4 = '0', $5 = '500', $6 = '500', $7 = '250000', $8 = '0', $9 = '0', $10 = '250000', $11 = '0', $12 = NULL, $13 = '2.96', $14 = '2015-10-10', $15 = NULL, $16 = '44274' <[н/д]%2015-11-02 11:04:47.580 EET%42601%2/8111%2478>ОШИБКА: ошибка синтаксиса (примерное положение: ",") (символ 41) <[н/д]%2015-11-02 11:04:47.580 EET%42601%2/8111%2478>ОПЕРАТОР: UPDATE "public"."Счета" SET UpdateDate= ,UpdateUserID=11 WHERE ("Id" = 38903 ) <[н/д]%2015-11-02 11:04:47.590 EET%00000%2/0%2478>ОТМЕТКА: оператор: ROLLBACK <[н/д]%2015-11-02 11:04:47.590 EET%00000%2/8112%0>ОТМЕТКА: оператор: BEGIN;SELECT "public"."Счета"."Id" FROM "public"."Счета" WHERE ("Id" = 38903 ) <[н/д]%2015-11-02 11:04:47.590 EET%00000%2/8112%0>ОТМЕТКА: выполнение _PLAN0C758EF8/_PLAN0C758EF8: SELECT "Id","UpdateUserID","UpdateDate" FROM "public"."Счета" WHERE "Id" = $1 <[н/д]%2015-11-02 11:04:47.590 EET%00000%2/8112%0>ПОДРОБНОСТИ: параметры: $1 = '38903' <[н/д]%2015-11-02 11:04:47.590 EET%00000%2/8112%0>ОТМЕТКА: выполнение _PLAN0C759160/_PLAN0C759160: UPDATE "public"."Счета" SET "UpdateUserID"=$1,"UpdateDate"=$2 WHERE "Id" = $3 <[н/д]%2015-11-02 11:04:47.590 EET%00000%2/8112%0>ПОДРОБНОСТИ: параметры: $1 = '11', $2 = '2015-11-02 12:04:47', $3 = '38903' <[н/д]%2015-11-02 11:04:47.600 EET%00000%2/8112%2479>ОТМЕТКА: оператор: SAVEPOINT _per_query_svp_;DEALLOCATE "_PLAN0C758EF8";RELEASE _per_query_svp_ <[н/д]%2015-11-02 11:04:47.600 EET%00000%2/8112%2479>ОТМЕТКА: оператор: SAVEPOINT _per_query_svp_;DEALLOCATE "_PLAN0C759160";RELEASE _per_query_svp_ <[н/д]%2015-11-02 11:04:49.208 EET%00000%2/8112%2479>ОТМЕТКА: оператор: COMMIT А это лог той же операции, если поменять местами tbl1.update и Execute: <[н/д]%2015-11-02 11:07:14.673 EET%00000%2/8124%0>ОТМЕТКА: оператор: BEGIN;SELECT "public"."СчетаДанные"."Id" FROM "public"."СчетаДанные" <[н/д]%2015-11-02 11:07:20.661 EET%00000%2/8124%0>ОТМЕТКА: оператор: SELECT MAX("Id" ) FROM "public"."СчетаДанные" WHERE ("Id" BETWEEN 0 AND 99999999 ) <[н/д]%2015-11-02 11:07:42.663 EET%42601%2/8124%0>ОШИБКА: ошибка синтаксиса (примерное положение: ",") (символ 41) <[н/д]%2015-11-02 11:07:42.663 EET%42601%2/8124%0>ОПЕРАТОР: UPDATE "public"."Счета" SET UpdateDate= ,UpdateUserID=11 WHERE ("Id" = 38903 ) <[н/д]%2015-11-02 11:07:42.663 EET%00000%2/0%0>ОТМЕТКА: оператор: ROLLBACK <[н/д]%2015-11-02 11:07:42.663 EET%00000%2/8125%0>ОТМЕТКА: оператор: BEGIN;SELECT "public"."Счета"."Id" FROM "public"."Счета" WHERE ("Id" = 38903 ) <[н/д]%2015-11-02 11:07:42.663 EET%00000%2/8125%0>ОТМЕТКА: выполнение _PLAN0E353468/_PLAN0E353468: SELECT "Id","UpdateUserID","UpdateDate" FROM "public"."Счета" WHERE "Id" = $1 <[н/д]%2015-11-02 11:07:42.663 EET%00000%2/8125%0>ПОДРОБНОСТИ: параметры: $1 = '38903' <[н/д]%2015-11-02 11:07:42.663 EET%00000%2/8125%0>ОТМЕТКА: выполнение _PLAN0E3536D0/_PLAN0E3536D0: UPDATE "public"."Счета" SET "UpdateUserID"=$1,"UpdateDate"=$2 WHERE "Id" = $3 <[н/д]%2015-11-02 11:07:42.663 EET%00000%2/8125%0>ПОДРОБНОСТИ: параметры: $1 = '11', $2 = '2015-11-02 12:07:42', $3 = '38903' <[н/д]%2015-11-02 11:07:42.673 EET%00000%2/8125%2480>ОТМЕТКА: оператор: SAVEPOINT _per_query_svp_;DEALLOCATE "_PLAN0E353468";RELEASE _per_query_svp_ <[н/д]%2015-11-02 11:07:42.673 EET%00000%2/8125%2480>ОТМЕТКА: оператор: SAVEPOINT _per_query_svp_;DEALLOCATE "_PLAN0E3536D0";RELEASE _per_query_svp_ <[н/д]%2015-11-02 11:07:45.752 EET%00000%2/8125%2480>ОТМЕТКА: выполнение <unnamed>: INSERT INTO "public"."СчетаДанные" ("Id","IdСчета","КодМЦ","КодЦвет","Количество","Цена","Сумма","НДСПроцент","НДССумма","СуммаВсего","ВозвратПроцент","Упаковка","ЦенаПрайс","СрокПоставки3","ЦенаПрайс2","ЦенаПрайс3") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16) <[н/д]%2015-11-02 11:07:45.752 EET%00000%2/8125%2480>ПОДРОБНОСТИ: параметры: $1 = '187024', $2 = '38903', $3 = '40001028', $4 = '0', $5 = '500', $6 = '500', $7 = '250000', $8 = '0', $9 = '0', $10 = '250000', $11 = '0', $12 = NULL, $13 = '2.96', $14 = '2015-10-10', $15 = NULL, $16 = '44274' <[н/д]%2015-11-02 11:07:48.819 EET%00000%2/8125%2480>ОТМЕТКА: оператор: COMMIT Очень весело. Получается, что Access зачем-то пробует послать Execute 2 раза, причём в первом не подставляется параметр Now(), что вызывает тихую ошибку, которая откатывает трансакцию на уровне сервера, чего сам акс не замечает и ошибку не выдаёт, а потом посылает второй запрос, уже "по правилам" с параметрами, но трансакции уже нету :/ ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.11.2015, 12:28 |
|
||
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
Шыфлtb1.close не помогает, включил лог ... Очень весело. Получается, что Access зачем-то пробует послать Execute 2 раза, причём в первом не подставляется параметр Now(), что вызывает тихую ошибку, которая откатывает трансакцию на уровне сервера, чего сам акс не замечает и ошибку не выдаёт, а потом посылает второй запрос, уже "по правилам" с параметрами, но трансакции уже нету :/Попробуй вместо Код: sql 1. перепиши на Код: sql 1. P.S.На самом деле это всё костыли и подпорки. IMHO, проще было написать процедуру на постгресе. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.11.2015, 14:16 |
|
||
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
ChAперепиши на Код: sql 1. P.S.На самом деле это всё костыли и подпорки. IMHO, проще было написать процедуру на постгресе. В том то и дело, что запрос генерирует Jet, и синтаксис должен быть его, CURRENT_TIMESTAMP он не понимает... Тут вопрос не в том, как оно будет работать, а в том, почему сейчас не работает? Почему Jet генерирует невалидный запрос, скрывает ошибку и через 10 милисекунд генерирует повторный запрос? Это явно глючное поведение, и переписывание этого конкретно места не решает проблемы в целом. П.С. Попробовал убрать параметр dbFailOnError, как ни странно, но стало работать корректно 8) Курю мануалы ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.11.2015, 23:54 |
|
||
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
ШыфлПочему Jet генерирует невалидный запрос, скрывает ошибку и через 10 милисекунд генерирует повторный запрос? Это явно глючное поведение, и переписывание этого конкретно места не решает проблемы в целом.Навскидку. Первый раз он, скорее всего, делает prepare, в том числе, проверяя синтаксис, чтобы в дальнейшем просто вызывать подготовленный запрос, подставляя параметры. Ему возвращается ошибка, дескать, так нельзя, но так как стоит dbFailOnError, то транзакция вместе с предыдущей вставкой откатывается. P.S. Непонятно, чем ему функция now() не угодила, она есть и в Access и Postres. Если бы подставлял прямое значение, то наверняка отката бы не было. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.11.2015, 08:53 |
|
||
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
И ещё вопрос, в догонку. Вот такую конструкцию Код: vbnet 1. 2. 3. 4. 5. 6. 7. Можно ли её запихнуть в генератор, если NextNumId(6) - это функция генерации первичного ключа на таблице 6("СчетаДанные"), которая вызывает что-то вроде Код: vbnet 1. 2. 3. Можно ли переделать стандартный генератор под этот код? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.11.2015, 15:53 |
|
||
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
ШыфлИ ещё вопрос, в догонку. Вот такую конструкцию Код: vbnet 1. 2. 3. 4. 5. 6. Можно ли её запихнуть в генератор, если NextNumId(6) - это функция генерации первичного ключа на таблице 6("СчетаДанные"), которая вызывает что-то вроде Код: vbnet 1. 2. 3. Можно ли переделать стандартный генератор под этот код?Простите, но такая реализация счетчика, IMHO, просто за гранью добра и зла. Боюсь, что переделывать надо всё, кардинально, подобными правками вы только усложняете жизнь. И хорошо, если только себе. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.11.2015, 16:18 |
|
||
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
ChAПростите, но такая реализация счетчика, IMHO, просто за гранью добра и зла. Боюсь, что переделывать надо всё, кардинально, подобными правками вы только усложняете жизнь. И хорошо, если только себе. Что ж вы так обычного генератора испугались? Да, не самое изящное решение для синхронизации данных по филиалам, зато простое и надёжное. Теоретический лимит Id в 100 миллионов записей за десять лет использовался на 0,001 процент, так что переполнение не грозит. И отчёты генерировать удобно. Зачем это переделывать? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.11.2015, 14:39 |
|
||
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
есть опыт подключения базы pg к access (базы обменивались данными). Извращение, конечно, но проект решал свои задачи. Так вот вопрос: что мешает использовать DAO и ADO? Для access таблиц-DAO. Для pg -только запросы к серверу, а все изменения через ADO + процедуры. Процедуры в pg отличные-все в рамках транзакции-можно забыть про commit (иногда просто печаль как надо, но, увы). Если хотите пользоваться серверными таблицами как локальными или связанными - тогда лучше использовать сервер MSSQL. Он в связке с access прекрасно работает. Можно переносить проект по частям и не спеша. Можно поюзать бесплатную версию MSSQL ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.11.2015, 18:28 |
|
||
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
ШыфлChAПростите, но такая реализация счетчика, IMHO, просто за гранью добра и зла. Боюсь, что переделывать надо всё, кардинально, подобными правками вы только усложняете жизнь. И хорошо, если только себе. Что ж вы так обычного генератора испугались? Да, не самое изящное решение для синхронизации данных по филиалам, зато простое и надёжное. Теоретический лимит Id в 100 миллионов записей за десять лет использовался на 0,001 процент, так что переполнение не грозит. И отчёты генерировать удобно. Зачем это переделывать? простое, но надежное ровно до первого одновременного получения нового значения из 2-х мест. Таки конечно рано или поздно ВСЕ переделывать придется. Может лучше рано? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.11.2015, 09:06 |
|
||
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
Ivan Durakпростое, но надежное ровно до первого одновременного получения нового значения из 2-х мест. Таки конечно рано или поздно ВСЕ переделывать придется. Может лучше рано? Одновременное получение из двух мест вызовет ошибку и откат транзакции, придётся нажать ещё раз. Ошибка перехватывается, при желании... Ничего криминального. Переделывать ВСЁ - это не конструктивно, и не выгодно экономически, нового функционала же не прибавится - какой в этом смысл с точки зрения клиентов-начальника? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.11.2015, 22:10 |
|
||
|
DAO транзакция - теряются
|
|||
|---|---|---|---|
|
#18+
ШыфлIvan Durakпростое, но надежное ровно до первого одновременного получения нового значения из 2-х мест. Таки конечно рано или поздно ВСЕ переделывать придется. Может лучше рано? Одновременное получение из двух мест вызовет ошибку и откат транзакции, придётся нажать ещё раз. Ошибка перехватывается, при желании... Ничего криминального. Переделывать ВСЁ - это не конструктивно, и не выгодно экономически, нового функционала же не прибавится - какой в этом смысл с точки зрения клиентов-начальника? так и на пг переводить незачем - нового функционала ж не прибавиться. Просто в один день работать уже не сможет и все... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.11.2015, 01:11 |
|
||
|
|

start [/forum/topic.php?fid=53&msg=39093347&tid=1997649]: |
0ms |
get settings: |
10ms |
get forum list: |
14ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
25ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
61ms |
get tp. blocked users: |
1ms |
| others: | 243ms |
| total: | 372ms |

| 0 / 0 |
