|
| 1 | +# **ProxySQL Prepared Statement Parameter Tracking Reference Manual** |
| 2 | +This document describes the changes made to the logging of prepared statement parameters in ProxySQL. |
| 3 | +Two logging formats are supported: |
| 4 | +- **Binary Format (Format 1)** via `write_query_format_1()` |
| 5 | +- **JSON Format (Format 2)** via `write_query_format_2_json()` (also using `extractStmtExecuteMetadataToJson()`) |
| 6 | +## **1. Overview** |
| 7 | +ProxySQL logs query events in two different formats. |
| 8 | +For prepared statements (i.e. `COM_STMT_EXECUTE` events), the logging functions now log extra parameter details. |
| 9 | +Both formats encode the number of parameters and, for each parameter, log its type and a human-readable string value, with special handling for `NULL` values. |
| 10 | +## **2. Binary Format Details (**`write_query_format_1()`**)** |
| 11 | +When logging a prepared statement execution in binary format, the following steps occur: |
| 12 | +- **Encoded Basic Query Data:** |
| 13 | +Standard fields such as event type, thread ID, username, schema name, client/server info, timestamps, query digest, and the query text itself are encoded using a variable-length encoding scheme. |
| 14 | +- **Logging Prepared Statement Parameters:** |
| 15 | +If the event type is `PROXYSQL_COM_STMT_EXECUTE` and valid statement metadata is present: |
| 16 | + |
| 17 | +- The number of parameters is encoded using `mysql_encode_length()`. |
| 18 | +- A **null bitmap** is constructed with one bit per parameter (set when the parameter is `NULL`). |
| 19 | +- For each parameter: |
| 20 | + - Two bytes are written to store the parameter's type. |
| 21 | + - If the parameter is not `NULL`, the function `getValueForBind()` is used to convert the binary data into a human-readable string. |
| 22 | + - The length of the converted value is encoded (again using `mysql_encode_length()`), and then the raw bytes of the converted value are written. |
| 23 | +- **Sequential Write Process:** |
| 24 | +All the fields are written sequentially. First, the total length of the event record is written (as a fixed-size 8-byte field), then each encoded field and the additional prepared statement parameter details. |
| 25 | +## **3. JSON Format Details (**`write_query_format_2_json()`**)** |
| 26 | +In JSON format, the logging function produces a JSON object that includes all standard query details plus additional fields for prepared statement parameters: |
| 27 | +- **Base JSON Object Information:** |
| 28 | +The JSON object includes key fields such as thread_id, username, schemaname, client, server information (if available), timestamps (starttime, endtime), duration, digest, etc. |
| 29 | +- **Event Type:** |
| 30 | +Depending on the event type, the field `"event"` is set to `"COM_STMT_EXECUTE"` (or `"COM_STMT_PREPARE"` / `"COM_QUERY"`) accordingly. |
| 31 | +- **Logging Prepared Statement Parameters:** |
| 32 | +If the event type is `PROXYSQL_COM_STMT_EXECUTE` and the session contains valid statement metadata: |
| 33 | + |
| 34 | +- The helper function `extractStmtExecuteMetadataToJson(json &j)` is called. |
| 35 | +- This function iterates over each parameter: |
| 36 | + - For `NULL` parameters, it logs `"type": "NULL"` and `"value": null`. |
| 37 | + - For non-`NULL` parameters, it uses getValueForBind() to obtain the parameter type (e.g., `"INT24"`, `"VARCHAR"`) and its string representation. |
| 38 | +- The result is a JSON array attached to the key `"parameters"`, where each element is an object with keys `"type"` and `"value"`. |
| 39 | +- **Output:** |
| 40 | +Finally the JSON object is dumped as a single line in the log file using `j.dump()`. |
| 41 | +## **4. Detailed Example** |
| 42 | +For example, consider a prepared statement with two parameters. The resulting JSON log might look like: |
| 43 | + |
| 44 | +```json |
| 45 | +{ |
| 46 | + "hostgroup_id": 3, |
| 47 | + "thread_id": 12345, |
| 48 | + "event": "COM_STMT_EXECUTE", |
| 49 | + "username": "dbuser", |
| 50 | + "schemaname": "production", |
| 51 | + "client": "192.0.2.1", |
| 52 | + "server": "10.0.0.5", |
| 53 | + "rows_affected": 1, |
| 54 | + "query": "INSERT INTO foo (bar1, bar2) VALUES (?, ?)", |
| 55 | + "starttime_timestamp_us": 1617181920000000, |
| 56 | + "starttime": "2021-03-31 12:32:00.000000" |
| 57 | + "endtime_timestamp_us": 1617181921000000, |
| 58 | + "endtime": "2021-03-31 12:32:01.000000", |
| 59 | + "duration_us": 1000000, |
| 60 | + "digest": "0x0000000000000001", "client_stmt_id": 101, |
| 61 | + "parameters": [ |
| 62 | + { |
| 63 | + "type": "INT24", |
| 64 | + "value": "42" |
| 65 | + }, |
| 66 | + { |
| 67 | + "type": "VARCHAR", |
| 68 | + "value": "example value" |
| 69 | + } |
| 70 | + ] |
| 71 | +} |
| 72 | +``` |
| 73 | + |
| 74 | +This JSON structure clearly shows each parameter’s type and value, which aids in debugging and analysis. |
| 75 | +## **5. Usage Considerations** |
| 76 | +- **Debuggability:** |
| 77 | +The enhanced logging allows administrators to see the full details of the parameters that are bound to a prepared statement. This is crucial for troubleshooting and performance analysis. |
| 78 | +- **Variable-Length Encoding:** |
| 79 | +Both binary and JSON formats rely on helper functions (`mysql_encode_length()` and `getValueForBind()`) to ensure that variable-length integers and parameter values are handled efficiently and unambiguously. |
| 80 | +- **Thread Safety and Performance:** |
| 81 | +The logging functions acquire write locks just before writing to disk to minimize contention. The design ensures that logging does not adversely impact performance while retaining detailed information. |
| 82 | +## **6. Summary** |
| 83 | +The changes in both `write_query_format_1()` and `write_query_format_2_json()` provide a comprehensive way to log prepared statement parameters: |
| 84 | +- In **binary format**, parameters are logged with a parameter count, a null bitmap, a two-byte parameter type, and then a variable-length encoded value. |
| 85 | +- In **JSON format**, parameters appear as an array of objects under the `"parameters"` key, with each object containing `"type"` and `"value"` fields. |
| 86 | + |
| 87 | +These enhancements aim to improve troubleshooting capabilities and ensure that all necessary information is captured for later analysis. |
0 commit comments