Sử dụng cơ sở dữ liệu/sql và gói trình điều khiển và Tx, nó không thể xuất hiện để phát hiện xem giao dịch đã được cam kết hay cuộn lại mà không thử một giao dịch khác và nhận lỗi và sau đó kiểm tra lỗi để xác định loại lỗi. Tôi muốn có thể xác định từ đối tượng Tx dù có cam kết hay không. Chắc chắn, tôi có thể xác định và thiết lập một biến khác trong hàm sử dụng Tx, nhưng tôi có khá nhiều biến, và đó là lần 2 mỗi lần (biến và gán). Tôi cũng có một chức năng trì hoãn để thực hiện một Rollback nếu cần, và nó cần phải được chuyển qua biến bool.
Có thể chấp nhận để đặt biến Tx thành không sau một Cam kết hoặc Rollback, và GC sẽ phục hồi bất kỳ bộ nhớ nào, hoặc là không có, hoặc là có một lựa chọn tốt hơn?cơ sở dữ liệu/sql Tx - phát hiện Cam kết hoặc Rollback
Trả lời
Tại sao bạn thậm chí cần thực hiện việc này? Chức năng gọi Begin()
cũng phải gọi số Commit()
hoặc Rollback()
và trả lại lỗi thích hợp.
Ví dụ, đoạn mã này thực hiện một cam kết hoặc rollback tuỳ thuộc vào việc một lỗi được trả về:
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
}
Chú ý làm thế nào tôi đang kiểm tra error
để xem có hay không tôi nên cam kết hoặc rollback. Ví dụ trên không, tuy nhiên, xử lý các vấn đề.
Tôi không thích thực hiện logic cam kết/rollback trên mọi thường trình cơ sở dữ liệu, vì vậy tôi thường quấn chúng trong trình xử lý giao dịch. Một cái gì đó dọc theo dòng này:
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
}
Điều này cho phép tôi làm điều này thay vì:
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
}
})
}
Chú ý rằng nếu bất cứ điều gì bên trong giao dịch của tôi hoảng sợ nó tự động xử lý bởi bộ xử lý giao dịch.
Khi triển khai thực tế, tôi chuyển giao diện thay vì * sql.Tx để ngăn các cuộc gọi không mong muốn đến Commit()
hoặc Rollback()
.
Dưới đây là một đoạn mã đơn giản để chứng minh như thế nào defer
công trình (in 4, không phải 5):
package main
func test() (i int) {
defer func() {
i = 4
}()
return 5
}
func main() {
println(test())
}
câu trả lời hay! Tôi nghĩ rằng bạn đã bỏ lỡ một "trở lại nil" vào cuối thực hiện doSomething() thứ hai của bạn. – splinter123
Luke, làm thế nào và khi nào sai được đánh giá? Theo tài liệu, "err" sẽ nhận được giá trị của nó khi nó được khai báo lần đầu tiên trong cuộc gọi trì hoãn.Vì vậy, điều này thực sự là một chút bối rối đối với tôi, kể từ khi giá trị cho "err", như được sử dụng trong trì hoãn, dường như thay đổi. – mirage
err được khai báo trước khi trì hoãn thông qua: = (dấu hai chấm bằng nhau). Anon func bắt giữ nó. Trì hoãn được gọi ngay trước khi giá trị được trả về. Điều đó cho phép nó được thiết lập. Khi một hoảng sợ xảy ra nó được phục hồi, biến thành một lỗi, sau đó quay trở lại. Nếu một lỗi xảy ra theo bất kỳ cách nào xảy ra thì cuộn ngược lại xảy ra. Cuối cùng, một cam kết sẽ xảy ra nếu không có lỗi và err (hiện tại nil) được đặt thành Cam kết trả về giá trị trong trường hợp lỗi. – Luke
- 1. Rollback để git cam kết cuối cùng
- 2. rollpoint cam kết rollback trong mysql
- 3. Tôi có nên rollback không thành công câu lệnh SELECT hoặc cam kết thành công?
- 4. Bảng xóa MySQL - Cơ sở dữ liệu hiện tại hoặc mọi cơ sở dữ liệu?
- 5. Mongoose phát hiện cơ sở dữ liệu chưa sẵn sàng
- 6. Di chuyển cơ sở dữ liệu MySQL phát triển sang cơ sở dữ liệu sản xuất
- 7. mangento trong cơ sở dữ liệu hoặc cơ sở oracle?
- 8. Cơ sở dữ liệu Azure SQL có hỗ trợ cam kết hai pha (2PC) không?
- 9. giao dịch rollback nếu cam kết lợi nhuận lỗi
- 10. Hoàn toàn xóa cam kết khỏi cơ sở dữ liệu git
- 11. Tệp cơ sở dữ liệu bị khóa không thể giải thích được trong khi thực hiện SQLite cam kết
- 12. Cơ sở dữ liệu và kết nối
- 13. Java, cách thay đổi cơ sở dữ liệu hiện tại sang cơ sở dữ liệu khác?
- 14. Liên kết cơ sở dữ liệu Oracle
- 15. Bảng cơ sở dữ liệu hoặc XML
- 16. triển khai cơ sở dữ liệu python
- 17. Kết hợp nhiều cơ sở dữ liệu vào một cơ sở dữ liệu đơn
- 18. Thực hiện giao dịch qua nhiều cơ sở dữ liệu
- 19. Người dùng Oracle bị ngắt kết nối mà không cam kết/quay lại, không còn có thể thay đổi cơ sở dữ liệu
- 20. Xếp hàng bằng Cơ sở dữ liệu hoặc MSMQ?
- 21. Máy phát thực thể từ cơ sở dữ liệu
- 22. Làm thế nào để git cam kết --amend một cam kết đó là cơ sở của một chi nhánh
- 23. Theo dõi xuống kết nối cơ sở dữ liệu phát hành
- 24. Phát triển nhanh và thay đổi cơ sở dữ liệu
- 25. Giữ mở một kết nối cơ sở dữ liệu MongoDB
- 26. Điều kiện kết nối với cơ sở dữ liệu
- 27. Hồ bơi kết nối cơ sở dữ liệu JBoss
- 28. Cơ sở dữ liệu sản xuất và phát triển?
- 29. PostgreSQL: Xem quyền kết nối cơ sở dữ liệu
- 30. Kết nối cơ sở dữ liệu CodeIgniter không được đóng
Không chắc nếu tôi hiểu được vấn đề. Bạn phải kết thúc một giao dịch với Commit hoặc Rollback để bạn biết bạn đã làm gì nhưng bạn không muốn nhớ điều này trong một biến phụ? Bạn có thể quấn Tx và bool trong RememberingTx của riêng bạn, điều này sẽ làm giảm số lượng dòng một chút. Về câu hỏi GC: Không quan trọng nếu bạn đặt thành 0 hoặc không: Bộ nhớ sẽ được xác nhận lại khi không có tham chiếu nào được để lại. Vì vậy: Có, bạn có thể có 'var tx * Tx; snip; nếu cond {tx.Commit; tx = nil} else {tx.Rollback}; snip; nếu tx == nil {được commit} else {was rollbacked} 'nhưng nó cảm thấy xấu xí. – Volker
Đó là loại của nó về, nhưng có một func hoãn lại mà không một rollback nếu Tx không phải là không. Khi một giao dịch được cam kết, Tx không thể được sử dụng anyway, vì vậy tôi có kế hoạch để thiết lập nó để nil. Nó không phải là khá, tuy nhiên cố gắng một rollback và thử nghiệm các thông báo lỗi không phải là khá hoặc. Vấn đề là AFAIK không có cách nào để kiểm tra xem giao dịch có được thực hiện từ Tx hay không. Tôi không chắc tại sao nó lại được thực hiện theo cách đó, có lẽ là hiệu suất. –