Mysql: اتصالات كثيرة جدًا

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

أشاهد رسالة الخطأ "اتصالات رجل جدًا" عند استدعاء db.sqlDB.Query (). قبل التعمق في هذه المشكلة ، أتساءل عما إذا كانت هناك مشكلة معروفة.

أفكار؟

013/07/23 03:05:35 yy.UpdateThingy () db.go: 264 [فشل إدراج السجل في XXXX: خطأ 1040: اتصالات كثيرة جدًا]

أنا أستخدم الإصدار 1.1.1 من go:
انتقل إلى الإصدار go1.1.1 linux / 386

أنا أستخدم إصدار برنامج تشغيل mysql:
الإصدار 1.0.1

نسخة MySQL:
إصدار الخادم: 5.5.22-0ubuntu1 (أوبونتو)

إليك عينة من أحد استفساراتي:
الصفوف ، يخطئ =
db.sqlDB.Query ("أدخل في قيمة XXXX (yyyy) (؟)"،
connect.ZZZZ)
إذا أخطأت! = لا شيء {
_ = rows.Close () ؛
نتيجة العودة ، يخطئ
}
_ = rows.Close () ؛

أضفت "rows.Close ()" على أمل أن يحل المشكلة ، ولكن بدون نرد.

لمعلوماتك ، تستخدم بعض استفساراتي "rows.Scan" والبعض الآخر لا يستخدم.

question working as intended

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

الخيار 1: التزامن مرتفع للغاية

لديك العديد من عمليات الوصول المتزامنة إلى قاعدة البيانات. في هذه الحالة ، يجب تحديد عدد الاتصالات المتزامنة يدويًا حتى توفر حزمة قاعدة البيانات / SQL آلية حظر في إصدار مستقبلي لذلك. ولكن في كثير من الحالات يكون التخزين المؤقت / التحديثات غير المتزامنة هو البديل الأفضل

الخيار 2: تسريب الوصلات

على الأرجح أن برنامجك يقوم فقط بتسريب اتصالات قاعدة البيانات. يحدث هذا إذا لم تغلق rows إرجاعه بواسطة db.Query أو نسيت إنهاء المعاملات (في قاعدة البيانات / sql's tx api ).

نصيحتي العامة هي استخدام

  • db.Exec إذا كنت لا تتوقع ظهور صف (بمعنى آخر ، فأنت لا تفعل أي شيء Scan ). الاتصال مجاني على الفور بعد التنفيذ.
  • db.QueryRow إذا كنت تتوقع صفًا واحدًا . إذا كنت تستخدم بناء الجملة المتسلسل ، فلا يمكنك تسريب الاتصالات
  • db.Query إذا كنت تتوقع صفوفًا متعددة . من المهم جدًا أن "تحرر" الاتصال بقراءة كل الصفوف التي تم إرجاعها (تكرار rows.Next ) أو استدعاء rows.Close . من المؤكد أن تأجيل مكالمة rows.Close فكرة جيدة. لا تنس حالات الخطأ وما إلى ذلك.

ال 9 كومينتر

يرجى إلقاء نظرة هنا: https://github.com/VividCortex/go-database-sql-tutorial

لا تستخدم .Query ، استخدم .Exec.

الخيار 1: التزامن مرتفع للغاية

لديك العديد من عمليات الوصول المتزامنة إلى قاعدة البيانات. في هذه الحالة ، يجب تحديد عدد الاتصالات المتزامنة يدويًا حتى توفر حزمة قاعدة البيانات / SQL آلية حظر في إصدار مستقبلي لذلك. ولكن في كثير من الحالات يكون التخزين المؤقت / التحديثات غير المتزامنة هو البديل الأفضل

الخيار 2: تسريب الوصلات

على الأرجح أن برنامجك يقوم فقط بتسريب اتصالات قاعدة البيانات. يحدث هذا إذا لم تغلق rows إرجاعه بواسطة db.Query أو نسيت إنهاء المعاملات (في قاعدة البيانات / sql's tx api ).

نصيحتي العامة هي استخدام

  • db.Exec إذا كنت لا تتوقع ظهور صف (بمعنى آخر ، فأنت لا تفعل أي شيء Scan ). الاتصال مجاني على الفور بعد التنفيذ.
  • db.QueryRow إذا كنت تتوقع صفًا واحدًا . إذا كنت تستخدم بناء الجملة المتسلسل ، فلا يمكنك تسريب الاتصالات
  • db.Query إذا كنت تتوقع صفوفًا متعددة . من المهم جدًا أن "تحرر" الاتصال بقراءة كل الصفوف التي تم إرجاعها (تكرار rows.Next ) أو استدعاء rows.Close . من المؤكد أن تأجيل مكالمة rows.Close فكرة جيدة. لا تنس حالات الخطأ وما إلى ذلك.

لقد غيرت "db.Query ()" إلى "db.Prepare () و db.Exec ()" وقد أدى ذلك إلى إصلاح مشكلتي. شكرا على الإجابات السريعة والرائعة.

حصلت على هذا أيضا.
وأستخدم "db.Prepare () و db.Exec ()" ،

var db * sql.DB

func getdb () * sql.DB {
db، err = sql.Open ("mysql"، connArgs)
db.SetMaxIdleConns (100)
عودة ديسيبل
}

func foo (ديسيبل * sql.DB) {
تفعل في بعض الأحيان .....
smint ، يخطئ: = db.Prepare (....)
تأجيل الابتسامة. أغلق ()
smint.Exec (....)
}

func main () {
go func () {
ديسيبل = get_db ()
تأجيل ديسيبل إغلاق ()
فو (ديسيبل)
} ()
}

حاول الذهاب 1.3
----- الرسالة الاصلية -----
من: liutaihua [email protected]
المستلم: go-sql-driver / mysql [email protected]
الموضوع: Re: [mysql] اتصالات كثيرة جدًا (# 111)
التاريخ: 15:43 ، 16 يوليو 2014

و ... لماذا تبدأ goroutine بشكل رئيسي؟
إذا كان الكود الخاص بك يشبه هذا بالفعل ، فقد يخرج main (وربما سيخرج) قبل تشغيل goroutine ولن يقوم برنامجك بأي شيء على الإطلاق.
ما عليك سوى إزالة go func(){ و }() . ستكون أفضل حالاً.

آسف لوصفتي ، في الواقع ، كود:

func socke_server () {
ل {
// Accept_something_from_socket كما تم استلامها
go func (some_receive) {
ديسيبل = get_db ()
تأجيل ديسيبل إغلاق ()
فو (ديسيبل)
}
}
}

func main () {
socke_server ()
}

لكن ، الآن ، أستخدم بروتوكول مجال Unix (' user: pwd @ unix (/tmp/mysql.sock)/') ، تم إصلاحه.

شكرا الرد

لا يجب عليك فعل ذلك أيضًا - فقد ينجح ، لكنه بطيء.

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

جرب الكود التالي:

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

شكرا انا حصلت عليه.

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

القضايا ذات الصلة

AlekSi picture AlekSi  ·  3تعليقات

mayurshivakumar picture mayurshivakumar  ·  5تعليقات

knadh picture knadh  ·  6تعليقات

albrow picture albrow  ·  7تعليقات

lunemec picture lunemec  ·  7تعليقات