Skip to content

Commit

Permalink
slstorage: migrate system.sqlliveness to an rbr table
Browse files Browse the repository at this point in the history
Migrate the sqlliveness table to a format that is compatible with
regional by row tables. Multi region serverless is the motiviation for
this change. When a sql server starts up, it must write its session to
the sqlliveness table. The remote session write can add ~400ms to a
servers startup time.

Part of #85736

Release note: None
  • Loading branch information
jeffswenson committed Oct 21, 2022
1 parent dc21074 commit 9707e5e
Show file tree
Hide file tree
Showing 19 changed files with 387 additions and 62 deletions.
2 changes: 1 addition & 1 deletion docs/generated/settings/settings-for-tenants.txt
Original file line number Diff line number Diff line change
Expand Up @@ -297,4 +297,4 @@ trace.jaeger.agent string the address of a Jaeger agent to receive traces using
trace.opentelemetry.collector string address of an OpenTelemetry trace collector to receive traces using the otel gRPC protocol, as <host>:<port>. If no port is specified, 4317 will be used.
trace.span_registry.enabled boolean true if set, ongoing traces can be seen at https://<ui>/#/debug/tracez
trace.zipkin.collector string the address of a Zipkin instance to receive traces, as <host>:<port>. If no port is specified, 9411 will be used.
version version 1000022.2-4 set the active cluster version in the format '<major>.<minor>'
version version 1000022.2-6 set the active cluster version in the format '<major>.<minor>'
2 changes: 1 addition & 1 deletion docs/generated/settings/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,6 @@
<tr><td><code>trace.opentelemetry.collector</code></td><td>string</td><td><code></code></td><td>address of an OpenTelemetry trace collector to receive traces using the otel gRPC protocol, as <host>:<port>. If no port is specified, 4317 will be used.</td></tr>
<tr><td><code>trace.span_registry.enabled</code></td><td>boolean</td><td><code>true</code></td><td>if set, ongoing traces can be seen at https://<ui>/#/debug/tracez</td></tr>
<tr><td><code>trace.zipkin.collector</code></td><td>string</td><td><code></code></td><td>the address of a Zipkin instance to receive traces, as <host>:<port>. If no port is specified, 9411 will be used.</td></tr>
<tr><td><code>version</code></td><td>version</td><td><code>1000022.2-4</code></td><td>set the active cluster version in the format '<major>.<minor>'</td></tr>
<tr><td><code>version</code></td><td>version</td><td><code>1000022.2-6</code></td><td>set the active cluster version in the format '<major>.<minor>'</td></tr>
</tbody>
</table>
7 changes: 7 additions & 0 deletions pkg/ccl/multiregionccl/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ go_test(
srcs = [
"datadriven_test.go",
"main_test.go",
"multiregion_system_table_test.go",
"multiregion_test.go",
"region_test.go",
"regional_by_row_test.go",
Expand Down Expand Up @@ -62,10 +63,12 @@ go_test(
"//pkg/sql/catalog/descpb",
"//pkg/sql/catalog/descs",
"//pkg/sql/catalog/desctestutils",
"//pkg/sql/enum",
"//pkg/sql/execinfra",
"//pkg/sql/parser",
"//pkg/sql/rowenc",
"//pkg/sql/sem/tree",
"//pkg/sql/sqlliveness/slstorage",
"//pkg/sql/sqltestutils",
"//pkg/sql/tests",
"//pkg/testutils",
Expand All @@ -74,12 +77,16 @@ go_test(
"//pkg/testutils/sqlutils",
"//pkg/testutils/testcluster",
"//pkg/util",
"//pkg/util/hlc",
"//pkg/util/leaktest",
"//pkg/util/log",
"//pkg/util/randutil",
"//pkg/util/syncutil",
"//pkg/util/timeutil",
"//pkg/util/tracing",
"//pkg/util/tracing/tracingpb",
"//pkg/util/uuid",
"@com_github_cockroachdb_apd_v3//:apd",
"@com_github_cockroachdb_datadriven//:datadriven",
"@com_github_cockroachdb_errors//:errors",
"@com_github_stretchr_testify//require",
Expand Down
115 changes: 115 additions & 0 deletions pkg/ccl/multiregionccl/multiregion_system_table_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright 2022 The Cockroach Authors.
//
// Licensed as a CockroachDB Enterprise file under the Cockroach Community
// License (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// https://github.com/cockroachdb/cockroach/blob/master/licenses/CCL.txt

package multiregionccl

import (
"context"
"fmt"
"testing"
"time"

"github.com/cockroachdb/apd/v3"
"github.com/cockroachdb/cockroach/pkg/base"
"github.com/cockroachdb/cockroach/pkg/ccl/multiregionccl/multiregionccltestutils"
"github.com/cockroachdb/cockroach/pkg/keys"
"github.com/cockroachdb/cockroach/pkg/kv"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb"
"github.com/cockroachdb/cockroach/pkg/sql/enum"
"github.com/cockroachdb/cockroach/pkg/sql/sqlliveness/slstorage"
"github.com/cockroachdb/cockroach/pkg/testutils/sqlutils"
"github.com/cockroachdb/cockroach/pkg/util/hlc"
"github.com/cockroachdb/cockroach/pkg/util/leaktest"
"github.com/cockroachdb/cockroach/pkg/util/log"
"github.com/cockroachdb/cockroach/pkg/util/timeutil"
"github.com/cockroachdb/cockroach/pkg/util/uuid"
"github.com/stretchr/testify/require"
)

func createSqllivenessTable(
t *testing.T, db *sqlutils.SQLRunner, dbName string,
) (tableID descpb.ID) {
t.Helper()
db.Exec(t, fmt.Sprintf(`
CREATE DATABASE IF NOT EXISTS "%s"
WITH PRIMARY REGION "us-east1"
REGIONS "us-east1", "us-east2", "us-east3"
`, dbName))

// expiration needs to be column 2. slstorage.Table assumes the column id.
// session_uuid and crdb_region are identified by their location in the
// primary key.
db.Exec(t, fmt.Sprintf(`
CREATE TABLE "%s".sqlliveness (
session_uuid BYTES NOT NULL,
expiration DECIMAL NOT NULL,
crdb_region "%s".public.crdb_internal_region,
PRIMARY KEY(crdb_region, session_uuid)
) LOCALITY REGIONAL BY ROW;
`, dbName, dbName))
db.QueryRow(t, `
select u.id
from system.namespace t
join system.namespace u
on t.id = u."parentID"
where t.name = $1 and u.name = $2`,
dbName, "sqlliveness").Scan(&tableID)
return tableID
}

func TestRbrSqllivenessTable(t *testing.T) {
defer leaktest.AfterTest(t)()
defer log.Scope(t).Close(t)

ctx := context.Background()

cluster, sqlDB, cleanup := multiregionccltestutils.TestingCreateMultiRegionCluster(t, 3, base.TestingKnobs{})
defer cleanup()
settings := cluster.Servers[0].Cfg.Settings
kvDB := cluster.Servers[0].DB()

tDB := sqlutils.MakeSQLRunner(sqlDB)

t0 := time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC)
timeSource := timeutil.NewManualTime(t0)
clock := hlc.NewClock(timeSource, base.DefaultMaxClockOffset)

setup := func(t *testing.T) slstorage.Table {
dbName := t.Name()
tableID := createSqllivenessTable(t, tDB, dbName)
return slstorage.MakeTestTable(settings, keys.SystemSQLCodec, tableID, 1, 2)
}

t.Run("SqlRead", func(t *testing.T) {
table := setup(t)

initialUUID := uuid.MakeV4()
session, err := slstorage.MakeSessionID(enum.One, initialUUID)
require.NoError(t, err)

writeExpiration := clock.Now().Add(10, 00)
require.NoError(t, kvDB.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error {
return table.SetExpiration(ctx, txn, session, writeExpiration)
}))

var sessionUUID string
var crdbRegion string
var rawExpiration apd.Decimal

row := tDB.QueryRow(t, fmt.Sprintf(`SELECT crdb_region, session_uuid, expiration FROM "%s".sqlliveness`, t.Name()))
row.Scan(&crdbRegion, &sessionUUID, &rawExpiration)

require.Contains(t, []string{"us-east1", "us-east2", "us-east3"}, crdbRegion)
require.Equal(t, sessionUUID, string(initialUUID.GetBytes()))

readExpiration, err := hlc.DecimalToHLC(&rawExpiration)
require.NoError(t, err)

require.Equal(t, writeExpiration, readExpiration)
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -941,7 +941,7 @@ func TestSQLLivenessExemption(t *testing.T) {
_ = r

codec := keys.MakeSQLCodec(tenantID)
key := codec.IndexPrefix(keys.SqllivenessID, 1)
key := codec.TablePrefix(keys.SqllivenessID)

// livenessValue returns the KV value for the one row in the
// system.sqlliveness table. The value contains the session expiration time
Expand Down
9 changes: 9 additions & 0 deletions pkg/clusterversion/cockroach_versions.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,11 @@ const (
// Step (1): Add new versions here.
// Do not add new versions to a patch release.
// *************************************************

// RbrSqlliveness switches the system.sqlliveness descriptor to the new
// regional by row compatible format. It also causes the slstorage package
// to stop writing to the legacy rbt index.
RbrSqlliveness
)

// TODOPreV22_1 is an alias for V22_1 for use in any version gate/check that
Expand Down Expand Up @@ -519,6 +524,10 @@ var rawVersionsSingleton = keyedVersions{
Key: TenantNames,
Version: roachpb.Version{Major: 22, Minor: 2, Internal: 4},
},
{
Key: RbrSqlliveness,
Version: roachpb.Version{Major: 22, Minor: 2, Internal: 6},
},

// *************************************************
// Step (2): Add new versions here.
Expand Down
5 changes: 3 additions & 2 deletions pkg/clusterversion/key_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 18 additions & 9 deletions pkg/sql/catalog/systemschema/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -457,10 +457,11 @@ CREATE TABLE system.scheduled_jobs (

SqllivenessTableSchema = `
CREATE TABLE system.sqlliveness (
session_id BYTES NOT NULL,
expiration DECIMAL NOT NULL,
CONSTRAINT "primary" PRIMARY KEY (session_id),
FAMILY fam0_session_id_expiration (session_id, expiration)
crdb_region BYTES NOT NULL,
session_uuid BYTES NOT NULL,
expiration DECIMAL NOT NULL,
CONSTRAINT "primary" PRIMARY KEY (crdb_region, session_uuid),
FAMILY "primary" (crdb_region, session_uuid, expiration)
)`

MigrationsTableSchema = `
Expand Down Expand Up @@ -2002,19 +2003,27 @@ var (
catconstants.SqllivenessTableName,
keys.SqllivenessID,
[]descpb.ColumnDescriptor{
{Name: "session_id", ID: 1, Type: types.Bytes, Nullable: false},
{Name: "crdb_region", ID: 4, Type: types.Bytes, Nullable: false},
{Name: "session_uuid", ID: 3, Type: types.Bytes, Nullable: false},
{Name: "expiration", ID: 2, Type: types.Decimal, Nullable: false},
},
[]descpb.ColumnFamilyDescriptor{
{
Name: "fam0_session_id_expiration",
Name: "primary",
ID: 0,
ColumnNames: []string{"session_id", "expiration"},
ColumnIDs: []descpb.ColumnID{1, 2},
ColumnNames: []string{"crdb_region", "session_uuid", "expiration"},
ColumnIDs: []descpb.ColumnID{4, 3, 2},
DefaultColumnID: 2,
},
},
pk("session_id"),
descpb.IndexDescriptor{
Name: "primary",
ID: 2,
Unique: true,
KeyColumnNames: []string{"crdb_region", "session_uuid"},
KeyColumnDirections: []catpb.IndexColumn_Direction{catpb.IndexColumn_ASC, catpb.IndexColumn_ASC},
KeyColumnIDs: []descpb.ColumnID{4, 3},
},
))

// MigrationsTable is the descriptor for the migrations table. It stores facts
Expand Down
Loading

0 comments on commit 9707e5e

Please sign in to comment.