h1

Sqlite3: «database is locked» en C++

23/11/2009

Utilizando la API de Sqlite 3 en C++ puede ocurrir el caso de acceder a una base de datos y tras una consulta, quedar ésta bloqueada, produciendo un mensaje de error «database is locked» y en el caso de terceras aplicaciones, generando una consulta «SELECT name FROM sqlite_master WHERE type = ‘table’» que en nada se relaciona con la base de datos en uso. Esto se debe a que si al intentar una base de datos se produce un error, se crea una auxiliar básica que en la mayoría de las veces no sirve para nada.

En el siguiente código se puede comprobar, si se invoca dos o más veces, el error:

CÓDIGO ERRÓNEO - WRONG CODE
std::integer countCrimes (string selectedCrimeID, std::vector trainingFileSet, string pathDB){
sqlite3* db;
char* db_err;
sqlite3_stmt *stmt;

cout << "Openning DB connection" << endl;
string SQLquery = "select count(*) from crimes";
sqlite3_open_v2( pathDB.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
int rc = sqlite3_prepare_v2(db, SQLquery.c_str(), strlen(SQLquery.c_str()), &stmt, NULL);
if (SQLITE_OK != rc) { cout << sqlite3_errmsg(db) << endl; //En el segundo acceso a la BD mostrará "database is locked"}
sqlite3_exec(db, SQLquery.c_str() , NULL, 0, &db_err);

sqlite3_step(stmt);
long int occurrencesFound = atoi (sqlite3_column_name(stmt, 0));
std::cout << occurrencesFound << "files hashes of crime " << selectedCrimeID << " in data base."<< endl;

sqlite3_close(db);
sqlite3_free(db_err);
return trainingFileSet;
}

Pese a que se cierra la conexión y aparentemente todo se realiza correctamente, el problema viene por no incluir la orden que indica a Sqlite que el resultado de esa sentencia SQL ya ha sido recibida y por tanto puede continuar procesando las siguientes que vengan, ya que la base de datos se queda bloqueada por la actual sentencia sql. Por lo tanto, siempre que se ejecute una instrucción, hay que utilizar el método sqlite3_finalize(stmt) para no dejar bloqueada la base de datos.

std::integer countCrimes (string selectedCrimeID, std::vector trainingFileSet, string pathDB){
sqlite3* db;
char* db_err;
sqlite3_stmt *stmt;

cout << "Openning DB connection" << endl;
string SQLquery = "select count(*) from crimes";
sqlite3_open_v2( pathDB.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
int rc = sqlite3_prepare_v2(db, SQLquery.c_str(), strlen(SQLquery.c_str()), &stmt, NULL);
if (SQLITE_OK != rc) { cout << sqlite3_errmsg(db) << endl; }
sqlite3_exec(db, SQLquery.c_str() , NULL, 0, &db_err);

sqlite3_step(stmt);
long int occurrencesFound = atoi (sqlite3_column_name(stmt, 0));
std::cout << occurrencesFound << "files hashes of crime " << selectedCrimeID << " in data base."<< endl;

sqlite3_finalize(stmt);

sqlite3_close(db);
sqlite3_free(db_err);
return trainingFileSet;
}

Fuentes: Igor Tandetnik, DMertl

Un comentario

  1. Very nice blog you haave here



Deja un comentario

Este sitio utiliza Akismet para reducir el spam. Conoce cómo se procesan los datos de tus comentarios.