最近又测试了一下内存数据库sqlite,发现功能增强了好多,比如多线程支持(用文件锁的方式实现的),并且也可以全内存化(用":memory:"的方式打开即可)了。
由于多线程的支持是通过操作系统文件锁的方式实现的,所以当以全内存数据库(即无磁盘文件)的方式打开sqlite时,就不支持多线程了,必须自行实现读写锁以互斥,推荐使用ACE读写锁。
由于sqlite的锁是文件锁的方式实现,所以它不能实现表级锁,而只能是全数据库文件锁。另外,线程间不能以共享数据库指针的方式实现共享,而要分别打开一个sqlite实例,互斥机制才能正确的工作。所以,如果你使用":memory:"的方式打开sqlite,不同线程之间很难共享一个数据库(每一个线程都打开了一个全新的实例),如果你简单的通过指针来共享,又会造成互斥机制不能正常工作,这个矛盾我还没有找到解决办法。
经过测试,发现sqlite和自己实现的数据结构(比如STL)的性能还是有一定差距,比如我遍历一个query的结果集的时间通常在几十毫秒(时间主要和记录集大小有关,几十毫秒是几十到几百条记录的结果),不过考虑到方便的存储和实现索引﹑事务等功能,这个开销还是值得的。
使用时注意如果你要使用显示事务(默认的DML语句操作使用autocommit模式),要自行控制重试,而不能像一般的网络数据库那样,由数据库连接进行阻塞等待,sqlite在你申请事务时会直接返回,不管成功与否;但你可以用下面的方法自行控制:
测试时,我用到了几个CodeProject网站上发表的封装类:
1)ODBC的封装类CODBCDatabase,CODBCRecordset
2)sqlite的封装类Cppsqlite
3)对象池的封装类PoolMgr
这些类都是比较好的封装类,可以轻易地集成进自己的应用。我还特地实现了几个直接通过ODBC把网络数据库的内容转到sqlite的通用函数,这样,可以轻易地进行本地应用的数据初始化(特别当这些初始数据来自于网络数据库时),还可以用几句话就为这些数据建立合适的索引,起到真正的内存数据库的作用。
原文链接:https://www.f2er.com/sqlite/203166.html