今天在对在线商城项目的添加订单接口进行压力测试时候,在设置并发用户数为10000,启动时间为五秒,循环次数为10次的时候,对接口进行压测,出现了如下报错。
Caused by: org.sqlite.SQLiteException: [SQLITE_BUSY] The database file is locked (database is locked)
直译过来就是数据库文件被锁定,随后去sqlite官网查阅文档,内容如下。
(5) SQLITE_BUSY
The SQLITE_BUSY result code indicates that the database file could not be written (or in some cases read) because of concurrent activity by some other database connection, usually a database connection in a separate process.
For example, if process A is in the middle of a large write transaction and at the same time process B attempts to start a new write transaction, process B will get back an SQLITE_BUSY result because SQLite only supports one writer at a time. Process B will need to wait for process A to finish its transaction before starting a new transaction. The sqlite3_busy_timeout() and sqlite3_busy_handler() interfaces and the busy_timeout pragma are available to process B to help it deal with SQLITE_BUSY errors.
An SQLITE_BUSY error can occur at any point in a transaction: when the transaction is first started, during any write or update operations, or when the transaction commits. To avoid encountering SQLITE_BUSY errors in the middle of a transaction, the application can use BEGIN IMMEDIATE instead of just BEGIN to start a transaction. The BEGIN IMMEDIATE command might itself return SQLITE_BUSY, but if it succeeds, then SQLite guarantees that no subsequent operations on the same database through the next COMMIT will return SQLITE_BUSY.
See also: SQLITE_BUSY_RECOVERY and SQLITE_BUSY_SNAPSHOT.
The SQLITE_BUSY result code differs from SQLITE_LOCKED in that SQLITE_BUSY indicates a conflict with a separate database connection, probably in a separate process, whereas SQLITE_LOCKED indicates a conflict within the same database connection (or sometimes a database connection with a shared cache).
提取关键信息,SQLite only supports one writer at a time. Process B will need to wait for process A to finish its transaction before starting a new transaction. 中文意思即为 sqlite在同一时间只支持一个写入器,进程B需要去等待进程A完成事务,然后才能开始新事务。 即是sqlite不支持多线程写入数据。
然后文档中给了两个C语言接口的解决方式,而我们使用的是JAVA语言的spring boot框架,其实只需要在配置文件中设置
spring.datasource.hikari.maximum-pool-size=1
将数据库连接池数量设置为1,即可解决上述问题,但希望还能找到更好的解决方法。