Batch jobs: failed (001), longer than their own history (002), late or never started (003), stuck in Executing (004). Number sequences: running out with a forecast from SQLInsight's own samples (005), format shorter than HIGHEST (006), blocked but still referenced (007), continuous and not cleaned up (008). RecId running out, flagged far earlier for AX 3.0's 32-bit RecId (009). AX user behind blocking from CONTEXT_INFO, honest where AX 3.0 cannot tell (010). Subjects carry the database, so findings follow the hub opt-in. SQL Scripts/<rule>.sql (and _collectors/) for every AX rule added or changed in 1.4, incl. COM-AX-001..007: a Danish header plus the exact SQL SQLInsight sends, generated from the code and checked by SqlScriptTests (rewrite with SQLINSIGHT_UPDATE_SQL_SCRIPTS=1). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
94 lines
7 KiB
MySQL
94 lines
7 KiB
MySQL
/*
|
||
Regel: SQLI-AX-009 – Dynamics AX RecId er ved at løbe tør
|
||
Alvorlighed: Axapta 3.0 (32-bit): Høj (High) fra advarselsgrænsen, Kritisk (Critical) fra den kritiske grænse;
|
||
64-bit: Høj (High); altid Kritisk, når RecId er opbrugt
|
||
|
||
Hvad og hvorfor
|
||
Når en tabels RecId-serie er brugt op, kan AX ikke oprette flere poster. Axapta 3.0 har 32-bit RecId (int, højst
|
||
2.147.483.647 pr. tabel og firma), og det løses kun med et stort projekt – derfor advares langt tidligere for 3.0.
|
||
|
||
Tærskler (agentens konfiguration SQLInsight:DynamicsAx)
|
||
RecId32WarnPercent = 50 Axapta 3.0: Høj fra så mange procent af int-intervallet
|
||
RecId32CriticalPercent = 75 Axapta 3.0: Kritisk
|
||
RecId32ForecastDays = 730 Axapta 3.0: Høj, hvis den løber tør inden for så mange dage; Kritisk inden for halvdelen
|
||
RecId64WarnPercent = 80 64-bit (eller sænket MAXVAL): Høj
|
||
ForecastWarnDays = 90 64-bit: Høj, hvis den løber tør inden for så mange dage
|
||
ForecastBasisDays = 30 prognosen bruger den ældste daglige måling inden for så mange dage
|
||
|
||
Vurdering (C#: src/SQLInsight.Rules/DynamicsAx/DynamicsAxRules.cs – AxRecIdExhaustionRule.Assess; tal i
|
||
src/SQLInsight.Core/DynamicsAx/AxSchemaAdapter.cs – Interpret(AxRecIdRow))
|
||
Grænse = typens maksimum (int, når SYSTEMSEQUENCES.NEXTVAL er int som i Axapta 3.0; ellers bigint), eller MAXVAL, hvis
|
||
den er sat lavere. Brugt % = NEXTVAL / grænse. Prognose ud fra SQLInsights egne daglige målinger af NEXTVAL
|
||
(insight.AxSequenceSamples). Højst 25 fund pr. database, de mest brugte først.
|
||
|
||
Collector: src/SQLInsight.Collectors/DynamicsAx/AxSequenceCollector.cs – AxSequenceCollector.CollectAsync (hver time).
|
||
SQL: src/SQLInsight.Core/DynamicsAx/AxSchemaAdapter.cs – RecIds.
|
||
Rettigheder: Valgfri AX-læseadgang, kun SELECT (db/permissions/grant-dynamics-ax-read.sql):
|
||
Axapta 3.0: GRANT SELECT ON [bmssa].[SYSTEMSEQUENCES] TO [<agentens bruger>];
|
||
GRANT SELECT ON [bmssa].[SQLDICTIONARY] TO [<agentens bruger>]; (valgfri: tabelnavne)
|
||
AX 4.0/2009/2012/F&O: de samme tabeller i [dbo]
|
||
Mangler SYSTEMSEQUENCES, er reglen "ikke målbar" med den nøjagtige GRANT for databasen.
|
||
Versioner: SQL Server 2005 og nyere (ikke 2000). Axapta 3.0: verificeret mod en kundes skema (SYSTEMSEQUENCES med
|
||
NEXTVAL/MAXVAL pr. TABID og DATAAREAID). AX 4.0, AX 2009, AX 2012 og F&O: baseret på Microsofts dokumenterede
|
||
skema – ikke verificeret mod kundedata.
|
||
Læsning: Kun SELECT med TOP (de højeste først), READ COMMITTED med SET LOCK_TIMEOUT 2000 (SNAPSHOT, når databasen
|
||
tillader det), aldrig NOLOCK, i AX-databasen via [db].sys.sp_executesql. Kun i databaser genkendt som AX og
|
||
valgt til overvågning.
|
||
*/
|
||
-- >>> SQL, som SQLInsight kører – genereret fra koden (tests/SQLInsight.Collectors.Tests/SqlScriptTests.cs). Ret ikke herunder i hånden.
|
||
-- Variant: Axapta 3.0 (skema bmssa): RecId pr. tabel (AxSchemaAdapter.RecIds)
|
||
DECLARE @Database sysname;
|
||
SET @Database = N'AXDB'; -- <== ret til AX-databasen
|
||
DECLARE @Schema sysname;
|
||
SET @Schema = N'bmssa'; -- <== ejeren af AX-tabellerne: bmssa i Axapta 3.0, ellers dbo
|
||
DECLARE @Sql nvarchar(max);
|
||
SET @Sql = N'SET NOCOUNT ON; SET LOCK_TIMEOUT 2000; SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SELECT TOP (500) s.[TABID], s.[DATAAREAID], CAST(s.[NEXTVAL] AS bigint), CAST(s.[MAXVAL] AS bigint), (SELECT TOP 1 d.[NAME] FROM [bmssa].[SQLDICTIONARY] d WHERE d.[TABLEID] = s.[TABID] AND d.[FIELDID] = 0) FROM [bmssa].[SYSTEMSEQUENCES] s WHERE s.[NAME] = N''SEQNO'' ORDER BY s.[NEXTVAL] DESC';
|
||
SET @Sql = REPLACE(@Sql, N'[bmssa].', QUOTENAME(@Schema) + N'.');
|
||
DECLARE @Procedure nvarchar(300);
|
||
SET @Procedure = QUOTENAME(@Database) + N'.sys.sp_executesql';
|
||
EXEC @Procedure @Sql;
|
||
SET LOCK_TIMEOUT -1; SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||
GO
|
||
|
||
-- Variant: AX 4.0 (skema dbo) – ikke verificeret mod kundedata: RecId pr. tabel (AxSchemaAdapter.RecIds)
|
||
DECLARE @Database sysname;
|
||
SET @Database = N'AXDB'; -- <== ret til AX-databasen
|
||
DECLARE @Schema sysname;
|
||
SET @Schema = N'dbo'; -- <== ejeren af AX-tabellerne: bmssa i Axapta 3.0, ellers dbo
|
||
DECLARE @Sql nvarchar(max);
|
||
SET @Sql = N'SET NOCOUNT ON; SET LOCK_TIMEOUT 2000; SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SELECT TOP (500) s.[TABID], s.[DATAAREAID], CAST(s.[NEXTVAL] AS bigint), CAST(s.[MAXVAL] AS bigint), (SELECT TOP 1 d.[NAME] FROM [dbo].[SQLDICTIONARY] d WHERE d.[TABLEID] = s.[TABID] AND d.[FIELDID] = 0) FROM [dbo].[SYSTEMSEQUENCES] s WHERE s.[NAME] = N''SEQNO'' ORDER BY s.[NEXTVAL] DESC';
|
||
SET @Sql = REPLACE(@Sql, N'[dbo].', QUOTENAME(@Schema) + N'.');
|
||
DECLARE @Procedure nvarchar(300);
|
||
SET @Procedure = QUOTENAME(@Database) + N'.sys.sp_executesql';
|
||
EXEC @Procedure @Sql;
|
||
SET LOCK_TIMEOUT -1; SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||
GO
|
||
|
||
-- Variant: AX 2009 – baseret på Microsofts dokumenterede skema, ikke verificeret mod kundedata: RecId pr. tabel (AxSchemaAdapter.RecIds)
|
||
DECLARE @Database sysname;
|
||
SET @Database = N'AXDB'; -- <== ret til AX-databasen
|
||
DECLARE @Schema sysname;
|
||
SET @Schema = N'dbo'; -- <== ejeren af AX-tabellerne: bmssa i Axapta 3.0, ellers dbo
|
||
DECLARE @Sql nvarchar(max);
|
||
SET @Sql = N'SET NOCOUNT ON; SET LOCK_TIMEOUT 2000; SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SELECT TOP (500) s.[TABID], s.[DATAAREAID], CAST(s.[NEXTVAL] AS bigint), CAST(s.[MAXVAL] AS bigint), (SELECT TOP 1 d.[NAME] FROM [dbo].[SQLDICTIONARY] d WHERE d.[TABLEID] = s.[TABID] AND d.[FIELDID] = 0) FROM [dbo].[SYSTEMSEQUENCES] s WHERE s.[NAME] = N''SEQNO'' ORDER BY s.[NEXTVAL] DESC';
|
||
SET @Sql = REPLACE(@Sql, N'[dbo].', QUOTENAME(@Schema) + N'.');
|
||
DECLARE @Procedure nvarchar(300);
|
||
SET @Procedure = QUOTENAME(@Database) + N'.sys.sp_executesql';
|
||
EXEC @Procedure @Sql;
|
||
SET LOCK_TIMEOUT -1; SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||
GO
|
||
|
||
-- Variant: AX 2012 RTM/R2/R3 og F&O – baseret på Microsofts dokumenterede skema, ikke verificeret mod kundedata: RecId pr. tabel (AxSchemaAdapter.RecIds)
|
||
DECLARE @Database sysname;
|
||
SET @Database = N'AXDB'; -- <== ret til AX-databasen
|
||
DECLARE @Schema sysname;
|
||
SET @Schema = N'dbo'; -- <== ejeren af AX-tabellerne: bmssa i Axapta 3.0, ellers dbo
|
||
DECLARE @Sql nvarchar(max);
|
||
SET @Sql = N'SET NOCOUNT ON; SET LOCK_TIMEOUT 2000; SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SELECT TOP (500) s.[TABID], s.[DATAAREAID], CAST(s.[NEXTVAL] AS bigint), CAST(s.[MAXVAL] AS bigint), (SELECT TOP 1 d.[NAME] FROM [dbo].[SQLDICTIONARY] d WHERE d.[TABLEID] = s.[TABID] AND d.[FIELDID] = 0) FROM [dbo].[SYSTEMSEQUENCES] s WHERE s.[NAME] = N''SEQNO'' ORDER BY s.[NEXTVAL] DESC';
|
||
SET @Sql = REPLACE(@Sql, N'[dbo].', QUOTENAME(@Schema) + N'.');
|
||
DECLARE @Procedure nvarchar(300);
|
||
SET @Procedure = QUOTENAME(@Database) + N'.sys.sp_executesql';
|
||
EXEC @Procedure @Sql;
|
||
SET LOCK_TIMEOUT -1; SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||
GO
|
||
-- <<< slut på genereret SQL
|