处理大量使用本地sqlite db的应用程序。最初它是为同步数据库通信设置的,但是由于使用频繁,我们经常看到应用程序在很短的时间内“冻结”。
在对异步通信进行重构之后,我们看到了一个不同的问题。该应用程序似乎远不那么可靠。乔布斯似乎根本就没有完成。经过多次调试和调整后,问题似乎是数据库事件句柄并不总是被捕获。我在开始交易或关闭连接时特别注意到这一点。
以下是一个例子:
con.addEventListener(SQLErrorEvent.ERROR, tran_ErrorHandler);
con.addEventListener(SQLEvent.BEGIN, con_beginHandler);
con.begin(SQLTransactionLockType.IMMEDIATE);
大部分时间这都很好。但是在con.begin被调用之后,con_beginHandler不会被击中。这使得我们拥有一个永远不会被提交的开放事务,并且可以真正挂起未来的请求。在使用连接关闭处理程序调查此相同问题时,其中一个解决方案就是简单地延迟它。在这种情况下,可以等待几秒钟。
setTimeout(function():void{ con.begin(SQLTransactionLockType.IMMEDIATE); }, 1000);
更改为类似的东西似乎确实使事务更可靠,但这确实延长了应用程序完成操作所需的时间。这是一个非常重的db应用程序,因此即使添加200ms也会产生明显的影响。但短至200毫秒的事情似乎也没有完全解决问题。它必须是500-1000ms或更高才能让我停止看到这个问题。
我编写了一个单独的AIR应用程序来尝试压力测试我们的代码和事务,但是无法在该环境中重现这一点。我甚至尝试做一些会“冻结”应用程序的东西(进行数学或其他处理的长循环),看看应用程序是否会导致它们失火,但一切看起来都很可靠。
我现在对如何解决这个问题感到茫然。我甚至尝试从绑定事件中运行con.begin,只是为了增加更多时间。唯一似乎有用的是过长的计时器/超时,我认为这是不可接受的解决方案。
有没有人碰到这个?我错过了异步的技巧吗?
答案 0 :(得分:0)
在清爽的周末之后,我还有一些想法可以尝试,但没有一个能够完成;然而,在这些尝试和更多的调查中,我终于找到了问题的模式。即使它不是一直发生的,当它确实发生时,它在发生的地方是相当一致的。在有问题的过程中有1或2个点,在数据清除后尝试压缩DB,以帮助保持较小的文件大小。我认为这里的问题是紧凑并没有正确地处理异步流程。因此,当我们尝试压缩数据库时,我们也在尝试启动新事务。因此,如果契约每隔一段时间花费一点时间,那么我们就会挂断。我认为假设的行为是异步事件处理在事务最终启动时调度而不是根本不发生,但这确实有些意义。