Skip to content

Drizzle queries appear to use writeLock for SELECT statements - need help understanding if this is expected #763

@wturon

Description

@wturon

Hey folks!

I'm experiencing a pretty bad performance issues in my React Native app where all database queries seem to block each other (5-10 second freezes). I've traced the execution paths and it appears that there's a writeLock being set for all queries.

What I'm Observing

When I trace the execution paths of different query types, I'm seeing that all Drizzle queries route through executeRaw() -> writeLock(), while raw PowerSync queries use readLock():

Drizzle queries (all use writeLock):

  • db.query.findMany() → executeRaw() → writeLock
  • db.query.findFirst() → executeRaw() → writeLock
  • db.select().from() → executeRaw() → writeLock
  • db.select({ cols }).from() → executeRaw() → writeLock

Raw PowerSync queries (use readLock):

  • powerSyncDb.getAll() → getAll() → readLock
  • powerSyncDb.get() → get() → readLock

Environment

  • @powersync/drizzle-driver: ^0.6.0
  • @powersync/op-sqlite: ^0.7.11
  • @powersync/react-native: ^1.25.1
  • @powersync/common: ^1.40.0
  • drizzle-orm: ^0.39.3
  • Platform: React Native (Expo)
  • SQLite: WAL mode enabled

Code Path I'm Seeing

Looking at the source, it appears the execution goes:

  PowerSyncSQLitePreparedQuery:
  async values(placeholderValues) {
      const params = fillPlaceholders(this.query.params, placeholderValues ?? {});
      this.logger.logQuery(this.query.sql, params);
      return await this.db.executeRaw(this.query.sql, params);
  }

This values() method is called by both .all() and .get() when field mappings exist (which seems to always be the case with Drizzle's query builder).

  Then in OPSqliteAdapter:
  executeRaw(query, params) {
      return this.writeLock(ctx => ctx.executeRaw(query, params));
  }

My Questions

  1. Is this the expected behavior for executeRaw()? Should it use writeLock() even for SELECT queries?
  2. Is there a different code path I should be using for read queries with Drizzle?
  3. Should .values() be calling a different method for SELECT queries?

I have test code that traces the exact execution paths if that would be helpful!

Thanks so much for any guidance! Really appreciate all the work you've done on PowerSync - it's been great otherwise. 🙏

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions