diff --git a/go/test/endtoend/vtcombo/recreate/recreate_test.go b/go/test/endtoend/vtcombo/recreate/recreate_test.go index a454adbd7e1..582fb9c3747 100644 --- a/go/test/endtoend/vtcombo/recreate/recreate_test.go +++ b/go/test/endtoend/vtcombo/recreate/recreate_test.go @@ -22,6 +22,7 @@ import ( "fmt" "os" "os/exec" + "strconv" "strings" "testing" @@ -102,6 +103,9 @@ func TestDropAndRecreateWithSameShards(t *testing.T) { cur := conn.Session(ks1+"@primary", nil) + mysqlConnCountBefore, err := getMySQLConnectionCount(ctx, cur) + require.Nil(t, err) + _, err = cur.Execute(ctx, "DROP DATABASE "+ks1, nil) require.Nil(t, err) @@ -109,6 +113,23 @@ func TestDropAndRecreateWithSameShards(t *testing.T) { require.Nil(t, err) assertTabletsPresent(t) + + // Check the connection count after the CREATE. There will be zero connections after the DROP as the database + // no longer exists, but after it gets recreated any open pools will be able to reestablish connections. + mysqlConnCountAfter, err := getMySQLConnectionCount(ctx, cur) + require.Nil(t, err) + + // Assert that we're not leaking mysql connections, but allow for some wiggle room due to transient connections + assert.InDelta(t, mysqlConnCountBefore, mysqlConnCountAfter, 5, + "not within allowable delta: mysqlConnCountBefore=%d, mysqlConnCountAfter=%d", mysqlConnCountBefore, mysqlConnCountAfter) +} + +func getMySQLConnectionCount(ctx context.Context, session *vtgateconn.VTGateSession) (int, error) { + result, err := session.Execute(ctx, "select variable_value from performance_schema.global_status where variable_name='threads_connected'", nil) + if err != nil { + return 0, err + } + return strconv.Atoi(result.Rows[0][0].ToString()) } func assertTabletsPresent(t *testing.T) { diff --git a/go/vt/vtcombo/tablet_map.go b/go/vt/vtcombo/tablet_map.go index 9f987087cf8..bc341f3079b 100644 --- a/go/vt/vtcombo/tablet_map.go +++ b/go/vt/vtcombo/tablet_map.go @@ -230,7 +230,11 @@ func DeleteKs( tablet.tm.Stop() tablet.tm.Close() tablet.qsc.SchemaEngine().Close() - err := ts.DeleteTablet(ctx, tablet.alias) + err := tablet.qsc.QueryService().Close(ctx) + if err != nil { + return err + } + err = ts.DeleteTablet(ctx, tablet.alias) if err != nil { return err }