vitess.io/vitess@v0.16.2/go/vt/vttablet/endtoend/transaction_test.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package endtoend
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"testing"
    23  	"time"
    24  
    25  	"vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv/tabletenvtest"
    26  
    27  	"google.golang.org/protobuf/proto"
    28  
    29  	"github.com/stretchr/testify/assert"
    30  	"github.com/stretchr/testify/require"
    31  
    32  	"vitess.io/vitess/go/mysql"
    33  	"vitess.io/vitess/go/test/utils"
    34  	querypb "vitess.io/vitess/go/vt/proto/query"
    35  	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
    36  	"vitess.io/vitess/go/vt/vttablet/endtoend/framework"
    37  	"vitess.io/vitess/go/vt/vttablet/tabletserver"
    38  	"vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv"
    39  )
    40  
    41  func TestCommit(t *testing.T) {
    42  	client := framework.NewClient()
    43  	defer client.Execute("delete from vitess_test where intval=4", nil)
    44  
    45  	vstart := framework.DebugVars()
    46  
    47  	query := "insert into vitess_test (intval, floatval, charval, binval) values (4, null, null, null)"
    48  	err := client.Begin(false)
    49  	require.NoError(t, err)
    50  
    51  	_, err = client.Execute(query, nil)
    52  	require.NoError(t, err)
    53  
    54  	err = client.Commit()
    55  	require.NoError(t, err)
    56  
    57  	qr, err := client.Execute("select * from vitess_test", nil)
    58  	require.NoError(t, err)
    59  	require.Equal(t, 4, len(qr.Rows), "rows affected")
    60  
    61  	_, err = client.Execute("delete from vitess_test where intval=4", nil)
    62  	require.NoError(t, err)
    63  
    64  	qr, err = client.Execute("select * from vitess_test", nil)
    65  	require.NoError(t, err)
    66  	require.Equal(t, 3, len(qr.Rows), "rows affected")
    67  
    68  	expectedDiffs := []struct {
    69  		tag  string
    70  		diff int
    71  	}{{
    72  		tag:  "Transactions/TotalCount",
    73  		diff: 2,
    74  	}, {
    75  		tag:  "Transactions/Histograms/commit/Count",
    76  		diff: 2,
    77  	}, {
    78  		tag:  "Queries/TotalCount",
    79  		diff: 6,
    80  	}, {
    81  		tag:  "Queries/Histograms/BEGIN/Count",
    82  		diff: 1,
    83  	}, {
    84  		tag:  "Queries/Histograms/COMMIT/Count",
    85  		diff: 1,
    86  	}, {
    87  		tag:  "Queries/Histograms/Insert/Count",
    88  		diff: 1,
    89  	}, {
    90  		tag:  "Queries/Histograms/DeleteLimit/Count",
    91  		diff: 1,
    92  	}, {
    93  		tag:  "Queries/Histograms/Select/Count",
    94  		diff: 2,
    95  	}}
    96  	vend := framework.DebugVars()
    97  	for _, expected := range expectedDiffs {
    98  		compareIntDiff(t, vend, expected.tag, vstart, expected.diff)
    99  	}
   100  }
   101  
   102  func TestRollback(t *testing.T) {
   103  	client := framework.NewClient()
   104  
   105  	vstart := framework.DebugVars()
   106  
   107  	query := "insert into vitess_test values(4, null, null, null)"
   108  	err := client.Begin(false)
   109  	require.NoError(t, err)
   110  	_, err = client.Execute(query, nil)
   111  	require.NoError(t, err)
   112  	err = client.Rollback()
   113  	require.NoError(t, err)
   114  
   115  	qr, err := client.Execute("select * from vitess_test", nil)
   116  	require.NoError(t, err)
   117  	assert.Equal(t, 3, len(qr.Rows))
   118  
   119  	expectedDiffs := []struct {
   120  		tag  string
   121  		diff int
   122  	}{{
   123  		tag:  "Transactions/TotalCount",
   124  		diff: 1,
   125  	}, {
   126  		tag:  "Transactions/Histograms/rollback/Count",
   127  		diff: 1,
   128  	}, {
   129  		tag:  "Queries/Histograms/BEGIN/Count",
   130  		diff: 1,
   131  	}, {
   132  		tag:  "Queries/Histograms/ROLLBACK/Count",
   133  		diff: 1,
   134  	}, {
   135  		tag:  "Queries/Histograms/Insert/Count",
   136  		diff: 1,
   137  	}}
   138  	vend := framework.DebugVars()
   139  	for _, expected := range expectedDiffs {
   140  		compareIntDiff(t, vend, expected.tag, vstart, expected.diff)
   141  	}
   142  }
   143  
   144  func TestAutoCommit(t *testing.T) {
   145  	client := framework.NewClient()
   146  	defer client.Execute("delete from vitess_test where intval=4", nil)
   147  
   148  	vstart := framework.DebugVars()
   149  
   150  	query := "insert into vitess_test (intval, floatval, charval, binval) values (4, null, null, null)"
   151  	_, err := client.Execute(query, nil)
   152  	require.NoError(t, err)
   153  
   154  	qr, err := client.Execute("select * from vitess_test", nil)
   155  	require.NoError(t, err)
   156  	assert.Equal(t, 4, len(qr.Rows))
   157  
   158  	_, err = client.Execute("delete from vitess_test where intval=4", nil)
   159  	require.NoError(t, err)
   160  
   161  	qr, err = client.Execute("select * from vitess_test", nil)
   162  	require.NoError(t, err)
   163  	assert.Equal(t, 3, len(qr.Rows))
   164  
   165  	expectedDiffs := []struct {
   166  		tag  string
   167  		diff int
   168  	}{{
   169  		tag:  "Transactions/TotalCount",
   170  		diff: 2,
   171  	}, {
   172  		tag:  "Transactions/Histograms/commit/Count",
   173  		diff: 2,
   174  	}, {
   175  		tag:  "Queries/TotalCount",
   176  		diff: 4,
   177  	}, {
   178  		tag:  "Queries/Histograms/BEGIN/Count",
   179  		diff: 0,
   180  	}, {
   181  		tag:  "Queries/Histograms/COMMIT/Count",
   182  		diff: 0,
   183  	}, {
   184  		tag:  "Queries/Histograms/Insert/Count",
   185  		diff: 1,
   186  	}, {
   187  		tag:  "Queries/Histograms/DeleteLimit/Count",
   188  		diff: 1,
   189  	}, {
   190  		tag:  "Queries/Histograms/Select/Count",
   191  		diff: 2,
   192  	}}
   193  	vend := framework.DebugVars()
   194  	for _, expected := range expectedDiffs {
   195  		got := framework.FetchInt(vend, expected.tag)
   196  		want := framework.FetchInt(vstart, expected.tag) + expected.diff
   197  		// It's possible that other house-keeping transactions (like messaging)
   198  		// can happen during this test. So, don't perform equality comparisons.
   199  		if got < want {
   200  			t.Errorf("%s: %d, must be at least %d", expected.tag, got, want)
   201  		}
   202  	}
   203  }
   204  
   205  func TestTxPoolSize(t *testing.T) {
   206  	tabletenvtest.LoadTabletEnvFlags()
   207  
   208  	vstart := framework.DebugVars()
   209  
   210  	client1 := framework.NewClient()
   211  	err := client1.Begin(false)
   212  	require.NoError(t, err)
   213  	defer client1.Rollback()
   214  	verifyIntValue(t, framework.DebugVars(), "TransactionPoolAvailable", tabletenv.NewCurrentConfig().TxPool.Size-1)
   215  
   216  	revert := changeVar(t, "TxPoolSize", "1")
   217  	defer revert()
   218  	vend := framework.DebugVars()
   219  	verifyIntValue(t, vend, "TransactionPoolAvailable", 0)
   220  	verifyIntValue(t, vend, "TransactionPoolCapacity", 1)
   221  
   222  	client2 := framework.NewClient()
   223  	err = client2.Begin(false)
   224  	require.Error(t, err)
   225  	require.Contains(t, err.Error(), "connection limit exceeded")
   226  	compareIntDiff(t, framework.DebugVars(), "Errors/RESOURCE_EXHAUSTED", vstart, 1)
   227  }
   228  
   229  func TestForUpdate(t *testing.T) {
   230  	for _, mode := range []string{"for update", "lock in share mode"} {
   231  		client := framework.NewClient()
   232  		query := fmt.Sprintf("select * from vitess_test where intval=2 %s", mode)
   233  		_, err := client.Execute(query, nil)
   234  		require.NoError(t, err)
   235  
   236  		// We should not get errors here
   237  		err = client.Begin(false)
   238  		require.NoError(t, err)
   239  		_, err = client.Execute(query, nil)
   240  		require.NoError(t, err)
   241  		err = client.Commit()
   242  		require.NoError(t, err)
   243  	}
   244  }
   245  
   246  func TestPrepareRollback(t *testing.T) {
   247  	client := framework.NewClient()
   248  	defer client.Execute("delete from vitess_test where intval=4", nil)
   249  
   250  	query := "insert into vitess_test (intval, floatval, charval, binval) " +
   251  		"values(4, null, null, null)"
   252  	err := client.Begin(false)
   253  	require.NoError(t, err)
   254  	_, err = client.Execute(query, nil)
   255  	require.NoError(t, err)
   256  	err = client.Prepare("aa")
   257  	if err != nil {
   258  		client.RollbackPrepared("aa", 0)
   259  		t.Fatalf(err.Error())
   260  	}
   261  	err = client.RollbackPrepared("aa", 0)
   262  	require.NoError(t, err)
   263  	qr, err := client.Execute("select * from vitess_test", nil)
   264  	require.NoError(t, err)
   265  	assert.Equal(t, 3, len(qr.Rows))
   266  }
   267  
   268  func TestPrepareCommit(t *testing.T) {
   269  	client := framework.NewClient()
   270  	defer client.Execute("delete from vitess_test where intval=4", nil)
   271  
   272  	query := "insert into vitess_test (intval, floatval, charval, binval) " +
   273  		"values(4, null, null, null)"
   274  	err := client.Begin(false)
   275  	require.NoError(t, err)
   276  	_, err = client.Execute(query, nil)
   277  	require.NoError(t, err)
   278  	err = client.Prepare("aa")
   279  	if err != nil {
   280  		client.RollbackPrepared("aa", 0)
   281  		t.Fatal(err)
   282  	}
   283  	err = client.CommitPrepared("aa")
   284  	require.NoError(t, err)
   285  	qr, err := client.Execute("select * from vitess_test", nil)
   286  	require.NoError(t, err)
   287  	assert.Equal(t, 4, len(qr.Rows))
   288  }
   289  
   290  func TestPrepareReparentCommit(t *testing.T) {
   291  	client := framework.NewClient()
   292  	defer client.Execute("delete from vitess_test where intval=4", nil)
   293  
   294  	query := "insert into vitess_test (intval, floatval, charval, binval) " +
   295  		"values(4, null, null, null)"
   296  	err := client.Begin(false)
   297  	require.NoError(t, err)
   298  	_, err = client.Execute(query, nil)
   299  	require.NoError(t, err)
   300  	err = client.Prepare("aa")
   301  	if err != nil {
   302  		client.RollbackPrepared("aa", 0)
   303  		t.Fatal(err)
   304  	}
   305  	// Rollback all transactions
   306  	err = client.SetServingType(topodatapb.TabletType_REPLICA)
   307  	require.NoError(t, err)
   308  	// This should resurrect the prepared transaction.
   309  	err = client.SetServingType(topodatapb.TabletType_PRIMARY)
   310  	require.NoError(t, err)
   311  	err = client.CommitPrepared("aa")
   312  	require.NoError(t, err)
   313  	qr, err := client.Execute("select * from vitess_test", nil)
   314  	require.NoError(t, err)
   315  	assert.Equal(t, 4, len(qr.Rows))
   316  }
   317  
   318  func TestShutdownGracePeriod(t *testing.T) {
   319  	client := framework.NewClient()
   320  
   321  	err := client.Begin(false)
   322  	require.NoError(t, err)
   323  	go func() {
   324  		_, err = client.Execute("select sleep(10) from dual", nil)
   325  		assert.Error(t, err)
   326  	}()
   327  
   328  	started := false
   329  	for i := 0; i < 10; i++ {
   330  		queries := framework.LiveQueryz()
   331  		if len(queries) == 1 {
   332  			started = true
   333  			break
   334  		}
   335  		time.Sleep(10 * time.Millisecond)
   336  	}
   337  	assert.True(t, started)
   338  
   339  	start := time.Now()
   340  	err = client.SetServingType(topodatapb.TabletType_REPLICA)
   341  	require.NoError(t, err)
   342  	assert.True(t, time.Since(start) < 5*time.Second, time.Since(start))
   343  	client.Rollback()
   344  
   345  	client = framework.NewClientWithTabletType(topodatapb.TabletType_REPLICA)
   346  	err = client.Begin(false)
   347  	require.NoError(t, err)
   348  	go func() {
   349  		_, err = client.Execute("select sleep(11) from dual", nil)
   350  		assert.Error(t, err)
   351  	}()
   352  
   353  	started = false
   354  	for i := 0; i < 10; i++ {
   355  		queries := framework.LiveQueryz()
   356  		if len(queries) == 1 {
   357  			started = true
   358  			break
   359  		}
   360  		time.Sleep(10 * time.Millisecond)
   361  	}
   362  	assert.True(t, started)
   363  	start = time.Now()
   364  	err = client.SetServingType(topodatapb.TabletType_PRIMARY)
   365  	require.NoError(t, err)
   366  	assert.True(t, time.Since(start) < 1*time.Second, time.Since(start))
   367  	client.Rollback()
   368  }
   369  
   370  func TestShutdownGracePeriodWithStreamExecute(t *testing.T) {
   371  	client := framework.NewClient()
   372  
   373  	err := client.Begin(false)
   374  	require.NoError(t, err)
   375  	go func() {
   376  		_, err = client.StreamExecute("select sleep(10) from dual", nil)
   377  		assert.Error(t, err)
   378  	}()
   379  
   380  	started := false
   381  	for i := 0; i < 10; i++ {
   382  		queries := framework.LiveQueryz()
   383  		if len(queries) == 1 {
   384  			started = true
   385  			break
   386  		}
   387  		time.Sleep(10 * time.Millisecond)
   388  	}
   389  	assert.True(t, started)
   390  
   391  	start := time.Now()
   392  	err = client.SetServingType(topodatapb.TabletType_REPLICA)
   393  	require.NoError(t, err)
   394  	assert.True(t, time.Since(start) < 5*time.Second, time.Since(start))
   395  	client.Rollback()
   396  
   397  	client = framework.NewClientWithTabletType(topodatapb.TabletType_REPLICA)
   398  	err = client.Begin(false)
   399  	require.NoError(t, err)
   400  	go func() {
   401  		_, err = client.StreamExecute("select sleep(11) from dual", nil)
   402  		assert.Error(t, err)
   403  	}()
   404  
   405  	started = false
   406  	for i := 0; i < 10; i++ {
   407  		queries := framework.LiveQueryz()
   408  		if len(queries) == 1 {
   409  			started = true
   410  			break
   411  		}
   412  		time.Sleep(10 * time.Millisecond)
   413  	}
   414  	assert.True(t, started)
   415  	start = time.Now()
   416  	err = client.SetServingType(topodatapb.TabletType_PRIMARY)
   417  	require.NoError(t, err)
   418  	assert.True(t, time.Since(start) < 1*time.Second, time.Since(start))
   419  	client.Rollback()
   420  }
   421  
   422  func TestShutdownGracePeriodWithReserveExecute(t *testing.T) {
   423  	client := framework.NewClient()
   424  
   425  	err := client.Begin(false)
   426  	require.NoError(t, err)
   427  	go func() {
   428  		_, err = client.ReserveExecute("select sleep(10) from dual", nil, nil)
   429  		assert.Error(t, err)
   430  	}()
   431  
   432  	started := false
   433  	for i := 0; i < 10; i++ {
   434  		queries := framework.LiveQueryz()
   435  		if len(queries) == 1 {
   436  			started = true
   437  			break
   438  		}
   439  		time.Sleep(10 * time.Millisecond)
   440  	}
   441  	assert.True(t, started)
   442  
   443  	start := time.Now()
   444  	err = client.SetServingType(topodatapb.TabletType_REPLICA)
   445  	require.NoError(t, err)
   446  	assert.True(t, time.Since(start) < 5*time.Second, time.Since(start))
   447  	client.Rollback()
   448  
   449  	client = framework.NewClientWithTabletType(topodatapb.TabletType_REPLICA)
   450  	err = client.Begin(false)
   451  	require.NoError(t, err)
   452  	go func() {
   453  		_, err = client.ReserveExecute("select sleep(11) from dual", nil, nil)
   454  		assert.Error(t, err)
   455  	}()
   456  
   457  	started = false
   458  	for i := 0; i < 10; i++ {
   459  		queries := framework.LiveQueryz()
   460  		if len(queries) == 1 {
   461  			started = true
   462  			break
   463  		}
   464  		time.Sleep(10 * time.Millisecond)
   465  	}
   466  	assert.True(t, started)
   467  	start = time.Now()
   468  	err = client.SetServingType(topodatapb.TabletType_PRIMARY)
   469  	require.NoError(t, err)
   470  	assert.True(t, time.Since(start) < 1*time.Second, time.Since(start))
   471  	client.Rollback()
   472  }
   473  
   474  func TestShortTxTimeout(t *testing.T) {
   475  	client := framework.NewClient()
   476  	defer framework.Server.Config().SetTxTimeoutForWorkload(
   477  		framework.Server.Config().TxTimeoutForWorkload(querypb.ExecuteOptions_OLTP),
   478  		querypb.ExecuteOptions_OLTP,
   479  	)
   480  	framework.Server.Config().SetTxTimeoutForWorkload(10*time.Millisecond, querypb.ExecuteOptions_OLTP)
   481  
   482  	err := client.Begin(false)
   483  	require.NoError(t, err)
   484  	start := time.Now()
   485  	_, err = client.Execute("select sleep(10) from dual", nil)
   486  	assert.Error(t, err)
   487  	assert.True(t, time.Since(start) < 5*time.Second, time.Since(start))
   488  	client.Rollback()
   489  }
   490  
   491  func TestMMCommitFlow(t *testing.T) {
   492  	client := framework.NewClient()
   493  	defer client.Execute("delete from vitess_test where intval=4", nil)
   494  
   495  	query := "insert into vitess_test (intval, floatval, charval, binval) " +
   496  		"values(4, null, null, null)"
   497  	err := client.Begin(false)
   498  	require.NoError(t, err)
   499  	_, err = client.Execute(query, nil)
   500  	require.NoError(t, err)
   501  
   502  	err = client.CreateTransaction("aa", []*querypb.Target{{
   503  		Keyspace: "test1",
   504  		Shard:    "0",
   505  	}, {
   506  		Keyspace: "test2",
   507  		Shard:    "1",
   508  	}})
   509  	require.NoError(t, err)
   510  
   511  	err = client.CreateTransaction("aa", []*querypb.Target{})
   512  	require.Error(t, err)
   513  	require.Contains(t, err.Error(), "Duplicate entry")
   514  
   515  	err = client.StartCommit("aa")
   516  	require.NoError(t, err)
   517  
   518  	err = client.SetRollback("aa", 0)
   519  	require.EqualError(t, err, "could not transition to ROLLBACK: aa (CallerID: dev)")
   520  
   521  	info, err := client.ReadTransaction("aa")
   522  	require.NoError(t, err)
   523  	info.TimeCreated = 0
   524  	wantInfo := &querypb.TransactionMetadata{
   525  		Dtid:  "aa",
   526  		State: 2,
   527  		Participants: []*querypb.Target{{
   528  			Keyspace:   "test1",
   529  			Shard:      "0",
   530  			TabletType: topodatapb.TabletType_PRIMARY,
   531  		}, {
   532  			Keyspace:   "test2",
   533  			Shard:      "1",
   534  			TabletType: topodatapb.TabletType_PRIMARY,
   535  		}},
   536  	}
   537  	utils.MustMatch(t, wantInfo, info, "ReadTransaction")
   538  
   539  	err = client.ConcludeTransaction("aa")
   540  	require.NoError(t, err)
   541  
   542  	info, err = client.ReadTransaction("aa")
   543  	require.NoError(t, err)
   544  	wantInfo = &querypb.TransactionMetadata{}
   545  	if !proto.Equal(info, wantInfo) {
   546  		t.Errorf("ReadTransaction: %#v, want %#v", info, wantInfo)
   547  	}
   548  }
   549  
   550  func TestMMRollbackFlow(t *testing.T) {
   551  	client := framework.NewClient()
   552  	defer client.Execute("delete from vitess_test where intval=4", nil)
   553  
   554  	query := "insert into vitess_test (intval, floatval, charval, binval) " +
   555  		"values(4, null, null, null)"
   556  	err := client.Begin(false)
   557  	require.NoError(t, err)
   558  	_, err = client.Execute(query, nil)
   559  	require.NoError(t, err)
   560  
   561  	err = client.CreateTransaction("aa", []*querypb.Target{{
   562  		Keyspace: "test1",
   563  		Shard:    "0",
   564  	}, {
   565  		Keyspace: "test2",
   566  		Shard:    "1",
   567  	}})
   568  	require.NoError(t, err)
   569  	client.Rollback()
   570  
   571  	err = client.SetRollback("aa", 0)
   572  	require.NoError(t, err)
   573  
   574  	info, err := client.ReadTransaction("aa")
   575  	require.NoError(t, err)
   576  	info.TimeCreated = 0
   577  	wantInfo := &querypb.TransactionMetadata{
   578  		Dtid:  "aa",
   579  		State: 3,
   580  		Participants: []*querypb.Target{{
   581  			Keyspace:   "test1",
   582  			Shard:      "0",
   583  			TabletType: topodatapb.TabletType_PRIMARY,
   584  		}, {
   585  			Keyspace:   "test2",
   586  			Shard:      "1",
   587  			TabletType: topodatapb.TabletType_PRIMARY,
   588  		}},
   589  	}
   590  	if !proto.Equal(info, wantInfo) {
   591  		t.Errorf("ReadTransaction: %#v, want %#v", info, wantInfo)
   592  	}
   593  
   594  	err = client.ConcludeTransaction("aa")
   595  	require.NoError(t, err)
   596  }
   597  
   598  func TestWatchdog(t *testing.T) {
   599  	client := framework.NewClient()
   600  
   601  	query := "insert into vitess_test (intval, floatval, charval, binval) " +
   602  		"values(4, null, null, null)"
   603  	err := client.Begin(false)
   604  	require.NoError(t, err)
   605  	_, err = client.Execute(query, nil)
   606  	require.NoError(t, err)
   607  
   608  	start := time.Now()
   609  	err = client.CreateTransaction("aa", []*querypb.Target{{
   610  		Keyspace: "test1",
   611  		Shard:    "0",
   612  	}, {
   613  		Keyspace: "test2",
   614  		Shard:    "1",
   615  	}})
   616  	require.NoError(t, err)
   617  
   618  	// The watchdog should kick in after 1 second.
   619  	dtid := <-framework.ResolveChan
   620  	if dtid != "aa" {
   621  		t.Errorf("dtid: %s, want aa", dtid)
   622  	}
   623  	diff := time.Since(start)
   624  	if diff < 1*time.Second {
   625  		t.Errorf("diff: %v, want greater than 1s", diff)
   626  	}
   627  
   628  	err = client.SetRollback("aa", 0)
   629  	require.NoError(t, err)
   630  	err = client.ConcludeTransaction("aa")
   631  	require.NoError(t, err)
   632  
   633  	// Make sure the watchdog stops sending messages.
   634  	// Check twice. Sometimes, a race can still cause
   635  	// a stray message.
   636  	dtid = ""
   637  	for i := 0; i < 2; i++ {
   638  		select {
   639  		case dtid = <-framework.ResolveChan:
   640  			continue
   641  		case <-time.After(2 * time.Second):
   642  			return
   643  		}
   644  	}
   645  	t.Errorf("Unexpected message: %s", dtid)
   646  }
   647  
   648  func TestUnresolvedTracking(t *testing.T) {
   649  	// This is a long running test. Enable only for testing the watchdog.
   650  	t.Skip()
   651  	client := framework.NewClient()
   652  	defer client.Execute("delete from vitess_test where intval=4", nil)
   653  
   654  	query := "insert into vitess_test (intval, floatval, charval, binval) " +
   655  		"values(4, null, null, null)"
   656  	err := client.Begin(false)
   657  	require.NoError(t, err)
   658  	_, err = client.Execute(query, nil)
   659  	require.NoError(t, err)
   660  	err = client.Prepare("aa")
   661  	defer client.RollbackPrepared("aa", 0)
   662  	require.NoError(t, err)
   663  	time.Sleep(10 * time.Second)
   664  	vars := framework.DebugVars()
   665  	if val := framework.FetchInt(vars, "Unresolved/Prepares"); val != 1 {
   666  		t.Errorf("Unresolved: %d, want 1", val)
   667  	}
   668  }
   669  
   670  func TestManualTwopcz(t *testing.T) {
   671  	// This is a manual test. Uncomment the Skip to perform this test.
   672  	// The test will print the twopcz URL. Navigate to that location
   673  	// and perform all the operations allowed. They should all succeed
   674  	// and cause the transactions to be resolved.
   675  	t.Skip()
   676  	client := framework.NewClient()
   677  	defer client.Execute("delete from vitess_test where intval=4", nil)
   678  
   679  	ctx := context.Background()
   680  	conn, err := mysql.Connect(ctx, &connParams)
   681  	require.NoError(t, err)
   682  	defer conn.Close()
   683  
   684  	// Successful prepare.
   685  	err = client.Begin(false)
   686  	require.NoError(t, err)
   687  	_, err = client.Execute("insert into vitess_test (intval, floatval, charval, binval) values(4, null, null, null)", nil)
   688  	require.NoError(t, err)
   689  	_, err = client.Execute("insert into vitess_test (intval, floatval, charval, binval) values(5, null, null, null)", nil)
   690  	require.NoError(t, err)
   691  	err = client.Prepare("dtidsuccess")
   692  	defer client.RollbackPrepared("dtidsuccess", 0)
   693  	require.NoError(t, err)
   694  
   695  	// Failed transaction.
   696  	err = client.Begin(false)
   697  	require.NoError(t, err)
   698  	_, err = client.Execute("insert into vitess_test (intval, floatval, charval, binval) values(6, null, null, null)", nil)
   699  	require.NoError(t, err)
   700  	_, err = client.Execute("insert into vitess_test (intval, floatval, charval, binval) values(7, null, null, null)", nil)
   701  	require.NoError(t, err)
   702  	err = client.Prepare("dtidfail")
   703  	defer client.RollbackPrepared("dtidfail", 0)
   704  	require.NoError(t, err)
   705  	conn.ExecuteFetch(fmt.Sprintf("update _vt.redo_state set state = %d where dtid = 'dtidfail'", tabletserver.RedoStateFailed), 10, false)
   706  	conn.ExecuteFetch("commit", 10, false)
   707  
   708  	// Distributed transaction.
   709  	err = client.CreateTransaction("distributed", []*querypb.Target{{
   710  		Keyspace: "k1",
   711  		Shard:    "s1",
   712  	}, {
   713  		Keyspace: "k2",
   714  		Shard:    "s2",
   715  	}})
   716  	defer client.ConcludeTransaction("distributed")
   717  
   718  	require.NoError(t, err)
   719  	fmt.Printf("%s/twopcz\n", framework.ServerAddress)
   720  	fmt.Print("Sleeping for 30 seconds\n")
   721  	time.Sleep(30 * time.Second)
   722  }