генератор в readonly транзакции

IBX, FIBPlus, UIB, ADO, .Net и прочее-прочее-прочее, в общем все, что относится к созданию приложений, работающих с InterBase, Firebird и Yaffil - клиент-серверных, трехзвенных, консольных и т.п.

Модератор: kdv

Ответить
Игорь Клопов
Сообщения: 5
Зарегистрирован: 10 ноя 2005, 16:00

генератор в readonly транзакции

Сообщение Игорь Клопов » 12 ноя 2005, 21:36

Здравствуйте. Прошу помочь мне решить проблему.
Иногда неправильно срабатывает генератор (для первичного ключа) в контексте readonly транзакции - возвращает увеличенное значение, а в базе остается прежним. Из-за этого следующее значение генератора оказывается таким-же, и вставка в таблицу происходит с Unique Key Violation.

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 12 ноя 2005, 21:42

Похоже, требование называть версию сервера пора вставить неотъемлемой частью шаблона для новых сообщений.

Чрезвычайно маловероятно. Больше похоже на старый-престарый баг с несбросом вовремя страниц генераторов на диск и потерей изменённых значений при краше сервера, исправленный в FB1.5.x, каким был икс - не помню.

Игорь Клопов
Сообщения: 5
Зарегистрирован: 10 ноя 2005, 16:00

Сообщение Игорь Клопов » 12 ноя 2005, 21:44

Пишу вызывая API-функции Firebird. Транцакция с хэндлом FReadTranHandle имеет TPB:

Код: Выделить всё

  GTPBRead: string = Char(isc_tpb_version3) + Char(isc_tpb_read) +
    Char(isc_tpb_read_committed) + Char(isc_tpb_rec_version) + Char(isc_tpb_wait);
собственно код (в незначительных сокращениях):

Код: Выделить всё

  GetMem(isqlda, XSQLDA_LENGTH(0));
  FillChar(isqlda^, XSQLDA_LENGTH(0), 0);
  isqlda^.version := SQLDA_VERSION1;
  isqlda^.sqln := 0; isqlda^.sqld := 0;
  GetMem(osqlda, XSQLDA_LENGTH(1));
  FillChar(osqlda^, XSQLDA_LENGTH(1), 0);
  osqlda^.version := SQLDA_VERSION1;
  osqlda^.sqln := 1; osqlda^.sqld := 1;
  with PXSQLVARArray(@osqlda^.sqlvar)^[0] do begin sqltype := SQL_LONG;
    sqldata := PChar(@FID); sqlind := @zero; end;
  isc_dsql_alloc_statement2(@status_vector, @FDatabaseHandle, @stmt_handle);
  isc_dsql_prepare(@status_vector, @FReadTranHandle, @stmt_handle, 0,
    PChar('select FID from GPICTUREVOTE_GENID'), SQL_DIALECT_V6, osqlda);
  isc_dsql_execute2(@status_vector, @FReadTranHandle, @stmt_handle, SQL_DIALECT_V6, isqlda, osqlda);
  isc_dsql_free_statement(@status_vector, @stmt_handle, DSQL_drop);
  FreeMem(isqlda, XSQLDA_LENGTH(isqlda^.sqln));
  FreeMem(osqlda, XSQLDA_LENGTH(osqlda^.sqln));
Процедура:

Код: Выделить всё

  CREATE PROCEDURE GPICTUREVOTE_GENID 
  RETURNS (
      FID INTEGER)
  AS
  begin
    FID = gen_id(GPICTUREVOTE_ID, 1);
    suspend;
  end
Сервер - CeleronD 2500, 512MB ОЗУ, SATA 80Gb, WIN2000 Professional SP4, Firebird 1.0.2.908

Заранее большое спасибо!

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 17 ноя 2005, 20:42

вопрос - зачем дергать генератор в read-only транзакции?

p.s. также вопрос, не тяготит ли Firebird 1.02 при наличии более свежих версий, а также зачем использовать процедуру для генератора.

Игорь Клопов
Сообщения: 5
Зарегистрирован: 10 ноя 2005, 16:00

Сообщение Игорь Клопов » 17 ноя 2005, 20:58

read транзакция меньше загружает сервер, чем write - а fb позволяет двигать генераторы в контексте read (недокументировано, но ведь у меня он движется!). версию сменил на 1.0.3. процедура - как обертка для gen_id (в свое время она делала нечто большее, но теперь gen_id - все что от нее осталось) - думаю не важно в каком виде исполняется gen_id, но будет время - перепишу этот момент.
а что до ошибки - то я немного разобрался. иногда после корректного останова и запуска службы FBServer некоторые генераторы оказываются меньше ("падают") на некоторые значения. и здесь уже другой вопрос - может ли сервер "не успеть" записать страницу генераторов в случае
1) остановки службы firebird
2) abnormal termination
3) обрыва клиентских соединений. и самое главное:
4) потери handle-ов к базе и завершения приложения без isc_detach_database???
база forced writes!
вот в чем дилема :))) поможите кто можите :)
P.S. или все-таки нужна write транзакция для генератора?
P.P.S. или вообще перейти на FB1.5, как посоветовал merlin ^^^ говорит это баг

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 17 ноя 2005, 21:16

Игорь Клопов писал(а): а что до ошибки - то я немного разобрался. иногда после корректного останова и запуска службы FBServer некоторые генераторы оказываются меньше ("падают") на некоторые значения. и здесь уже другой вопрос - может ли сервер "не успеть" записать страницу генераторов в случае
1) остановки службы firebird
Затрудняюсь сказать. Смотря что считать нормальной остановкой. Да и при ней недавно что-то опять правили в супере, не с генераторами, но всё же.
Игорь Клопов писал(а): 2) abnormal termination
FB1.x - однозначно да.
Игорь Клопов писал(а): 3) обрыва клиентских соединений. и самое главное:
4) потери handle-ов к базе и завершения приложения без isc_detach_database???
Не наблюдалось.
Игорь Клопов писал(а): база forced writes!
Не имеет значения. FW - указание оси что делать со сбрасываемыми страницами, а не FB.
Игорь Клопов писал(а): P.S. или все-таки нужна write транзакция для генератора?
Нет.

Игорь Клопов
Сообщения: 5
Зарегистрирован: 10 ноя 2005, 16:00

Сообщение Игорь Клопов » 17 ноя 2005, 21:18

ааааааа Володя я Володя. точно. вижу

3) Generator pages were not flushed properly, causing generator value changes to be lost after a
server failure, even in Forced Writes mode
(Oleg Loa, Vlad Horsun, Dmitry Yemanov)

в http://www.ibase.ru/firebird/fb_1_51_releasenotes.pdf

все спасибо большое. перейду на 1.5
P.S. блин, сервер падает. надо срочно принять меры

Ответить