Sort labels for membership update (#1156)

This may help with deadlocks on the `label_membership` table. It is not
clear from MySQL documentation whether the order of the records is
significant for locking within a single query. If it is, this should
help the problem. If it is not, this should have no negative impact.

May fix #1146
This commit is contained in:
Zach Wasserman 2021-06-21 16:10:24 -07:00 committed by GitHub
parent 62e7c1699a
commit b859f7b747
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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, "(?,?,?)")