2014-09-09 19 views
9

Tôi đang gặp rắc rối với SQLite ném một cờ lê trong máy móc của tôi khi tôi gọi cơ sở dữ liệu viết vào cùng thời điểm chính xác như đã đọc. Điều này xảy ra khi các phương pháp khác nhau xảy ra để cố gắng truy cập cơ sở dữ liệu tại cùng một thời điểm chính xác.golang kết nối cơ sở dữ liệu sqlite pooling

Điều tôi đang làm tương tự với những gì đang được thực hiện trong this thread, câu trả lời được chấp nhận giải thích cách sử dụng các giao dịch cơ sở dữ liệu để tránh các khóa cơ sở dữ liệu.

Dưới đây là một số mã của tôi:

stmt, err := dbtx.Prepare(`statement`) 
if err != nil { 
    log.Fatal(err) 
} 

_, err = stmt.Exec(values, values, values) 
if err != nil {   
    log.Fatal(err) 
} 

err = dbtx.Commit() 
if err != nil { 
    fmt.Println("database lock?") 
    fmt.Println(err) 
    dbtx.Rollback() 
} 

fmt.Println("Database storage complete!") 

Điều khó hiểu là chương trình tồn tại sau khi xuất ra này:

database lock? 
database is locked 
Database storage complete! 
2014/09/09 18:33:11 database is locked 
exit status 1 

Tôi không muốn chương trình của tôi để ngăn chặn trên một khóa cơ sở dữ liệu, Tôi muốn nó lưu trữ dữ liệu trong bộ nhớ và tiếp tục kinh doanh cho đến khi cơ sở dữ liệu được mở khóa và tôi có thể thử lại.

Có cách nào tiêu chuẩn tôi có thể đạt được điều này, có thể là một hàng đợi hoặc cấu trúc dữ liệu của một số loại hoặc có cách cụ thể về cơ sở dữ liệu để giải quyết vấn đề này?

Tại sao chương trình thoát sau khi xuất ra Database storage complete!?

Edit:

Tôi tin rằng tôi đã khắc phục các vấn đề, nhưng tôi không thể chắc chắn. Tôi đang sử dụng goroutines và một kết nối DB trọn gói. Trước đây, mỗi func trong mã của tôi đã khởi tạo một kết nối cơ sở dữ liệu khi nó được gọi. Bây giờ, tôi có một biến "toàn cầu" cho kết nối DB được định nghĩa ở đầu gói và được khởi tạo trước khi bất kỳ thường trình nào bắt đầu. Dưới đây là mã trong một nutshell:

var nDB *sql.DB 

Sau đó trong func chính ...

mypkg.InitDB() 
go mypkg.RunDatabaseOperations() 
mypkg.BeginHTTPWatcher(rtr) 

InitDB() được định nghĩa như sau:

func InitDB() { 
    fmt.Println("Init DB ...") 
    var err error 
    nDB, err = sql.Open("sqlite3", "./first.db") 
    if err != nil { 
     log.Fatal(err) 
    } 
    if nDB == nil { 
     log.Fatal(err) 
    } 
    fmt.Printf("nDB: %v\n", ODB) 
    fmt.Println("testing db connection...") 
    err2 := nDB.Ping() 
    if err2 != nil { 
     log.Fatalf("Error on opening database connection: %s", err2.Error()) 
    } 
} 

Vì vậy, RunDatabaseOperations quét tài nguyên trực tuyến cho dữ liệu định kỳ và lưu trữ nó vào cơ sở dữ liệu khi có thay đổi (cứ sau vài giây). BeginHTTPWatcher lắng nghe các yêu cầu HTTP để dữ liệu có thể được đọc từ chương trình đang chạy và truyền qua dây tới người yêu cầu dữ liệu, cho dù đó là yêu cầu địa phương hay bên ngoài. Tôi chưa có vấn đề gì.

+1

'2014/09/09 18:33:11 cơ sở dữ liệu bị khóa' trông giống như công việc' log.Fatal (err) '. Bạn có thể cung cấp thêm thông tin, để làm mẫu thử không? Nhà cung cấp sqlite nào bạn sử dụng? – RoninDev

+1

Tôi đang sử dụng 'github.com/mattn/go-sqlite3' – bvpx

+0

Có vẻ như vấn đề đồng thời ... bạn có đang chạy mã này đồng thời không? Nếu có, vui lòng đăng thêm mã của bạn để chúng tôi có thể xem điều gì đang diễn ra. –

Trả lời

7

Các documentation nói:

Một ví dụ kết nối duy nhất và tất cả các đối tượng có nguồn gốc của nó (báo cáo chuẩn bị, hoạt động sao lưu, vv) có thể KHÔNG được sử dụng đồng thời từ nhiều goroutines mà không cần đồng bộ hóa bên ngoài.

(Đây là một trình điều khiển SQLite khác nhau, nhưng hạn chế này cũng áp dụng cho bạn.)

Khi bạn đang sử dụng goroutines, bạn phải sử dụng các kết nối cơ sở dữ liệu riêng biệt.

Theo mặc định, SQLite sẽ hủy ngay lập tức khi nó gặp một cơ sở dữ liệu bị khóa bởi giao dịch khác. Để cho phép đồng thời nhiều hơn, bạn có thể yêu cầu nó chờ giao dịch khác kết thúc bằng cách đặt thời gian chờ bận.

Sử dụng chức năng BusyTimeout, nếu trình điều khiển SQLite của bạn có hoặc thực hiện lệnh trực tiếp PRAGMA busy_timeout SQL.

0

Vui lòng đăng thêm mã của bạn để chúng tôi có thể hiểu rõ hơn về những gì đang diễn ra.

Tuy nhiên, đây là một vài suy nghĩ. Golang gộp các kết nối db theo mặc định (mặc dù, CENTOS dường như có lẽ không ..). Ngoài ra, chương trình của bạn bị 'tạm dừng' vì chương trình đang chờ kết nối mở từ nhóm kết nối db. Nếu bạn muốn phần còn lại của chương trình tiếp tục trong thời gian này, bạn nên chạy hàm này dưới dạng hàm không đồng bộ - hãy xem goroutines here. Điều đó có hiệu quả sẽ khiến chương trình của bạn xếp hàng, như bạn muốn, vì các kết nối sẽ được gán theo thứ tự mà chúng được yêu cầu bất cứ khi nào chúng có sẵn. Read more over here nếu bạn quan tâm đến nội bộ.

Nếu bạn cần một số đoạn mã cho cách mà goroutine của bạn có thể trông, hãy cho chúng tôi biết.

+0

Tôi đã cập nhật bài đăng gốc với mã tôi đang sử dụng ngay bây giờ và mọi thứ có vẻ hoạt động tốt, nhưng tôi không chắc liệu tôi có đang sử dụng goroutines và kết nối DB trọn gói chính xác hay không. – bvpx

Các vấn đề liên quan