I've got a problem. I'm using SQLite3 in my C++ project. In the log, I've got errors: DB is locked error code 5
. As I know, error code 5 means that DB is busy. To solve this, I started to use WAL journal mode. But it doesn't help.
In my program, I've got 2 connections to the same DB. I use mutexes for both DB connections. I'm opening connections with this code:
if (sqlite3_open_v2(db_path.c_str(), &this->db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX, 0) ) {
LOG4CPLUS_FATAL(this->logger, "Can not open/create DB " << sqlite3_errmsg(db));
sqlite3_close(this->db);
}
if (sqlite3_exec(this->db, "PRAGMA journal_mode = WAL;", 0, 0, &err)) {
LOG4CPLUS_ERROR(this->logger, "SQL det journal mode error: " << err);
sqlite3_free(err);
}
The first connection is used for inserting data to the DB. It happens 4 times every second.
The second connection is used for starting transaction, selecting, updating, deleting data, and committing. It happens every 5 seconds.
I'm getting errors from the first connection.
Please help me to solve this problem.
Update:
First connection:
void readings_collector::flushToDb()
{
this->db_mutex.lock();
LOG4CPLUS_DEBUG(this->logger, "Flush to DB start.");
const char *query = "INSERT INTO `readings` (`sensor_id`, `value`, `error`, `timestamp`) VALUES (?,?,?,?)";
sqlite3_stmt *stmt = NULL;
int rc = sqlite3_prepare_v2(this->db, query, -1, &stmt, NULL);
if (SQLITE_OK != rc) {
LOG4CPLUS_ERROR(this->logger, "sqlite prepare insert statment error: " << sqlite3_errmsg(this->db));
}
LOG4CPLUS_TRACE(this->logger, "--------------------");
LOG4CPLUS_TRACE(this->logger, this->readings.size());
while(!this->readings.empty()) {
sensor::reading temp_reading = this->readings.front();
this->readings.pop();
LOG4CPLUS_TRACE(this->logger, "Reading " << temp_reading.sensor_id << " : " << temp_reading.value << " : " << temp_reading.error << " : " << temp_reading.timestamp);
sqlite3_clear_bindings(stmt);
sqlite3_bind_int(stmt, 1, temp_reading.sensor_id);
sqlite3_bind_text(stmt, 2, temp_reading.value.c_str(), sizeof(temp_reading.value.c_str()), NULL);
sqlite3_bind_int(stmt, 3, temp_reading.error);
sqlite3_bind_int(stmt, 4, temp_reading.timestamp);
rc = sqlite3_step(stmt);
if (SQLITE_DONE != rc) {
LOG4CPLUS_ERROR(this->logger, "sqlite insert statment exec error: " << sqlite3_errmsg(this->db) << "; status: " << rc);
}
}
sqlite3_finalize(stmt);
LOG4CPLUS_TRACE(this->logger, "Flush to DB finish.");
this->db_mutex.unlock();
}
Second connection:
void dataSend_task::sendData()
{
this->db_mutex.lock();
char *err = 0;
LOG4CPLUS_INFO(this->logger, "Send data function");
if (sqlite3_exec(this->db, "BEGIN TRANSACTION", 0, 0, &err)) {
LOG4CPLUS_ERROR(this->logger, "SQL exec error: " << err);
sqlite3_free(err);
}
if (sqlite3_exec(this->db, this->SQL_UPDATE_READINGS_QUERY, 0, 0, &err)) {
LOG4CPLUS_ERROR(this->logger, "SQL exec error: " << err);
sqlite3_free(err);
}
this->json.clear();
this->readingsCounter = 0;
if (sqlite3_exec(this->db, this->SQL_SELECT_READINGS_QUERY, +[](void *instance, int x, char **y, char **z) {
return static_cast<dataSend_task *>(instance)->callback(0, x, y, z);
}, this, &err)) {
LOG4CPLUS_ERROR(this->logger, "SQL exec error: " << err);
sqlite3_free(err);
} else {
LOG4CPLUS_TRACE(this->logger, "Json data: " << this->json);
if (this->curlSend()) {
if (sqlite3_exec(this->db, this->SQL_DELETE_READINGS_QUERY, 0, 0, &err)) {
LOG4CPLUS_ERROR(this->logger, "SQL exec error: " << err);
sqlite3_free(err);
}
}
}
if (sqlite3_exec(this->db, "COMMIT", 0, 0, &err)) {
LOG4CPLUS_ERROR(this->logger, "SQL exec error: " << err);
sqlite3_free(err);
}
this->db_mutex.unlock();
this->json.clear();
}