Database file is locked, and stack traces in 3.0.0-RC1?

108 views
Skip to first unread message

Shawn

unread,
Mar 19, 2015, 10:58:01 PM3/19/15
to scala...@googlegroups.com
I'm having trouble writing to a SQLITE database with lines like:

val dbio = Dal.Game += new dal.Dal.GameRow(2, 0, 0, 0, description)

val f = Dal.db.run(dbio)
val i = Await.result(f, 5.seconds)

I'm using Slick generated Tables, and GameRow is the generated case class.

My first question is why such a query should lock up? My second (and perhaps more important) is why does the stack trace not show anything I can recognize as coming from my code? It's very painful to debug Slick when it gives me no idea which line of my code may be at fault. Thoughts?

java.sql.SQLException: [SQLITE_BUSY]  The database file is locked (database is locked)
        at org.sqlite.core.DB.newSQLException(DB.java:890)
        at org.sqlite.core.DB.newSQLException(DB.java:901)
        at org.sqlite.core.DB.execute(DB.java:807)
        at org.sqlite.core.DB.executeUpdate(DB.java:847)
        at org.sqlite.jdbc3.JDBC3PreparedStatement.executeUpdate(JDBC3PreparedStatement.java:86)
        at slick.jdbc.LoggingPreparedStatement$$anonfun$executeUpdate$5.apply$mcI$sp(LoggingStatement.scala:85)
        at slick.jdbc.LoggingPreparedStatement$$anonfun$executeUpdate$5.apply(LoggingStatement.scala:85)
        at slick.jdbc.LoggingPreparedStatement$$anonfun$executeUpdate$5.apply(LoggingStatement.scala:85)
        at slick.jdbc.LoggingStatement.logged(LoggingStatement.scala:16)
        at slick.jdbc.LoggingPreparedStatement.executeUpdate(LoggingStatement.scala:85)
        at slick.driver.JdbcInsertInvokerComponent$BaseInsertInvoker$$anonfun$internalInsert$1.apply(JdbcInsertInvokerComponent.scala:190)
        at slick.driver.JdbcInsertInvokerComponent$BaseInsertInvoker$$anonfun$internalInsert$1.apply(JdbcInsertInvokerComponent.scala:187)
        at slick.jdbc.JdbcBackend$SessionDef$class.withPreparedStatement(JdbcBackend.scala:300)
        at slick.jdbc.JdbcBackend$BaseSession.withPreparedStatement(JdbcBackend.scala:384)
        at slick.driver.JdbcInsertInvokerComponent$BaseInsertInvoker.preparedInsert(JdbcInsertInvokerComponent.scala:177)
        at slick.driver.JdbcInsertInvokerComponent$BaseInsertInvoker.internalInsert(JdbcInsertInvokerComponent.scala:187)
        at slick.driver.JdbcInsertInvokerComponent$BaseInsertInvoker.insert(JdbcInsertInvokerComponent.scala:182)
        at slick.driver.JdbcInsertInvokerComponent$InsertInvokerDef$class.$plus$eq(JdbcInsertInvokerComponent.scala:72)
        at slick.driver.JdbcInsertInvokerComponent$BaseInsertInvoker.$plus$eq(JdbcInsertInvokerComponent.scala:152)
        at slick.driver.JdbcActionComponent$InsertActionComposerImpl$$anonfun$$plus$eq$1.apply(JdbcActionComponent.scala:457)
        at slick.driver.JdbcActionComponent$InsertActionComposerImpl$$anonfun$$plus$eq$1.apply(JdbcActionComponent.scala:457)
        at slick.driver.JdbcActionComponent$InsertActionComposerImpl$$anon$8.run(JdbcActionComponent.scala:449)
        at slick.driver.JdbcActionComponent$InsertActionComposerImpl$$anon$8.run(JdbcActionComponent.scala:447)
        at slick.backend.DatabaseComponent$DatabaseDef$$anon$2.liftedTree1$1(DatabaseComponent.scala:214)
        at slick.backend.DatabaseComponent$DatabaseDef$$anon$2.run(DatabaseComponent.scala:214)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)

Stefan Zeiger

unread,
Mar 30, 2015, 6:39:58 AM3/30/15
to scala...@googlegroups.com
On 2015-03-20 3:58, Shawn wrote:
I'm having trouble writing to a SQLITE database with lines like:

val dbio = Dal.Game += new dal.Dal.GameRow(2, 0, 0, 0, description)

val f =  Dal.db.run(dbio)
val i = Await.result(f, 5.seconds)

I'm using Slick generated Tables, and GameRow is the generated case class.

My first question is why such a query should lock up?

SQLite doesn't properly support access through multiple connections. The best solution for SQLite is probably to use Slick's default pool and set numThreads=1 so that Slick serializes all access to the database file.


My second (and perhaps more important) is why does the stack trace not show anything I can recognize as coming from my code? It's very painful to debug Slick when it gives me no idea which line of my code may be at fault. Thoughts?

It's an unfortunate side-effect of asynchronous code. We could fake stack traces by appending the asynchronous call but this would require getting a stack trace upfront (which is expensive) for every single dispatch. It's too late by the time an error occurs.

--
Stefan Zeiger
Slick Tech Lead
Typesafe - Build Reactive Apps!
Twitter: @StefanZeiger

Bruno Bieth

unread,
Jan 14, 2016, 4:20:22 AM1/14/16
to Slick / ScalaQuery
Hi,

I'm running into the same problems, although I configured the db with a single-threaded-executor:

val sqlEc = ExecutionContext.fromExecutor(newSingleThreadedExecutor("sql"))

Database.forURL(s"jdbc:sqlite:$path",
driver = "org.sqlite.JDBC",
executor = new AsyncExecutor {
override def executionContext: ExecutionContext = sqlEc
override def close(): Unit = ()
})

Any clue?

Thanks
Reply all
Reply to author
Forward
0 new messages