github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/metric_test.go (about)

     1  // Copyright 2016 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package sql_test
    12  
    13  import (
    14  	"bytes"
    15  	"context"
    16  	"regexp"
    17  	"testing"
    18  
    19  	"github.com/cockroachdb/cockroach/pkg/base"
    20  	"github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvserverbase"
    21  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    22  	"github.com/cockroachdb/cockroach/pkg/sql"
    23  	"github.com/cockroachdb/cockroach/pkg/sql/catalog/lease"
    24  	"github.com/cockroachdb/cockroach/pkg/sql/tests"
    25  	"github.com/cockroachdb/cockroach/pkg/testutils"
    26  	"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
    27  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    28  )
    29  
    30  type queryCounter struct {
    31  	query                           string
    32  	expectError                     bool
    33  	txnBeginCount                   int64
    34  	selectCount                     int64
    35  	selectExecutedCount             int64
    36  	distSQLSelectCount              int64
    37  	fallbackCount                   int64
    38  	updateCount                     int64
    39  	insertCount                     int64
    40  	deleteCount                     int64
    41  	ddlCount                        int64
    42  	miscCount                       int64
    43  	miscExecutedCount               int64
    44  	failureCount                    int64
    45  	txnCommitCount                  int64
    46  	txnRollbackCount                int64
    47  	txnAbortCount                   int64
    48  	savepointCount                  int64
    49  	restartSavepointCount           int64
    50  	releaseRestartSavepointCount    int64
    51  	rollbackToRestartSavepointCount int64
    52  }
    53  
    54  func TestQueryCounts(t *testing.T) {
    55  	defer leaktest.AfterTest(t)()
    56  
    57  	params, _ := tests.CreateTestServerParams()
    58  	params.Knobs = base.TestingKnobs{
    59  		SQLLeaseManager: &lease.ManagerTestingKnobs{
    60  			// Disable SELECT called for delete orphaned leases to keep
    61  			// query stats stable.
    62  			DisableDeleteOrphanedLeases: true,
    63  		},
    64  	}
    65  	s, sqlDB, _ := serverutils.StartServer(t, params)
    66  	defer s.Stopper().Stop(context.Background())
    67  
    68  	var testcases = []queryCounter{
    69  		// The counts are deltas for each query.
    70  		{query: "SET DISTSQL = 'off'", miscCount: 1, miscExecutedCount: 1},
    71  		{query: "BEGIN; END", txnBeginCount: 1, txnCommitCount: 1},
    72  		{query: "SELECT 1", selectCount: 1, selectExecutedCount: 1, txnCommitCount: 1},
    73  		{query: "CREATE DATABASE mt", ddlCount: 1},
    74  		{query: "CREATE TABLE mt.n (num INTEGER PRIMARY KEY)", ddlCount: 1},
    75  		{query: "INSERT INTO mt.n VALUES (3)", insertCount: 1},
    76  		// Test failure (uniqueness violation).
    77  		{query: "INSERT INTO mt.n VALUES (3)", failureCount: 1, insertCount: 1, expectError: true},
    78  		// Test failure (planning error).
    79  		{
    80  			query:        "INSERT INTO nonexistent VALUES (3)",
    81  			failureCount: 1, insertCount: 1, expectError: true,
    82  		},
    83  		{query: "UPDATE mt.n SET num = num + 1", updateCount: 1},
    84  		{query: "DELETE FROM mt.n", deleteCount: 1},
    85  		{query: "ALTER TABLE mt.n ADD COLUMN num2 INTEGER", ddlCount: 1},
    86  		{query: "EXPLAIN SELECT * FROM mt.n", miscCount: 1, miscExecutedCount: 1},
    87  		{
    88  			query:         "BEGIN; UPDATE mt.n SET num = num + 1; END",
    89  			txnBeginCount: 1, updateCount: 1, txnCommitCount: 1,
    90  		},
    91  		{
    92  			query:       "SELECT * FROM mt.n; SELECT * FROM mt.n; SELECT * FROM mt.n",
    93  			selectCount: 3, selectExecutedCount: 3,
    94  		},
    95  		{query: "SET DISTSQL = 'on'", miscCount: 1, miscExecutedCount: 1},
    96  		{
    97  			query:       "SELECT * FROM mt.n",
    98  			selectCount: 1, selectExecutedCount: 1, distSQLSelectCount: 1,
    99  		},
   100  		{query: "SET DISTSQL = 'off'", miscCount: 1, miscExecutedCount: 1},
   101  		{query: "DROP TABLE mt.n", ddlCount: 1},
   102  		{query: "SET database = system", miscCount: 1, miscExecutedCount: 1},
   103  		{query: "SELECT 3", selectCount: 1, selectExecutedCount: 1},
   104  		{query: "CREATE TABLE mt.n (num INTEGER PRIMARY KEY)", ddlCount: 1},
   105  		{query: "UPDATE mt.n SET num = num + 1", updateCount: 1},
   106  	}
   107  
   108  	accum := initializeQueryCounter(s)
   109  
   110  	for _, tc := range testcases {
   111  		t.Run(tc.query, func(t *testing.T) {
   112  			if _, err := sqlDB.Exec(tc.query); err != nil && !tc.expectError {
   113  				t.Fatalf("unexpected error executing '%s': %s'", tc.query, err)
   114  			}
   115  
   116  			// Force metric snapshot refresh.
   117  			if err := s.WriteSummaries(); err != nil {
   118  				t.Fatal(err)
   119  			}
   120  
   121  			var err error
   122  			if accum.txnBeginCount, err = checkCounterDelta(s, sql.MetaTxnBeginStarted, accum.txnBeginCount, tc.txnBeginCount); err != nil {
   123  				t.Errorf("%q: %s", tc.query, err)
   124  			}
   125  			if accum.distSQLSelectCount, err = checkCounterDelta(s, sql.MetaDistSQLSelect, accum.distSQLSelectCount, tc.distSQLSelectCount); err != nil {
   126  				t.Errorf("%q: %s", tc.query, err)
   127  			}
   128  			if accum.txnRollbackCount, err = checkCounterDelta(s, sql.MetaTxnRollbackStarted, accum.txnRollbackCount, tc.txnRollbackCount); err != nil {
   129  				t.Errorf("%q: %s", tc.query, err)
   130  			}
   131  			if accum.txnAbortCount, err = checkCounterDelta(s, sql.MetaTxnAbort, accum.txnAbortCount, 0); err != nil {
   132  				t.Errorf("%q: %s", tc.query, err)
   133  			}
   134  			if accum.selectCount, err = checkCounterDelta(s, sql.MetaSelectStarted, accum.selectCount, tc.selectCount); err != nil {
   135  				t.Errorf("%q: %s", tc.query, err)
   136  			}
   137  			if accum.selectExecutedCount, err = checkCounterDelta(s, sql.MetaSelectExecuted, accum.selectExecutedCount, tc.selectExecutedCount); err != nil {
   138  				t.Errorf("%q: %s", tc.query, err)
   139  			}
   140  			if accum.updateCount, err = checkCounterDelta(s, sql.MetaUpdateStarted, accum.updateCount, tc.updateCount); err != nil {
   141  				t.Errorf("%q: %s", tc.query, err)
   142  			}
   143  			if accum.insertCount, err = checkCounterDelta(s, sql.MetaInsertStarted, accum.insertCount, tc.insertCount); err != nil {
   144  				t.Errorf("%q: %s", tc.query, err)
   145  			}
   146  			if accum.deleteCount, err = checkCounterDelta(s, sql.MetaDeleteStarted, accum.deleteCount, tc.deleteCount); err != nil {
   147  				t.Errorf("%q: %s", tc.query, err)
   148  			}
   149  			if accum.ddlCount, err = checkCounterDelta(s, sql.MetaDdlStarted, accum.ddlCount, tc.ddlCount); err != nil {
   150  				t.Errorf("%q: %s", tc.query, err)
   151  			}
   152  			if accum.miscCount, err = checkCounterDelta(s, sql.MetaMiscStarted, accum.miscCount, tc.miscCount); err != nil {
   153  				t.Errorf("%q: %s", tc.query, err)
   154  			}
   155  			if accum.miscExecutedCount, err = checkCounterDelta(s, sql.MetaMiscExecuted, accum.miscExecutedCount, tc.miscExecutedCount); err != nil {
   156  				t.Errorf("%q: %s", tc.query, err)
   157  			}
   158  			if accum.failureCount, err = checkCounterDelta(s, sql.MetaFailure, accum.failureCount, tc.failureCount); err != nil {
   159  				t.Errorf("%q: %s", tc.query, err)
   160  			}
   161  			if accum.fallbackCount, err = checkCounterDelta(s, sql.MetaSQLOptFallback, accum.fallbackCount, tc.fallbackCount); err != nil {
   162  				t.Errorf("%q: %s", tc.query, err)
   163  			}
   164  		})
   165  	}
   166  }
   167  
   168  func TestAbortCountConflictingWrites(t *testing.T) {
   169  	defer leaktest.AfterTest(t)()
   170  
   171  	testutils.RunTrueAndFalse(t, "retry loop", func(t *testing.T, retry bool) {
   172  		params, cmdFilters := tests.CreateTestServerParams()
   173  		s, sqlDB, _ := serverutils.StartServer(t, params)
   174  		defer s.Stopper().Stop(context.Background())
   175  
   176  		accum := initializeQueryCounter(s)
   177  
   178  		if _, err := sqlDB.Exec("CREATE DATABASE db"); err != nil {
   179  			t.Fatal(err)
   180  		}
   181  		if _, err := sqlDB.Exec("CREATE TABLE db.t (k TEXT PRIMARY KEY, v TEXT)"); err != nil {
   182  			t.Fatal(err)
   183  		}
   184  
   185  		// Inject errors on the INSERT below.
   186  		restarted := false
   187  		cmdFilters.AppendFilter(func(args kvserverbase.FilterArgs) *roachpb.Error {
   188  			switch req := args.Req.(type) {
   189  			// SQL INSERT generates ConditionalPuts for unique indexes (such as the PK).
   190  			case *roachpb.ConditionalPutRequest:
   191  				if bytes.Contains(req.Value.RawBytes, []byte("marker")) && !restarted {
   192  					restarted = true
   193  					return roachpb.NewErrorWithTxn(
   194  						roachpb.NewTransactionAbortedError(
   195  							roachpb.ABORT_REASON_ABORTED_RECORD_FOUND), args.Hdr.Txn)
   196  				}
   197  			}
   198  			return nil
   199  		}, false)
   200  
   201  		txn, err := sqlDB.Begin()
   202  		if err != nil {
   203  			t.Fatal(err)
   204  		}
   205  		if retry {
   206  			if _, err := txn.Exec("SAVEPOINT cockroach_restart"); err != nil {
   207  				t.Fatal(err)
   208  			}
   209  		}
   210  		// Run a batch of statements to move the txn out of the AutoRetry state,
   211  		// otherwise the INSERT below would be automatically retried.
   212  		if _, err := txn.Exec("SELECT 1"); err != nil {
   213  			t.Fatal(err)
   214  		}
   215  
   216  		_, err = txn.Exec("INSERT INTO db.t VALUES ('key', 'marker')")
   217  		expErr := "TransactionAbortedError(ABORT_REASON_ABORTED_RECORD_FOUND)"
   218  		if !testutils.IsError(err, regexp.QuoteMeta(expErr)) {
   219  			t.Fatalf("expected %s, got: %v", expErr, err)
   220  		}
   221  
   222  		var expRestart, expRollback, expCommit, expAbort int64
   223  		if retry {
   224  			if _, err := txn.Exec("ROLLBACK TO SAVEPOINT cockroach_restart"); err != nil {
   225  				t.Fatal(err)
   226  			}
   227  			if _, err := txn.Exec("RELEASE SAVEPOINT cockroach_restart"); err != nil {
   228  				t.Fatal(err)
   229  			}
   230  			if err = txn.Commit(); err != nil {
   231  				t.Fatal(err)
   232  			}
   233  
   234  			expRestart = 1
   235  			expCommit = 1
   236  		} else {
   237  			if err = txn.Rollback(); err != nil {
   238  				t.Fatal(err)
   239  			}
   240  
   241  			expRollback = 1
   242  			expAbort = 1
   243  		}
   244  
   245  		if _, err := checkCounterDelta(s, sql.MetaTxnBeginStarted, accum.txnBeginCount, 1); err != nil {
   246  			t.Error(err)
   247  		}
   248  		if _, err := checkCounterDelta(s, sql.MetaInsertStarted, accum.insertCount, 1); err != nil {
   249  			t.Error(err)
   250  		}
   251  		if _, err := checkCounterDelta(s, sql.MetaRestartSavepointStarted, accum.restartSavepointCount, expRestart); err != nil {
   252  			t.Error(err)
   253  		}
   254  		if _, err := checkCounterDelta(s, sql.MetaRollbackToRestartSavepointStarted, accum.rollbackToRestartSavepointCount, expRestart); err != nil {
   255  			t.Error(err)
   256  		}
   257  		if _, err := checkCounterDelta(s, sql.MetaReleaseRestartSavepointStarted, accum.releaseRestartSavepointCount, expRestart); err != nil {
   258  			t.Error(err)
   259  		}
   260  		if _, err := checkCounterDelta(s, sql.MetaTxnRollbackStarted, accum.txnRollbackCount, expRollback); err != nil {
   261  			t.Error(err)
   262  		}
   263  		if _, err := checkCounterDelta(s, sql.MetaTxnCommitStarted, accum.txnCommitCount, expCommit); err != nil {
   264  			t.Error(err)
   265  		}
   266  		if _, err := checkCounterDelta(s, sql.MetaTxnAbort, accum.txnAbortCount, expAbort); err != nil {
   267  			t.Error(err)
   268  		}
   269  	})
   270  }
   271  
   272  // TestErrorDuringTransaction tests that the transaction abort count goes up when a query
   273  // results in an error during a txn.
   274  func TestAbortCountErrorDuringTransaction(t *testing.T) {
   275  	defer leaktest.AfterTest(t)()
   276  	params, _ := tests.CreateTestServerParams()
   277  	s, sqlDB, _ := serverutils.StartServer(t, params)
   278  	defer s.Stopper().Stop(context.Background())
   279  
   280  	accum := initializeQueryCounter(s)
   281  
   282  	txn, err := sqlDB.Begin()
   283  	if err != nil {
   284  		t.Fatal(err)
   285  	}
   286  
   287  	if _, err := txn.Query("SELECT * FROM i_do.not_exist"); err == nil {
   288  		t.Fatal("Expected an error but didn't get one")
   289  	}
   290  
   291  	if _, err := checkCounterDelta(s, sql.MetaTxnBeginStarted, accum.txnBeginCount, 1); err != nil {
   292  		t.Error(err)
   293  	}
   294  	if _, err := checkCounterDelta(s, sql.MetaSelectStarted, accum.selectCount, 1); err != nil {
   295  		t.Error(err)
   296  	}
   297  
   298  	if err := txn.Rollback(); err != nil {
   299  		t.Fatal(err)
   300  	}
   301  
   302  	if _, err := checkCounterDelta(s, sql.MetaTxnAbort, accum.txnAbortCount, 1); err != nil {
   303  		t.Error(err)
   304  	}
   305  }
   306  
   307  func TestSavepointMetrics(t *testing.T) {
   308  	defer leaktest.AfterTest(t)()
   309  
   310  	params, _ := tests.CreateTestServerParams()
   311  	s, sqlDB, _ := serverutils.StartServer(t, params)
   312  	defer s.Stopper().Stop(context.Background())
   313  
   314  	accum := initializeQueryCounter(s)
   315  
   316  	// Normal-case use of all three savepoint statements.
   317  	txn, err := sqlDB.Begin()
   318  	if err != nil {
   319  		t.Fatal(err)
   320  	}
   321  	if _, err := txn.Exec("SAVEPOINT cockroach_restart"); err != nil {
   322  		t.Fatal(err)
   323  	}
   324  	if _, err := txn.Exec("ROLLBACK TRANSACTION TO SAVEPOINT cockroach_restart"); err != nil {
   325  		t.Fatal(err)
   326  	}
   327  	if _, err := txn.Exec("RELEASE SAVEPOINT cockroach_restart"); err != nil {
   328  		t.Fatal(err)
   329  	}
   330  	if err := txn.Commit(); err != nil {
   331  		t.Fatal(err)
   332  	}
   333  
   334  	if _, err := checkCounterDelta(s, sql.MetaRestartSavepointStarted, accum.restartSavepointCount, 1); err != nil {
   335  		t.Error(err)
   336  	}
   337  	if _, err := checkCounterDelta(s, sql.MetaRestartSavepointStarted, accum.releaseRestartSavepointCount, 1); err != nil {
   338  		t.Error(err)
   339  	}
   340  	if _, err := checkCounterDelta(s, sql.MetaRestartSavepointStarted, accum.rollbackToRestartSavepointCount, 1); err != nil {
   341  		t.Error(err)
   342  	}
   343  
   344  	// Unsupported savepoints go in a different counter.
   345  	txn, err = sqlDB.Begin()
   346  	if err != nil {
   347  		t.Fatal(err)
   348  	}
   349  	if _, err := txn.Exec("SAVEPOINT blah"); err != nil {
   350  		t.Fatal(err)
   351  	}
   352  	if err := txn.Rollback(); err != nil {
   353  		t.Fatal(err)
   354  	}
   355  	if _, err := checkCounterDelta(s, sql.MetaSavepointStarted, accum.savepointCount, 1); err != nil {
   356  		t.Error(err)
   357  	}
   358  	if _, err := checkCounterDelta(s, sql.MetaTxnRollbackStarted, accum.txnRollbackCount, 1); err != nil {
   359  		t.Error(err)
   360  	}
   361  
   362  	// Custom restart savepoint names are recognized.
   363  	txn, err = sqlDB.Begin()
   364  	if err != nil {
   365  		t.Fatal(err)
   366  	}
   367  	if _, err := txn.Exec("SET force_savepoint_restart = true"); err != nil {
   368  		t.Fatal(err)
   369  	}
   370  	if _, err := txn.Exec("SAVEPOINT blah"); err != nil {
   371  		t.Fatal(err)
   372  	}
   373  	if err := txn.Rollback(); err != nil {
   374  		t.Fatal(err)
   375  	}
   376  	if _, err := checkCounterDelta(s, sql.MetaRestartSavepointStarted, accum.restartSavepointCount, 2); err != nil {
   377  		t.Error(err)
   378  	}
   379  	if _, err := checkCounterDelta(s, sql.MetaTxnRollbackStarted, accum.txnRollbackCount, 2); err != nil {
   380  		t.Error(err)
   381  	}
   382  }