本篇文章旨在探讨sqlite数据库的事务处理。
关于sqlite,我封装了几个类方法方便调用sqlite,课参考我的开源项目,欢迎广大网友加入项目中一起优化这个项目!
好了接下来先贴上测试程序代码:
#include <cstring>
#include "./Wtime.h"
#include <sys/time.h>
#include <unistd.h>
#include "./main.hpp"
typedef struct {
bool output;
bool timing;
} dbCfg_t;
int test_exec(int argc, char* argv[])
{
class sql::sqlite* handle;
struct timeval start,end;
dbCfg_t cfg;
std::string sqlCmd;
if (argc>2) {
handle = new sql::sqlite(argv[2]);
if (handle == nullptr) {
std::cout << "数据库[" << argv[2] << "]打开失败!" << std::endl;
return -1;
}
} else {
std::cout << "参数错误:输入正确的参数,如:./app 6 database.db" << std::endl;
return -1;
}
//memset (&cfg, 0, sizeof (TdbCfg));
cfg.timing = true;
cfg.output = true;
while (1) {
std::cout << ">";
//std::cin >> sqlCmd;
std::getline (std::cin, sqlCmd);
if (sqlCmd == "help") {
std::cout << "[帮助]" << std::endl;
std::cout << "output disable:关闭查询输出" << std::endl;
std::cout << "output enable:打开查询输出" << std::endl;
std::cout << "timing disable:关闭计时器" << std::endl;
std::cout << "timing enable:打开计数器" << std::endl;
std::cout << "exit:退出" << std::endl;
} else if (sqlCmd == "output disable") {
cfg.output = false;
} else if (sqlCmd == "output enable") {
cfg.output = true;
} else if (sqlCmd == "timing disable") {
cfg.timing = false;
} else if (sqlCmd == "timing enable") {
cfg.timing = true;
} else if (sqlCmd == "exit") {
delete handle;
return 0;
} else {
gettimeofday (&start, NULL);
cfg.output?handle->exec (sqlCmd.c_str(), test_callback):handle->exec (sqlCmd.c_str());
//sleep (1);
gettimeofday (&end, NULL);
if (cfg.timing) {
std::cout << "耗时:" << (end.tv_sec-start.tv_sec)*1000 + (end.tv_usec-start.tv_usec)/1000 << " ms,";
std::cout << (end.tv_usec-start.tv_usec)%1000 << " us" << std::endl;
}
}
sqlCmd.clear ();
}
}
首先创建表和插入两条记录
然后开启事务,插入一条记录后执行回滚操作
如图中效果所示,回滚之后插入的数据没有了。现在来试试插入数据后提交。
如图中所示,插入的数据保存在了数据库中。接下来测试一下未提交时的查询。
执行回滚后记录被撤回了。
现在来试试多进程间的事务处理关系。
左边窗口执行事务,在开启事务后插入了一条数据,但是还没有提交或回滚,此时在右边窗口执行查询操作,结果查不到刚刚插入的数据,说明事务是线程互斥的。
在一个进程开启事务后,另一个进程插入记录会报错,显示数据库被锁住了。