أشاهد رسالة الخطأ "اتصالات رجل جدًا" عند استدعاء 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" والبعض الآخر لا يستخدم.
يرجى إلقاء نظرة هنا: https://github.com/VividCortex/go-database-sql-tutorial
لا تستخدم .Query ، استخدم .Exec.
لديك العديد من عمليات الوصول المتزامنة إلى قاعدة البيانات. في هذه الحالة ، يجب تحديد عدد الاتصالات المتزامنة يدويًا حتى توفر حزمة قاعدة البيانات / SQL آلية حظر في إصدار مستقبلي لذلك. ولكن في كثير من الحالات يكون التخزين المؤقت / التحديثات غير المتزامنة هو البديل الأفضل
على الأرجح أن برنامجك يقوم فقط بتسريب اتصالات قاعدة البيانات. يحدث هذا إذا لم تغلق 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)
}
}
شكرا انا حصلت عليه.
التعليق الأكثر فائدة
الخيار 1: التزامن مرتفع للغاية
لديك العديد من عمليات الوصول المتزامنة إلى قاعدة البيانات. في هذه الحالة ، يجب تحديد عدد الاتصالات المتزامنة يدويًا حتى توفر حزمة قاعدة البيانات / SQL آلية حظر في إصدار مستقبلي لذلك. ولكن في كثير من الحالات يكون التخزين المؤقت / التحديثات غير المتزامنة هو البديل الأفضل
الخيار 2: تسريب الوصلات
على الأرجح أن برنامجك يقوم فقط بتسريب اتصالات قاعدة البيانات. يحدث هذا إذا لم تغلق
rows
إرجاعه بواسطةdb.Query
أو نسيت إنهاء المعاملات (في قاعدة البيانات / sql's tx api ).نصيحتي العامة هي استخدام
db.Exec
إذا كنت لا تتوقع ظهور صف (بمعنى آخر ، فأنت لا تفعل أي شيءScan
). الاتصال مجاني على الفور بعد التنفيذ.db.QueryRow
إذا كنت تتوقع صفًا واحدًا . إذا كنت تستخدم بناء الجملة المتسلسل ، فلا يمكنك تسريب الاتصالاتdb.Query
إذا كنت تتوقع صفوفًا متعددة . من المهم جدًا أن "تحرر" الاتصال بقراءة كل الصفوف التي تم إرجاعها (تكرارrows.Next
) أو استدعاءrows.Close
. من المؤكد أن تأجيل مكالمةrows.Close
فكرة جيدة. لا تنس حالات الخطأ وما إلى ذلك.