Mam bazę danych, którą "wypuszczam" co tydzień, co oznacza, że publikuję kopię zapasową, z której mogą zacząć korzystać, i opublikuję skrypt aktualizacyjny, którego mogą użyć do aktualizacji z zeszłego tygodnia (aby mogli zachować swoje bieżące dane, tak bardzo, jak to możliwe). Ten skrypt oczywiście zawiera wiele DDL-CREATE TABLE
, ALTER TABLE
i tak dalej. Podstawowa struktura to jest tak:Czy instrukcje CREATE TABLE w SQL Server są odporne na ROLLBACK?
/*
HOW TO USE THIS SCRIPT
1. Run it against your existing DB
2. Check whether there were any errors
3. If there were, issue a rollback by highlighting this:
ROLLBACK
and executing it
4. If there weren't, issue a commit by highlighting this:
COMMIT
and executing it
5. !!! Not doing either of these will leave a transaction open, which will
probably cause all further queries to time out till you do !!!
*/
SET XACT_ABORT ON;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
GO
-- Boilerplate checking and whatnot goes here
GO
-- Guts of operation, part 1
GO
-- Guts of operation, part 2
GO
-- Guts of operation, part 3
GO
-- . . .
GO
-- Guts of operation, part N
GO
-- Boilerplate cleanup stuff here
GO
Będziesz pamiętać, że pozostawił otwartą transakcję i powiedział im, aby radzić sobie z jej ukończeniu ręcznie, w zależności od tego, co się stało. Wolałbym, żeby to było automatyczne, ale rozpaczam o tym, biorąc pod uwagę, że całość to zawsze długa seria kilku partii, a bloki TRY
nie mogą oczywiście obejmować partii. Tak więc ostatnie dodanie SET XACT_ABORT ON;
w celu złagodzenia bólu nieznacznie. Niezależnie od tego, próbowałem tego sam, ponieważ bez niego i nie ma znaczenia dla scenariusza. Tak czy inaczej.
Ostatnio jeden z tych skryptów posiadał instrukcje do tworzenia tabel i innych instrukcji w celu dodania ograniczeń sprawdzających do istniejących tabel. Jeden z moich użytkowników uruchomił skrypt i wystąpił błąd związany z ograniczeniem; Okazuje się, że posiadał wcześniej istniejące dane, które naruszały ograniczenia. OK, nie ma problemu, zrób ROLLBACK
. Racja, nie musiał tego robić, XACT_ABORT
już to zrobił. Idź i popraw wiersze danych ... gotowe. Teraz, aby spróbować ponownie! Uhp ... co? Tym razem nie ma błędu ograniczenia, ale powoduje to błąd w instrukcjach CREATE TABLE
, mówiąc, że tabele już istnieją ...! Huh? Czy to się nie wycofało?
Zakończyliśmy przywracanie z kopii zapasowej i ponowne ustalanie danych i ponowne uruchamianie. Ale to nie jest ani tu, ani tam.
Drodzy czytelnicy: W jaki sposób tworzenie tych tabel przetrwało wycofanie transakcji? Jak mogę je wyeliminować?
EDYCJA: OK, oto przykład, który można uruchomić.
USE tempdb;
GO
CREATE DATABASE example;
GO
USE example;
GO
CREATE TABLE foo (a INT);
GO
INSERT INTO foo
VALUES (100);
GO
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
GO
ALTER TABLE foo ADD CHECK (a < 10);-- Gives error "The ALTER TABLE statement conflicted with the CHECK constraint…", as expected
GO
CREATE TABLE bar (b INT);
GO
ROLLBACK;-- Gives error "The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION." Huh? Where did our transaction go?
GO
SELECT *
FROM bar;-- Gives no error. Table still exists! NOT expected!
GO
USE tempdb;
GO
DROP DATABASE example;
Nie. Nie są odporne na wycofywanie, trudno się domyślić, co stało się w twoim przypadku z opisu. –
Spróbuj znaleźć najprostszy sposób, w jaki można odtworzyć problem. To pomogłoby nam przeanalizować problem. – Andomar