问题还原
在做嵌入式产品时使用了Sqlite3的数据库,发现内存会异常增长,所有写了个Demo进行验证测试。此处仅提出个人的问题、分析和解决的方法,欢迎大神提出建议,共同进步。
CPU:A40i
架构:Cortex-A7
主频:1.2GHz
内存:2GB DDR3
ROM:8GB eMMC
创建表结构不在代码中体现,创建表方法:
CREATE TABLE Table_0_1 (
[Index] INTEGER PRIMARY KEY AUTOINCREMENT
UNIQUE,
Id INT NOT NULL,
Name TEXT (128) NOT NULL,
ValType INT NOT NULL,
Value TEXT (64),
Csq INT,
CreatedTime TIMESTAMP NOT NULL
DEFAULT (datetime(‘now’, ‘localtime’) )
);
#include <iostream>
#include <stdint.h>
#include <sqlite3.h>
using namespace std;
bool g_bAppExitFalge = true;
static void exitSignalCall(const int32_t nSig)
{
g_bAppExitFalge = false;
}
static int32_t registerSignal(void)
{
signal(SIGINT, exitSignalCall);
signal(SIGKILL, exitSignalCall);
signal(SIGTERM, exitSignalCall);
return 0;
}
int main(int argc, char const *argv[])
{
sqlite3 *pDb = NULL;
registerSignal();
int32_t nRet = sqlite3_open("./MySqlite.db", &pDb);
if (SQLITE_OK != nRet) {
cout << "Open err!!!" << endl;
return -1;
}
char szSql[128] = "INSERT INTO Table_0_1 VALUES (1,'TagTest',10,'100',1)";
while(g_bAppExitFalge) {
nRet = sqlite3_exec(pDb, szSql, NULL, NULL, &errMsg);
if (SQLITE_OK != nRet) {
cout << "数据插入错误:" << errMsg << endl;
sqlite3_free(errMsg);
errMsg = NULL;
} else {
if (errMsg) {
cout << "执行正常:" << errMsg << endl;
sqlite3_free(errMsg);
errMsg = NULL;
}
}
sleep(1);
}
sqlite3_close(pDb);
return 0;
}
</sqlite3.h></stdint.h></iostream>
内存会不断增长,直至将内存耗尽;
问题分析
问题初期一直认为是Sqlite3库的问题,所有使用了更高版本的库,还是会出现该问题。所有将代码放到PC虚拟机中执行,发现不会出现内存泄露,会稳定在一个定值。所以分析可能的原因:
所以使用复合的SQL语句,代码如下:
#include <iostream>
#include <stdint.h>
#include <sqlite3.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
using namespace std;
bool g_bAppExitFalge = true;
static void exitSignalCall(const int32_t nSig)
{
g_bAppExitFalge = false;
}
/********************************************************************************************************************
函数描述 : 注册信号处理函数
参 数 : int32_t nSig: 触发信号
返 回 值 : eSuccess: 成功 其他:失败
********************************************************************************************************************/
static int32_t registerSignal(void)
{
signal(SIGINT, exitSignalCall);
signal(SIGKILL, exitSignalCall);
signal(SIGTERM, exitSignalCall);
return 0;
}
int main(int argc, char const *argv[])
{
sqlite3 *pDb = NULL;
char *errMsg = NULL;
int32_t nIndex = 199;
registerSignal();
int32_t nRet = 0;
nRet = sqlite3_open("/extp/DefineTag.db", &pDb);
if (SQLITE_OK != nRet) {
cout << "Open err!!!" << endl;
return -1;
}
printf("Open every one...\n");
char szSql[2048] = "INSERT INTO Table_0_1 (Id,Name,ValType,Value,Csq) "
"SELECT 1,'TagTest',10,'100',1 "
"UNION ALL SELECT 2,'TagTest',10,'100',1 "
"UNION ALL SELECT 3,'TagTest',10,'100',1 "
"UNION ALL SELECT 4,'TagTest',10,'100',1 "
"UNION ALL SELECT 5,'TagTest',10,'100',1 "
"UNION ALL SELECT 6,'TagTest',10,'100',1 "
"UNION ALL SELECT 7,'TagTest',10,'100',1 "
"UNION ALL SELECT 8,'TagTest',10,'100',1 "
"UNION ALL SELECT 9,'TagTest',10,'100',1 "
"UNION ALL SELECT 10,'TagTest',10,'100',1 "
"UNION ALL SELECT 11,'TagTest',10,'100',1 "
"UNION ALL SELECT 12,'TagTest',10,'100',1 "
"UNION ALL SELECT 13,'TagTest',10,'100',1 "
"UNION ALL SELECT 14,'TagTest',10,'100',1 "
"UNION ALL SELECT 15,'TagTest',10,'100',1 "
"UNION ALL SELECT 16,'TagTest',10,'100',1 "
"UNION ALL SELECT 17,'TagTest',10,'100',1 "
"UNION ALL SELECT 18,'TagTest',10,'100',1 "
"UNION ALL SELECT 19,'TagTest',10,'100',1 "
"UNION ALL SELECT 20,'TagTest',10,'100',1;";
while(g_bAppExitFalge) {
nRet = sqlite3_exec(pDb, szSql, NULL, NULL, &errMsg);
if (SQLITE_OK != nRet) {
cout << "数据插入错误:" << errMsg << endl;
sqlite3_free(errMsg);
errMsg = NULL;
} else {
if (errMsg) {
cout << "执行正常:" << errMsg << endl;
sqlite3_free(errMsg);
errMsg = NULL;
}
}
sleep(10);
}
printf("close success...\n");
sqlite3_close(pDb);
pDb = NULL;
sleep(1);
return 0;
}
</stdio.h></unistd.h></signal.h></sqlite3.h></stdint.h></iostream>
内存的消耗比V0.0版本的速度明显减慢,但是经过一晚上的运行,发现内存还是会增长。
针对于V1.0 版本的代码内存还是会增长的问题查资料,看到有人提出这样的分析,所有继续改良代码:
---内存持续增加研究---
原来,数据库是这样设计的:用内存保存数据,以提高增删查改的速度,同时把数据写入磁盘,让数据落地。
如果不删除数据库里的数据,随着数据不断地添加到数据库,数据库越来越大,RES内存也越来越大。
开启如下的删除数据库数据的功能代码后,虽然不断地有新数据添加到数据库,但也一直从数据库中删除着数据。
数据库的数据总量一直保持一定数据的总量,VIRT、RES、SHR长期保存不变。
所以,数据库里已经使用过的数据,应该尽量删除。
或者,每次操作数据库的数据后,要关闭数据库连接,下一次要操作数据库的数据时,再打开连接。
即重复如下逻辑:"打开数据->操作数据库数据->关闭数据库"。
当然,数据库文件也要定期缩减。因为即使你删除了数据库的数据,sqlite3也不会自动缩减数据库。
所以,需要定期执行sql缩减数据库文件命令:"vacuum;"。
#include <iostream>
#include <stdint.h>
#include <sqlite3.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
using namespace std;
bool g_bAppExitFalge = true;
static void exitSignalCall(const int32_t nSig)
{
g_bAppExitFalge = false;
}
/********************************************************************************************************************
函数描述 : 注册信号处理函数
参 数 : int32_t nSig: 触发信号
返 回 值 : eSuccess: 成功 其他:失败
********************************************************************************************************************/
static int32_t registerSignal(void)
{
signal(SIGINT, exitSignalCall);
signal(SIGKILL, exitSignalCall);
signal(SIGTERM, exitSignalCall);
return 0;
}
int main(int argc, char const *argv[])
{
sqlite3 *pDb = NULL;
char *errMsg = NULL;
int32_t nIndex = 199;
registerSignal();
int32_t nRet = 0;
nRet = sqlite3_open("/extp/DefineTag.db", &pDb);
if (SQLITE_OK != nRet) {
cout << "Open err!!!" << endl;
return -1;
}
printf("Open every one...\n");
char szSql[2048] = "INSERT INTO Table_0_1 (Id,Name,ValType,Value,Csq) "
"SELECT 1,'TagTest',10,'100',1 "
"UNION ALL SELECT 2,'TagTest',10,'100',1 "
"UNION ALL SELECT 3,'TagTest',10,'100',1 "
"UNION ALL SELECT 4,'TagTest',10,'100',1 "
"UNION ALL SELECT 5,'TagTest',10,'100',1 "
"UNION ALL SELECT 6,'TagTest',10,'100',1 "
"UNION ALL SELECT 7,'TagTest',10,'100',1 "
"UNION ALL SELECT 8,'TagTest',10,'100',1 "
"UNION ALL SELECT 9,'TagTest',10,'100',1 "
"UNION ALL SELECT 10,'TagTest',10,'100',1 "
"UNION ALL SELECT 11,'TagTest',10,'100',1 "
"UNION ALL SELECT 12,'TagTest',10,'100',1 "
"UNION ALL SELECT 13,'TagTest',10,'100',1 "
"UNION ALL SELECT 14,'TagTest',10,'100',1 "
"UNION ALL SELECT 15,'TagTest',10,'100',1 "
"UNION ALL SELECT 16,'TagTest',10,'100',1 "
"UNION ALL SELECT 17,'TagTest',10,'100',1 "
"UNION ALL SELECT 18,'TagTest',10,'100',1 "
"UNION ALL SELECT 19,'TagTest',10,'100',1 "
"UNION ALL SELECT 20,'TagTest',10,'100',1;";
while(g_bAppExitFalge) {
nRet = sqlite3_exec(pDb, szSql, NULL, NULL, &errMsg);
if (SQLITE_OK != nRet) {
cout << "数据插入错误:" << errMsg << endl;
sqlite3_free(errMsg);
errMsg = NULL;
} else {
if (errMsg) {
cout << "执行正常:" << errMsg << endl;
sqlite3_free(errMsg);
errMsg = NULL;
}
}
sleep(10);
#if 1
nIndex++;
if (nIndex > 200) {
cout << "开始执行删除" << endl;
nRet = sqlite3_exec(pDb, "DELETE FROM Table_0_1 "\
"WHERE julianday('now', 'localtime')-julianday(CreatedTime) >= 0.05;", \
NULL, NULL, &errMsg);
if (SQLITE_OK != nRet) {
cout << "执行删除错误:" << errMsg << endl;
sqlite3_free(errMsg);
} else {
cout << "执行删除成功:" << endl;
}
cout << "开始执行VACUUM:" << endl;
nRet = sqlite3_exec(pDb, "VACUUM;", NULL, NULL, &errMsg);
if (SQLITE_OK != nRet) {
cout << "执行VACUUM错误:" << errMsg << endl;
sqlite3_free(errMsg);
} else {
cout << "执行VACUUM成功:" << endl;
}
nIndex = 0;
}
#endif
}
printf("close success...\n");
sqlite3_close(pDb);
pDb = NULL;
sleep(1);
return 0;
}
</stdio.h></unistd.h></signal.h></sqlite3.h></stdint.h></iostream>
Original: https://blog.csdn.net/qinbo1234567890/article/details/123522480
Author: 古城码农
Title: 使用 Sqlite3内存增长原因复盘
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/815468/
转载文章受原作者版权保护。转载请注明原作者出处!