diff --git a/go/vt/vtorc/config/config.go b/go/vt/vtorc/config/config.go index 96d5eef221f..e64cc51ee30 100644 --- a/go/vt/vtorc/config/config.go +++ b/go/vt/vtorc/config/config.go @@ -307,6 +307,11 @@ func GetSQLiteDataFile() string { return sqliteDataFile.Get() } +// SetSQLiteDataFile is a Setter function. +func SetSQLiteDataFile(dataFile string) { + sqliteDataFile.Set(dataFile) +} + // GetReasonableReplicationLagSeconds gets the reasonable replication lag but in seconds. func GetReasonableReplicationLagSeconds() int64 { return int64(reasonableReplicationLag.Get() / time.Second) diff --git a/go/vt/vtorc/db/db.go b/go/vt/vtorc/db/db.go index 870a3d15949..33c9b56a0e7 100644 --- a/go/vt/vtorc/db/db.go +++ b/go/vt/vtorc/db/db.go @@ -18,6 +18,7 @@ package db import ( "database/sql" + "strings" "vitess.io/vitess/go/vt/external/golib/sqlutils" "vitess.io/vitess/go/vt/log" @@ -99,6 +100,25 @@ func ClearVTOrcDatabase() { } } +// getSqlitePragmaSQLs returns a slice of SQL statements to set sqlite PRAGMAs. +func getSqlitePragmaSQLs() []string { + // PRAGMAs: https://www.sqlite.org/pragma.html + pragmaSQLs := []string{ + `PRAGMA journal_mode = WAL`, + `PRAGMA synchronous = NORMAL`, + } + + // Enable read_uncommitted transaction isolation (no read locks) when in shared cache mode. + // Dirty reads should not be a concern for VTOrc's use of sqlite/transactions. No read + // locks allows updates to tables to not be blocked by reads. + // https://www.sqlite.org/pragma.html#pragma_read_uncommitted + if strings.Contains(config.GetSQLiteDataFile(), "cache=shared") { + pragmaSQLs = append(pragmaSQLs, `PRAGMA read_uncommitted = 1`) + } + + return pragmaSQLs +} + // initVTOrcDB attempts to create/upgrade the vtorc backend database. It is created once in the // application's lifetime. func initVTOrcDB(db *sql.DB) error { @@ -110,11 +130,12 @@ func initVTOrcDB(db *sql.DB) error { if err := registerVTOrcDeployment(db); err != nil { return err } - if _, err := ExecVTOrc(`PRAGMA journal_mode = WAL`); err != nil { - return err - } - if _, err := ExecVTOrc(`PRAGMA synchronous = NORMAL`); err != nil { - return err + + for _, pragmaSQL := range getSqlitePragmaSQLs() { + if _, err := ExecVTOrc(pragmaSQL); err != nil { + log.Errorf("Failed to execute PRAGMA query %q: %+v", pragmaSQL, err) + return err + } } return nil } diff --git a/go/vt/vtorc/db/db_test.go b/go/vt/vtorc/db/db_test.go new file mode 100644 index 00000000000..ff85997f262 --- /dev/null +++ b/go/vt/vtorc/db/db_test.go @@ -0,0 +1,45 @@ +/* +Copyright 2025 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package db + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/vt/vtorc/config" +) + +func TestGetSqlitePragmaSQLs(t *testing.T) { + origSqliteDataPath := config.GetSQLiteDataFile() + defer config.SetSQLiteDataFile(origSqliteDataPath) + + // no shared-cache mode + config.SetSQLiteDataFile("file::memory:?mode=memory") + require.Equal(t, []string{ + "PRAGMA journal_mode = WAL", + "PRAGMA synchronous = NORMAL", + }, getSqlitePragmaSQLs()) + + // shared-cache mode + config.SetSQLiteDataFile("file::memory:?mode=memory&cache=shared") + require.Equal(t, []string{ + "PRAGMA journal_mode = WAL", + "PRAGMA synchronous = NORMAL", + "PRAGMA read_uncommitted = 1", + }, getSqlitePragmaSQLs()) +}