2015-01-25 19 views
7

Tôi đang sử dụng trình điều khiển github.com/go-sql-driver/mysql để đi.Golang, mysql: Lỗi 1040: Quá nhiều kết nối

tôi mở một cơ sở dữ liệu:

db, err := sql.Open("mysql", str) 

Sau đó, tôi có hai chức năng được gọi là mỗi 200 lần với mã mysql sau:

rows, err := db.Query("select name from beehives") 
if err != nil { 
    panic(err) 
}  
defer rows.Close() 

Thứ hai:

err = db.QueryRow("select id, secret, shortname from beehives where shortname = ?", beehive).Scan(&id, &secre 
    switch { 
    case err == sql.ErrNoRows: 
     err = errors.New("Beehive '"+beehive+"' not found.") 
    case err != nil: 
     panic("loginBeehive: "+ err.Error()) 
    default: 
     // ... do the work 

Các đầu tiên là hoảng sợ.

Làm cách nào để có nhiều kết nối khi tôi chỉ mở cơ sở dữ liệu một lần và làm cách nào để đóng chúng?

Trả lời

11

sql.Open doesn't really open a connection to your database.

Một sql.DB duy trì một hồ bơi của các kết nối đến cơ sở dữ liệu của bạn. Mỗi khi bạn truy vấn cơ sở dữ liệu của bạn, chương trình của bạn sẽ cố gắng để có được một kết nối từ hồ bơi này hoặc tạo một cái mới khác. Các kết nối này được đặt trở lại vào hồ bơi khi bạn đóng chúng lại.

Đây là những gì rows.Close() thực hiện. db.QueryRow("...") của bạn thực hiện tương tự nội bộ khi bạn gọi Scan(...).

Vấn đề cơ bản là bạn đang tạo quá nhiều truy vấn, trong đó mỗi truy vấn cần kết nối nhưng bạn không đóng kết nối đủ nhanh. Bằng cách này, chương trình của bạn phải tạo một kết nối mới cho mỗi truy vấn.

Bạn có thể giới hạn số lượng kết nối tối đa mà chương trình của bạn sử dụng bằng cách gọi SetMaxOpenConns trên sql.DB.

Xem http://go-database-sql.org/surprises.html để biết thêm thông tin.

2

Cố gắng lập báo cáo đã chuẩn bị db.Prepare(query string) (*Stmt, error) và hơn stmt.Query hoặc stmt.Exec và hơn stmt.Close để sử dụng lại kết nối.

3

Đối tượng *DB mà bạn lấy lại từ sql.Open không tương ứng với kết nối đơn. Đó là suy nghĩ tốt hơn như là một xử lý cho cơ sở dữ liệu: nó quản lý một hồ bơi kết nối cho bạn.

Bạn có thể kiểm soát số lượng kết nối mở với `(*DB).SetMaxOpenConnsits pair cho các kết nối không tải. Vì vậy, về cơ bản những gì xảy ra ở đây là db.Querydb.QueryRow cố gắng để có được kết nối cho bản thân và xử lý DB không đặt bất kỳ hạn chế nào về số lượng kết nối đồng thời. .

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