@@ -29,7 +29,6 @@ import (
29
29
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
30
30
"github.com/cockroachdb/cockroach/pkg/sql/sessiondata"
31
31
"github.com/cockroachdb/cockroach/pkg/sql/sqlliveness"
32
- "github.com/cockroachdb/cockroach/pkg/sql/types"
33
32
"github.com/cockroachdb/cockroach/pkg/util/cidr"
34
33
"github.com/cockroachdb/cockroach/pkg/util/envutil"
35
34
"github.com/cockroachdb/cockroach/pkg/util/hlc"
@@ -1175,26 +1174,6 @@ FROM system.job_info
1175
1174
WHERE written < $1 AND job_id NOT IN (SELECT id FROM system.jobs)
1176
1175
LIMIT $2`
1177
1176
1178
- // The ordering is important as we keep track of the maximum ID we've seen.
1179
- const expiredJobsQueryWithJobInfoTable = `
1180
- WITH
1181
- latestpayload AS (
1182
- SELECT job_id, value
1183
- FROM system.job_info AS payload
1184
- WHERE job_id > $2 AND info_key = 'legacy_payload'
1185
- ORDER BY written desc
1186
- ),
1187
- jobpage AS (
1188
- SELECT id, status
1189
- FROM system.jobs
1190
- WHERE (created < $1) and (id > $2)
1191
- ORDER BY id
1192
- LIMIT $3
1193
- )
1194
- SELECT distinct (id), latestpayload.value AS payload, status
1195
- FROM jobpage AS j
1196
- INNER JOIN latestpayload ON j.id = latestpayload.job_id`
1197
-
1198
1177
// jobMetadataTables are all of the tables that have rows storing additional
1199
1178
// attributes or data about jobs beyond the core job record in system.jobs. All
1200
1179
// of these tables identity the job which own rows in them using a "job_id"
@@ -1209,86 +1188,31 @@ var jobMetadataTables = []string{"job_info", "job_progress", "job_progress_histo
1209
1188
func (r * Registry ) cleanupOldJobsPage (
1210
1189
ctx context.Context , olderThan time.Time , minID jobspb.JobID , pageSize int ,
1211
1190
) (done bool , maxID jobspb.JobID , retErr error ) {
1212
- query := expiredJobsQueryWithJobInfoTable
1191
+ query := "SELECT id, status, finished, $1 FROM system.jobs WHERE status in (" + terminalStateList + ") AND (finished < $1) and (id >= $2) ORDER BY id LIMIT $3"
1213
1192
1214
1193
it , err := r .db .Executor ().QueryIterator (ctx , "gc-jobs" , nil , /* txn */
1215
1194
query , olderThan , minID , pageSize )
1216
1195
if err != nil {
1217
1196
return false , 0 , err
1218
1197
}
1219
- // We have to make sure to close the iterator since we might return from the
1220
- // for loop early (before Next() returns false).
1221
- defer func () { retErr = errors .CombineErrors (retErr , it .Close ()) }()
1222
- toDelete := tree .NewDArray (types .Int )
1223
- oldMicros := timeutil .ToUnixMicros (olderThan )
1224
-
1198
+ var candidates []jobspb.JobID
1225
1199
var ok bool
1226
- var numRows int
1227
1200
for ok , err = it .Next (ctx ); ok ; ok , err = it .Next (ctx ) {
1228
- numRows ++
1229
- row := it .Cur ()
1230
- payload , err := UnmarshalPayload (row [1 ])
1231
- if err != nil {
1232
- return false , 0 , err
1233
- }
1234
- remove := false
1235
- switch State (* row [2 ].(* tree.DString )) {
1236
- case StateSucceeded , StateCanceled , StateFailed :
1237
- remove = payload .FinishedMicros < oldMicros
1238
- }
1239
- if remove {
1240
- toDelete .Array = append (toDelete .Array , row [0 ])
1241
- }
1242
- }
1243
- if err != nil {
1244
- return false , 0 , err
1201
+ candidates = append (candidates , jobspb .JobID (tree .MustBeDInt (it .Cur ()[0 ])))
1245
1202
}
1246
- if numRows == 0 {
1247
- return true , 0 , nil
1203
+ err = errors .CombineErrors (err , it .Close ())
1204
+
1205
+ if err != nil || len (candidates ) == 0 {
1206
+ return len (candidates ) == 0 , 0 , err
1248
1207
}
1249
1208
1250
- log .VEventf (ctx , 2 , "read potentially expired jobs: %d" , numRows )
1251
- if len (toDelete .Array ) > 0 {
1252
- log .VEventf (ctx , 2 , "attempting to clean up %d expired job records" , len (toDelete .Array ))
1253
- const stmt = `DELETE FROM system.jobs WHERE id = ANY($1)`
1254
- nDeleted , err := r .db .Executor ().Exec (
1255
- ctx , "gc-jobs" , nil /* txn */ , stmt , toDelete ,
1256
- )
1257
- if err != nil {
1258
- log .Warningf (ctx , "error cleaning up %d jobs: %v" , len (toDelete .Array ), err )
1259
- return false , 0 , errors .Wrap (err , "deleting old jobs" )
1260
- }
1261
-
1262
- counts := make (map [string ]int )
1263
- for _ , tbl := range jobMetadataTables {
1264
- var deleted int
1265
- if err := r .db .Txn (ctx , func (ctx context.Context , txn isql.Txn ) error {
1266
- // Tables other than job_info -- the 0th -- are only present if the txn is
1267
- // running at a version that includes them.
1268
- deleted , err = txn .Exec (ctx , redact .RedactableString ("gc-job-" + tbl ), txn .KV (),
1269
- "DELETE FROM system." + tbl + " WHERE job_id = ANY($1)" , toDelete ,
1270
- )
1271
- if err != nil {
1272
- return err
1273
- }
1274
- return nil
1275
- }); err != nil {
1276
- return false , 0 , errors .Wrapf (err , "deleting old job metadata from %s" , tbl )
1277
- }
1278
- counts [tbl ] = deleted
1279
- }
1280
- if nDeleted > 0 {
1281
- log .Infof (ctx , "cleaned up %d expired job records (%d infos, %d progresses, %d progress_hists, %d statuses, %d messages)" ,
1282
- nDeleted , counts ["job_info" ], counts ["job_progress" ], counts ["job_progress_history" ], counts ["job_status" ], counts ["job_message" ])
1209
+ log .VEventf (ctx , 2 , "found %d expired jobs" , len (candidates ))
1210
+ for _ , id := range candidates {
1211
+ if err := r .DeleteTerminalJobByID (ctx , id ); err != nil {
1212
+ return false , 0 , err
1283
1213
}
1284
1214
}
1285
- // If we got as many rows as we asked for, there might be more.
1286
- morePages := numRows == pageSize
1287
- // Track the highest ID we encounter, so it can serve as the bottom of the
1288
- // next page.
1289
- lastRow := it .Cur ()
1290
- maxID = jobspb .JobID (* (lastRow [0 ].(* tree.DInt )))
1291
- return ! morePages , maxID , nil
1215
+ return len (candidates ) < pageSize , candidates [len (candidates )- 1 ], nil
1292
1216
}
1293
1217
1294
1218
// DeleteTerminalJobByID deletes the given job ID if it is in a
0 commit comments