android.os.Binder.execTransact(Binder.java:565) 如上异常堆栈中的错误信息error code 5: database is locked,经过查找发现code为5代表sqlite中的SQLITE_BUSY 异常,详见:https://www.sqlite.org/rescode.html#busy,这里面说,SQLITE_BUSY(5)异常是一个数据库文件在被其他不同的数据库连接进行并发操作的时候写操作将补发继续 ,通常是多个进程的不同数据库连接对同一个数据库进行并发操作,例如进程A在进行耗时的数据库事务,而于此同时进程B也要进行一个数据库事务,这时候进程B就会直接返回SQLITE_BUSY的错误码,因为sqlite contentprovider暴露出去的接口来实现对宿主app进程的数据库的操作,实际上这时候的数据库操作就都是由宿主app进程来操作的了,就不会出现如上的异常 拓展 上面提及的数据库操作异常的code是5,对应的是SQLITE_BUSY
重试一定次数依然失败后,则返回SQLITE_BUSY错误码。 3. SQLite Busy Retry 方案的不足 Busy Retry 的方案虽然基本能解决问题,但对性能的压榨做的不够极致。 然后比较状态量,若当前状态不可跳转,则返回SQLITE_BUSY 通过fcntl进行文件锁,防止其他进程介入。 若锁失败,则返回SQLITE_BUSY 而 SQLite 选择 Busy Retry 的方案的原因也正是在此---文件锁没有线程锁类似 pthread_cond_signal 的通知机制。 该方案上线后,卡顿检测系统检测到 等待线程锁的造成的卡顿下降超过90% SQLITE_BUSY 的发生次数下降超过95% I/O 性能优化 保留 WAL 文件大小 如上文多线程优化时提到,开启 WAL
重试一定次数依然失败后,则返回SQLITE_BUSY错误码。 3. SQLite Busy Retry方案的不足 Busy Retry的方案虽然基本能解决问题,但对性能的压榨做的不够极致。 然后比较状态量,若当前状态不可跳转,则返回SQLITE_BUSY 2、通过fcntl进行文件锁,防止其他进程介入。 若锁失败,则返回SQLITE_BUSY 而SQLite选择Busy Retry的方案的原因也正是在此---文件锁没有线程锁类似pthread_cond_signal的通知机制。 该方案上线后,卡顿检测系统检测到 等待线程锁的造成的卡顿下降超过90% SQLITE_BUSY的发生次数下降超过95% I/O 性能优化 保留WAL文件大小 如上文多线程优化时提到,开启WAL模式后
背景针对Go语言modernc.org/sqlite驱动并发读写过程中的报错“database is locked (5) (SQLITE_BUSY)”的研究。
sqlite3_step()接口去执行预编译后的语句,也会返回一些结果代码,下面介绍一些常用的结果代码:SQLITE_BUSY, SQLITE_DONE, SQLITE_ROW, SQLITE_ERROR SQLITE_BUSY 意味着数据库引擎无法获得所需的数据库锁然后做它的工作。如果语句是commit或执行一个外部的显式事务,你可以重试。
但是,别的连接可以对数据库进行读操作;但是,RESERVED锁会阻止其它连接的BEGIN IMMEDIATE或者BEGIN EXCLUSIVE命令,当其它连接执行上述命令时,会返回SQLITE_BUSY 这时你就可以对数据库进行修改操作了,但是你还不能提交,当你 COMMIT时,会返回SQLITE_BUSY错误,这意味着还有其它的读事务没有完成,得等它们执行完后才能提交事务。
PRIMARY KEY ("id") ); 基本表创建完成后可以和mybatis结合,增删查改和MySQL无异,如果有特殊语句自行查询,最后提一点,sqlite支持多线程查询,但不支持多线程修改,不然会抛出异常[SQLITE_BUSY
permission denied */ #define SQLITE_ABORT 4 /* Callback routine requested an abort */ #define SQLITE_BUSY Otherwise, SQLITE_BUSY is returned and the ** database connection remains open. */ int sqlite3_close(
当 SQLite 尝试操作一个被另一个进程锁定的文件时,缺省的行为是返回 SQLITE_BUSY。你可以用 C代码更改这一行为。
SQLException support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private static final int SQLITE_BUSY return new DataException(message, sqlException, sql); } else if (errorCode == SQLITE_BUSY
重试一定次数依然失败后,则返回 SQLITE_BUSY 错误码。 下面这段代码是 SQLite 默认的 Busy Handler ? 然后比较状态量,若当前状态不可跳转,则返回 SQLITE_BUSY 通过 fcntl 进行文件锁,防止其他进程介入。 若锁失败,则返回 SQLITE_BUSY 而 SQLite 选择 Busy Retry 的方案的原因也正是在此 文件锁没有线程锁类似 pthread_cond_signal 的通知机制。
团队研发了高易用接口的 WCDB 组件,统一了微信内的 DB 线程模型和事务机制;根据微信客户端的消息、联系人、朋友圈和收藏等模块做了针对性的 DB 分离和数据表拆分;通过修改 SQLite 源码,大幅度降低了 SQLITE_BUSY
在多线程写操作的测试中, FMDB 直接返回错误 SQLITE_BUSY,无法完成。
当 SQLite 试图对一个已经被其他任务加了锁的数据库访问时,将会得到一个 SQLITE_BUSY 的错误,你可以使用以下两个函数来控制此时你的程序的下一步行为。
denied */ #define SQLITE_ABORT 4 /* 回调函数请求取消操作,Callback routine requested an abort */ #define SQLITE_BUSY
运行过程 int sqlite3_step(sqlite3_stmt*); 可能的返回值: *SQLITE_BUSY: 数据库被锁定,须要等待再次尝试直到成功。
如果在调用sqlite3_close函数关闭数据库之前,还有某些没有完成的(nonfinalized)SQL语句,那么sqlite3_close函数将会返回SQLITE_BUSY错误。 下面就是执行工作,我们依然使用sqlite3_step // 对于不返回结果的语句(如:INSERT,UPDATE,或DELETE),sqlite3_step()只执行一次就返回 // 返回SQLITE_BUSY // 返回SQLITE_BUSY表示暂时无法执行操作,SQLITE_DONE表示操作执行完毕,SQLITE_ROW表示执行完毕并且有返回(执行select语句时)。
其他错误代码: 如 SQLITE_ERROR, SQLITE_BUSY, SQLITE_MISUSE 等,表示某种类型的错误。
SQLITE_PERM : return "SQLITE_PERM"; case SQLITE_ABORT : return "SQLITE_ABORT"; case SQLITE_BUSY : return "SQLITE_BUSY"; case SQLITE_LOCKED : return "SQLITE_LOCKED"; case SQLITE_NOMEM SQLITE_PERM : return "SQLITE_PERM"; case SQLITE_ABORT : return "SQLITE_ABORT"; case SQLITE_BUSY : return "SQLITE_BUSY"; case SQLITE_LOCKED : return "SQLITE_LOCKED"; case SQLITE_NOMEM
/ #define SQLITE_PERM 3 /* 没有访问权限 */ #define SQLITE_ABORT 4 /* 回调请求终止 */ #define SQLITE_BUSY