Korzystanie z bazy danych/sql i pakietów sterowników i Tx, nie jest możliwe, aby wykryć, czy transakcja została zatwierdzona lub wycofana bez próby kolejnego i otrzymania błędu jako wynik, a następnie przeanalizowanie błędu w celu określenia typu błędu. Chciałbym móc określić z obiektu Tx, czy został popełniony, czy nie. Oczywiście, mogę zdefiniować i ustawić inną zmienną w funkcji, która używa Tx, ale mam ich całkiem sporo i za każdym razem jest to 2 razy (zmienna i przypisanie). Mam również funkcję odroczoną, aby wykonać Cofanie, jeśli jest to konieczne, i musi zostać przekazana zmienna bool.
Czy można zaakceptować ustawienie zmiennej Tx na zero po zatwierdzeniu lub wycofaniu i czy GC odzyska jakąkolwiek pamięć, czy jest to nie-nie, czy istnieje lepsza alternatywa?database/sql Tx - wykrywanie Commit lub Rollback
Odpowiedz
Dlaczego miałbyś to zrobić? Funkcja wywołująca Begin()
powinna również wywoływać Commit()
lub Rollback()
i zwracać odpowiedni błąd.
Na przykład ten kod robi commit lub rollback w zależności od tego, czy zwracany jest błąd:
func (s Service) DoSomething() (err error) {
tx, err := s.db.Begin()
if err != nil {
return
}
defer func() {
if err != nil {
tx.Rollback()
return
}
err = tx.Commit()
}()
if _, err = tx.Exec(...); err != nil {
return
}
if _, err = tx.Exec(...); err != nil {
return
}
// ...
return
}
zauważyć, jak ja sprawdzanie error
, aby zobaczyć, czy nie powinienem popełnić lub wycofania. Powyższy przykład nie obsługuje jednak paniki.
Nie lubię robić logiki commit/rollback w każdej procedurze bazy danych, więc zwykle pakuję je w procedurę obsługi transakcji. Coś wzdłuż linii to:
func Transact(db *sql.DB, txFunc func(*sql.Tx) error) (err error) {
tx, err := db.Begin()
if err != nil {
return
}
defer func() {
if p := recover(); p != nil {
tx.Rollback()
panic(p) // re-throw panic after Rollback
} else if err != nil {
tx.Rollback()
} else {
err = tx.Commit()
}
}()
err = txFunc(tx)
return err
}
Pozwala mi to zrobić w zamian:
func (s Service) DoSomething() error {
return Transact(s.db, func (tx *sql.Tx) error {
if _, err := tx.Exec(...); err != nil {
return err
}
if _, err := tx.Exec(...); err != nil {
return err
}
})
}
Zauważ, że jeśli coś w moim transakcji panikuje ona automatycznie obsługiwane przez procedurę obsługi transakcji.
W mojej aktualnej implementacji przekazuję interfejs zamiast * sql.Tx, aby zapobiec niechcianym połączeniom do Commit()
lub Rollback()
.
Oto prosty fragment wykazać jak defer
prace (Wydruki 4, a nie 5):
package main
func test() (i int) {
defer func() {
i = 4
}()
return 5
}
func main() {
println(test())
}
dobra odpowiedź! Myślę, że brakowało ci "powrotu zero" pod koniec twojej drugiej implementacji doSomething(). – splinter123
Luke, jak i kiedy błędy są oceniane? Zgodnie z dokumentacją, "err" powinien uzyskać wartość, gdy zostanie po raz pierwszy zadeklarowany w wywołaniu odroczonym.Tak więc jest to dla mnie nieco mylące, ponieważ wartość "err" użyta w odroczeniu wydaje się zmieniać. – mirage
err jest zadeklarowane przed odroczeniem przez: = (dwukropek równy). Anon func przechwytuje to. Defer jest wywoływany tuż przed zwróceniem wartości. To pozwala na ustawienie. Kiedy pojawia się panika, jest odzyskiwana, zamieniana na błąd, a następnie zwracana. Jeśli błąd wystąpi w jakikolwiek sposób, nastąpi wycofanie. W końcu następuje zatwierdzenie, jeśli nie ma błędów, a wartość err (obecnie zero) jest ustawiona na wartość zwracaną Commit w przypadku wystąpienia błędów. – Luke
- 1. . NET TransactionScope i T-SQL TRAN COMMIT i ROLLBACK
- 2. transakcja count po EXECUTE wskazuje, że COMMIT lub ROLLBACK TRANSAKCJI oświadczenie brakuje - serwer SQL 2005
- 3. JMS rollback
- 4. Transakcje rollback z TABLAMAMI ZABLOKOWANIA
- 5. PDO :: commit() sukces lub niepowodzenie
- 6. Kliknij raz rollback aplikacji
- 7. Różnica między tx i rx?
- 8. Xcode commit brakuje pliku lub katalogu
- 9. Wykrywanie środowiska: node.js lub przeglądarka
- 10. Wykrywanie systemu Windows lub Linux?
- 11. Wykrywanie nastrój tweet lub wiadomości
- 12. python opencv - wykrywanie obiektów typu blob lub wykrywanie kolejek
- 13. Dwufazowy commit
- 14. Sprężyna "Prefiks" tx "dla elementu" tx: adnotacja sterowana "nie jest powiązany."
- 15. Używanie tx: adnotacja sterowana zapobiega Autowiring fasoli
- 16. Testrpc: TX nie ma prawidłowego nonce
- 17. TFS seryjnej nie odebrać changeset rollback (y)
- 18. Mercurial: jak cofnąć ostatnie zanurzenie commit?
- 19. Spring TransactionManager - commit nie działa
- 20. Wykrywanie jeśli tablica jest indeksowane lub asocjacyjne
- 21. Wykrywanie lub reagowanie na dostęp z przewodnikiem?
- 22. Wykrywanie wejścia na QLineEdit lub QPushButton
- 23. Wykrywanie otwarcia lub zamknięcia elementu szczegółów
- 24. Wykrywanie, czy _ jest domieszką lub podkreślnikiem
- 25. iOS Wykrywanie szybkości połączenia lub rodzaj
- 26. Wykrywanie puszki lub butelki w opencv
- 27. git find fat commit
- 28. Jak grep Git commit diffs lub content dla określonego słowa?
- 29. git commit auto dodaje nowe foldery lub pliki?
- 30. Czy dwufazowy Commit Protect chroni przed końcowymi awariami Commit?
Nie jestem pewien, czy rozumiem problemu. Musisz zakończyć transakcję za pomocą Commit lub Rollback, aby wiedzieć, co zrobiłeś, ale nie chcesz tego pamiętać w dodatkowej zmiennej? Możesz owinąć Tx i bool we własny RememberingTx, co zmniejszy nieco liczbę linii. W odniesieniu do pytania GC: Nie ma znaczenia, czy ustawiłeś zero, czy nie: pamięć zostanie odzyskana, gdy nie pozostanie do niej żadne odniesienie. Tak: Tak, możesz mieć 'var tx * Tx; fantastyczna okazja; if cond {tx.Commit; tx = nil} else {tx.Rollback}; fantastyczna okazja; if tx == nil {was commited} else {was rollbacked} 'ale czuje się brzydko. – Volker
To o to chodzi, ale istnieje odroczony func, który wykonuje rollback, jeśli Tx nie jest zerowe. Po zatwierdzeniu transakcji, Tx i tak nie może być użyty, więc planuję ustawić go na zero. To nie jest ładne, jednak próba wycofania i testowanie komunikatu o błędzie nie jest ładna. Problem polega na tym, że AFAIK nie ma możliwości sprawdzenia, czy transakcja jest "wykonana" od Tx. Nie jestem pewien, dlaczego tak się stało, być może wydajność. –