Ce problème peut survenir :

  • à partir de la version 2012 de SQL Server
  • si vous faites un redémarrage ou un failover "brutal" de votre instance

Ce fonctionnement est considéré comme normal et n'est pas vraiment un bug : depuis SQL Server 2012, le moteur ne génère plus les valeurs IDENTITY pour chaque insertion, mais en réserve tout un lot. Seule la valeur la plus élevée est écrite dans le journal de transactions. L'objectif est de limiter les écritures dans le journal pour améliorer les performances. En cas de crash, seule la dernière valeur de la plage peut être lue dans le journal de transactions, ce qui provoque le saut de toute la plage.

Si ce problème est gênant pour vous, sachez qu'il est possible d'activer le traceflag 272 (mettre -T272 dans les paramètres de démarrage pour l'appliquer à toute l'instance), afin de revenir au fonctionnement des versions précédentes. Autre alternative, à la place d'IDENTITY utilisez une séquence avec l'option NO CACHE.

Pour ces deux solutions, bien évidemment, on perd l'avantage éventuel en performances car un enregistrement de journal sera écrit à chaque nouvelle valeur...