דיבוג SQL

איך רואים אילו שאילתות רצות ואיפה הן נכשלות ב-WIZZO CMS: DB::$print_sql, לוג sqllog.txt והפאנל שלו, הודעות השגיאה של DB::sql, DB::$last_error ו-DB::had_error, ופאנל server_load.

⏱ 3 דק' קריאה 561 מילים ערוך דף זה ב-GitHub

כשאתם צריכים לדעת איזה SQL הליבה שלחה, כמה זמן זה לקח, או למה שאילתה נכשלה, יש כמה כלים בליבה. הדף עובר עליהם מהפשוט למורכב: הדפסה, לוג לקובץ, פאנל הצפייה, ומאפייני השגיאה של מחלקת DB.

בעמוד הזה system/ הוא תיקיית הליבה הפרוסה (= api/core בריפו) ו-{admin} הוא CONFIG::$admin_url של האתר.

הדפסת כל שאילתה#

DB::$print_sql = true;    // כל SQL מודפס בזמן שהוא רץ
// ... קוד שאתם בודקים
DB::$print_sql = false;

מתאים לדיבוג נקודתי בסביבת פיתוח. בסביבה חיה זה מדפיס למשתמשים, אל תשאירו.

DB::$is_sql_debug = true;  // מוסיף לכל שאילתה הערה: /* REQUEST_URI */ SELECT ...

התוספת מאפשרת לזהות ב-slow query log של MySQL מאיזו כתובת שאילתה הגיעה.

REQUEST_URI בתוך הערת SQL
$is_sql_debug מדביק את ה-REQUEST_URI כפי שהוא בתוך הערה. כתובת שמכילה */ יכולה לצאת מההערה. השתמשו בו רק בזמן דיבוג.

לוג שאילתות לקובץ#

כש-DB::$log_sql הוא true, או כשהפרמטר log_sql ב-CRM_params שווה "1", כל שאילתה נכתבת כשורת JSON אל sqllog.txt בשורש האתר (CONFIG::$base_path):

שדהתוכן
urlהכתובת שביקשה את השאילתה
dateזמן
sqlטקסט ה-SQL
traceמחסנית הקריאות שהביאה אליה
sourceadmin או site

הקובץ מתגלגל: כשהוא עובר 5MB נשמר רק השליש האחרון.

הפאנל sqllog#

הפאנל {admin}/sqllog מציג את הקובץ בעימוד (100 שורות לעמוד, סינון לפי admin או site), מדליק ומכבה את הלוג (הוא מעדכן את log_sql ב-CRM_params ומנקה את מטמון params), ומאפשר לנקות. פאנל server_load מציג CPU, זיכרון ודיסק חיים, ו-40 השורות האחרונות של הלוג, עם כפתור הדלקה.

sqllog.txt נגיש מהרשת ומכיל הכול

הקובץ יושב בשורש האתר ויכול להיות נגיש ב-HTTP, והוא כולל את טקסט השאילתות (לפעמים עם נתונים אישיים) ואת מחסנית הקריאות. הפעילו אותו לזמן קצר, חסמו גישה אליו בשרת, וכבו וניקו בסיום.

שגיאות#

שאילתה שנכשלת זורקת Exception מ-DB::sql(). ההודעה בנויה כך:

<הודעת הדרייבר> | <טקסט ה-SQL>

כשהמצב DB::$throw_on_error כבוי, לחריגה מצורפת גם מחסנית. ב-PHP 8.3 PDO זורק חריגות מעצמו, ולכן שני המצבים זורקים. ההערות בקוד על "silent mode" הן שריד של PHP 7.

try {
    $res = DB::sql("SELECT * FROM CRM_no_such_table");
} catch (Exception $e) {
    error_log($e->getMessage());     // "Table '...' doesn't exist | SELECT * FROM CRM_no_such_table"
}
תכונהמשמעות
DB::$error_countכמה שגיאות היו בבקשה
DB::$last_errorהודעת השגיאה האחרונה
DB::had_error()true אם $error_count > 0

error_log("DB query failed: ...") נכתב ללוג השגיאות של PHP. את הלוג הזה קוראים בשרת, או דרך כלי הלוגים של סביבת הפיתוח.

שגיאה מונעת שמירה במטמון
cache_engine::get($key, $func) בודק אם DB::$error_count עלה בזמן בניית הערך, ואם כן לא שומר אותו. כך שאילתה שנכשלה לא "נתקעת" במטמון. ראו API של cache_engine.

מדידת זמנים#

מדידת זמן לכל שאילתה קיימת בליבה רק במצב "capture" של יועץ הביצועים (אולג): כשקובץ הסימון cache/perf_advisor/capture_on.json קיים, DB::sql() מתעדת לכל שאילתה את משך הריצה במילישניות, עד 2000 שאילתות לבקשה, וכותבת JSONL. המצב כבוי כברירת מחדל ומופעל על ידי השירות, לא ידנית. למדידה ידנית:

$t = microtime(true);
$rows = DB::get_all("SELECT ...");
error_log("query took " . round((microtime(true) - $t) * 1000) . "ms");

ולנתיבים בעייתיים: DB::$is_sql_debug יחד עם slow query log של MySQL, כדי למצוא את הכתובת האחראית. ראו גם אבחון ו-בריאות וביצועים.

ראו גם#

מצאתם טעות או חוסר? תקנו את הדף או פתחו Issue בריפו. התיעוד נכתב מתוך הקוד של ליבה 5.0.115.