Although a debugger can be used to debug a specific instance of your application, you may find it beneficial to enable the debug traces of the connector. Some problems happen randomly which makes them difficult to debug using a debugger. In such cases, debug traces and protocol files are more useful because they allow you to trace the activities of all instances of your program.
Connector/C++ can write two trace files:
A trace file generated by the MySQL client library
A trace file generated internally by Connector/C++
The first trace file can be generated by the underlying MySQL
client library (libmysqlclient
). To enable this
trace, the connector calls the
mysql_debug()
C API function
internally. Because only debug versions of the MySQL client
library are capable of writing a trace file, compile Connector/C++
against a debug version of the library to use this trace. The
trace shows the internal function calls and the addresses of
internal objects as shown here:
>mysql_stmt_init
| >_mymalloc
| | enter: Size: 816
| | exit: ptr: 0x68e7b8
| <_mymalloc | >init_alloc_root
| | enter: root: 0x68e7b8
| | >_mymalloc
| | | enter: Size: 2064
| | | exit: ptr: 0x68eb28
[...]
The second trace is the Connector/C++ internal trace. It is available
with debug and nondebug builds of the connector as long as you
have enabled the tracing module at compile time. By default,
tracing functionality is not available and calls to trace
functions are removed by the preprocessor. To enable the tracing
module, configure Connector/C++ with the
-DMYSQLCPPCONN_TRACE_ENABLE=1
CMake option.
Compiling the connector with tracing functionality enabled causes two additional tracing function calls per each connector function call. For example:
| INF: Tracing enabled
<MySQL_Connection::setClientOption
>MySQL_Prepared_Statement::setInt
| INF: this=0x69a2e0
| >MySQL_Prepared_Statement::checkClosed
| <MySQL_Prepared_Statement::checkClosed
| <MySQL_Prepared_Statement::setInt
[...]
Run your own benchmark to find out how much this will impact the performance of your application.
A simple test using a loop running 30,000
INSERT
SQL statements showed no
significant real-time impact. The two variants of this application
using a trace enabled and trace disabled version of the connector
performed equally well. The runtime measured in real time was not
significantly impacted as long as writing a debug trace was not
enabled. However, there will be a difference in the time spent in
the application. When writing a debug trace, the I/O subsystem may
become a bottleneck.
In summary, use connector builds with tracing enabled carefully. Trace-enabled versions may cause higher CPU usage even if the overall runtime of your application is not impacted significantly.
The example from examples/debug_output.cpp
demonstrates how to activate the debug traces in your program.
Currently they can only be activated through API calls. The traces
are controlled on a per-connection basis. You can use the
setClientOption()
method of a connection object
to activate and deactivate trace generation. The MySQL client
library trace always writes its trace to a file, whereas the
connector writes protocol messages to the standard output.
sql::Driver *driver;
int on_off = 1;
/* Using the Driver to create a connection */
driver = get_driver_instance();
std::auto_ptr< sql::Connection > con(driver->connect(host, user, pass));
/*
Activate debug trace of the MySQL client library (C API)
Only available with a debug build of the MySQL client library!
*/
con->setClientOption("libmysql_debug", "d:t:O,client.trace");
/*
Connector/C++ tracing is available if you have compiled the
driver using cmake -DMYSQLCPPCONN_TRACE_ENABLE:BOOL=1
*/
con->setClientOption("clientTrace", &on_off);