2009-09-09 2 views
4

У меня есть хранимая процедура T-SQL, работающая на сервере базы данных Sybase ASE, которая иногда не выполняет все свои операции, даже если она завершена без исключения. Вот пример того, что он делает.транзакция базы данных только частично совершает

BEGIN TRANSACTION 

UPDATE TABLE1 
SET FIELD1 = @NEW_VALUE1 
WHERE KEY1 = @KEY_VALUE1 

IF @@error <> 0 OR @@rowcount <> 1 BEGIN 
    ROLLBACK 
    RETURN 1 
END 

UPDATE TABLE2 
SET FIELD2 = @NEW_VALUE2 
WHERE KEY2 = @KEY_VALUE2 

IF @@error <> 0 OR @@rowcount <> 1 BEGIN 
    ROLLBACK 
    RETURN 2 
END 

INSERT TABLE2 (FIELD2, FIELD3) 
VALUES (@NEW_VALUE3a, @NEW_VALUE3b) 

IF @@error <> 0 OR @@rowcount <> 1 BEGIN 
    ROLLBACK 
    RETURN 3 
END 

COMMIT TRANSACTION 
RETURN 0 

Процедура называется по меньшей мере сотни раз в день. В небольшом проценте случаев (вероятно, < 3%), завершается только заявление INSERT. Процесс завершает и возвращает 0, но два UPDATE s не принимают. Изначально мы думали, что статьи WHERE на UPDATE s не соответствуют друг другу, поэтому мы добавили логику IF @@rowcount. Но даже с теми проверками там INSERT все еще происходит, и процедура по-прежнему завершается и возвращается 0.

Я ищу идеи о том, что может вызвать эту проблему. Есть ли что-нибудь о том, как работают транзакции SQL или как работает Sybase, что может привести к тому, что COMMIT не будет выполнять все? Есть ли что-то в моих блоках IF, которые могут позволить UPDATE не соответствовать чему-либо, кроме процедуры продолжить? Любые другие идеи?

+0

У вас есть _IF @Error <> 0_ два раза, что должно быть _IF @@ ERROR <> 0_, но это скорее всего тип 0 в вашем примере кода –

+0

@KM, спасибо, я исправил пример , Фактический код имеет @@ s. –

ответ

1

Возможно, что они обновляются, но что-то меняет значения обратно? попробуйте добавить триггер обновления в эти таблицы и внутри этого триггера вставить в таблицу журналов. для строк, которые, как представляется, не были обновлены, смотрите в журнале, есть ли строка или нет?

+0

Вот и все! Я искал проблему с базой данных, но на самом деле это проблема приложения. В логике приложения есть ошибка, которая позволяет пользователю открывать одну и ту же запись дважды и сохранять ее двумя разными способами, эффективно отменяя обновления (но оставляя вставку) из первого сохранения. Это происходит не часто, потому что для пользователя не имеет никакого смысла использовать приложение таким образом. Но пользователи не всегда имеют смысл, поэтому мне нужно подключить отверстие и убедиться, что рабочий процесс усложняет им работу. Благодаря! –

+0

, если это устаревшая вещь, в которой два экрана открыты, а первая сохраняется, а вторая сохраняется (удаление первых данных), вы можете использовать LastChgDate для предотвращения проблемы. Когда вы загружаете данные, загружайте LastChgDate, когда вы сохраняете, передаете его и в UPDATE добавьте _AND LastChgDate = @ LastChgDate_. Если @@ ROWCOUNT = 0 выдает сообщение об ошибке, что «кто-то еще только что сохранил данные перед вами» –

1

Не зная, как вы устанавливаете значения для своих переменных, мне приходит в голову, что если значение @ NEW_VALUE1 совпадает с предыдущим значением в FIELD1, обновление будет успешным и, по-видимому, ничего не изменит, что сделало бы вас подумайте, что сделка не состоялась.

У вас также может быть триггер, который влияет на обновление.

+0

Спасибо. Я, к сожалению, не мог дать много фактических подробностей, что затрудняет дать конкретный ответ. Я не упоминал об этом в вопросе, но у меня есть данные журнала приложений, в которых указаны детали хранимого вызова proc, и я подтвердил, что значения @ NEW_VALUE1 и @ KEY_VALUE1 являются ожидаемыми (и не идентичными) , –

+0

Я не думал о спусковом крючке. Sybase (по крайней мере, версия, в которой мы находимся) не имеет триггеров перед триггером, поэтому триггер не может ее предотвратить, но возможно, что триггер UPDATE может изменить его. Я проверю это. –

+0

Нет, никаких триггеров на этой таблице нет. –

Смежные вопросы