diff --git a/server/datastore/mysql/labels.go b/server/datastore/mysql/labels.go index a93f606832..2ae509ae9b 100644 --- a/server/datastore/mysql/labels.go +++ b/server/datastore/mysql/labels.go @@ -3,6 +3,7 @@ package mysql import ( "database/sql" "fmt" + "sort" "strings" "time" @@ -318,13 +319,21 @@ func (d *Datastore) LabelQueriesForHost(host *fleet.Host, cutoff time.Time) (map } func (d *Datastore) RecordLabelQueryExecutions(host *fleet.Host, results map[uint]bool, updated time.Time) error { + // Sort the results to have generated SQL queries ordered to minimize + // deadlocks. See https://github.com/fleetdm/fleet/issues/1146. + orderedIDs := make([]uint, 0, len(results)) + for labelID, _ := range results { + orderedIDs = append(orderedIDs, labelID) + } + sort.Slice(orderedIDs, func(i, j int) bool { return orderedIDs[i] < orderedIDs[j] }) + // Loop through results, collecting which labels we need to insert/update, // and which we need to delete vals := []interface{}{} bindvars := []string{} removes := []uint{} - - for labelID, matches := range results { + for _, labelID := range orderedIDs { + matches := results[labelID] if matches { // Add/update row bindvars = append(bindvars, "(?,?,?)")