本文试图对数据库异步操作进行一个入门式的介绍,并且对在应用中常遇到的简单的问题给出方案建议.
文档结构:
- 数据库的同步和异步
- websql
- 异步下的一些状况和方案
1.数据库的异步和同步
通常我们使用DB的方式都是同步的:连接上DB后,我们发起一个sql操作请求,等待操作结束和结果返回后,继续下一步操作。这个等待的过程会导致:
1.之后的操作在结果返回前不会被执行;
2.等待导致被动阻塞,被动阻塞甚至不会释放相关资源,从而进一步造成资源闲置。因此,同步方式的缺点在于并发能力随着sql操作请求耗时的增加而急剧降低,尤其当某一步sql操作耗时较大时
我们也可以选择使用异步的方式来操作DB:连接上DB后,我们发起一个sql操作请求,同时定义一个该sql操作完成后被触发执行的方法,然后程序不进行任何等待,直接做下一步的操作。真正的sql操作在另一个时刻被单独执行,完成后调用我们定义好的方法。由于DB操作通常是最耗费时间的,因此在异步操作中,常常是程序的主流程很快的被执行完成,而大部分的DB操作甚至还没有开始,他们会在随后开始运行,但此时已不再有被堵塞的线程了——就像一个蓄水池,把过量的河水拦住,避免洪水泛滥。
异步操作常常依赖于回调的方式,从而把原本顺序的连贯的逻辑拆开来放在不同的地方,复杂情况下就有点四分五裂的感觉了.考虑到容错和异常处理的话,在代码组织和维护上就需要大大的费神了。对于异步操作的简化需要语言级别的支持,而对于常见的js和java而言,缺乏更加强大的机制,因此回调是唯一选择
当然,对于DB本身而言,都是同步的。不存在一个叫‘异步数据库’的产品。
2.WebSQL
在.net平台上,提供了这种异步操作DB的方式,并且支持的相当优雅。而Java用户可以参考ADBCJ。本文则要谈的是另一个平台:浏览器上的类似产品,相对前者而言有些简陋的WebSQL。
WebSQL包括一个sqlite3数据库和一个同时支持同步和异步方式的API,支持这个WebSQL的浏览器有chrome,safari和opera。原本WebSQL是被当做HTML5的一部分被推广的,但是最近'有关部门'停止了维护,在将来会由‘indexedDB’所取代,同样的,‘indexedDB’也支持异步的方式。
WebSQL主要用于在客户端存储一些较为复杂的关系型数据,这些数据需要能够按照多种条件组合被查询出来;如果仅仅是通过key/id来查询数据的,可以适用简单的支持更广泛的localStorage。
对于支持WebSQL的浏览器,可以通过db = openDatabase(‘WebDB’, '1.0', 'db on client side', 1 * 1024 * 1024) 获取数据库的连接,如果指定的数据库不存在,在浏览器端创建一个名为WebDB,版本为1.0, 大小1M的数据库。
----WebSQL的基本使用
上文中,获取到的db是一个js对象,里面封装了异步使用数据库的方法。
假设DB中有表blogs{id, title, gmtCreate}, 页面依赖了jQuery
var lastId = 10;
db.transaction() {
function(t) {
t.executeSql('select * from blogs where id > ? limit 5 order by id asc', [lastId], function(t, result){
$('.blogs').append('' + result.title + '');
})
}
}
这一段代码做的事情是:把id>lastId的5条记录按照先后顺序展示在blogs列表中。
这段代码背后的执行过程是这样的:
1. executeSql执行的时候,仅仅是把要执行的sql语句和对应的回调方法推送到一个全局队列S中,然后马上返回
2. 接下来的某个时候,全局队列S中的sql语句按序被调用
3. 当sql成功返回时,对应的回调方法(连同sql执行结果)会被推送到另一个全局队列C中,执行sql的程序马上返回
4. 接下来的某个时候,全局队列C中的回调方法按序被调用,从而完成整个执行过程
在这里可以找到关于WebSQL的详细规范和API文档
3.异步下的一些状况
3.1 数据过时问题
在js中,定义的回调函数是可以使用定义外的一些数据的,假设全局有个counter的变量,负责sql执行次数的统计,我们需要在sql执行完后把’自己是第几个执行的sql‘打印出来。在同步方式下,我们会把这个counter++放在sql执行的语句之后,然后输出counter;但是在异步方式下,我们必须把这个步骤放进回调函数中,而不是t.executeSQL()之后,因为sql真正的执行常常是在这个函数调用完成之后做的,这意味着,当回调函数开始执行的时候,counter的值已经被累加过了,如果executeSQL()多调用了几次,那么counter的数值就会被多次累加并且所有的回调函数中输出的counter都是一个值
这也要求我们,对于引用外部的值需要保持刻意的谨慎,一方面,它随时可能被改动;另一方面,对它的改动很可能不是按照你预期的方式进行的
最理想的方式所有需要用的数据都在’推送回调函数至全局队列C‘这个步骤时都一起传给回调函数,保证数据之间的隔离。但是对于WebSQL,我们看到它的API并不支持这么自由的应用方式,并且它现在已经停止维护了。
所以退而求其次的,我们尽量将会造成影响的改动推迟到回调函数中去完成。
3.2 最后的输出问题
在饭店,无论多么的和服务员异步,她最后总得说一句:“菜已经齐了,先生”,这句话就是’最后的输出‘。操作数据库的时候,很少是一个表就能完成的,碰到需要同时去多个表拿数据组装的场合,我们就得知道那个所有数据都查询到并组装好的’菜齐了的‘时刻。
同步场合下,这根本不是个问题,大不了就一直死等下去,但只要返回了,数据就一定有了。
异步场合下,这几个sql各干各的,回调函数彼此平行,互不了解,就不知道是不是全部数据都有了。为了解决这个问题,通常需要引入一个对所有相关回调函数都知道并可以操作的变量,从而对全局有整体的了解。
这个变量可以是,比如状态表,当状态表中的所有状态都是’OVER‘的时候,我们就知道全部’OVER‘了;又比如计数器,要求计数到指定阀值。根据“数据过时问题”中的描述,对这个变量的更改操作需要放进回调函数中去。
参考Java中的Barrier,其原理是,要求指定数量的线程完成某个操作后,程序才继续往下走, 我们可以设置一个Barrier形式的变量b,在executeSQL()调用前b.counter+1,在对应的回调函数执行后,b.counter-1,当b.counter再度回到0的时候,表示’全部执行完毕‘;如果预先知道sql执行的次数,则设置b.counter,并且省略'调用前b.counter+1'的步骤。这种方式主要解决,状态表复杂或者计数阀值预先不可知的情况
在异步场合下,感知’菜齐了‘的方式当然也是异步的,在变量中封装几个方法吧。
3.3 应用设计
无论是同步还是异步,都只有针对应用场景作最优设计才能最大限度的发掘系统潜力,神奇的应用设计一样具有把异步处理’化神奇为腐朽‘的能力。
比如,我们知道DB操作时非常消耗时间的,如果你把一次调用做成调用三次,那么你就过度给力了。在WebSQL中,由于executeSQL()没有提供对where id in(某个数组)操作的原生支持,需要我们自己去做些额外的操作,像自己拼装sql或者根据该数组大小来拼装带对应数目的’?‘的sql。如果不注意直接在数组循环里逐个调用sql,耗时就会成倍增加。
又比如,上文所讲,不可能全部异步,总会有一些环节是要严格按照先后顺序的,比如这么一个场景:user(id, name) box(id, uid), thing(id, bid, what),必须要知道user,才可以查到box,继而才能查到thing,响应时间是比较长的,因为查到user后,查询box的sql会推入到全局队列等待调度,而在同步场合下是没有这个等待时间的,它会被立刻执行。这意味着这种环节数越多,一个请求的响应时间就越长,因此必须减少环节数,增加单个环节并行执行的sql数。对于例子中的解决办法,如果这种获取是常用的,则可能的方式是在thing中冗余一个uid,从而在user获取到后,并发执行两个查询:box和thing。
分享到:
相关推荐
本学习实例将深入探讨WebSQL的基本概念、功能、使用方法以及注意事项。 1. **WebSQL概述** - WebSQL基于SQLite数据库引擎,为Web应用程序提供了结构化的存储能力。 - 它是W3C的一个草案,但目前已被弃用,推荐...
尽管现在更多的前端开发倾向于使用 IndexedDB 或者 LocalStorage,但 WebSQL 依然在一些项目中发挥着作用,尤其是对于那些需要复杂查询操作的应用。 WebSQL API 基于 SQLite3,SQLite3 是一个轻量级的关系型数据库...
9. **替代方案**:由于Web SQL Database的标准化问题,现代浏览器更倾向于使用IndexedDB和Web Storage(包括localStorage和sessionStorage)。IndexedDB提供类似的关系型数据存储,而Web Storage则更简单,适合存储...
本篇文章将详细探讨JavaScript离线存储的使用,特别是如何通过简单而功能强大的API——localForage来改进传统的IndexedDB、WebSQL或localStorage。 1. **离线存储的重要性** 在移动设备和Web应用日益普及的今天,...
标题中的“indexeddb-vs-websql”涉及到的是两种在浏览器端进行本地数据存储的技术:WebSQL和IndexedDB。这两种技术都是为了让网页应用能在用户设备上持久化存储数据,从而提高性能,减少网络通信,实现离线应用等...
WebSQL和IndexedDB都是浏览器本地存储技术,但随着WebSQL被弃用,开发者逐渐转向使用IndexedDB。这个“WebSQL到IndexedDB的示例:待办事项列表示例”是帮助开发者理解如何从WebSQL平滑过渡到IndexedDB的一个实用教程...
但随着数据量增加,IndexedDB的异步处理和索引机制使其在读写速度上超越WebSQL。 2. **数据量**:IndexedDB支持更大的数据存储量,对于需要大量本地存储的应用更有利。 3. **查询效率**:WebSQL的SQL查询语言对复杂...
然而,需要注意的是,由于Web SQL Database已被废弃,新的开发项目通常会转向使用IndexedDB或localStorage等更现代的存储方案。尽管如此,理解如何使用这些HTML5的旧特性仍然是有益的,因为它们在某些特定场景下仍...
7. **未来发展趋势**:由于Web SQL的局限性和不再更新,开发者更倾向于使用更现代的Web存储技术,如IndexedDB和Web Storage(Local Storage和Session Storage)。然而,理解Web SQL的概念和技术仍然是了解Web存储...
1. **完整的SQL支持**:WebSQL允许开发者使用标准的SQL语法进行数据操作,如CREATE, INSERT, UPDATE, DELETE等,这使得对数据的管理和处理更为灵活。 2. **大容量存储**:相比于cookies和localStorage,WebSQL提供...
(websql) Android 浏览器 2.1+ (websql), 4+ (indexeddb) Android 网页客户端、iOS 网页客户端 (websql) Opera 10+ (websql), Opera 15+ (indexeddb) 特征 IndexedDB、WebDatabase 和 WebStorage 存储机制上的统一...
但是,此插件支持sql的异步执行,其中MSOpenTech的WebSQL插件是完全同步的。 支持平台 该插件仅支持windows平台,因为大多数其他平台( ios , android等)已本机支持WebSQL。 您还可以将此插件与结合。 它们共同...
这意味着它是一个具有多个后端(IndexedDB、WebSQL、localStorage)的异步浏览器存储,旨在提供更好的离线体验。 与localForage的主要区别: 批量获取/设置支持 回调或承诺 浏览器友好 受启发的简单 API 发展...
4. **异步编程:** JavaScript 是单线程的,因此与 WebSQL 的交互通常是异步的,使用回调函数、Promise 或者现代的 async/await 语法来处理异步操作。 5. **错误处理:** 在使用 WebSQL API 时,我们需要捕获并处理...
从2010年开始,W3C推荐使用IndexedDB来替代WebSQL。IndexedDB提供了更好的性能和更丰富的查询能力,而且它不需要打开连接,可以异步操作,更加符合现代Web应用的需求。如果需要操作客户端存储数据,建议优先考虑使用...
localForage通过将异步存储(IndexedDB或WebSQL)与简单的localStorage的API一起使用来改善Web应用程序的脱机体验。 localForage在不支持IndexedDB或WebSQL的浏览器中使用localStorage。 有关请参见 。 要使用...
这个插件基本上是一个IndexedDB-to-WebSql适配器 安装 通过安装。 对于Cordova CLI 4.x ,请使用GIT URL语法: cordova plugin add https://github.com/ABB-Austin/cordova-plugin-indexeddb-async.git 对于...
配合IBM DB2,可以构建动态的、响应式的Web应用,通过异步调用后端服务,实现实时数据交换。 总之,IBM DB2通用数据库结合SQL,为开发者提供了强大且灵活的数据管理平台。通过学习和掌握这些知识点,你可以有效地...
JQuery Mobile是jQuery库的一个分支,专门用于优化移动设备上的网页交互体验,而WebSQL则是旧版的离线存储标准,虽然现在已被IndexedDB取代,但在一些老版本的iOS和Android设备上仍被广泛使用。 **1. JQuery Mobile...