Saya melihat pesan kesalahan "Koneksi terlalu man" saat memanggil db.sqlDB.Query (). Sebelum saya menggali lebih jauh masalah ini, saya ingin tahu apakah ada masalah yang diketahui.
Pikiran?
013/07/23 03:05:35 yy.UpdateThingy () db.go: 264 [Gagal memasukkan catatan ke XXXX: Kesalahan 1040: Terlalu banyak koneksi]
Saya menggunakan go versi 1.1.1:
pergi versi go1.1.1 linux / 386
Saya menggunakan versi driver mysql:
v1.0.1
Versi MySql:
Versi server: 5.5.22-0ubuntu1 (Ubuntu)
Berikut adalah contoh dari salah satu pertanyaan saya:
baris, err =
db.sqlDB.Query ("masukkan ke dalam nilai XXXX (yyyy) (?)",
hubungkan.ZZZZ)
jika err! = nihil {
_ = baris.Close ();
hasil kembali, err
}
_ = baris.Close ();
Saya menambahkan "row.Close ()" berharap itu akan memperbaiki masalah, tetapi tidak ada dadu.
FYI, beberapa kueri saya menggunakan "baris.Scan" dan beberapa tidak.
Silakan lihat di sini: https://github.com/VividCortex/go-database-sql-tutorial
Jangan gunakan .Query, gunakan .Exec.
Anda memiliki terlalu banyak akses database bersamaan. Dalam hal ini, Anda harus secara manual membatasi jumlah koneksi serentak hingga paket database / sql menyediakan mekanisme pemblokiran di versi mendatang untuk itu. Namun dalam banyak kasus, pembaruan caching / asynchronous akan menjadi alternatif yang lebih baik.
Kemungkinan besar program Anda hanya membocorkan koneksi database. Ini terjadi jika Anda tidak menutup rows
dikembalikan oleh db.Query
atau lupa mengakhiri transaksi (dalam api tx database / sql ).
Saran umum saya adalah menggunakan
db.Exec
jika Anda tidak mengharapkan baris yang dikembalikan (dengan kata lain Anda tidak Scan
apa pun). Koneksi segera gratis setelah eksekusi.db.QueryRow
jika Anda mengharapkan satu baris. Jika Anda menggunakan sintaks yang dirantai , Anda tidak dapat membocorkan koneksidb.Query
jika Anda mengharapkan beberapa baris. Sangat penting bagi Anda untuk "membebaskan" koneksi dengan membaca baik semua baris yang dikembalikan (mengulang rows.Next
) atau memanggil rows.Close
. Yang pasti, menunda panggilan rows.Close
adalah ide yang bagus. Jangan lupa tentang kasus kesalahan, dll.Saya mengubah "db.Query ()" menjadi "db.Prepare () dan db.Exec ()" dan itu memperbaiki masalah saya. Terima kasih atas jawaban yang cepat dan hebat.
Saya punya ini juga.
dan, saya menggunakan "db.Prepare () dan db.Exec ()",
var db * sql.DB
func getdb () * sql.DB {
db, err = sql.Open ("mysql", connArgs)
db.SetMaxIdleConns (100)
kembali db
}
func foo (db * sql.DB) {
lakukan sesuatu .....
smint, err: = db.Prepare (....)
menunda smint.Close ()
smint.Exec (....)
}
func main () {
go func () {
db = get_db ()
menunda db.Close ()
foo (db)
} ()
}
coba pergi 1.3
----- Pesan asli -----
Dari: liutaihua [email protected]
Penerima: go-sql-driver / mysql [email protected]
Subjek: Re: [mysql] Terlalu banyak koneksi (# 111)
Tanggal: 15:43, 16 Juli 2014
dan ... mengapa Anda memulai goroutine di main?
Jika kode Anda benar-benar terlihat seperti ini, main may (dan mungkin akan) keluar sebelum goroutine dijalankan dan program Anda tidak akan melakukan apa-apa.
Hapus saja go func(){
dan }()
. Anda akan menjadi lebih baik.
maaf untuk uraian saya, sebenarnya, kode:
func socke_server () {
untuk {
// accept_something_from_socket as accept
go func (some_receive) {
db = get_db ()
menunda db.Close ()
foo (db)
}
}
}
func main () {
socke_server ()
}
Tapi, sekarang, saya menggunakan protokol domain Unix (' user: pwd @ unix (/tmp/mysql.sock)/'), sudah diperbaiki.
terima kasih balasan
Anda juga tidak boleh melakukan itu - ini mungkin berhasil, tetapi lambat.
Tempatkan loop terima di main.
Ubah goroutine menjadi fungsi tingkat atas.
Letakkan kode get_db Anda di bagian atas main dan tunda db.Closer di sana juga (dan hanya di sana).
Jangan buka dan tutup db seperti ini.
Coba kode berikut:
func handleConnection(db *sql.DB, args...interface{}) {
// do someting.....
// db.Exec("STATEMENT", args...)
}
func main() {
db, err := sql.Open("mysql", connArgs)
if err != nil {
panic(err)
}
db.SetMaxIdleConns(100)
defer db.Close()
for {
// accept connections and pass relevant stuff to handleConnection
go handleConnection(db, nil)
}
}
Terima kasih, saya mengerti.
Komentar yang paling membantu
Opsi 1: Konkurensi terlalu tinggi
Anda memiliki terlalu banyak akses database bersamaan. Dalam hal ini, Anda harus secara manual membatasi jumlah koneksi serentak hingga paket database / sql menyediakan mekanisme pemblokiran di versi mendatang untuk itu. Namun dalam banyak kasus, pembaruan caching / asynchronous akan menjadi alternatif yang lebih baik.
Opsi 2: Koneksi bocor
Kemungkinan besar program Anda hanya membocorkan koneksi database. Ini terjadi jika Anda tidak menutup
rows
dikembalikan olehdb.Query
atau lupa mengakhiri transaksi (dalam api tx database / sql ).Saran umum saya adalah menggunakan
db.Exec
jika Anda tidak mengharapkan baris yang dikembalikan (dengan kata lain Anda tidakScan
apa pun). Koneksi segera gratis setelah eksekusi.db.QueryRow
jika Anda mengharapkan satu baris. Jika Anda menggunakan sintaks yang dirantai , Anda tidak dapat membocorkan koneksidb.Query
jika Anda mengharapkan beberapa baris. Sangat penting bagi Anda untuk "membebaskan" koneksi dengan membaca baik semua baris yang dikembalikan (mengulangrows.Next
) atau memanggilrows.Close
. Yang pasti, menunda panggilanrows.Close
adalah ide yang bagus. Jangan lupa tentang kasus kesalahan, dll.