Mysql: خطأ غريب في الاتصال المقطوع

تم إنشاؤها على ٥ ديسمبر ٢٠١٣  ·  25تعليقات  ·  مصدر: go-sql-driver/mysql

عندما أقتل الاتصالات التي تحتوي على استعلامات طويلة الأمد ، أحصل على أشياء مثل هذه:

[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

اعتدت على رؤية هذا الخطأ:

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

بقدر ما أعرف ، يتم إرسال هذا الخطأ بالفعل عبر اتصال الشبكة مرة أخرى إلى العميل الذي تم قتله. هل يتم إخفاء هذا في برنامج التشغيل أو قاعدة البيانات / SQL ، أم أنه ليس خطأ ينتقل عبر البروتوكول كما أعتقد؟ هل يمكننا توضيح ما يحدث بطريقة أو بأخرى؟

bug thinking

التعليق الأكثر فائدة

وأعتقد أن هذه هي المشكلة:

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()
}

ال 25 كومينتر

لا ، لم يتم إرسال أي خطأ. الخطأ هو في الواقع أنه لا يمكن تلقي أي شيء: غمزة:
ولكن قد يكون من الجيد طباعة رسالة خطأ وصفية أكثر من EOF

أعتقد أن أخطاء statement.go:24: Invalid Connection هي نتيجة http://golang.org/issue/5718
يجب أن تختفي هذه الأخطاء عند إصلاح منطق إعادة الاتصال التلقائي في حزمة قاعدة البيانات / SQL.

EOF هو io.EOF ، لست متأكدًا مما إذا كان يجب علينا تصفية هذا واستبداله. إنه نوع من مصطلحات Go لاستخدامه في حالات مثل هذه (على سبيل المثال في حزمة net ، حيث ينشأ هذا الخطأ). ولكن على الأقل يجب توثيق المعنى في مكان ما.

ما هو رأيك؟

أود أن أسمع رأيgkristic في هذا أيضًا. كان يدرسها.

لقد اتبعت الكود في قاعدة البيانات / SQL. أخطاء statement.go:24: Invalid Connection ليست نتيجة http://golang.org/issue/5718 ، على الرغم من أنني أتفق مع julienschmidt في أن الحزمة يجب أن تحاول إعادة المحاولة. هناك ما يصل إلى عشر محاولات لمكالمات Query() و Exec() عند تشغيلها على مستوى قاعدة البيانات ، ولكن لا شيء عند استخدام جهاز استقبال Stmt.

يرجع سبب "اتصال غير صالح" Close() للحصول على بيان مُعد ، على سبيل المثال ، stmt.mc.netConn غير موجود هنا . إنها رسالة غير ضارة ، لأنه سيتم إغلاق الاتصال في قاعدة البيانات / sql بمجرد إرجاع ErrBadConn .

لكن هذا ليس الاحتمال الوحيد الذي رأيته ؛ قد تواجه قاعدة البيانات / sql (Go 1.2) بعض مشكلات التزامن التي قد تنتهي بهذه الرسالة أيضًا. إذا تم إغلاق جملة (database / sql) عندما يستخدمها اتصال برنامج التشغيل ، فمن المقرر أن يتم إغلاق بيان برنامج التشغيل عند putConn() بواسطة noteUnusedDriverStatement() . ولكن putConn() يمكن تشغيلها قبل removeOpenStmt() يسمى (انظر (*Stmt) finalClose() ). إذا ، بعد استدعاء الوظائف المعلقة onPut ، تم إغلاق الاتصال نفسه بسبب حد الاتصال الخامل ، فستحاول الحزمة إغلاق العبارة مرة أخرى ، مما يؤدي إلى ظهور الرسالة. هذا مرة أخرى غير ضار ، لكنه مع ذلك مزعج.

تحتاج قاعدة بيانات / SQL IMHO Go إلى إعادة النظر بعناية ...

gkristic هل تقترح أي تغييرات في السائق؟

تحتوي حزمة قاعدة البيانات / SQL على بعض العيوب ، وآمل أن أجري بعض التحسينات على Go 1.3. إعادة النظر في إدارة التبعية عنصر واحد في قائمتي.

إذا اكتشفت مثل هذه المشكلات ، فيرجى الإبلاغ عنها على https://code.google.com/p/go/issues/list.

بالنظر إلى أن هذه الشروط (أي فقدان الاتصال أو الإغلاق المزدوج بواسطة قاعدة البيانات / sql) غير ضارة ، أتوقع أن يتخطى السائق هذه الشروط بصمت ، بدلاً من طباعة رسالة "اتصال غير صالح". في رأيي ، يمكن أن يكون التالي إما: مخيف ، إذا كنت لا تعرف أنه غير ضار ؛ مزعج بمجرد القيام بذلك ؛ ولكن ربما تكون مضللة ، إذا كانت هناك رسالة متطابقة مطبوعة في مكان آخر (وهناك ، باستثناء رقم السطر) ، تخفي تحذيرًا حقيقيًا يمكنك تخطيه بسهولة. إذا لم يكن أي من stmt.mc أو stmt.mc.netConn صفراً في كشف الدالة Close() ، فأنا أفضل الإرجاع بدون مزيد من التسجيل. لاحظ أيضًا أن إرجاع driver.ErrBadConn هناك (كما تم تقديمه في 4d3764bbcb17c31575642626baeab1bcdc30c301) ليس له أي تأثير على الإطلاق ، لأن قاعدة البيانات / sql لا تتحقق أبدًا من رمز الإرجاع لإغلاق العبارة.

كملاحظة جانبية ، ربما سأضيف وظيفة لتعديل المسجل. حاليًا ، تمت تهيئة errLog داخل الحزمة وهو خاص. يطبع إلى خطأ قياسي قد يكون أو لا يكون متاحًا ؛ على سبيل المثال ، قد تختار العملية إغلاق الواصف لأسباب أخرى. ولكن حتى لو لم يحدث ذلك ، فقد يكون لدى المستخدم فكرة مختلفة عن التسجيل (فكر في الملفات ، أو سجل النظام ، أو أي شيء آخر). يمكن أن يوفر برنامج التشغيل هذا المسجل الافتراضي ، ولكن ربما يسمح أيضًا للمستخدم بتعيين آخر.

بمجرد أن يكون لدي بعض وقت الفراغ ، سأقوم بإعداد مثال صغير للمسألة التي ذكرتها من قبل وأكتب تقريرًا.

شكرا!

gkristic بخصوص المسجل - هل تقصد شيئًا مثل https://github.com/go-sql-driver/mysql/pull/182 (تم دمجه في Master منذ أسبوع)؟

تضمين التغريدة لقد كنت أعمل مع v1.1. لقد تحققت من الأشياء الأخرى في الماجستير أيضًا قبل النشر ، لكنني نسيت التحقق من التسجيل. آسف وشكرا!

gkristic ليست مشكلة على الإطلاق: ابتسامة عريضة:

أي تغييرات يجب القيام بها قبل الإصدار التالي؟ ترحيب PRs :)

مرحبًا يا شباب ، مستخدم جديد لبرنامج go-sql-driver هنا. ألاحظ مشكلات مماثلة ، لكني كنت أتساءل عما إذا كان بإمكان أحدهم مساعدتي في التأكد من أن السبب هو نفسه؟ في crons الطويلة التي تستخدم goroutines ، أتلقى بشكل روتيني ما يلي.

[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

أنا أكثر من راغب في جعل يدي متسخة هنا ، فقط أبحث عن بعض الإرشادات حول كيفية التعامل مع المشكلة. هل هذا الخطأ "اتصال غير صالح" آمن ليتم تجاهله في ظروف معينة؟ هل هناك طريقة للحصول تلقائيًا على اتصال آخر إذا تم اكتشاف ذلك؟

آه ، أوه ... الآن بعد أن رأيت ، فاتني تعليق julienschmidt من الجمعة الماضية. (أعتذر جوليان.) rmulley ، يبدو أنك أصفها أعلاه. انظر إلى هذا التعليق. "اتصال غير صالح" الموجود في statement.go: 24 غير ضار. يجب على السائق أن يفعل الشيء المناسب باختيار اتصال مختلف. لست متأكدًا من "المخزن المؤقت مشغول" بالرغم من ذلك ؛ لا أذكر أنني رأيت ذلك. لقد مر وقت طويل منذ أن تحققت من هذا الرمز. سأخصص بعض الوقت لإلقاء نظرة عليه مرة أخرى ومعرفة ما إذا كان بإمكاني المساعدة. لسوء الحظ ، لا يمكن أن يحدث هذا قبل نهاية الأسبوع المقبل. لكنني سأعود إليك بحلول ذلك الوقت.

rmulley : يبدو لي أن هذا لا علاقة له بهذه المشكلة.
يرجى محاولة إعادة إنتاج هذا الخطأ بإصدار git master الحالي في حالة استخدامك لإصدار تم تثبيته بواسطة go get (وهو إصدار أقدم).
الرجاء فتح قضية جديدة بعد ذلك. من المؤكد أن نموذج رمز بسيط يؤدي إلى هذا الخطأ سيساعد.

يبدو أن (b *buffer) takeBuffer يُرجع nil . يبدو أن هذا يحدث فقط عندما يكون b.length > 0 . هذا يعني أنه لسبب ما توجد بيانات غير مقروءة في المخزن المؤقت.
لم يسبق لي أن رأيت هذا الخطأ من قبل وقمت فقط بتنفيذ هذه الفحوصات الإضافية لمزيد من الأمان. لم أكن لأصدق هذا الخطأ في البرية.

وفقًا للرقم 206 ، يختفي هذا الخطأ في الواقع عندما يتم تشغيل go من الحافة. أليس هذا هو الحال في الواقع؟

أولاً ، آسف على الرد المتأخر الذي كنت في إجازة ثم نسيت المتابعة. لقد تأكدت من أن لدي أحدث إصدار من MySQL Driver وأقوم الآن باختبار Go 1.3. يبدو أنني أرى المزيد من التفاصيل في رسالة الخطأ الآن.

[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

هل هذه مشكلة MySQL من جانبي؟ (لم أجد أي شيء مفيد عبر الإنترنت حول كيفية حل هذه المشكلة)
أو هل هذا شيء يمكنني التحقق منه ثم إعادة الاتصال في الكود الخاص بي بطريقة ما؟

لقد واجهت نفس المشكلة كما وصفها rmulley. الشيء المختلف هو أن "المخزن المؤقت مشغول" ظهر في استعلام قصير للغاية (قصير مثل 1 Query + 2 Exec).

أشعر أن المشكلة تتعلق بالبيانات المعدة. لقد وجدت أنه إذا أعددت بيانًا في معاملة ، مثل

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

يجب أن أغلق هذا stmt قبل أن أقوم بإعداد بيان آخر ، أو سأواجه "المخزن المؤقت" في كل مرة. إذا لم أستخدم العبارات المعدة ، على سبيل المثال القيام مباشرة بـ tx like

 tx.Query("...")

أو

tx.Exec("...")

، كان جيدا.

وإذا أعددت بيانًا ثم قمت بتنفيذ Query أو Exec الأخرى ، فلا بأس أيضًا ... فقط لا تعد عبارة أخرى دون إغلاق الجملة السابقة ، ويبدو الأمر جيدًا.

آمل أن يكون مكان المشكلة حقًا.

شكرا.

هل يمكنك إنشاء برنامج Go صغير يمكن من خلاله تكرار الخطأ؟
يبدو أنه بالتأكيد خطأ في برنامج التشغيل ، ولكنه لا يتعلق بالمشكلة الأصلية التي تم الإبلاغ عنها هنا.
الرجاء إنشاء مشكلة جديدة بعد ذلك.

وأعتقد أن هذه هي المشكلة:

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()
}

لقد واجهت للتو مشكلة مماثلة في المخزن المؤقت المشغول ويمكنني أن أؤكد أن

مرحبًا يا شباب ، لا أعرف ما إذا كان قد تم حل هذه المشكلة بأي شكل من الأشكال. أرى هذه المشكلة في إدخالات قصيرة يتم إجراؤها باستخدام "Exec" ->

var sql = "أدخل قيم الجدول (f1 ، f2 ... f25) (؟ ،؟ ، ...؟)"
_، يخطئ: = db.Exec (sql، ...)

بعد حوالي 4000 ، في بعض الأحيان 5000 إدراج أحصل على "EOF غير متوقع" و "مخزن مؤقت مشغول".
الإدخالات ضيقة (في حلقة for) ولكن هناك طلب REST بين كل منها ، لذلك ، ليس إطلاق نار سريع ؛ نفس مرجع الاتصال. هذا هو Go 1.3.

شكرا،
سال

Sal - ماذا يحدث عند استخدام

يوم الأربعاء ، 31 ديسمبر 2014 ، الساعة 10:11 مساءً ، Sal A. Magnone [email protected]
كتب:

مرحبًا يا شباب ، لا أعرف ما إذا كان قد تم حل هذه المشكلة بأي شكل من الأشكال. أنا أرى هذا
إصدار في إدخالات قصيرة يتم إجراؤها باستخدام "Exec" ->

var sql = "أدخل قيم الجدول (f1 ، f2 ... f25) (؟ ،؟ ، ...؟)"
_، يخطئ: = db.Exec (sql، ...)

بعد حوالي 4000 ، أحيانًا 5000 إدخال أحصل على "EOF غير متوقع" و "مشغول
متعادل".
الإدخالات ضيقة (في حلقة for) ولكن يوجد طلب REST بينهما
كل النار ، لذلك ، ليست بهذه السرعة ؛ نفس مرجع الاتصال. هذا هو Go 1.3.

شكرا،
سال

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68479413.

شكرا لردك.

1.4 - نفس الخطأ. مات عند 4205 إدراجًا في حوالي 50 دقيقة (هناك شبكة وشاشة i / o بين كل إدخال).

لقد أعدت بناء الكود لاختيار المكان الذي تركته في المرة السابقة اختياريًا. لذلك ليس حرجًا لهذا التطبيق ، ولكن قد يكون مهمًا للتطبيقات الأخرى في هذا المشروع إذا كانت هذه مشكلة طلب تراكمية.

-سال

من: carbocation [mailto: [email protected]]
تاريخ الإرسال: الأحد 4 يناير 2015 الساعة 9:50 صباحًا
إلى: go-sql-driver / mysql
نسخة إلى: Sal A. Magnone
الموضوع: Re: [mysql] خطأ غريب في الاتصال المقطوع (# 185)

Sal - ماذا يحدث عند استخدام

يوم الأربعاء ، 31 ديسمبر 2014 الساعة 10:11 مساءً ، سال أ. ماجنوني < [email protected] [email protected] >
كتب:

مرحبًا يا شباب ، لا أعرف ما إذا كان قد تم حل هذه المشكلة بأي شكل من الأشكال. أنا أرى هذا
إصدار في إدخالات قصيرة يتم إجراؤها باستخدام "Exec" ->

var sql = "أدخل قيم الجدول (f1 ، f2 ... f25) (؟ ،؟ ، ...؟)"
_، يخطئ: = db.Exec (sql، ...)

بعد حوالي 4000 ، أحيانًا 5000 إدخال أحصل على "EOF غير متوقع" و "مشغول
متعادل".
الإدخالات ضيقة (في حلقة for) ولكن يوجد طلب REST بينهما
كل النار ، لذلك ، ليست بهذه السرعة ؛ نفس مرجع الاتصال. هذا هو Go 1.3.

شكرا،
سال

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68479413.

-
قم بالرد على هذه الرسالة الإلكترونية مباشرةً أو اعرضها على GitHub https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68635254. https://github.com/notifications/beacon/AA4DdvfCFMdiqPlTZITEs9VrxyyJqqFQks5neUqigaJpZM4BSM1b.gif

هل هذا الخيط يتحول إلى خيوط قليلة الآن؟ هل يجب وضع أحدث التعليقات في إصدار جديد وإغلاق هذا العدد؟

xaprb أوافق ، أعتقد أن هناك بعض الخيوط الجارية الآن. ربما يمكننا إغلاق هذا واحد والاستفادة من https://github.com/go-sql-driver/mysql/issues/185#issuecomment -68479413 في إصدار جديد.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات