From f6cae3be89c3643b4f956c68d12804f94fdeaee3 Mon Sep 17 00:00:00 2001 From: Azhng Date: Mon, 14 Feb 2022 17:19:30 +0000 Subject: [PATCH] sql: add option to enable/disable txn id cache Resolves #76329 Release note (sql change): when `sql.contention.txn_id_cache.max_size` is set to 0, it would effectively turn off transaction ID cache. --- .../settings/settings-for-tenants.txt | 2 +- docs/generated/settings/settings.html | 2 +- .../contention/txnidcache/cluster_settings.go | 3 +- pkg/sql/contention/txnidcache/txn_id_cache.go | 2 +- pkg/sql/contention/txnidcache/writer.go | 9 +++- pkg/sql/contention/txnidcache/writer_test.go | 51 ++++++++++++++++++- 6 files changed, 63 insertions(+), 6 deletions(-) diff --git a/docs/generated/settings/settings-for-tenants.txt b/docs/generated/settings/settings-for-tenants.txt index c665a1c7ccb4..2c9b0620308f 100644 --- a/docs/generated/settings/settings-for-tenants.txt +++ b/docs/generated/settings/settings-for-tenants.txt @@ -77,7 +77,7 @@ server.web_session.purge.max_deletions_per_cycle integer 10 the maximum number o server.web_session.purge.period duration 1h0m0s the time until old sessions are deleted server.web_session.purge.ttl duration 1h0m0s if nonzero, entries in system.web_sessions older than this duration are periodically purged server.web_session_timeout duration 168h0m0s the duration that a newly created web session will be valid -sql.contention.txn_id_cache.max_size byte size 64 MiB the maximum byte size TxnID cache will use +sql.contention.txn_id_cache.max_size byte size 64 MiB the maximum byte size TxnID cache will use. Set it to zero to disable txn id cache sql.cross_db_fks.enabled boolean false if true, creating foreign key references across databases is allowed sql.cross_db_sequence_owners.enabled boolean false if true, creating sequences owned by tables from other databases is allowed sql.cross_db_sequence_references.enabled boolean false if true, sequences referenced by tables from other databases are allowed diff --git a/docs/generated/settings/settings.html b/docs/generated/settings/settings.html index 4f1e1b6f9ad7..1e16f0a9eb39 100644 --- a/docs/generated/settings/settings.html +++ b/docs/generated/settings/settings.html @@ -88,7 +88,7 @@ server.web_session.purge.periodduration1h0m0sthe time until old sessions are deleted server.web_session.purge.ttlduration1h0m0sif nonzero, entries in system.web_sessions older than this duration are periodically purged server.web_session_timeoutduration168h0m0sthe duration that a newly created web session will be valid -sql.contention.txn_id_cache.max_sizebyte size64 MiBthe maximum byte size TxnID cache will use +sql.contention.txn_id_cache.max_sizebyte size64 MiBthe maximum byte size TxnID cache will use. Set it to zero to disable txn id cache sql.cross_db_fks.enabledbooleanfalseif true, creating foreign key references across databases is allowed sql.cross_db_sequence_owners.enabledbooleanfalseif true, creating sequences owned by tables from other databases is allowed sql.cross_db_sequence_references.enabledbooleanfalseif true, sequences referenced by tables from other databases are allowed diff --git a/pkg/sql/contention/txnidcache/cluster_settings.go b/pkg/sql/contention/txnidcache/cluster_settings.go index c2fbf3c47474..09eefbff0525 100644 --- a/pkg/sql/contention/txnidcache/cluster_settings.go +++ b/pkg/sql/contention/txnidcache/cluster_settings.go @@ -16,6 +16,7 @@ import "github.com/cockroachdb/cockroach/pkg/settings" var MaxSize = settings.RegisterByteSizeSetting( settings.TenantWritable, `sql.contention.txn_id_cache.max_size`, - "the maximum byte size TxnID cache will use", + "the maximum byte size TxnID cache will use. Set it to zero to disable "+ + "txn id cache", 64*1024*1024, // 64 MB ).WithPublic() diff --git a/pkg/sql/contention/txnidcache/txn_id_cache.go b/pkg/sql/contention/txnidcache/txn_id_cache.go index a2faa44bfa4d..90d2410813c9 100644 --- a/pkg/sql/contention/txnidcache/txn_id_cache.go +++ b/pkg/sql/contention/txnidcache/txn_id_cache.go @@ -145,7 +145,7 @@ func NewTxnIDCache(st *cluster.Settings, metrics *Metrics) *Cache { return MaxSize.Get(&st.SV) / entrySize } /* capacity */) - t.writer = newWriter(t) + t.writer = newWriter(st, t) return t } diff --git a/pkg/sql/contention/txnidcache/writer.go b/pkg/sql/contention/txnidcache/writer.go index 0a553c04ecd8..0788d2357e29 100644 --- a/pkg/sql/contention/txnidcache/writer.go +++ b/pkg/sql/contention/txnidcache/writer.go @@ -11,6 +11,7 @@ package txnidcache import ( + "github.com/cockroachdb/cockroach/pkg/settings/cluster" "github.com/cockroachdb/cockroach/pkg/util/encoding" "github.com/cockroachdb/cockroach/pkg/util/uuid" ) @@ -20,6 +21,8 @@ import ( const shardCount = 16 type writer struct { + st *cluster.Settings + shards [shardCount]*concurrentWriteBuffer sink messageSink @@ -27,8 +30,9 @@ type writer struct { var _ Writer = &writer{} -func newWriter(sink messageSink) *writer { +func newWriter(st *cluster.Settings, sink messageSink) *writer { w := &writer{ + st: st, sink: sink, } @@ -41,6 +45,9 @@ func newWriter(sink messageSink) *writer { // Record implements the Writer interface. func (w *writer) Record(resolvedTxnID ResolvedTxnID) { + if MaxSize.Get(&w.st.SV) == 0 { + return + } shardIdx := hashTxnID(resolvedTxnID.TxnID) buffer := w.shards[shardIdx] buffer.Record(resolvedTxnID) diff --git a/pkg/sql/contention/txnidcache/writer_test.go b/pkg/sql/contention/txnidcache/writer_test.go index 0ed85e6efa59..c646623faac0 100644 --- a/pkg/sql/contention/txnidcache/writer_test.go +++ b/pkg/sql/contention/txnidcache/writer_test.go @@ -24,6 +24,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/util/log" "github.com/cockroachdb/cockroach/pkg/util/stop" "github.com/cockroachdb/cockroach/pkg/util/uuid" + "github.com/stretchr/testify/require" ) type blackHoleSink struct { @@ -71,11 +72,12 @@ func BenchmarkWriter(b *testing.B) { defer log.Scope(b).Close(b) ctx := context.Background() + st := cluster.MakeTestingClusterSettings() run := func(b *testing.B, sink messageSink, numOfConcurrentWriter int) { starter := make(chan struct{}) - w := newWriter(sink) + w := newWriter(st, sink) b.ResetTimer() b.SetBytes(messageBlockSize * entrySize) @@ -149,3 +151,50 @@ func BenchmarkWriter(b *testing.B) { }) } } + +type counterSink struct { + numOfRecord int +} + +var _ messageSink = &counterSink{} + +func (c *counterSink) push(block *messageBlock) { + for i := 0; i < messageBlockSize; i++ { + if !block[i].valid() { + break + } + c.numOfRecord++ + } +} + +func TestTxnIDCacheCanBeDisabledViaClusterSetting(t *testing.T) { + st := cluster.MakeTestingClusterSettings() + ctx := context.Background() + + sink := &counterSink{} + w := newWriter(st, sink) + w.Record(ResolvedTxnID{ + TxnID: uuid.FastMakeV4(), + }) + + w.Flush() + require.Equal(t, 1, sink.numOfRecord) + + // This should disable txn id cache. + MaxSize.Override(ctx, &st.SV, 0) + + w.Record(ResolvedTxnID{ + TxnID: uuid.FastMakeV4(), + }) + w.Flush() + require.Equal(t, 1, sink.numOfRecord) + + // This should re-enable txn id cache. + MaxSize.Override(ctx, &st.SV, MaxSize.Default()) + + w.Record(ResolvedTxnID{ + TxnID: uuid.FastMakeV4(), + }) + w.Flush() + require.Equal(t, 2, sink.numOfRecord) +}