Search code examples
mysqlscalatransactionsslick

Slick transactional queries are not being rolled back


The way to issue transactional queries in slick according to docs is to invoke transactionally on the DBIOAction instance. However, in my case only the action producing an error is not being executed. The changes introduced by other actions in the sequence, occuring before but not after the failing one, are written to the DB and not rolled back.

def runTx(db: Database, queries: Iterable[DBIOAction[Int, NoStream, Effect]])(
    implicit ec: ExecutionContext
): Future[Try[Iterable[Int]]] = {
  val combined: DBIOAction[Iterable[Int], NoStream, Effect] = DBIO.sequence(queries)
  val tx: DBIOAction[Try[Iterable[Int]], NoStream, Effect with Effect.Transactional] =
    combined.transactionally.asTry
  db.run(tx)
}

I want to correlate incoming data that is stored in multiple tables but must be either stored completely or not at all.

The DBActions are inserts, created using the sql interpolator.

I have confirmed the data being written and retained despite failures of individual actions by unit tests and external tools.

slick 3.2.3 with mysql 5.7.22.

What can I do to guarantee transactionality and rollback all queries of a sequence in case one of them fails?


Solution

  • The reason for transactions not working was the DB engine. It had nothing to do with Slick. The tables I have been working with used the MyISAM engine, which does not support transactions.

    After switching the engine to InnoDB transactions worked as expected.

    others have found this out long before I did:
    https://stackoverflow.com/a/32913817/216021

    https://stackoverflow.com/a/8036049/216021