CORRECTIF : Un repositionnement (ROLLBACK) sur un point d'enregistrement induit une assertion et des erreurs

Ancien nº de publication de cet article : F294902
Cet article a été archivé. Il est proposé « en l'état » et ne sera plus mis à jour.
N° DE BOGUE : 352501 (SHILOH_bugs)
Symptômes
Si un client affecte la première page, la page racine et la page firstIAM d'une table dans le cadre d'une transaction utilisateur, et qu'il utilise la commande ROLLBACK pour effectuer un repositionnement sur un point d'enregistrement au sein de cette même transaction, il se peut qu'un message d'erreur 3624 (assertion de la version commerciale) s'affiche et que la connexion du client avec SQL Server soit interrompue. Le message d'erreur suivant est retourné dans l'Analyseur de requêtes si celui-ci est utilisé comme client :
Serveur : Msg 3624, Niveau 20, État 1, Ligne 1

Emplacement : page.cpp:2777
Expression : rowLength >= offset + deleteLength
SPID : 51
ID du processus : 596

Connexion interrompue
En outre, des erreurs 3448, 3314 et des vidages de pile peuvent apparaître dans le journal des erreurs de SQL Server.
Cause
Dans SQL Server 2000, les tables sont créées sous la forme de tables vides. Cela signifie que lors de la création d'une table, aucune page ne lui est affectée. Des pages sont affectées à une table lorsque des données sont insérées dans celle-ci.

C'est pourquoi le scénario ci-dessous peut conduire à une assertion et à des messages d'erreur :
  • Une transaction utilisateur est lancée avec l'instruction BEGIN TRAN.
  • Une table est créée avec l'instruction CREATE TABLE.
  • Un point d'enregistrement est spécifié dans la transaction.
  • Des instructions DML (Data Manipulation Language) sont appliquées à la table mentionnée au deuxième point de la liste, aboutissant à l'affectation de la première page, la page racine et la page firstIAM à cette table.
  • La commande ROLLBACK est utilisée pour effectuer un repositionnement sur le point d'enregistrement mentionné au troisième point de la liste.
  • Des instructions DML supplémentaires sont appliquées à la table mentionnée au deuxième point de la liste.
Ce problème se produit lorsque les instructions DML supplémentaires mentionnées au dernier point de la liste ne réaffectent pas de pages à la table. Les instructions DML ne réaffectent pas de pages à la table car, en se basant sur les informations provenant d'un cache SQL Server non valide, elles considèrent que des pages ont déjà été affectées à la table. Le cache SQL Server n'est pas au courant du fait que les instructions DML qui ont affecté des pages à la table ont été repositionnées.
Résolution
Pour résoudre ce problème, procurez-vous le dernier Service Pack pour SQL Server 2000. Pour plus d'informations, consultez l'article suivant dans la Base de connaissances Microsoft :
290211 INF : Procédure d'obtention du dernier Service Pack pour SQL Server 2000
Statut
Microsoft a confirmé l'existence de ce problème dans SQL Server 2000. Ce problème a été corrigé dans le Service Pack 1 de SQL Server 2000.
Plus d'informations
Un point d'enregistrement est un marqueur au sein d'une transaction qui définit un emplacement auquel une transaction peut revenir en cas d'annulation conditionnelle d'une partie de celle-ci. Pour plus d'informations sur les points d'enregistrement, consultez la rubrique " SAVE TRANSACTION " dans la documentation en ligne SQL Server.

Pour reproduire le problème, exécutez le script suivant :
use mastergocreate database reprogouse reprogo-- use tempdbgobegin trangocreate table t1 (i1 int null)create table t2 (i2 int null)go-- SIMPLE WITH CHECK--create view vt as  select * from t1 where i1 between 1 and 10  with check optiongosave tran emptygoinsert vt values(1)       -- OKinsert vt values(5)       -- OKinsert vt values(10)      -- OKinsert vt values(0)       -- FAIL (<1)insert vt values(11)      -- FAIL (>10)insert vt values(null)    -- FAIL (null)gorollback tran emptygo-- WITH CHECK JOIN--create view vt as  select * from t1 inner join t2 on t1.i1 = t2.i2  with check optiongoinsert vtJN(i1) values(1)	-- FAIL (no match)insert t2(i2) values(1)		-- OK (prime row)insert vtJN(i1) values(1)	-- FAIL (no match)
Voici le vidage de pile réduit pour cette assertion sur la version commerciale 8.00.194 :
-------------------------------------------------------------------------------Vidage de pile réduit77F97AC6 Module(ntdll+00017AC6) (ZwGetContextThread+0000000B)0092569E Module(sqlservr+0052569E) (utassert_fail(enum UTASSERT_TYPE,char const *,char const *,                                    int,char const *,...)+000002E9)00843FAC Module(sqlservr+00443FAC) (Page::ModifyRow(int,unsigned int,unsigned int,unsigned int,void const *,                                    unsigned int,class XdesId const *)+000000D0)0042DEAB Module(sqlservr+0002DEAB) (PageRef::ModifyRow(struct BUF *,int,unsigned int,unsigned int,                                    unsigned int,void const *,enum ETabStatus,int,class XDES *,                                    void const *,unsigned int)+0000033A)0041CC24 Module(sqlservr+0001CC24) (AllocationReq::AllocatePages(void)+00000690)0041B777 Module(sqlservr+0001B777) (AllocationReq::Allocate(void)+00000078)0043EF30 Module(sqlservr+0003EF30) (AllocateHeapPage(struct CINSTABLE *)+0000007D)0080C76D Module(sqlservr+0040C76D) (AllocatePageForInsert(class SDES *,struct INDEX *)+000000CD)0043461A Module(sqlservr+0003461A) (FreeSpaceScan::GetNextPage(struct BUF * *)+000003B0)00434A1B Module(sqlservr+00034A1B) (FindExistingFreeSpace(class SDES *,struct INDEX *,                                    unsigned int,int &)+000000B8)004348AD Module(sqlservr+000348AD) (ncinsert(class SDES * volatile,unsigned char *,int,class Scan_rid &)+00000081)00418543 Module(sqlservr+00018543) (rowinsert(class SDES * volatile,void *,int,unsigned char)+00000118)004185E0 Module(sqlservr+000185E0) (insert(class SDES *,void *,int)+00000013)00433D8F Module(sqlservr+00033D8F) (RowsetSS::InsertRow(unsigned long,unsigned long,void *,                                    unsigned long *)+00000201)0042EE6A Module(sqlservr+0002EE6A) (CValRow::SetDataX(unsigned long *,class CXVariant *)+00000025)00431C2F Module(sqlservr+00031C2F) (CEs::FastMoveEval(unsigned long *,class CEsExec *,                                    class CXVariant *)+00000039)00433FD6 Module(sqlservr+00033FD6) (CQScanScalarInsert::GetRow(unsigned long *,unsigned long *)+00000035)0042C85E Module(sqlservr+0002C85E) (CQScanNLJoin::GetRow(unsigned long *,unsigned long *)+00000112)004C09E1 Module(sqlservr+000C09E1) (CQScanAssert::GetRow(unsigned long *,unsigned long *)+0000001B)00427985 Module(sqlservr+00027985) (CQueryScan::GetRow(unsigned long *,unsigned long *)+00000014)00426F64 Module(sqlservr+00026F64) (CStmtQuery::ErsqExecuteQuery(class CMsqlExecContext *,                                    class CEsComp const *,class CEsComp const *,unsigned long *,                                    int,int)const +000003C4)0042EA36 Module(sqlservr+0002EA36) (CStmtDML::XretExecuteNormal(class CMsqlExecContext *)const +000002F0)0042E82D Module(sqlservr+0002E82D) (CStmtDML::XretExecute(class CMsqlExecContext *)const +0000001C)004160DB Module(sqlservr+000160DB) (CMsqlExecContext::ExecuteStmts(class ExecutionContext *)+0000027E)00415765 Module(sqlservr+00015765) (CMsqlExecContext::Execute(class CCompPlan *,class CParamExchange *)+000001C7)00415410 Module(sqlservr+00015410) (CSQLSource::Execute(class CParamExchange *)+00000343)005A683F Module(sqlservr+001A683F) (CStmtPrepQuery::XretExecute(class CMsqlExecContext *)const +00000211)004160DB Module(sqlservr+000160DB) (CMsqlExecContext::ExecuteStmts(class ExecutionContext *)+0000027E)00415765 Module(sqlservr+00015765) (CMsqlExecContext::Execute(class CCompPlan *,class CParamExchange *)+000001C7)00415410 Module(sqlservr+00015410) (CSQLSource::Execute(class CParamExchange *)+00000343)00459A54 Module(sqlservr+00059A54) (language_exec(struct srv_proc *)+000003C8)004175D8 Module(sqlservr+000175D8) (process_commands(struct srv_proc *)+000000E0)410735D0 Module(UMS+000035D0) (ProcessWorkRequests(class UmsWorkQueue *)+00000264)4107382C Module(UMS+0000382C) (ThreadStartRoutine(void *)+000000BC)7800BEA1 Module(MSVCRT+0000BEA1) (_beginthread+000000CE)77E92CA8 Module(KERNEL32+00012CA8) (CreateFileA+0000011B)-------------------------------------------------------------------------------
Voici un vidage de pile réduit avec une erreur 3448 sur la version commerciale 8.00.194 :
-------------------------------------------------------------------------------Vidage de pile réduit77F97AC6 Module(ntdll+00017AC6) (ZwGetContextThread+0000000B)00926069 Module(sqlservr+00526069) (ex_raise2(int,int,int,int,void *,char *)+00000174)0046C368 Module(sqlservr+0006C368) (ex_raise(int,int,int,int,...)+00000063)008686FE Module(sqlservr+004686FE) (FixPageForUndo(class PageRef &,class DBTABLE *,class LSN const &,                                    enum LatchBase::LATCH_TYPE,class PageLog const &)+00000098)00863962 Module(sqlservr+00463962) (XdesRMReadWrite::UndoPageOperation(class PageLog const *,                                    class LSN const &,int)+0000032B)00440FBA Module(sqlservr+00040FBA) (XdesRMReadWrite::RollbackToLsn(class LSN const &,                                    class LogIterBackLink &,class IndexErrorTable *,int)+000002EB)00865932 Module(sqlservr+00465932) (XdesRMFull::RollbackNested(int)+00000143)0086062F Module(sqlservr+0046062F) (XactRM::RollbackNestedXact(int)+0000009E)0085DEB5 Module(sqlservr+0045DEB5) (FullXactImpBase::RollbackNestedXact(int)+00000037)0064089F Module(sqlservr+0024089F) (CMsqlXact::RollbackNestedXact(enum CMsqlXact::ReadWriteMode,int)+00000017)006403DD Module(sqlservr+002403DD) (CAutoMsqlXact::RollbackNestedXact(void)+00000032)0062F2D1 Module(sqlservr+0022F2D1) (CStmtDML::XretExecuteNormal(class CMsqlExecContext *)const +00000456)0042E82D Module(sqlservr+0002E82D) (CStmtDML::XretExecute(class CMsqlExecContext *)const +0000001C)004160DB Module(sqlservr+000160DB) (CMsqlExecContext::ExecuteStmts(class ExecutionContext *)+0000027E)00415765 Module(sqlservr+00015765) (CMsqlExecContext::Execute(class CCompPlan *,class CParamExchange *)+000001C7)00415410 Module(sqlservr+00015410) (CSQLSource::Execute(class CParamExchange *)+00000343)005A683F Module(sqlservr+001A683F) (CStmtPrepQuery::XretExecute(class CMsqlExecContext *)const +00000211)004160DB Module(sqlservr+000160DB) (CMsqlExecContext::ExecuteStmts(class ExecutionContext *)+0000027E)00415765 Module(sqlservr+00015765) (CMsqlExecContext::Execute(class CCompPlan *,class CParamExchange *)+000001C7)00415410 Module(sqlservr+00015410) (CSQLSource::Execute(class CParamExchange *)+00000343)00459A54 Module(sqlservr+00059A54) (language_exec(struct srv_proc *)+000003C8)004175D8 Module(sqlservr+000175D8) (process_commands(struct srv_proc *)+000000E0)410735D0 Module(UMS+000035D0) (ProcessWorkRequests(class UmsWorkQueue *)+00000264)4107382C Module(UMS+0000382C) (ThreadStartRoutine(void *)+000000BC)7800BEA1 Module(MSVCRT+0000BEA1) (_beginthread+000000CE)77E92CA8 Module(KERNEL32+00012CA8) (CreateFileA+0000011B)-------------------------------------------------------------------------------2001-03-30 03:08:44.56 spid51    Erreur : 3448, Gravité : 21, État : 12001-03-30 03:08:44.56 spid51    Impossible d'annuler l'enregistrement du journal (5:23:99),                                  pour l'ID de transaction (0:157), sur la page (1:76),                                  base de données 'repro' (ID de base de données 7).                                  Informations sur la page : LSN = (5:23:96), type = 1.                                  Informations sur le journal : OpCode = 4, contexte 1..2001-03-30 03:08:44.56 spid51    ex_raise2: Exception générée, majeure=34, mineure=48,                                  gravité=25, en tentative de création d'un pile de symptômes
Propriétés

ID d'article : 294902 - Dernière mise à jour : 01/16/2015 22:12:48 - Révision : 4.1

  • Microsoft SQL Server 2000 Standard
  • kbnosurvey kbarchive kbbug kbfix kbsqlserv2000bug kbsqlserv2000sp1fix KB294902
Commentaires