Mysql: Kesalahan aneh pada koneksi yang terputus

Dibuat pada 5 Des 2013  ·  25Komentar  ·  Sumber: go-sql-driver/mysql

Saat saya mematikan koneksi yang memiliki kueri yang berjalan lama, saya mendapatkan hal-hal seperti ini:

[MySQL] 2013/12/05 22:17:19 packets.go:30: EOF
[MySQL] 2013/12/05 22:17:19 statement.go:24: Invalid Connection
[MySQL] 2013/12/05 22:17:27 packets.go:30: EOF
[MySQL] 2013/12/05 22:17:27 statement.go:24: Invalid Connection
[MySQL] 2013/12/05 22:17:39 packets.go:30: EOF
[MySQL] 2013/12/05 22:17:39 statement.go:24: Invalid Connection

Saya terbiasa melihat kesalahan ini:

2013 (HY000) at line 1: Lost connection to MySQL server during query

Sejauh yang saya tahu, kesalahan itu sebenarnya dikirim melalui koneksi jaringan kembali ke klien yang terbunuh. Apakah ini disamarkan di driver atau database / sql, atau bukankah ini merupakan kesalahan yang ditransmisikan melalui protokol seperti yang saya pikirkan? Bisakah kita memperjelas apa yang terjadi?

bug thinking

Komentar yang paling membantu

Saya pikir inilah masalahnya:

package main

import (
    "database/sql"

    _ "github.com/go-sql-driver/mysql"
)

func main() {
    db, _ := sql.Open("mysql", "/")
    defer db.Close()
    tx, err := db.Begin()
    if err != nil {
        panic(err)
    }
    defer tx.Commit()
    stmt1, err := tx.Prepare("SELECT 1")
    if err != nil {
        panic(err)
    }
    rows1, err := stmt1.Query()
    if err != nil {
        panic(err)
    }
    stmt2, err := tx.Prepare("SELECT 2")
    if err != nil {
        // rows1 is not closed -> triggers busy buffer because transaction is on one connection
        // and stmt1, stmt2 use the same one.
        // Move rows1.Close() in front of tx.Prepare and it disappears
        panic(err)
    }
    rows2, err := stmt2.Query()
    if err != nil {
        panic(err)
    }
    rows1.Close()
    rows2.Close()
    stmt1.Close()
    stmt2.Close()
}

Semua 25 komentar

Tidak, tidak ada kesalahan yang dikirimkan. Kesalahannya sebenarnya tidak ada yang bisa diterima: wink:
Tapi mungkin ide yang bagus untuk mencetak pesan kesalahan yang lebih deskriptif daripada EOF

Saya kira kesalahan statement.go:24: Invalid Connection adalah akibat dari http://golang.org/issue/5718
Kesalahan tersebut akan hilang ketika logika koneksi ulang otomatis diperbaiki dalam paket database / sql.

EOF hanya io.EOF , saya tidak yakin apakah kita harus memfilter dan mengganti ini. Ini adalah semacam idiom Go yang menggunakannya untuk kasus-kasus seperti ini (seperti misalnya dalam paket net, dari mana kesalahan ini berasal). Tapi setidaknya maknanya harus didokumentasikan di suatu tempat.

Apa pendapatmu?

Saya ingin mendengar pendapat @gkristic tentang hal ini juga. Dia sedang mempelajarinya.

Saya mengikuti kode di database / sql. Kesalahan statement.go:24: Invalid Connection bukan akibat dari http://golang.org/issue/5718 , meskipun saya setuju dengan @julienschmidt bahwa paket harus mencoba untuk mencoba lagi. Ada hingga sepuluh percobaan untuk panggilan Query() dan Exec() saat dijalankan pada level DB, tetapi tidak ada saat Anda menggunakan penerima Stmt.

Gergaji "Invalid Connection" Close() dipanggil untuk pernyataan yang telah disiapkan, yaitu stmt.mc.netConn adalah nihil di sini . Ini adalah pesan yang tidak berbahaya, karena koneksi di database / sql akan ditutup segera setelah ErrBadConn dikembalikan.

Tapi itu bukan satu-satunya kemungkinan yang pernah saya lihat; database / sql (Go 1.2) mungkin memiliki beberapa masalah konkurensi yang mungkin berakhir dengan pesan itu juga. Jika pernyataan (database / sql) ditutup ketika koneksi driver sedang menggunakannya, pernyataan driver dijadwalkan untuk ditutup pada putConn() oleh noteUnusedDriverStatement() . Tapi putConn() bisa berjalan sebelum removeOpenStmt() dipanggil (lihat (*Stmt) finalClose() ). Jika, setelah memanggil fungsi onPut tertunda, koneksi itu sendiri ditutup karena batas koneksi yang tidak aktif, maka paket akan mencoba menutup pernyataan itu lagi, menghasilkan pesan. Ini sekali lagi tidak berbahaya, tapi tetap saja mengganggu.

Database / sql IMHO Go perlu ditinjau ulang dengan cermat ...

@gkristic, apakah Anda menyarankan perubahan pada driver?

Paket database / sql memiliki beberapa kekurangan, saya berharap dapat membuat beberapa perbaikan untuk Go 1.3. Mengunjungi kembali manajemen ketergantungan adalah salah satu item di daftar saya.

Jika Anda menemukan masalah seperti ini, laporkan di https://code.google.com/p/go/issues/list.

Mengingat bahwa kondisi ini (yaitu, koneksi terputus atau double-close oleh database / sql) tidak berbahaya, saya berharap pengemudi melewatkannya secara diam-diam, alih-alih mencetak pesan "Invalid Connection". Menurut pendapat saya, nanti bisa: menakutkan, jika Anda tidak tahu itu tidak berbahaya; menjengkelkan, begitu Anda melakukannya; tetapi mungkin menyesatkan, jika ada pesan identik yang dicetak di tempat lain (dan ada, kecuali untuk nomor baris), menyembunyikan peringatan nyata yang dapat Anda lewati dengan mudah. Jika salah satu dari stmt.mc atau stmt.mc.netConn nihil pada pernyataan Close() function, saya akan memilih pengembalian tanpa logging lebih lanjut. Juga, perhatikan bahwa mengembalikan driver.ErrBadConn sana (seperti yang diperkenalkan di 4d3764bbcb17c31575642626baeab1bcdc30c301) sama sekali tidak berpengaruh, karena database / sql tidak pernah memeriksa kode yang dikembalikan untuk menutup pernyataan.

Sebagai catatan tambahan, saya mungkin akan menambahkan fungsi untuk mengubah logger. Saat ini, errLog diinisialisasi di dalam paket dan bersifat pribadi. Ini mencetak ke kesalahan standar yang mungkin, atau mungkin tidak tersedia; yaitu, proses dapat memilih untuk menutup deskriptor karena alasan lain. Tetapi bahkan jika tidak, pengguna mungkin memiliki gagasan yang berbeda tentang pencatatan (pikirkan file, syslog, apa pun). Pengemudi dapat menyediakan logger default ini, tetapi mungkin juga mengizinkan pengguna untuk mengatur yang lain.

Begitu saya punya waktu luang, saya akan menyiapkan contoh kecil untuk masalah yang saya sebutkan sebelumnya dan menulis laporan.

Terima kasih!

@gkristic tentang logger - maksud Anda seperti https://github.com/go-sql-driver/mysql/pull/182 (digabungkan menjadi master seminggu yang lalu)?

@arnehormann Oh, man ... tepatnya. Saya telah bekerja dengan v1.1. Saya juga memeriksa hal-hal lain di master sebelum memposting, tetapi lupa untuk memeriksa logging. Maaf dan terima kasih!

@gkristic tidak masalah sama sekali: nyengir:

Adakah perubahan yang harus dilakukan sebelum rilis berikutnya? Humas selamat datang :)

Hai teman-teman, pengguna baru go-sql-driver di sini. Saya memperhatikan masalah serupa, tetapi bertanya-tanya apakah seseorang dapat membantu saya memastikan bahwa penyebabnya sama? Dalam cron jangka panjang yang menggunakan goroutine, saya secara rutin menerima yang berikut ini.

[MySQL] 2014/05/14 20:33:05 packets.go:356: Busy buffer
[MySQL] 2014/05/14 20:33:05 packets.go:73: EOF
[MySQL] 2014/05/14 20:33:05 statement.go:24: Invalid Connection
[MySQL] 2014/05/14 20:33:05 connection.go:206: Invalid Connection

Saya lebih dari bersedia untuk mengotori tangan saya di sini, hanya mencari beberapa panduan tentang bagaimana mendekati masalah. Apakah kesalahan "Koneksi Tidak Valid" ini aman untuk diabaikan dalam keadaan tertentu? Apakah ada cara untuk secara otomatis mengambil koneksi lain jika ini terdeteksi?

Uh, oh ... sekarang saya mengerti, saya melewatkan komentar oleh @julienschmidt dari Jumat lalu. (Saya minta maaf Julien.) @Rmulley , sepertinya Anda mengalami masalah yang sama yang saya jelaskan di atas. Lihat komentar ini . "Koneksi Tidak Valid" di statement.go: 24 tidak berbahaya. Pengemudi harus melakukan hal yang sesuai dengan memilih koneksi yang berbeda. Saya tidak yakin tentang "Buffer sibuk"; Saya tidak ingat pernah melihat itu. Sudah cukup lama sejak saya memeriksa kode ini. Saya akan menyisihkan waktu untuk melihatnya lagi dan melihat apakah saya dapat membantu. Sayangnya, itu tidak bisa terjadi sebelum akhir minggu depan. Tapi aku akan kembali padamu saat itu.

@rmulley : Bagi saya ini sepertinya tidak ada hubungannya dengan masalah ini.
Silakan coba untuk mereproduksi kesalahan ini dengan versi git master saat ini jika Anda menggunakan versi yang diinstal oleh go get (yang merupakan versi yang lebih lama).
Tolong buka terbitan baru kalau begitu. Sampel kode minimal yang memicu kesalahan ini pasti akan membantu.

Sepertinya (b *buffer) takeBuffer mengembalikan nil . Ini tampaknya hanya terjadi jika b.length > 0 . Ini berarti bahwa karena alasan tertentu ada data yang belum dibaca di buffer.
Saya belum pernah melihat kesalahan ini sebelumnya dan saya hanya menerapkan pemeriksaan ekstra ini untuk keamanan ekstra. Saya tidak akan pernah percaya kesalahan ini di alam liar.

Menurut # 206 kesalahan ini sebenarnya hilang ketika go dijalankan dari tip. Bukankah itu masalahnya?

Pertama, maaf atas tanggapan yang terlambat saya sedang berlibur dan kemudian lupa untuk menindaklanjuti. Saya memastikan bahwa saya memiliki versi terbaru Driver MySQL dan sekarang saya menguji dengan Go 1.3. Sepertinya saya melihat lebih detail dalam pesan kesalahan sekarang.

[MySQL] 2014/06/23 11:46:04 packets.go:356: Busy buffer
[MySQL] 2014/06/23 11:46:04 packets.go:73: read tcp xxx.xxx.xxx.xx:3306: connection reset by peer

Apakah ini masalah MySQL di pihak saya? (Saya belum menemukan apa pun yang berguna secara online tentang cara menyelesaikan masalah ini)
Atau apakah ini sesuatu yang dapat saya periksa dan kemudian menghubungkan kembali dalam kode saya entah bagaimana?

saya mengalami masalah yang sama seperti yang dijelaskan rmulley. apa yang berbeda adalah bahwa "buffer sibuk" muncul dalam permintaan yang sangat pendek (sesingkat 1 Query + 2 Exec's).

Saya merasa masalahnya terkait dengan pernyataan yang disiapkan. saya menemukan bahwa jika saya telah menyiapkan pernyataan dalam transaksi, seperti

 stmt, err = tx.Prepare("SELECT ...")

saya harus menutup stmt ini sebelum saya menyiapkan pernyataan lain, atau saya akan menemukan "buffer sibuk" setiap kali. jika saya tidak menggunakan pernyataan yang disiapkan, misalnya melakukan langsung ke tx like

 tx.Query("...")

atau

tx.Exec("...")

, itu baik-baik saja.

dan, jika saya menyiapkan pernyataan dan kemudian mengeksekusi Query lain atau menjalankan item lain, tidak apa-apa juga ... hanya saja jangan menyiapkan pernyataan lain tanpa menutup yang sebelumnya, dan itu terlihat baik-baik saja.

berharap itu benar-benar di mana masalahnya.

Terima kasih.

Bisakah Anda membuat program Go kecil yang bisa mereproduksi kesalahan?
Tampaknya pasti ada bug pada driver, tetapi tidak terkait dengan masalah asli yang dilaporkan di sini.
Harap buat masalah baru.

Saya pikir inilah masalahnya:

package main

import (
    "database/sql"

    _ "github.com/go-sql-driver/mysql"
)

func main() {
    db, _ := sql.Open("mysql", "/")
    defer db.Close()
    tx, err := db.Begin()
    if err != nil {
        panic(err)
    }
    defer tx.Commit()
    stmt1, err := tx.Prepare("SELECT 1")
    if err != nil {
        panic(err)
    }
    rows1, err := stmt1.Query()
    if err != nil {
        panic(err)
    }
    stmt2, err := tx.Prepare("SELECT 2")
    if err != nil {
        // rows1 is not closed -> triggers busy buffer because transaction is on one connection
        // and stmt1, stmt2 use the same one.
        // Move rows1.Close() in front of tx.Prepare and it disappears
        panic(err)
    }
    rows2, err := stmt2.Query()
    if err != nil {
        panic(err)
    }
    rows1.Close()
    rows2.Close()
    stmt1.Close()
    stmt2.Close()
}

Saya baru saja mengalami masalah buffer sibuk yang serupa dan dapat mengonfirmasi bahwa @arnehormann tampaknya benar. Masalah terjadi saat mencoba menggunakan transaksi yang sama untuk beberapa kueri saat objek baris masih terbuka

Hai teman-teman, saya tidak tahu apakah ini telah diselesaikan dengan cara apa pun. Saya melihat masalah ini dalam penyisipan singkat yang dilakukan dengan "Exec" ->

var sql = "masukkan ke dalam tabel (f1, f2 ... f25) nilai (?,?, ...?)"
_, err: = db.Exec (sql, ...)

Setelah sekitar 4000, terkadang 5000 penyisipan saya mendapatkan "EOF Tidak Terduga" dan "Buffer Sibuk".
Sisipannya ketat (dalam loop for) tetapi ada permintaan REST di antara masing-masing, jadi, tidak terlalu cepat; referensi koneksi yang sama. Ini adalah Go 1.3.

Terima kasih,
Sal

@Sal - apa yang terjadi jika Anda menggunakan go 1.4?

Pada Rabu, 31 Desember 2014 pukul 22:11, Sal A. Magnone [email protected]
menulis:

Hai teman-teman, saya tidak tahu apakah ini telah diselesaikan dengan cara apa pun. Saya melihat ini
masalah dalam penyisipan singkat dilakukan dengan "Exec" ->

var sql = "masukkan ke dalam tabel (f1, f2 ... f25) nilai (?,?, ...?)"
_, err: = db.Exec (sql, ...)

Setelah sekitar 4000, terkadang 5000 sisipan saya mendapatkan "EOF Tidak Terduga" dan "Sibuk
Penyangga".
Sisipannya ketat (dalam loop for) tetapi ada permintaan REST di antaranya
masing-masing, jadi, api tidak begitu cepat; referensi koneksi yang sama. Ini adalah Go 1.3.

Terima kasih,
Sal

-
Balas email ini secara langsung atau lihat di GitHub
https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68479413.

Terima kasih untuk balasan Anda.

1.4 - kesalahan yang sama. Meninggal di 4205 sisipan dalam waktu sekitar 50 menit (ada net dan layar i / o antara setiap sisipan).

Saya telah merefaktor kode untuk secara opsional mengambil tempat yang ditinggalkannya sebelumnya. Jadi tidak penting untuk aplikasi ini, tetapi akan menjadi penting untuk aplikasi lain dalam proyek ini jika ini adalah masalah permintaan kumulatif.

-Sal

Dari: karbokation [mailto: [email protected]]
Dikirim: Minggu, 4 Januari 2015 09.50
Ke: go-sql-driver / mysql
Cc: Sal A. Magnone
Subjek: Re: [mysql] Kesalahan aneh pada koneksi terputus (# 185)

@Sal - apa yang terjadi jika Anda menggunakan go 1.4?

Pada Rabu, 31 Desember 2014 pukul 22:11, Sal A. Magnone < [email protected] [email protected] >
menulis:

Hai teman-teman, saya tidak tahu apakah ini telah diselesaikan dengan cara apa pun. Saya melihat ini
masalah dalam penyisipan singkat dilakukan dengan "Exec" ->

var sql = "masukkan ke dalam tabel (f1, f2 ... f25) nilai (?,?, ...?)"
_, err: = db.Exec (sql, ...)

Setelah sekitar 4000, terkadang 5000 sisipan saya mendapatkan "EOF Tidak Terduga" dan "Sibuk
Penyangga".
Sisipannya ketat (dalam loop for) tetapi ada permintaan REST di antaranya
masing-masing, jadi, api tidak begitu cepat; referensi koneksi yang sama. Ini adalah Go 1.3.

Terima kasih,
Sal

-
Balas email ini secara langsung atau lihat di GitHub
https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68479413.

-
Balas email ini secara langsung atau lihat di GitHub https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68635254. https://github.com/notifications/beacon/AA4DdvfCFMdiqPlTZITEs9VrxyyJqqFQks5neUqigaJpZM4BSM1b.gif

Apakah utas ini berubah menjadi beberapa utas sekarang? Haruskah komentar terbaru dimasukkan ke dalam masalah baru dan yang ini ditutup?

@xaprb Saya setuju, saya pikir ada beberapa utas yang sedang berlangsung sekarang. Kami mungkin dapat menutup yang ini dan mengubah dari https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68479413 menjadi masalah baru.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat