Mysql: Terlalu banyak koneksi

Dibuat pada 23 Jul 2013  ·  9Komentar  ·  Sumber: go-sql-driver/mysql

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.

question working as intended

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 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 koneksi
  • db.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.

Semua 9 komentar

Silakan lihat di sini: https://github.com/VividCortex/go-database-sql-tutorial

Jangan gunakan .Query, gunakan .Exec.

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 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 koneksi
  • db.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.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat