[Maria-discuss] Question about MariaDB Non-blocking Client
Greetings, I'm using the MariaDB Non-blocking API to write a C++ client, but I've hit a wall regarding connection checking. I've been referencing the binding from node-mariasql ( https://github.com/mscdex/node-mariasql/blob/master/src/binding.cc). My app parses a config and creates new objects for each query, where each object has a MYSQL struct and MYSQL *pointer. Then, for each I set state to STATE_CONNECT and call doWork(). This works fine, when I can connect right away. The problem I'm experiencing is if I have a connection and kill the server (/etc/init.d/mysql stop) and then start it back (/etc/init.d/mysql start), I can never get clean reconnects. It's usually a mixture of errcode 2058, 2003, 2013. I'm really confused how to gracefully manage connections. Before I was using the official MySQL C++ connector, and it provides a connection->isConnected() method. I'm wondering how I can get something similar with MariaDB's client, as I need the non-blocking interface. Given: MYSQL mysql, *mysqlHandle; Look at the mysql_real_connect_start() or cont() functions. I provide MYSQL struct and on connect I get a copy of the struct stored in *mysqlHandle. It's not clear to me what the purpose of the copy is at this point as I still use the initial struct to call query(). In the case that I can detect a disconnection, how do I properly clean up the connection and attempt reconnect? Do I mysql_close(&mysql) and/or mysql_close(mysqlHandle), shutdown/close the file descriptor, mysql_init() a new handle and go through mysql_real_connect_start/cont()? Does it even make sense for each object to have its own MYSQL struct that I mysql_init(), or would it be better to have layer on top that mysql_init()s a single MYSQL struct, connects, and passes the returned *mysqlHandle to each query? Thanks for providing the async client, any help is appreciated.
Mike Gibson <notmikegibson@gmail.com> writes:
Greetings,
Hi, sorry for taking a few days to get back to you:
I'm using the MariaDB Non-blocking API to write a C++ client, but I've hit a wall regarding connection checking. I've been referencing the binding from node-mariasql ( https://github.com/mscdex/node-mariasql/blob/master/src/binding.cc).
Ok, great that you can use the non-blocking API!
The problem I'm experiencing is if I have a connection and kill the server (/etc/init.d/mysql stop) and then start it back (/etc/init.d/mysql start), I can never get clean reconnects. It's usually a mixture of errcode 2058, 2003, 2013.
I'm really confused how to gracefully manage connections. Before I was using the official MySQL C++ connector, and it provides a connection->isConnected() method. I'm wondering how I can get something similar with MariaDB's client, as I need the non-blocking interface.
I am not familiar with the MySQL C++ connector. I tried downloading the source for mysql-connector-c++-1.1.3.tar.gz, but it does not seem to have any isConnected() method? Anyway, the usual way to do this is to issue a mysql_ping() to the server, to check if the connection is working. With the non-blocking API, you would do this with mysql_ping_start() and mysql_ping_cont(). This will issue a request to the server to check if the connection is ok. If you have autoconnect enabled (MYSQL_OPT_RECONNECT), then this will automatically reconnect if the old connection was broken for some reason. (Note that you will need to be aware of the usual issues with automatic reconnect. For example, even if ping is successful, the connection may break immediately afterwards. And an autoconnect will loose any existing state on the connection such as temporary tables, SET @user_var, BEGIN, etc.)
Given: MYSQL mysql, *mysqlHandle;
Look at the mysql_real_connect_start() or cont() functions. I provide MYSQL struct and on connect I get a copy of the struct stored in *mysqlHandle. It's not clear to me what the purpose of the copy is at this point as I still use the initial struct to call query().
Agree, it is not very useful, it is just a copy of the pointer to your own structure. You only need it to check for error (in which case the pointer will be NULL). After that you can just you the pointer to your own struct that you already have.
In the case that I can detect a disconnection, how do I properly clean up the connection and attempt reconnect? Do I mysql_close(&mysql) and/or mysql_close(mysqlHandle), shutdown/close the file descriptor, mysql_init() a new handle and go through mysql_real_connect_start/cont()?
I am not sure, but it seems to me from looking at the code that if you already got an error that the connection was closed, then you can just go through the mysql_real_connect_start/cont() sequence again to reconnect. But if that does not work, you can always mysql_close() and mysql_init() your struct again. There is no need to explicitly shutdown or close the file descriptor.
Does it even make sense for each object to have its own MYSQL struct that I mysql_init(), or would it be better to have layer on top that mysql_init()s a single MYSQL struct, connects, and passes the returned *mysqlHandle to each query?
This depends on your application. You can only have a single query in progress on one MYSQL struct at a time. So if you have multiple queries working at the same time on the server, you need one MYSQL struct for each. If you only have one query processing at a time, a single MYSQL struct will be sufficient.
Thanks for providing the async client, any help is appreciated.
I hope this helps, though it is of a somewhat generic nature. If you need more details, please ask again, perhaps with some example code that shows your problems. - Kristian.
Thanks, Kristian. This cleared up a lot for me. I'll implement the async mysql_ping() and follow up if I have any serious issues. On Wed, Aug 7, 2013 at 7:33 AM, Kristian Nielsen <knielsen@knielsen-hq.org>wrote:
Mike Gibson <notmikegibson@gmail.com> writes:
Greetings,
Hi, sorry for taking a few days to get back to you:
I'm using the MariaDB Non-blocking API to write a C++ client, but I've hit a wall regarding connection checking. I've been referencing the binding from node-mariasql ( https://github.com/mscdex/node-mariasql/blob/master/src/binding.cc).
Ok, great that you can use the non-blocking API!
The problem I'm experiencing is if I have a connection and kill the server (/etc/init.d/mysql stop) and then start it back (/etc/init.d/mysql start), I can never get clean reconnects. It's usually a mixture of errcode 2058, 2003, 2013.
I'm really confused how to gracefully manage connections. Before I was using the official MySQL C++ connector, and it provides a connection->isConnected() method. I'm wondering how I can get something similar with MariaDB's client, as I need the non-blocking interface.
I am not familiar with the MySQL C++ connector. I tried downloading the source for mysql-connector-c++-1.1.3.tar.gz, but it does not seem to have any isConnected() method?
Anyway, the usual way to do this is to issue a mysql_ping() to the server, to check if the connection is working. With the non-blocking API, you would do this with mysql_ping_start() and mysql_ping_cont(). This will issue a request to the server to check if the connection is ok. If you have autoconnect enabled (MYSQL_OPT_RECONNECT), then this will automatically reconnect if the old connection was broken for some reason.
(Note that you will need to be aware of the usual issues with automatic reconnect. For example, even if ping is successful, the connection may break immediately afterwards. And an autoconnect will loose any existing state on the connection such as temporary tables, SET @user_var, BEGIN, etc.)
Given: MYSQL mysql, *mysqlHandle;
Look at the mysql_real_connect_start() or cont() functions. I provide MYSQL struct and on connect I get a copy of the struct stored in *mysqlHandle. It's not clear to me what the purpose of the copy is at this point as I still use the initial struct to call query().
Agree, it is not very useful, it is just a copy of the pointer to your own structure. You only need it to check for error (in which case the pointer will be NULL). After that you can just you the pointer to your own struct that you already have.
In the case that I can detect a disconnection, how do I properly clean up the connection and attempt reconnect? Do I mysql_close(&mysql) and/or mysql_close(mysqlHandle), shutdown/close the file descriptor, mysql_init() a new handle and go through mysql_real_connect_start/cont()?
I am not sure, but it seems to me from looking at the code that if you already got an error that the connection was closed, then you can just go through the mysql_real_connect_start/cont() sequence again to reconnect. But if that does not work, you can always mysql_close() and mysql_init() your struct again. There is no need to explicitly shutdown or close the file descriptor.
Does it even make sense for each object to have its own MYSQL struct that I mysql_init(), or would it be better to have layer on top that mysql_init()s a single MYSQL struct, connects, and passes the returned *mysqlHandle to each query?
This depends on your application. You can only have a single query in progress on one MYSQL struct at a time. So if you have multiple queries working at the same time on the server, you need one MYSQL struct for each. If you only have one query processing at a time, a single MYSQL struct will be sufficient.
Thanks for providing the async client, any help is appreciated.
I hope this helps, though it is of a somewhat generic nature. If you need more details, please ask again, perhaps with some example code that shows your problems.
- Kristian.
participants (2)
-
Kristian Nielsen
-
Mike Gibson