פתיחת מסד נתונים בכל קריאה
-
@יוסף-בן-שמעון
אני יודע שאני יכול לעשות את זה (לכן שאלתי)
השאלה היא מה ההשלכות? -
בכל הכלים המודרניים שיש היום, יצירת קונקשיים חדש עושה שימוש בconnection pull שזה אוסף של קונקשנים מנוהל.
שימוש באותו חיבור למסד, עושה בעיות במקביליות ובטרנזקציות נדמה לי ועוד כמה דברים שאינני מבין בהם. אני לא מבין בהם כי אין צורך, אני לא ממציא את הגלגל ואם אומרים לי ליצור חיבור כל פעם (עם מנהל שמאחורי הקלעים ממחזר אם צריך) אני מסודר.
תשובה יפה בנושא הזה, במקרה שם זה על דוטנט: https://softwareengineering.stackexchange.com/a/398790/112215 -
-
@dovid חושבני שלא זו הכוונה, כשאתה פותח מאגר חיבורים מנוהל, אתה לא אמור לסגור אותו אחרי כל שאילתה, המאגר מנהל את יצירת החיבור וסגירתו.
אם הוא יסגור כל פעם את המאגר זה יצור עומס מיותר לחלוטין
לפי ההוראות בגיטהאב, וכך גם בלינק שהוא הביא מסטאק, צריך להגדיר משתנה גלובלי שמקבל את הערך מ sql.Open וזה מחזיק את המאגר המנוהל, מכאן ואילך הוא צריך לבקש מהמאגר חיבור פנוי ולתשאל אותו על ידי db.QueryRow וזהו -
לא ביקשתי שייצור מאגר, אם ככה היה נשמע זה ראיה טובה לזה שאני לא מכיר את go.
מה שאמרתי שצריך להיות ככה
--פתיחת חיבור
----תשאול
--סגירת חיבור
כל מקום ומקום שבשימוש. לגבי הבזבוז שבסגירה יש את ניהול הpool שאמרתי בבטחון שהוא לבטח קיים בgo (שזה אומר שהחיבור לא נסגר ומתי שפותחים חיבור חדש בעצם ייעשה בו שימוש חוזר).
אני לא יודע איך בגו פותחים חיבור, ייתכן שזה אוטומטי כפי שאתה אומר אני לא יודע.
ממילא אם השאלה של @nigun זה מה לעשות תכלס אני יענה לעבור לC# כי אני לא מכיר go. -
@dovid אכן, עכשיו אני מבין שנכנסתי לסוגיא בראש של נוד, אם אתה עושה close אתה הורג את המאגר, צחוק הגורל שדוטנט השפה הכי עילית שרק עושים פווו ויש לך אפליקציה, דוקא הם לא טרחו להסתיר ממך את המימוש של סגירת חיבור והחזרתו למאגר, ואילו בנוד ובגו שלכאורה הרבה יותר "ברזליות", המימוש הזה מוסתר מעיני המפתח
-
@יוסף-בן-שמעון
אז מה אני אמור לעשות?- ליצור משתנה גלובלי
2.לבצע פתיחה רק פעם אחת
- ליצור משתנה גלובלי
-
-
@nigun כן.
לפי מה שכתוב לך אין לך בכלל פתיחת קונקשיין.
הdb.Open לא יוצר קונקשיין אלא סה"כ מקים מופע שנועד מטבעו להיות בעל חיים ארוכים ולא אמורים לסגרו (שם הוא סוגר אותו עם defer כשהתוכנית תיגמר). המופע הזה יכול להיות אחד לכל התוכנה כמו ש@יוסף-בן-שמעון אמר.
מה עם קונקשנים? זה נראה שמנהלים לך את זה מצויין מאחורי הקלעים (יש לזה חיסרון קצת כי אם אני מבין טוב אתה לא יכול להבטיח ששתי פקודות ירוצו על אותו קונקשיין) ובעצם כל קריאה לQuery מחזיקה קונקשיין שנסגר בrows.Close().
אז סיכמנו: var db *sql.DB אחד לכל האפליקציה. -
שוב למדתי בדרך הקשה שצריך לקרוא דוקומנטיצות מהתחלה לסוף
בגלל שלא ידעתי בדיוק איך מתנהל הסשנים בGO
הגעתי מהר מאוד לSQL Error 1040: Too Many Connection
אחרי שקראתי את המדריך שהבאתי למעלה הייתי צריך לעשות שינויים גדולים בקוד בשביל לתקן את זה
(מזל שהרצתי בדיקת עומסים) -
@יוסף-בן-שמעון
א. קראתי לבקשת INSERT עם Query ולא עם exec
כיוון שאני לא צריך את הפלט זה מבזבז נתונים, כי הוא יוצר פלט וזה משאיר את החיבור פתוח ליותר זמן
ב. במקרה של שגיאה עשיתי return בלי פקודה נוספת לrows.Close()
מה שגרם לחלק מהבקשות להישאר פתוח משום מה.
ולמדתי שמומלץ לזרוק הרבה Close כי אם לא יועיל לא יזיק
ג. למדתי שעדיף באופן כללי להכין את הבקשה עם Prepare ולעשות עליו כמה בקשות
(במקרה שלי כל בקשה נמצא בתוך פונקציה נפרדת כך שוויתרתי על זה כי זה מידי הרבה עבודה לבנות את כל הפונקציות מחדש)
ד. למדתי שאם בקשה אמורה לקבל רק שורה אחת משתמשים בQueryRow ולא בQuery
יש עוד כמה דברים שלא ירדתי לעומקם עדיין למשל ניהול ערכים רקים (NULL)