Qt中针对SQLite的并发访问

问题:SQLite是一种文件级别的数据库,因此他的锁机制也是文件级别的,只支持并发读访问数据库,不支持并发写,也不支持并发读写。只要有一个线程进行写操作,其他线程都将等待,如果同时执行读写操作,会返回SQLite_Busy。因此对于写操作是需要串行执行的。

解决方案:

  • 1.最初是想通过循环执行,如果query.exec执行失败,那么会循环直到执行成功为止,但是我看了下Qt的文档,以及网上查了资料,并没有找到Qt对SQLite_Busy错误返回的相关资料,Qt文档仅提供下列的error type。

QSqlError::NoError     0    没有错误发生
QSqlError::ConnectionError  1   (数据库)连接错误
QSqlError::StatementError  2    SQL语句语法错误
QSqlError::TransactionError  3    事务失败错误
QSqlError::UnknownError   4    未知错误

重新翻了翻qt assistant,在QSqlDataBase页的void QSqlDatabase::setConnectOptions(const QString &options = QString())让我找到了QSQLITE_BUSY_TIMEOUT
在这里插入图片描述
文档中关于这些option的使用也提供了一个例子:

  // MySQL connection
  db.setConnectOptions("SSL_KEY=client-key.pem;SSL_CERT=client-cert.pem;SSL_CA=ca-cert.pem;CLIENT_IGNORE_SPACE=1"); // use an SSL connection to the server
  if (!db.open()) {
      db.setConnectOptions(); // clears the connect option string
      ...
  }
  ...
  // PostgreSQL connection
  db.setConnectOptions("requiressl=1"); // enable PostgreSQL SSL connections
  if (!db.open()) {
      db.setConnectOptions(); // clear options
      ...
  }
  ...
  // ODBC connection
  db.setConnectOptions("SQL_ATTR_ACCESS_MODE=SQL_MODE_READ_ONLY;SQL_ATTR_TRACE=SQL_OPT_TRACE_ON"); // set ODBC options
  if (!db.open()) {
      db.setConnectOptions(); // don't try to set this option
      ...
  }
  • 2.新增一条专门执行写操作的任务队列,其由一条专属线程维护,只要task任务线程有写操作就将他push到任务队列中(push应该push一个包含写操作命令类型cmdtype和data的封装,然后任务队列会根据cmdtype来调用不同的数据库操作函数,并将data作为实参传入)
  • 3.信号量或锁。只要执行写操作,都要先加锁或者先查看信号量,如果信号量为1,那么获取信号量,并将他置0,执行完后解锁或归还信号量 。
    • 3.1在第3个方案的基础上,要降低数据库的压力,尽量减少对数据库的访问,特别是并发争夺一个资源的写操作时,可以在应用程序一启动时,将待抢夺资源全部导入到应用程序的缓存当中,比如放入Qset(针对每种资源只有一个,第一个线程夺取后就从set中remove)或者QHash<QString,int>容器(可针对一种资源多个数量),当有新增资源时,会同时更新数据库和缓存。当要争夺资源的时候,使用锁来处理其并发情况。当接到用户请求资源的情况下,先将资源数量递减(加锁/解锁)后再进行其他方面的处理,处理失败在将数量递增1(加锁/解锁),否则表示处理成功。当资源数量递减到0时,表示资源抢夺完毕,拒绝其他用户的请求。
总结:

实际应用中,并不是让数据库去直面大并发读写,会借助“外力”,比如缓存、利用主从库实现读写分离、分表、使用队列写入等方法来降低并发读写。特别是对于sqlite来说,相较于mysql等数据库毕竟缺乏了许多功能(例如乐观锁、悲观锁),所以更多还是要在应用层上下功夫来处理并发。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值