Fixes for the 3.x line, including a regression in 3.22.7 that made TriggerJob slower the more triggers its job had stored. There is no public API change and no schema change.
Fixed
TriggerJobno longer slows down as its job's backlog grows (regression in 3.22.7). 3.22.7 gave a manual firing the execution group its job's triggers share (#4110), and found that group by loading every stored trigger of the job, three statements per trigger. A queued manual firing is a stored trigger too, so each call cost more than the one before. The group is now read with one statement. (#4170, from #4167)- A
[DisallowConcurrentExecution]job's completion reads only the triggers that misfired (since 3.17.0). Each completion loaded every remaining trigger of the job underTRIGGER_ACCESSto apply the misfire policy to the late ones, so draining a backlog was quadratic in statements, andScheduleJobandTriggerJobwaited behind the lock. The completion now asks the database only for the job's misfired triggers, with the misfire handler's predicate. (#4168, from #4167) - A restart keeps a declared trigger's fire count and an individual pause. A start re-applies every
AddTriggerandScheduleJobregistration and every scheduling file throughRescheduleJob. That resetTimesTriggered, so a finiteWithRepeatCountran again from the beginning, and it resumed a trigger an operator had paused on its own. Both are now kept while the declared schedule is unchanged; a changed schedule starts fresh. An application's ownRescheduleJobstill ends an individual pause. (#4149, from #4128)
The #4167 workload on SQL Server: 400 queued triggers on one serial job with a 50 ms body, which would drain in 20 s with no scheduler overhead.
| Version | Drain time | Misfire events | TriggerJob median
|
|---|---|---|---|
| 3.16.1 | 58 s | 0 | 58 ms |
| 3.22.7 | 212 s | 137 | 1.4 s |
| 3.22.8 | 50 s | 0 | 58 ms |
Against a remote database every one of those statements is a round trip, so the difference grows with latency.
Behaviour changes
- A serial job's completion no longer reports a late
IgnoreMisfirePolicytrigger toITriggerListener.TriggerMisfired, and no longer writes it back unchanged. Acquisition fires it, as the misfire handler andRAMJobStorealready did. (#4168) - The completion no longer calls the
protected virtualJobStoreSupport.GetTriggersForJob(conn, …)andUpdateMisfiredTrigger(conn, key, …). A subclass that overrode either to change what a completion does is bypassed there;ResumeTriggerstill callsUpdateMisfiredTrigger. (#4168)
Thanks to @kostekk88 for the report and the repro in #4167.
What's Changed
Other changes
- A start that re-applies declared triggers keeps their run state and an individual pause (3.x) by @lahma in #4149
- A serial job's completion reads only the misfired triggers it lets go of, not the job's whole backlog (3.x) by @lahma in #4168
- A manual firing reads the execution group its job's triggers share in one statement, not by loading every trigger of the job (3.x) by @lahma in #4170
Full Changelog: v3.22.7...v3.22.8