DatabaseCampaign: MySQL / concurrency fixes

According to
<http://dev.mysql.com/doc/refman/5.5/en/c-api-threaded-clients.html>,
a MySQL connection handle must not be used concurrently with an open
result set and mysql_use_result() in one thread
(DatabaseCampaign::run()), and mysql_query() in another
(DatabaseCampaign::collect_result_thread()).  This indeed leads to
crashes when bounding the outgoing job queue (SERVER_OUT_QUEUE_SIZE),
and maybe even more insidous effects in other cases.  The solution is
to create separate connections for both threads.

Additionally, call mysql_library_init() before spawning any threads.

Change-Id: I2981f2fdc67c9a2cbe8781f1a21654418f621aeb
This commit is contained in:
Horst Schirmeier
2013-12-02 19:33:24 +01:00
parent 0907dfb0ae
commit 33b63651ae
4 changed files with 41 additions and 12 deletions

View File

@ -13,8 +13,9 @@
namespace fail {
class DatabaseProtobufAdapter {
Database *db;
Database *db, *db_insert;
MYSQL_STMT *stmt;
std::stringstream insert_stmt;
void error_create_table();
@ -192,8 +193,20 @@ class DatabaseProtobufAdapter {
public:
DatabaseProtobufAdapter() : db(0), top_level_msg(0, 0, 0) {}
void set_database_handle(Database *db) { this->db = db; }
DatabaseProtobufAdapter() : db(0), db_insert(0), stmt(0), top_level_msg(0, 0, 0) {}
void set_database_handle(Database *db)
{
this->db = db;
if (!db_insert) {
db_insert = db;
}
}
/**
* Set a different database handle to be used in insert_row(). Necessary
* if INSERTs are done in a separate thread, while the handle set with
* set_database_handle() is still in use concurrently.
*/
void set_insert_database_handle(Database *db) { db_insert = db; }
void create_table(const google::protobuf::Descriptor *);
bool insert_row(const google::protobuf::Message *msg);
std::string result_table() { return result_table_name; }