1s kontrollert låseinformasjonsregister. Konvertering av konfigurasjonen til administrerte låser. VI. Batch-syklus etter FIFO

1C:Enterprise-systemet lar deg bruke to moduser for å jobbe med databasen: modusen for automatiske låser i en transaksjon og modusen for kontrollerte låser i en transaksjon.

Den grunnleggende forskjellen mellom disse modusene er som følger. Den automatiske låsemodusen krever ikke at utvikleren tar noen handling for å administrere låser i en transaksjon. Disse reglene sikres av 1C:Enterprise-systemplattformen gjennom bruk av visse nivåer av transaksjonsisolasjon i et bestemt DBMS. Denne driftsmodusen er den enkleste for utvikleren, men i noen tilfeller (for eksempel med intensivt samtidig arbeid av et stort antall brukere), kan ikke transaksjonsisolasjonsnivået som brukes i DBMS gi tilstrekkelig parallellitet, noe som manifesterer seg i form av et stort antall låsekonflikter når brukere jobber.

Når du opererer i administrert låsemodus, bruker 1C:Enterprise-systemet et mye lavere nivå av transaksjonsisolering i DBMS, noe som kan øke samtidigheten til brukere av applikasjonsløsningen betydelig. Imidlertid, i motsetning til den automatiske låsemodusen, kan dette nivået av transaksjonsisolering ikke lenger i seg selv sikre overholdelse av alle regler for arbeid med data i en transaksjon. Derfor, når du arbeider i administrert modus, er utvikleren pålagt å uavhengig administrere låsene satt i transaksjonen.

Oppsummert er forskjellene ved arbeid i automatisk blokkeringsmodus og kontrollert blokkeringsmodus vist i følgende tabell:

Lås type Transaksjonsisolasjonsnivå
Automatiske låser
Fildatabase Tabeller Serialiserbar
MS SQL Server Innlegg
IBM DB2 Innlegg Repeterbar Les eller Serialiserbar
PostgreSQL Tabeller Serialiserbar
Oracle Database Tabeller Serialiserbar
Administrerte låser
Fildatabase Tabeller Serialiserbar
MS SQL Server Innlegg Les Engasjert
IBM DB2 Innlegg Les Engasjert
PostgreSQL Innlegg Les Engasjert
Oracle Database Innlegg Les Engasjert

Stille inn blokkeringsmodus i konfigurasjonen
Konfigurasjonen har egenskapen . Hvert programkonfigurasjonsobjekt har også egenskapen Datalås kontrollmodus.
Datalåskontrollmodusen for hele konfigurasjonen kan settes til Automatisk, Administrert (standard for en ny konfigurasjon) og Automatisk og kontrollert. Verdiene Automatic og Managed betyr at den tilsvarende blokkeringsmodusen vil bli brukt for alle konfigurasjonsobjekter, uavhengig av verdiene som er satt for hvert av objektene. Betydning Automatisk og kontrollert betyr at for et spesifikt konfigurasjonsobjekt vil modusen spesifisert i egenskapen brukes Datalåskontrollmodus: Automatisk eller kontrollert.
Det skal bemerkes at datalåsingskontrollmodusen som er spesifisert for et metadataobjekt er satt for de transaksjonene som initieres av 1C:Enterprise-systemet når du arbeider med dataene til dette objektet (for eksempel når du endrer objektdataene).
Hvis for eksempel operasjonen med å skrive et objekt utføres i en transaksjon initiert av utvikleren (metode StartTransaction()), så vil datablokkeringskontrollmodusen bli bestemt av verdien til parameteren Låsemodus metode StartTransaction(), ikke verdien til metadataobjektegenskapen Datalåskontrollmodus.
Standard parameter Låsemodus har betydningen Datalåskontrollmodus: Automatisk, derfor for
For å bruke administrert låsemodus i en eksplisitt transaksjon, må du spesifisere verdien av denne parameteren
Datalåskontrollmodus.Administrert (det er fornuftig å angi denne parameteren hviskonfigurasjonsegenskapen "Data Lock Control Mode" er satt til "Automatic and Managed") .

Arbeide med administrerte låser ved å bruke det innebygde språket
Et innebygd språkobjekt brukes til å administrere låser i en transaksjon LockData. En forekomst av dette objektet kan opprettes ved hjelp av en konstruktør og lar deg beskrive de nødvendige låseplassene og låsemodusene. For å angi alle opprettede låser, bruk objektets Lock()-metode LockData. Hvis denne metoden utføres i en transaksjon (eksplisitt eller implisitt), anskaffes låser og frigjøres automatisk når transaksjonen avsluttes. Hvis Lock()-metoden utføres utenfor en transaksjon, vil ingen låser bli anskaffet.

Det er satt betingelser for at feltverdien skal være lik den angitte verdien eller at feltverdien skal være innenfor det angitte området.
Betingelsene kan settes på to måter:

● ved eksplisitt å spesifisere feltnavnet og -verdien (metode Angi verdi() gjenstand DataLock-element);
● ved å spesifisere datakilden som inneholder de nødvendige verdiene (DataSource-egenskapen til objektet DataLock-element).

For hvert blokkeringselement kan en av to blokkeringsmoduser angis:

● delt,
● eksepsjonell.

Tabellen for administrerte låsekompatibilitet ser slik ut:

Delt låsemodus betyr at låste data ikke kan endres av en annen transaksjon før slutten av gjeldende transaksjon.
Eksklusiv låsing betyr at låste data ikke kan endres av en annen transaksjon før slutten av gjeldende transaksjon, og den kan heller ikke leses av en annen transaksjon som har en delt lås på dataene.

Funksjoner for drift i "Automatisk og kontrollert" modus

Når du arbeider i automatisk og kontrollert blokkeringskontrollmodus, bør to funksjoner tas i betraktning:

● Uavhengig av modusen spesifisert for en gitt transaksjon, vil systemet installere den tilsvarende administrerte
blokkering.
● Låsekontrollmodusen bestemmes av transaksjonen på "topp" nivå. Med andre ord, hvis en annen transaksjon ble startet på det tidspunktet transaksjonen startet, kan den startet transaksjonen kun utføres i modusen som er satt for den allerede kjørende transaksjonen.

La oss vurdere de oppførte funksjonene mer detaljert.
Første funksjon er at selv om den automatiske låseadministrasjonsmodusen brukes for en transaksjon, vil systemet i tillegg installere tilsvarende administrerte låser når data skrives i denne transaksjonen. Det følger at transaksjoner utført i administrert låsemodus kan å konfrontere med transaksjoner,
utføres i automatisk låsekontrollmodus.
Andre funksjon er at låseadministrasjonsmodusen spesifisert for et metadataobjekt i konfigurasjonen eller spesifisert eksplisitt ved starten av en transaksjon (som en metodeparameter StartTransaction()), er bare en "ønsket" modus. Den faktiske låseadministrasjonsmodusen som transaksjonen vil bli utført i, avhenger av om dette er den første samtalen som starter en transaksjon, eller om en annen transaksjon allerede har startet i denne økten av 1C:Enterprise-systemet i det øyeblikket.
For eksempel, hvis du trenger å administrere låser når du skriver sett med registerposter når du posterer et dokument, må den administrerte låsemodusen settes både for selve registeret og for dokumentet, siden skriving av sett med registerposter vil bli utført i transaksjonen åpnet når du skriver dokumentet.

For implementere som jobber med standard eller egne konfigurasjoner – og de som forbereder seg på sertifisering hos 1C: Plattformspesialist.

I denne artikkelen skal vi se på:

  • Hvordan bruke administrerte låser riktig for operativ og ikke-operativ behandling av dokumenter
  • hva kan det føre til ingen blokkering
  • hvordan unngå å gjøre feil som ikke oppdages umiddelbart og kan få alvorlige konsekvenser :)

Lesetid: 20 minutter.

Så, to metoder for å kontrollere saldoene i 1C:Enterprise 8.3

La oss starte med det faktum at betegnelsene "gammel metode" og "ny metode" er ganske vilkårlige. Faktisk, hvis en "ny teknikk" har blitt brukt siden 2010, er den ikke lenger veldig ny :)

Vi er imidlertid nok en gang tvunget til å stoppe her, pga det er nødvendig å skille mellom disse tilnærmingene, og dette er kritisk.

Den "gamle metoden" er en tilnærming for å kontrollere rester som har blitt brukt siden 1C:Enterprise 8.0.

Siden 2010, med utviklingen av plattformen og tillegg av nye funksjoner med 1C:Enterprise 8.2, har en "ny metodikk" blitt brukt ( imidlertid - ikke overalt).

Hva er forskjellen?

Den grunnleggende forskjellen er i øyeblikket for kontroll av rester:

  • I den «gamle» metoden kontrolleres saldoene FØR registrering av bevegelser i registre.
    Først sjekker vi saldoene; hvis saldoene er "ikke nok" (negative saldoer vil oppstå), vil vi ikke poste dokumentet
  • I den "nye" metoden skjer kontroll ETTER registrering av bevegelser, det vil si i ettertid.
    Hvis det dannes negative saldoer etter utførelse, må du "rulle tilbake" transaksjonen, det vil si kansellere dokumentet.

Fordelene og ulempene med den nye teknikken diskuteres i detalj i en egen artikkel, så vi vil begrense oss til bare den generelle oppgaven - den nye teknikken er mer optimal når det gjelder ytelse og skalerbarhet.

Ok, så den gamle teknikken hører fortiden til, og dette er skjebnen til UT 10.3?

Nei, det er ikke helt sant.

Den nye metodikken kan brukes ved avskrivning av varer alle nødvendige data er i dokumentet og trenger ikke å beregnes.

For eksempel når beløpet som skal avskrives er kjent fra tabelldelen av dokumentet. Problemet oppstår med kostprisen, fordi den må beregnes før du skriver til registeret, det vil si utfører en spørring til databasen.

Derfor kan den nye metodikken med hell brukes dersom data om mengde og kostnad lagres i separate registre.

For eksempel slik:

Det finnes imidlertid konfigurasjoner hvor både mengde og kostnad er tatt i betraktning på samme register. Og her er det berettiget den gamle metoden for restkontroll fungerer fortsatt!

Her er et eksempel på ett register for både mengde og kostnad:

Hva med typiske konfigurasjoner? Det er bare en ny teknikk, ikke sant?

Ikke alltid!

For eksempel, i "1C: Trade Management 11.3" er det 2 registre:

Ved kontering av fraktdokumenter fylles ikke varekostnadsregisteret ut i det hele tatt. Data kommer kun inn i dette registeret når du utfører rutineoperasjoner for å lukke måneden.

UT 11 bruker en ny teknikk, siden alle data for kontering av dokumenter kan hentes uten tilgang til kontrollerte registre.

Når det gjelder "1C: Regnskap", lagres både mengde og kostnad der i ett register regnskapsavdelingen, på tilsvarende regnskapskonti.

Derfor BP 3.0 bruker den gamle teknikken.

Vær oppmerksom på at kvantitativt og kostnadsregnskap i UT 11 gjennomføres med ulike analyser. For eksempel vedlikeholdes kostnadene i tillegg av organisasjon, divisjon, leder, type aktivitet, moms og så videre.

Som en del av denne artikkelen vil vi analysere blokkering for både de gamle og nye metodene for å kontrollere saldoene.

Om rask behandling av dokumenter

Det er ofte misoppfatninger om dette enkle spørsmålet.

Noen ganger tror man at operasjonell implementering er kontroll av rester ved hjelp av en ny metode. Dette er ikke sant, fra ordet "i det hele tatt".

Driftsytelsen kan analyseres mens rester overvåkes, men er ikke nødvendig.

Operativ gjennomføring– dette er dokumentets evne til å registrere nye hendelser her og nå, det vil si i sanntid.

Den er konfigurert ved hjelp av en spesiell dokumentegenskap:

Hva betyr det å "registrere seg her og nå"? Plattformen for raskt behandlede dokumenter utfører en rekke handlinger:

  • Dokumenter som legges ut i dag tildeles gjeldende tid
  • Hvis to dokumenter legges ut samtidig, vil hvert av dem ha sin egen tid (det vil si at systemet vil plassere dokumentene i forskjellige sekunder)
  • Dokumenter kan ikke legges ut på en fremtidig dato.

Men hovedsaken er at systemet overfører et tegn på effektivitet dokument for behandling:

For dokumenter som sendes umiddelbart, kan du utelate å spesifisere parameteren i forespørselen; gjeldende saldoer vil bli innhentet fra og med 31. desember 3999:

Gjeldende saldoer lagres i systemet og innhentes så raskt som mulig (saldo for andre datoer innhentes i de fleste tilfeller ved beregning).

Dermed operativ implementering kan tas i bruk for både gamle og nye metoder for restkontroll.

Interessant fakta.

I UT 11 er det forbudt å gjennomføre dokumenter som avskriver nomenklatur umiddelbart. Dette er for eksempel dokumenter "Salg av varer og tjenester", "Montering av varer", "Bevegelse av varer", "Innenlandsk forbruk av varer" og andre.

Hvorfor gjøres dette?

I systemet utføres alltid balansekontroll på gjeldende tidspunkt (Periode-parameteren er ikke spesifisert i forespørselen). Og mangelen på operasjonell utførelse lar deg legge inn dokumenter i fremtiden, en slik oppgave kreves ofte av klienter.

Kontroll av saldo ved hjelp av ny metode - uten blokkering

La oss kort vurdere algoritmen for å kontrollere saldoene når du utfører dokumentet "Salg av varer og tjenester" ved hjelp av en modellkonfigurasjon.

Det er to registre:

  • Tilgjengelige saldoer – for kvantitativt regnskap
  • Varekostnad – for kostnadsregnskap

For å kontrollere produktbalanser er det nok å jobbe med "Free balanser"-registeret.

Posteringsbehandlingskoden vil se slik ut:

Request = Ny forespørsel;


#Areal Area1
Query.TemporaryTableManager = NewTemporaryTableManager;
#EndArea


#Area Area2
Request.Text =
"VELGE

|Plasser varedokument
|FRA
|HVOR
|
|GRUPP ETTER
|
|INDEKSER ETTER
| Nomenklatur
|;

|VELG
| &Dato AS-periode,
| VERDI(Type MovementAccumulation.Expense) AS Type Movement,
| ProductsDocument.Quantity AS Quantity
|FRA
";
Query.SetParameter("Dato", Dato);
#EndArea

// 4. Registrering av bevegelser i databasen
#Arealområde4
Movements.Record();
#EndArea


#RegionRegion5
Request.Text =
"VELGE
| -FreeRemainingRemaining.QuantityRemaining AS Underskudd
|FRA
| ProductsDocument HVORDAN DU ProductsDocument
| INNER JOIN RegisterAccumulations.FreeRemains.Remains(
| &Øyeblikk,
| Nomenklatur B
| (VELGE
| ProductsDocument.Nomenclature AS Nomenclature
| FRA
| Products of the Document AS Products of the Document)) AS Gratis Gjenværende Gjenværende
| Software ProductsDocument.Nomenclature = AvailableRemainingRemaining.Nomenclature
|HVOR
| AvailableRemainingRemaining.QuantityRemaining< 0";
#EndArea


#RegionRegion6
Moment of Remaining Control =
?(Modus = dokumentholdemodus. Operativ,
Udefinert,
Ny grense(TimePoint(), BoundaryView.Inkludert));
Request.SetParameter("Moment of Time", Moment of Remaining Control);
RequestResult = Request.Execute();
#EndArea


#RegionRegion7
Hvis IKKE Spør Result.Empty() Deretter
Avslå = Sant;
ErrorSelect = QueryResult.Select();
Mens SelectErrors.Next() Loop
Message.Text = "Ikke nok produkt i antall: "+SelectionErrors.Shortage;
Message.Field = "Produkter["+(ErrorSelection.LineNumber-1)+"].Quantity";
Message.Message();
EndCycle;
slutt om;
#EndArea


#Region Region8
Hvis feil da
Komme tilbake;
slutt om;
#EndArea

Slutt på prosedyre

La oss vurdere nøkkelpunktene i restkontrollalgoritmen.

1. Initialisere den midlertidige tabellbehandleren

Administratoren vil være nødvendig slik at den midlertidige tabellen opprettet i spørringen er tilgjengelig i påfølgende spørringer.

Dermed hentes dataene fra tabelldelen én gang, lagres i en midlertidig tabell og brukes deretter gjentatte ganger.

2. Spørr gruppering av tabelldata

Spørringen velger grupperte data fra tabelldelen.

Vær oppmerksom på at dokumentlinjenummeret også er valgt - det vil være nødvendig for å kontekstualisere feilmeldingen. For linjenummeret brukes den aggregerte funksjonen MINIMUM() - det vil si at meldingen blir knyttet til den første linjen der den angitte nomenklaturen forekommer.

Den første forespørselen i batchen oppretter en midlertidig tabell. I den andre spørringen velges midlertidige tabelldata og det legges til 2 felter som kreves for hver registeroppføring - Periode og Bevegelsestype.

Fordelene med denne tilnærmingen:

  • Det er ikke nødvendig å utføre forhåndsopprydding, det vil si å bruke Clear()-metoden
  • Det er ikke nødvendig å organisere en løkke basert på utvalget eller tabelldelen.

Forresten, en lignende tilnærming brukes i standardkonfigurasjoner, spesielt i UT 11 og BP 3.0.

4. Registrering av bevegelser i databasen

Opptaket kan utføres med én kommando (i stedet for to) - Movements.FreeRemains.Record().

Og i vårt tilfelle, når ett register er skrevet, vil det ikke være noen forskjell.

Men denne tilnærmingen er mer universell:

  • Først setter du skriveflagget for de nødvendige settene med registerposter
  • Deretter kaller du Write()-metoden til Movement-samlingen, som skriver alle sett med Write-flagget satt til databasen

Etter å ha utført kommandoen "Movements.Record()", vil Record-flagget for alle sett tilbakestilles til False.

Du må også huske at ved slutten av transaksjonen (etter Post Processing), vil systemet automatisk skrive til databasen bare de settene med poster der Write-flagget er satt til True.

Typiske løsninger bruker et lignende opplegg for å registrere bevegelser. Hvorfor?

Write()-metoden i Movement-samlingen skriver sett med poster i samme sekvens, selv for forskjellige dokumenter.

Å registrere bevegelser manuelt kan føre til problemer.

La oss gi et eksempel.

Hvis du skriver i «Implementering»-dokumentet slik:

Movements.FreeRemainders.Write();
...
Movements.Cost of Goods.Write();

Og i dokumentet "Bevegelse av varer" endre rekkefølgen:

Bevegelser. Cost of Items.Write();
...
Bevegelser. FreeRemainings.Write();

Dette kan føre til låsing av dokumenter på kryssende sett med gjenstander.

Tilnærmingen ovenfor for bevegelsesregistrering kan brukes hvis riktig bevegelsesregistreringsverdi er spesifisert i dokumentegenskapene:

5. Forespørsel som mottar negative saldoer

Forespørselen velger negative saldoer etter post fra dokumentet.

En negativ saldo er en mangel (mangel) på et produkt.

Koblingen til elementene fra dokumentet utføres kun for å få linjenummeret.

Hvis vi ikke planla å koble meldinger til dokumentfelt, kunne spørringen forenkles betydelig - data ville hentes fra én tabell (resten av registeret).

6. Bestemme tidspunktet for kontroll av rester

Det var her operativ utførelse kom godt med.

Hvis dokumentet utføres raskt, er tidspunktet for mottak av saldo ubestemt, noe som betyr mottak av gjeldende saldoer.

Hvis dette er en ikke-operativ transaksjon, får vi et tidspunkt "etter" dokumentet - for å ta hensyn til bevegelsene som nettopp er gjort.

La oss huske at å oppnå gjeldende saldoer er en rask operasjon sammenlignet med å skaffe saldoer på et vilkårlig tidspunkt.

Dette er nettopp fordelen med raskt utførte dokumenter.

7. Hvis forespørselen ikke er tom, betyr det at det er dannet negative saldoer

I løkken går vi gjennom alle de negative restene og viser en melding knyttet til radene i den tabellformede delen.

Slik ser diagnosemeldingen ut:

8. Hvis det er feil, gå tilbake fra hendelsesbehandleren

Hvis det var minst én feil, avslutter vi prosedyren.

Siden det ikke er noen vits i å fortsette transaksjonen, vil ikke transaksjonen bli registrert uansett (og da vil vi utvikle en kode for avskrivning av batcher).

Gjennomføring av kostnadsavskrivninger batchvis

Etter at saldoene har vært vellykket, kan du begynne å skrive av batchene.

Koden for avskrivning av FIFO vil være slik:

// I. Analyse av dokumentdatoforskyvning fremover


OG IKKE ThisObject.ThisNew()
Og ThisObject.Conducted Then

Request = Ny forespørsel;
Request.Text =
"VELGE
| Document.Date AS Dato
|FRA
|HVOR

RequestResult = Request.Execute();
SelectDocument.Next();

Ellers
Å ligge);
slutt om;

Slutt på prosedyre

Prosedyre ved opptak (avslag)

ThisObject.AdditionalProperties.Insert("DocumentDateMovedForward",
ThisObject.Date>


slutt om;

Slutt på prosedyre

Behandlingsprosedyre (feil, modus)

Request = Ny forespørsel;

// 1. Initialisering av den midlertidige tabellbehandleren
#Areal Area1
...
#EndArea

// 2. Spørringsgrupperingstabelldata
#Area Area2
...
#EndArea

// 4. Registrering av bevegelser i databasen
#Arealområde4
...
#EndArea

// 5. Forespørsel som mottar negative saldoer
#RegionRegion5
...
#EndArea

// 6. Bestemme tidspunktet for å kontrollere saldoene
#RegionRegion6
...
#EndArea

// 7. Hvis forespørselen ikke er tom, har det blitt dannet negative saldoer
#RegionRegion7
...
#EndArea

// 8. Hvis det er feil, gå tilbake fra hendelsesbehandleren
#Region Region8
...
#EndArea

// II. Utarbeide sett med poster for "Varekostnad"-registeret
#ArealområdeII

Movements.Record();
slutt om;
Movements.Cost of Goods.Record = Sant;
#EndArea

// III. Be om mottak av batchsaldoer for avskrivning ved bruk av FIFO
#AreaAreaIII
Request.Text =
"VELGE
| ProductsDocument.Nomenclature AS Nomenclature,
| ProductsDocument.Line Number AS Line Number,

| Forblir.Part AS Parti
|FRA
| ProductsDocument HVORDAN DU ProductsDocument
| &Øyeblikk,
| Nomenklatur B
| (VELGE
| FRA

| BESTILL ETTER
|RESULTATER
| MAKSIMUM(Antall),
| SUM(Resterende mengde)
|programvare
| Nomenklatur";
RequestResult = Request.Execute();
#EndArea

// IV. Syklus etter dokumentnomenklatur
#AreaAreaIV

// V. Få beløpet som skal avskrives
//VI. Batch-syklus etter FIFO
Mens SelectionBatch.Next() And RemainingWrite>0 Loop
// VII. Sjekk for nullbalanse
Hvis SampleBatch.QuantityRemaining=0 Da
Fortsette;
slutt om;
Movement.Period = Dato;

// VIII. Beregning av mengde og beløp som skal avskrives

// IX. Vi vil redusere beløpet som skal avskrives
EndCycle;
EndCycle;
#EndArea

Slutt på prosedyre

La oss se på nøkkelpunktene i algoritmen for å skrive av batcher ved hjelp av FIFO.

I. Analyse av dokumentdatoforskyvning fremover

Her forstår vi om datoen for det postede dokumentet går fremover. Denne informasjonen vil være nyttig nedenfor når du skal rydde opp i bevegelser.

For å analysere dokumentdatoforskyvningen kreves 2 hendelser:

  • Før opptak– for å få den gamle datoen for dokumentet og sjekke dokumentposteringsmodus
  • Ved opptak– for å få en ny dokumentdato

Vi overfører data mellom hendelser gjennom en spesiell samling av objektet – «Ytterligere egenskaper». Den eksisterer så lenge den gjeldende versjonen av objektet er i minnet, det vil si at den er tilgjengelig for alle hendelser under utførelse.

En lignende teknikk brukes i standarden "1C: Accounting 8". Men det er brukt en hendelse "Før opptak".

Hvorfor er det ikke nødvendig å bruke "On recording" i BP?

Det er enkelt - fraktdokumenter kan ikke behandles raskt i regnskapsavdelingen. Dette betyr at tidspunktet for dokumentet ikke vil godta et operativt stempel (hvis dokumentet legges ut på nytt på gjeldende dag), derfor kan både den gamle og nye datoen for dokumentet fås i hendelsen "Før opptak".

II. Forberede sett med poster for "Varekostnad"-registeret

Modusen for bevegelsessletting er satt for dokumentet – "Når posting avbrytes":

Dermed er det en mulighet for at vi ved repostering kan ta hensyn til bevegelsene til selve dokumentet. MEN dette vil bare skje hvis datoen for dokumentet flyttes frem. Det vil si at det er fornuftig å fjerne bevegelser bare når dokumentdatoen flyttes fremover.

Her er et eksempel:

  • Saldoen på LG-skjermer på dokumenttidspunktet er 10 stk.
  • Det legges ut et dokument som avskriver 8 stk.
  • I det samme dokumentet økes tiden med 1 minutt, la oss gjenta

Dersom gamle bevegelser ikke slettes, vil systemet rapportere en mangel på 6 monitorer, siden dagens dokumentbevegelser allerede har avskrevet 8 av de 10 tilgjengelige monitorene.

Merk. Noen ganger er det råd - å fjerne bevegelser bare under operasjonen.

Men dette er feil: de vil ikke ta hensyn til situasjonen med å endre "ikke-operative" dokumenter (gårsdagens og tidligere).

Det vil si at problemet med "mangel på 6 skjermer" (se ovenfor) vil i dette tilfellet bare løses for dokumenter som er endret i dag.

III. Forespørsel som mottar batchsaldo for avskrivning ved bruk av FIFO

I forespørselen refererer vi til saldoene partivis, og samtidig legger vi summene på post.

På det totale nivået oppnås mengden fra dokumentet - MAKSIMUM(Antall) og saldoen for partiet - SUM(Gjenstående kvantitet).

Tror du mengden fra dokumentet kan overstige den totale saldoen for varen for alle batcher?

Hvis bevegelser i registrene "Free Remains" og "Cost of Goods" etter mengde gjøres synkront (både inngående og utgående), kan en slik situasjon ikke oppstå. Det er dette vi vil stole på når vi avskriver partier.

IV. Syklus etter dokumentnomenklatur

Takket være resultatene i spørringen i den ytre sløyfen, omgår vi nomenklaturen fra dokumentet.

V. Få beløpet som skal avskrives

La oss huske hvor mye du trenger å skrive av. Dette beløpet vil ytterligere reduseres.

VI. Batch-syklus etter FIFO

Den nestede syklusen vil inneholde batcher i henhold til gjeldende element.

VII. Sjekk for nullbalanse

Generelt er situasjonen når batchbalansen er null en feil i systemdataene (likevel er en slik situasjon mulig). Poenget er at i dette tilfellet er summen IKKE null (den virtuelle tabellen med registerbalanser returnerer ikke poster med null ressursverdier).

Derfor bestemmer vi at vi skal hoppe over slike feilspill. Hvis ønskelig, kan du utstede diagnostikk til brukeren.

VIII. Beregning av mengde og beløp som skal avskrives

Mengden som skal avskrives er minimumsverdien mellom resten av partiet og det som gjenstår å avskrive.

Beløpet beregnes av en elementær andel.

Hvis hele saldoen til en batch avskrives, vil hele mengden av den batchen bli avskrevet. Dette er matematikk i 3. klasse på en folkeskole: X*Y/X = Y:)

Det vil si at det IKKE er nødvendig å gjøre ytterligere kontroller (noen ganger gir de slike råd) for å sikre at hele beløpet blir avskrevet. Dette rådet har til og med sitt eget navn - " problemet med pennies».

Og for de som gir dårlige råd, er det fornuftig å se på "1C: Accounting 8"-konfigurasjonen. Der (oh, horror!) er det ingen sjekk for at hele batchen er avskrevet :)

Her er et skjermbilde av den generelle modulen "Vareregnskap", metoden "Skriv av gjenstående varer":

IX. Vi vil redusere beløpet som skal avskrives

Du må forstå hvor mye som er igjen å avskrive. For å gjøre dette trekker du mengden fra registerbevegelsen.

Hvorfor trengs administrerte låser?

Her kommer vi til kontrollert blokkering.

Det ser ut til at algoritmene presentert ovenfor fungerer som smurt. Du kan teste dem selv (lenker til databasenedlastinger på slutten av artikkelen).

Men under ekte flerbrukerdrift vil problemer begynne, og som ofte skjer, vil problemer ikke bli oppdaget umiddelbart...

La oss gi et eksempel på det mest typiske problemet ved avskrivning av en vare, når 2 brukere nesten samtidig prøver å avskrive en vare (foreta et salg):

I dette eksemplet utfører to brukere nesten samtidig varesalg - dokument nr. 2 begynte å bli utført litt senere enn dokument 1.

Ved mottak av saldoen rapporterer systemet at saldoen er 10 enheter, og begge dokumentene er behandlet. Det triste resultatet er at det er minus 5 LG-skjermer på lager.

Men samtidig fungerer restkontroll! Det vil si at hvis dokument nr. 2 er bokført etter slutten av dokument nr. 1, vil ikke systemet poste dokument nr. 2:

Noen ganger er det en misforståelse - "Bare 3-4 brukere jobber i databasen min samtidig, sannsynligheten for parallell behandling av dokumenter er null, så du trenger ikke å bli distrahert av blokkering."

Dette er veldig farlig resonnement.

Selv to brukere kan poste dokumenter nesten samtidig, for eksempel hvis en av dem utfører gruppepostering av dokumenter.

I tillegg kan du ikke være immun mot en økning i antall brukere. Hvis virksomheten tar fart, vil det være behov for nye selgere, lagerholdere, logistikkere og så videre. Derfor må du umiddelbart lage løsninger som vil fungere stabilt i et flerbrukermiljø.

Hvordan løser man problemet når man legger ut dokumenter parallelt?

Løsningen er enkel – blokker LG-skjermer på tidspunkt T1, slik at andre transaksjoner ikke får tilgang til saldoene for dette produktet.

På tidspunkt T2 vil systemet vente på at LG-skjermen låses opp. Og etter dette vil systemet motta gjeldende varebalanse og avskrivningen av varer vil bli fullført (eller ikke fullført).

Bare noen få ord om klassifiseringen av blokkering.

Det er 2 typer låser:

  • Gjenstand
  • Transaksjonsmessig.

For å si det enkelt, tillater ikke objektlåser interaktivt endre ett objekt (katalogelement eller dokument) for to brukere.

Og transaksjonslåser tillater det programmatisk operere med aktuelle data når du utfører bevegelser på tvers av registre.

I denne artikkelen vil vi være interessert i transaksjonslåser, så ganske enkelt låser.

Når bør blokkering brukes?

Oppgaven med å sette låser blir aktuelt så snart databasen starter jobbe mer enn én bruker.

Låser må plasseres på transaksjoner, men når skjer transaksjoner? Det stemmer, den vanligste saken er dokumentbehandling.

Det vil si at sperring må brukes ved behandling av alle dokumenter?

Ikke i noe tilfelle. Det er definitivt ikke verdt å sette opp låser "i tilfelle.". Tross alt reduserer låsene i seg selv samtidigheten til brukere (systemskalerbarhet).

Låser må plasseres på ressurser (tabellrader) som leses og endres i transaksjoner. For eksempel ved utføring av dokumenter.

I eksemplet ovenfor er en slik ressurs saldoen til produktet. Systemet måtte blokkere saldoen fra det øyeblikk saldodata ble mottatt (T1) til slutten av transaksjonen (T3).

Merk. Transaksjonen ved kontering av bilag nr. 1 begynner tidligere enn det øyeblikk saldoen mottas. Men for enkelhets skyld antar vi at T1 både er starttidspunktet for dokumentbehandlingen og tidspunktet for mottak av saldo.

Eksempel når ikke nødvendig å låse– utføre dokumentet "Mottak av varer". I dette tilfellet er det ingen konkurranse om ressurser (rester, ...), så blokkering vil være skadelig: det vil redusere skalerbarheten til systemet.

Automatisk og kontrollert blokkering

Her skal vi ikke gå inn på teori (dette er tema for en egen artikkel), men vil bare si at administrerte låser er mer optimale.

I stedet for teori kan vi gi bevis - alle moderne standardkonfigurasjoner fungerer på kontrollerte forriglinger.

Derfor, i vår modellkonfigurasjon vil riktig modus bli valgt:

Kontrollerte låser i ny restkontrollteknologi

Vi vil bruke en lås på «Fri saldo»-registeret og kun på vareposter som finnes i dokumentet.

Dessuten riktig blokkeringsalternativ– så sent som mulig.

I den nye metoden for kontroll av saldoer, må dette gjøres før registrering (eller på registreringstidspunktet) bevegelser i «Fri saldo»-registeret, slik at andre transaksjoner ikke kan endre denne delte ressursen.

Låsen kan påføres manuelt (programmatisk) og litt senere viser vi hvordan dette gjøres.

Men en ekstra bonus med den nye balansekontrollteknologien er at det bare trengs én kodelinje for å låse delte ressurser.

Du trenger bare å angi BlockForChange-egenskapen på registeroppføringssettet:

// 3.1. Låseregisterrester
#Area Area3_1
Moves.FreeRemainders.BlockForChange = Sant;
#EndArea

// 4. Registrering av bevegelser i databasen
#Arealområde4
Movements.FreeRemainders.Write = Sant;
Movements.Record();
#EndArea
...

Som et resultat vil 2 transaksjoner ikke kunne endre frie saldoer for én vare.

Faktisk, når eiendommen er BlockForChange installerer ikke administrert låsing, slår den bare av modusen for å skille registertotaler når du skriver.

Men for vår artikkel er følgende grunnleggende: systemet vil sette en lås på kombinasjonen av data skrevet til registeret. Vi vil se på arbeidet til BlockForChange-egenskapen i detalj i en egen artikkel.

Forresten, i standard UT 11 er det ikke så lett å finne innstillingen til BlockForChange-egenskapen for "Free saldo"-registeret. Faktum er at dette utføres i register recordset-modulen, i hendelsen "Før skriving".

Det er alt, med én kodelinje var riktig drift av systemet sikret!

Viktig. Vi låser ikke varekostnadsregisteret.

Hvorfor? Slik blokkering ville være unødvendig (og dette er en viss belastning på 1C-serveren), siden bevegelser til registrene "Free saldo" og "Kostnad for varer" alltid utføres synkront, det vil si sekvensielt etter hverandre.

Derfor, ved å blokkere varer fra "frie saldoer", vil vi ikke tillate andre transaksjoner før disse varene og i "Kostnad for varer"-registeret.

Men for den gamle restkontrollmetoden vil blokkeringen brukes annerledes. La oss først se på batch-avskrivingsalgoritmen for denne saken.

Gammel metode for restkontroll

La oss minne om at den gamle metodikken kan brukes dersom mengde og kostnad tas med i ett register.

La dette være varekostnadsregisteret:

Da vil algoritmen for å legge ut dokumentet "Salg av varer" se slik ut:

// 1. Hendelsesbehandler "Før opptak"
Prosedyre før opptak (feil, opptaksmodus, konduktørmodus)

Hvis Opptaksmodus = Dokumentopptaksmodus
OG IKKE ThisObject.ThisNew()
Og ThisObject.Conducted Then

Request = Ny forespørsel;
Request.Text =
"VELGE
| Document.Date AS Dato
|FRA
| Dokument Salg av varer og tjenester AS Dokument
|HVOR
| Document.Link = &Link";
Request.SetParameter("Link", ThisObject.Link);
RequestResult = Request.Execute();
SelectionDocument = Query Result.Select();
SelectDocument.Next();

ThisObject.AdditionalProperties.Insert("OldDocumentDate", SelectDocument.Date);

Ellers
slutt om;

Slutt på prosedyre

Prosedyre ved opptak (avslag)

Hvis IKKE ThisObject.AdditionalProperties.Property("DocumentDateShiftedForward") Da

ThisObject.AdditionalProperties.Insert("DocumentDateMovedForward",
ThisObject.Date>ThisObject.AdditionalProperties.OldDocumentDate);

Rapport(ThisObject.AdditionalProperties.DocumentDateMovedForward);
slutt om;

Slutt på prosedyre

Behandlingsprosedyre (feil, modus)

// 2. Fjerning av "gamle" dokumentbevegelser
Hvis AdditionalProperties.DocumentDate er ShiftedForward Then
Movements.Cost of Goods.Record = Sant;
Movements.Product Cost.Clear();
Movements.Record();
slutt om;

// 3. Sette flagget for å registrere bevegelser ved slutten av transaksjonen
Movements.Cost of Goods.Record = Sant;

// 4. Forespørsel som mottar saldo i batch på tidspunktet for dokumentet
Request = Ny forespørsel;
Request.Text =
"VELGE
| Salg av produkter Nomenclature AS Nomenclature,
| SUM(SalesProducts.Quantity) AS Quantity,
| MINIMUM(Salgsprodukter.Linjenummer) ASLinjenummer
|Plasser varedokument
|FRA
| Dokument. Salg av varer og tjenester. Varer HVORDAN Salg av varer
|HVOR
| SalesProducts.Link = &Link
|GRUPP ETTER
| Salg av produkter Nomenklatur
|INDEKSER ETTER
| Nomenklatur
|;
|////////////////////////////////////////////////////////////////////////////////
|VELG
| ProductsDocument.Nomenclature AS Nomenclature,
| ProductsDocument.Quantity AS Quantity,
| ProductsDocument.Line Number AS Line Number,
| ISNULL(Remaining.NumberRemaining, 0) AS QuantityRemaining,
| ISNULL(Remaining.AmountRemaining, 0) AS AmountRemaining,
| Forblir.Part AS Parti
|FRA
| ProductsDocument HVORDAN DU ProductsDocument
| VENSTRE TILKOBLING Registrer akkumuleringer. Varekostnader. Rester(
| &Øyeblikk,
| Nomenklatur B
| (VELGE
| T. Nomenclature AS Nomenclature
| FRA
| ProductsDocument AS T)) AS Rester
| Software ProductsDocument.Nomenclature = Resterende.Nomenclature
| BESTILL ETTER
| Remains.Batch.Moment of Time
|RESULTATER
| MAKSIMUM(Antall),
| SUM(Resterende mengde)
|programvare
| Radnummer";

Request.SetParameter("TimePoint", TimePoint());
Request.SetParameter("Link", Link);

RequestResult = Request.Execute();

SelectionNomenclature = Query Result.Select(BypassQueryResult.ByGrouping);

// 5. Syklus for vare - kontroller om kvantumet er tilstrekkelig for avskrivning
Mens SelectionNomenclature.Next() Loop

Nomenclature Deficit = SampleNomenclature.Quantity - SampleNomenclature.QuantityRemaining;

Hvis nomenklaturunderskudd>0 Da
Message = New MessageToUser;
Message.Text = "Ikke nok produkt i antall: "+Nomenklaturmangel;
Message.Field = "Produkter["+(SelectionNomenclature.LineNumber-1)+"].Quantity";
Message.SetData(ThisObject);
Message.Message();
Avslå = Sant;
slutt om;

Hvis feil da
Fortsette;
slutt om;

// 6. Få beløpet som skal avskrives
RemainingWrite = SampleNomenclature.Quantity;
SelectionBatch = SelectionNomenclature.Select();

// 7. Batch-syklus
Mens SelectionBatch.Next() And RemainingWrite>0 Loop

Movement = Movements.Cost of Goods.AddExpense();
Movement.Period = Dato;
Movement.Nomenclature = SelectionBatch.Nomenclature;
Movement.Batch = SelectionBatch.Batch;
// 9. Beregning av mengde som skal avskrives
Movement.Quantity = Min(RemainingWrite, BatchSelection.QuantityRemaining);
// 10. Beregning av avskrivningsbeløpet
Movement.Amount = Movement.Quantity*
SampleBatch.AmountRemaining/SampleBatch.QuantityRemainder;

// 11. Reduser beløpet som skal avskrives
RemainingWrite = RemainingWrite - Movement.Quantity;

EndCycle;
EndCycle;

La oss se hvordan det ser ut typisk eksklusiv låsing i 1C.

For meg ser det omtrent slik ut: noen lånte noe for å utføre en handling. Alle andre kan ikke gjøre denne handlingen, de venter. For å løse slike situasjoner, Trenger å vite i det minste noen grunnleggende teori- Det er i det minste nødvendig forstå, når en lås er plassert, hva slags lås er plassert etc.

Det tror jeg du vet veldig godt i 1C Det er to låsemoduser: automatisk og kontrollert.

  • I automatisk modus det er enkelt:
    • For enhver lesing, legg S-låse.
    • EN for enhver oppføring den er sattX-låse– og, det er bare låser på DBMS-serveren, 1C plasserer ingen låser.
  • Mye mer interessant kontrollert modus. Hovedtrekket er det i 8.2 og 8.3 låser fungerer annerledes.
    • For eksempel, i 8.2 du enhver lesing vil setteS-blokkering. Lesing er dessuten ikke bare Request.Execute(), men også Link.Props, Link.GetObject(), etc.
    • EN i 8.3 ingen kompatibilitetsmodus lenger det vil ikke være noen leselåser. Dermed vinner 8,3 definitivt når det gjelder parallellitet.
    • Vel, da begynner moroa - f.eks. for constructionRecordSet.Read() i administrert modus 8.2 vil du ha S-låsing på DBMS-serveren (dette er naturlig). Men i tillegg til dette blir det også delt låsing på 1C-server, og dette viser seg både i 8.2 og 8.3. Og hovedproblemet er at du har denne delte låsen vil vare til slutten av transaksjonen– inntil transaksjonen avsluttes, vil dataene bli blokkert.
      Derfor er anbefaling nummer én at hvis du trenger et skrivebeskyttet postsett, er det bedre å bruke en spørring i stedet for en objektmodell. Da vil du ikke blokkere noe, og hvis du gjør det, vil det ikke vare lenge.
    • Naturlig, for enhver dataendring(opptak, hold, sletting) vil en eksklusiv lås plasseres på 1C-serveren og en eksklusiv lås på DBMS-serveren.

Med denne tabellen foran deg vil det være mye lettere for deg å forstå i hvilke tilfeller du kan støte på blokkeringer.

Varighet av blokkering i administrert modus

Det viktigste å huske på når du arbeider med låser er det enhver administrert lås vil alltid holdes til slutten av transaksjonen, Derfor det er viktig å minimere varigheten.

Når du har et valg om hvor du vil sette låsen (i begynnelsen av transaksjonen eller på slutten), er det bedre å velge på slutten, fordi i dette tilfellet er det mye mindre risiko for å vente.

Når det gjelder Query.Execute()-designen, hvis den er 8.2, frigjøres låsen umiddelbart etter at spørringen er utført, og hvis den er 8.3 (eller Read Committed Snapshot Isolation-modus er aktivert i MS SQL DBMS), så er det vil ikke være noen lås i det hele tatt. Derfor hvis du har 8.2 eller 8.3 i 8.2-kompatibilitetsmodus, jeg vil hjelpe deg på alle mulige måter Jeg anbefaler å slå på modusenLeseEngasjertØyeblikksbildeIsolering– uansett vil arbeidet ditt øke i parallellitet.

Her er et typisk eksempel: du kan først sette en blokkering, utføre noen beregninger og kontroller (se om detaljene er fylt ut osv.) og først deretter fullføre transaksjonen – da blir blokkeringstiden lang. Men det er bedre, hvis det er en slik mulighet, å gjøre det annerledes: først gjør alle slags beregninger (sjekk fyllingen, etc.), og bruk blokkeringen helt til slutt. Da vil sperretiden din bli kortere, og følgelig reduseres også risikoen for venting. Prøv derfor å bruke eksplisitte kontrollerte låser eller skrive til databasen så nær slutten av transaksjonen som mulig.

De vanligste årsakene til blokkering

Forespørsel med skanning

Oftere venting på en blokk oppstår når en forespørsel ikke er optimal. For eksempel har du en bruker Ivanov, som i ferd med å legge ut et dokument blokkerte flere vareelementer - bare det han trengte. Og det er en bruker Petrov som utførte en forespørsel med skanning i en transaksjon (Request.Execute()). Og hvis, mens du leser, denne forespørselen kjører inn i et element som ble blokkert av Ivanov, så hvis du bruker versjon 8.2 (eller 8.3 i kompatibilitetsmodus med 8.2), vil den stoppe og vente 20 sekunder som standard. Samtidig vil brukeren Petrov bli stående å vente, noe han selvfølgelig ikke vil like. Hvordan løse denne situasjonen? Det ser ut til at svaret er åpenbart - du kan ta omskriv spørringen slik at den ikke leser ekstra linjer, da blir alt flott.

Hva om denne forespørselen er plattformbasert? Eller denne forespørselen brukes i en standardkonfigurasjon, som du av åpenbare grunner ikke kan endre - hva skal du gjøre da? Hva er mulighetene?

Vil du slå av kompatibilitetsmodus? Det ville være mer riktig å si - kryss deg selv, lag en kopi, test den i en uke og slå den av, for hvis du slår den av med en gang, kan du ha en "morsom helg", og kanskje ikke bare en helg .

Et annet alternativ er aktiver versjonsmodus forMSSQLServer. La meg ta en reservasjon med en gang at den beskrevne situasjonen kun er mulig i et blokkerende DBMS, for hvis du har en versjonert DBMS, kan ikke denne situasjonen eksistere der. Og hvis du aktiverer Read Committed Snapshot Isolation, begynner MS SQL å fungere nesten som en versjonert versjon. OG spørringen din vil ikke blokkere rader.

Det er ingen "magisk pille" i 1C, men slå på modusenLeseEngasjertØyeblikksbildeIsolering– nærmest analog dette "magisk pille". Med minimale handlinger kan du umiddelbart dramatisk redusere antallet forventninger i databasen. For dette du bare trenger å utføre flere linjer vist på skjermbildet skript innMSSQL server, og du vil umiddelbart få en veldig god økning i samtidighet. Selvfølgelig gir dette bare mening for den kontrollerte låsemodusen i 1C-konfigurasjonen. For automatisk modus gir det ingen mening å aktivere RCSI-modus på DBMS-serveren.

Ingen registerdelt modus

Ofte oppstår forventninger nettopp til akkumuleringsregistrene og til regnskapsregistrene – i tilfellet man får tilgang til samme data. For å unngå slike forventninger ble den oppfunnet totalt delt modus.

Denne modusen kan aktiveres i konfiguratoren i registeregenskapene på fanen "Annet" - det er avmerkingsboksen "Tillat oppdeling av totaler". Når du oppretter et nytt akkumuleringsregister, er denne avmerkingsboksen allerede aktivert som standard. Dermed antyder utviklerne at det er veldig praktisk å bruke denne funksjonen, fordi den hjelper deg å skrive til registeret parallelt, selv om dataene dine krysser hverandre.

Men det er en nyanse her - hvis du bruker balansekontroll ved å bruke dette registeret, vil denne metoden ikke hjelpe deg på noen måte, du må bare fremskynde transaksjonstiden slik at blokkeringen blir så kort som mulig. Men generelt er det en kul funksjon å slå på totalseparatoren, og jeg anbefaler på det sterkeste å bruke den. Spesielt sunn slå den på for regnskapsregister, fordi det nesten aldri er noen kontroll over rester.

Flytt sekvensgrensen når du sveiper

Hvis du bruker en sekvens der grensen forskyves når du posterer dokumenter, har du mest sannsynlig ventetider på låsene. For eksempel vil to dokumenter hvis dimensjoner i sekvensen sammenfaller ikke kunne behandles parallelt - noen vil vente på noen.

Hva kan du gjøre her? Du putter sequence-egenskapen "Ikke flytt automatisk" og gjør reguleringsoppgave, som om kvelden hos deg denne sekvensen vil flytte seg. Dette er en enkel løsning - bare bryte opp disse operasjonene over tid, så blir det ikke mer venting i løpet av dagen.

Lange transaksjoner

Prøv å gjøre transaksjoner så korte som mulig:

  • Du bruker alle slags sjekker og oppgjør utover transaksjonen– ethvert opptak, en eventuell blokkering må gjøres helt til slutt.
  • Ikke i noe tilfelle ingen dialogbokser i transaksjonen det er ikke nødvendig å gjøre dette, spesielt hvis du bruker en tykk klient. Vi har møtt slike tilfeller at når en regnskapsfører postet et dokument, dukket det opp en dialogboks med "Ja" og "Nei"-knappene. Og mens hun bestemmer seg for hva hun skal klikke, mens hun rådfører seg med noen, mens hun ringer noen, vil dette vinduet henge, og hele denne tiden vil transaksjonen være aktiv, og følgelig vil blokkeringen også være aktiv - tiden vil være veldig lang. Det er ikke nødvendig å gjøre dette.
  • Hvordan kan du fremskynde transaksjonstidene ytterligere? Kan fremskynde koden, som utføres der. Få fart på spørringene, hvis du vet hvordan du gjør det. Dette vil umiddelbart gi en kraftig økning i produktiviteten.
  • Et annet alternativ er få fart på skrivingen til registre. Hvordan? Det kan gjøres i programvare, eller det kan gjøres i maskinvare. For eksempel, hvis du kjøpte vanlige SSD-stasjoner, vil skrivehastigheten din naturlig øke - selv forespørsler vil bli behandlet raskere. Og følgelig vil også transaksjonstiden reduseres. Dette betyr ikke at oppgradering av disker alene kan løse problemet med blokkering, men du kan i det minste jevne ut denne effekten - den vil ikke lenger være så merkbar.

Eskalering i flertrådsmodus

Jeg håper virkelig at mange av dere bruker multithreading for å forbedre ytelsen til alle nedlastinger, utlastinger, reoverføring av dokumenter, når store datamengder kollapser. Dette er en virkelig kraftig funksjon som lar deg få flere ganger raskere. En gang trengte jeg å kollapse et register som inneholder mer enn 100 millioner rader, og de irrelevante restene måtte lastes ut et sted, og bare etterlate en viss gjeldende tidsperiode i databasen. Jeg tenkte på det og bestemte meg for å implementere flertrådsbehandling for denne saken. Som et resultat viste det seg at disse trådene begynte å blokkere hverandre, selv om dataene deres ikke krysset hverandre i det hele tatt (hver tråd hadde forskjellige opptakere) - likevel var det en ventetid på blokkeringen.

Det viste seg at en av trådene inneholdt et stort, tungt dokument som førte til eskalering. Eskalering- det er når blokkering overlagret ikke til noen rad i tabellen, men til hele bordet på en gang. Og i mitt tilfelle, i en av trådene, var hele bordet låst.

I denne forbindelse la jeg til algoritmen korreksjon, som tok hensyn til slike dokumenter, og utsatte behandlingen "for senere" slik at slik eskalering ikke skjedde, og tråder ikke blokkerte hverandre og ikke falt av med feil.

Når skjer eskalering vanligvis i 1C? Oftest er dette en slags tung operasjon - stenge måneden, kalkulere kostnader osv. - når du begynner å behandle mange dokumenter i en gigantisk transaksjon, er hele bordet blokkert og ingen kan jobbe på dette tidspunktet - parallelliteten faller . Slike operasjoner må tas i betraktning særskilt og utføres utenom arbeidstid., fordi du ikke vil kunne behandle dem i parallell modus.

Plattformfeil - blokkering ved bruk av dataområdeavgrensning

Det er flere feil på plattformen som fører til unødvendige låseventinger. For eksempel er det en feil som virkelig overrasket meg. Situasjonen er som følger - vi samlet inn data om forventninger og så det streng Request.Execute() pålegger en kontrollert eksklusiv lås, som i prinsippet ikke kan og skal skje. Da vi så dette, trodde vi at verktøyet «feilet». Lastet ned dataene igjen. Alt ble sjekket på nytt. Det pålegger faktisk. Det viste seg at en slik feil dukket opp i plattform 8.3.6. Når du leser - det spiller ingen rolle, Query.Run() eller Constant.Read() - generelt, under en hvilken som helst leseplattform plassert en kontrollert eksklusiv (X) lås på et felt som er en dataavgrensning og parallellismen falt umiddelbart. Dessuten var blokkeringen eksepsjonell.

Dette er en plattformfeil.

Heldigvis for oss brukte ikke klienten som opplevde dette problemet denne dataseparatoren i det hele tatt, så vi fjernet rett og slett attributtet fra attributtet at det er en separator. Og det var det, feilen forsvant. Men om det er fikset eller ikke, vet jeg fortsatt ikke. Jeg kan med sikkerhet si at 1C vet om denne feilen, men dessverre vet jeg ikke når de vil fikse det. Vær derfor forberedt på at dette kan skje deg også.

Plattformfeil -

Vi støter også ofte på plattformfeil når vi jobber med beregningsregisteret. Fra et ytelsessynspunkt har det generelt mange problemer, fordi Beregningsregisteret er det eneste objektet i 1C som ikke har en klyngeindeks. Derfor, når du skriver flere hundre linjer inn i beregningsregisteret (hvis det er få linjer, blir ikke denne feilen gjengitt), eller fjerner bevegelser der (skriver et tomt sett med bevegelser der), vil det indeksen til beregningsregistertabellen skannes. Og siden dette er en plattformforespørsel, kan du ikke rette den på noen måte, og siden dette er en sletting (en X-lås er pålagt), endrer heller ikke situasjonen ved å aktivere Read Committed Snapshot-modus.

Som et resultat ble det funnet en løsning på dette problemet gjennom prøving og feiling. Siden beregningsregisteret ikke har en klynget indeks (det er bare en ikke-klynget), måtte vi deaktivere denne ikke-klyngede indeksen og lage en lignende, men en klynget. Alle. Etter det begynte indeksen å bli brukt, og alt ble flott. Slik kom vi oss rundt situasjonen. Og hvis du har en ZUP, og du står overfor problemet med parallelle oppføringer i beregningsregisteret, kan du ta den og bruke den.

Et annet problem med beregningsregisteret er ved lesing og er at plattformspørringen som leser dataene fra beregningsregisteret også skanner indeksen. Men her er det inkluderingen av enten Read Committed Snapshot som hjelper, eller, hvis du har 8.3, kan du fjerne kompatibilitetsmodusen med 8.2, da vil du ikke lenger ha dette problemet.

Plattformfeil - umulighet å parallellskrive til et periodisk uavhengig informasjonsregister

En veldig gammel feil, som 1C også er godt klar over, men som likevel ikke er rettet - denne umulighet for parallell registrering i et periodisk uavhengig informasjonsregister. Det ser ut til at hvis periodene dine er forskjellige (målingene er de samme, men periodene er forskjellige), kan du skrive data der parallelt. Men dette skjer ikke, selv om det burde være det. Fordi på 1C-serveren er det en overdreven blokkering etter dato. Denne situasjonen oppstår ikke ofte på prosjekter - informasjonsregisteret blir svært sjelden en "flaskehals" for låser. Vanligvis oppstår problemer på grunn av akkumuleringsregisteret eller regnskapsregisteret. Men ikke desto mindre, hvis du støter på dette, kan du prøve å gjøre periode til en dimensjon. Ja, selvfølgelig, i dette tilfellet vil dette informasjonsregisteret ikke lenger generere noen virtuelle tabeller (en del av den første, en del av den siste), men du kan enkelt skrive til den parallelt, og du kan opprette en spørring for å skaff deg en bit av de første/siste selv.

  • For det første, bytt til administrert blokkeringsmodus. Jeg tror dette er ganske åpenbart, for hvis du bruker automatisk modus, vil du kanskje ikke engang bli overrasket over spørsmålene "Hvorfor har vi lite samtidighet, hvorfor er det mange låser?" Bytt først til administrert modus, og hvis du fortsatt har problemer etter det, kan du finne ut av det videre.
  • Når konfigurasjonen er byttet til administrert låsemodus, sørg for å gjøre det DBMS-modus må være aktivertLeseEngasjertØyeblikksbildeIsolering. Dette er et direkte must – det vil umiddelbart være en kraftig økning i parallelliteten i arbeidet.
  • Bruk en totalseparator for registre. Der det ikke er balansekontroll, må den aktiveres slik at det ikke er forventninger.
  • OG Recordset.Read()- prøv i det hele tatt ikke bruk til lesing, fordi dette vil pålegge en kontrollert lås, som vil "henge" til slutten av transaksjonen. Hvorfor trenger du dette? Les dataene på forespørsel, og da vil det ikke være noen blokkering i det hele tatt hvis du har 8.3 uten kompatibilitetsmodus eller Read Committed Snapshot-modus er aktivert.
  • Når det gjelder sekvensgrensen, prøv også å akseptere det som standard flytte grensen kun ved rutinemessige oppgaver i ikke-arbeidstid. Ikke beveg deg mens du utfører.
  • Del store transaksjoner i flere. I stedet for å utføre en million dokumenter i én transaksjon, er det bedre å foreta små transaksjoner på 100 dokumenter, 1000 dokumenter hver - enda bedre hvis i flertrådsmodus. Det blir mer stabilt.
  • Alle slags beregninger, sjekker etc. gjøre utenfor transaksjonen. Transaksjonstiden bør være minimal, så kort som mulig.

Et eksempel på løsning av låseproblemet

Hvordan kan du ellers bli kvitt unødvendige forventninger?

La oss si at du har salgsrepresentanter som etter endt arbeidsdag (kl. 18.00) sender dokumenter til databasen. Og der, så snart disse dokumentene kommer via mobilt Internett, prøver de umiddelbart å laste ned og logge på. Som et resultat, hvis selgere har bestilt den samme varen fra samme lager, er det en venting fordi de får tilgang til de samme dataene, og siden det er lagerkontroll, vil totalseparatoren ikke hjelpe noen. Da må du vente.

Hvordan kan dette unngås? Kan Når du laster dokumenter, opprett, men ikke post, og så skrive en mekanisme som, For eksempel, redskaper dette er videre gjennomfører i flertrådsmodus, hvor hver tråd vil behandle dokumenter gjennom sitt eget lager. Separer derfor disse prosessene i tid: den første flyten behandler dokumenter gjennom ett lager, den andre flyten gjennom det andre lageret, etc. Da vil problemet være løst.

Forriglinger og utstyr

Hvordan påvirker låser utstyret? Når du står overfor blokkeringsproblemet, kan det være lurt å kjøpe en ny server. Selvfølgelig kan du prøve, men du vil fortsatt ikke endre noe rotmessig. Ja, transaksjoner vil bli raskere, forespørsler vil bli raskere. Men hun selv problem med låser vil bli fordi hun kan bare løses på kodenivå.

Hvordan påvirker låseoptimalisering maskinvaren din? Du byttet for eksempel fra automatisk modus til administrert modus, eller du tok og slo på Les forpliktet øyeblikksbilde. Mens systemet venter, hun utstyr bruker det ikke, og du har det i dette tilfellet tomgang. EN så snart som systemet ditt fungerer med full kapasitet, ingen forventninger, ser du umiddelbart en kraftig økning, . Og avhengig av hvilken tilstand den er i for øyeblikket, kan dette være kritisk. For eksempel, hvis serveren din var 80 % lastet, og du også fjernet blokkeringene dine, kan den til og med gå ned. Dette må tas hensyn til.

hvori, spørringsoptimalisering-omvendt, reduserer belastningen, derfor, hvis du gjør optimalisering, er det bedre å eliminere blokkering og, hvis mulig, optimalisere spørringer.

Verktøy for blokkeringsanalyse

Og avslutningsvis vil jeg vise verktøyet du bruker i virkeligheten du kan se hvilke data som for øyeblikket er blokkert i systemet.

De viktigste årsakene til å bytte til administrerte låser:

  • Hovedårsaken er anbefalingen fra 1C:Expert basert på vitnesbyrd eller 1C:TsUP
  • Problemer med samtidige brukere ()
  • Bruker Oracle, PostgreSQL og .

Kostnader for arbeid:

Essensen av administrerte låser

Når du arbeider i automatisk låsekontrollmodus, setter 1C:Enterprise en høy grad av dataisolering i en transaksjon på DBMS-nivå. Dette lar deg helt eliminere muligheten for å skaffe ufullstendige eller feil data uten noen spesiell innsats fra applikasjonsutviklernes side.

Dette er en praktisk og riktig tilnærming for et lite antall aktive brukere. Prisen for enkel utvikling er en viss redundant låsing på DBMS-nivå. Disse låsene er assosiert både med særegenhetene ved implementeringen av låsemekanismer i selve DBMS, og med det faktum at DBMS ikke kan (og ikke) ta hensyn til den fysiske betydningen og strukturen til 1C:Enterprise metadataobjekter.

Når du jobber med høy strid om ressurser (et stort antall brukere), blir på et tidspunkt virkningen av redundante låser merkbar når det gjelder ytelse i parallellmodus.

Etter å ha overført konfigurasjonen til administrert modus, aktiveres tilleggsfunksjonaliteten til "lock manager" i plattformen og dataintegritetskontroll utføres nå ikke på DBMS-siden, men på 1C-serversiden. Dette øker belastningen på 1C-servermaskinvaren (raskere prosessorer og mer minne er nødvendig), og introduserer faktisk til og med en liten nedgang (flere prosent), men det forbedrer situasjonen betydelig med låser (færre låser på grunn av låser på et objekt, og ikke på en kombinasjon av tabeller, mindre blokkeringsareal og i noen tilfeller er levetiden til leselåser kortere, dvs. ikke før slutten av transaksjonen). Dette forbedrer den generelle samtidigheten.


Nye konfigurasjoner fra 1C ble implementert umiddelbart i en kontrollert modus.

  • Spørsmål: Er det mulig å gjøre revisjon først og deretter overføre til FM?

Svar: Ja, tilsynet vil tjene som en ekstra begrunnelse for muligheten for å bytte til administrerte låser og også for å evaluere bidraget fra automatiske låser til den generelle nedgangen og om det er behov for ytterligere innsats i tillegg til overføringen.

  • Spørsmål: For å overføre til UX, hva slags tilgang bør gis - RDP, TeamViewer? Eller kan jeg sende deg konfigurasjonsfilen?

Svar: Vi prøver å ikke begrense oss til én spesifikk fjerntilgangsteknologi, det vil gjøre det hvilken som helst fjerntilgangsteknologi. Hvis det ikke spiller noen rolle for deg, er RDP mer praktisk.
Vi kan utføre optimalisering basert på den sendte konfigurasjonsfilen, men da vil vi ikke kunne feilsøke noen reelle data og du må teste mer nøye. Hvis vi utfører optimering på en kopi av databasen, kan vi teste den grundigere før vi gir deg resultatet av arbeidet.

  • Spørsmål: Vi har 10 programmerere på heltid som endrer noe på konferansen hver dag. Et delt konfigurasjonslager brukes." Hvordan vil interaksjonen organiseres under overføringen til UX? Eller skal alle programmerere sendes på ferie?

Svar: Som regel gjøres våre endringer i løpet av et par dager. Resten av tiden går med til å teste endringene som er gjort, inkludert fra synspunktet om nødvendig logikk bestemt av virksomheten og ikke av tekniske hensyn. Vi vi kan gjøre endringer i en egen konfigurasjonsfil cf , og deretter vil programmereren forplikte det til depotet. Ingen vil måtte reise på ferie. I andre alternativer for interaksjon trenger du bare å bli enige om hvilke objekter utviklerne planlegger å fange, slik at vi kan bygge en arbeidsplan som er praktisk for begge parter. Som regel trenger ikke utviklerne dine å fange opp hele konfigurasjonen, eller gi oss "rattet" for dagen.

Få fart på 1C ved å trykke på noen få knapper 2. Kontrollerte låser. 4. september 2011

Hvis du leser metodikken for å overføre konfigurasjonen til administrerte låser fra 1C, kan du finne mange interessante og skumle ting der. Det er faktisk enkelt: I konfigurasjonsegenskapene endrer du datablokkeringsmodus - "Administrert". Alle. Gratulerer - du har nettopp byttet til administrerte låser. Faktisk er alt noe mer komplisert - men ikke mye.

Først en kort teoretisk ekskursjon - hvorfor blokkering trengs: De som har tilgang kan selvfølgelig lese den her: http://kb.1c.ru/articleView.jsp?id=30 1C gadd å skrive en ganske tilgjengelig artikkel om datablokkering. For de som ikke har tilgang, vil jeg beskrive i et nøtteskall hvorfor låser er nødvendig:

Eksempel 1. Hvis du, etter å ha aktivert kontrollerte låser, ikke gjør noe, og samtidig begynner å behandle 2 dokumenter parallelt (ett av dem er fortsatt en brøkdel av et sekund tidligere), så får vi omtrent følgende bilde:

Transaksjon 1 Transaksjon 2 Status for saldoer
Start | 1 PC
| Start 1 PC
| | 1 PC
Lese balanser | 1 PC
| Lese balanser 1 PC
| | 1 PC
Avskrivning fra saldoer | 0 stk
| Avskrivning av saldoer -1 PC
Fullføring |
Fullføring

Hva er galt her? Restkontroll har mislyktes. Det andre dokumentet klarte å lese resten før det første klarte å skrive dem ned. Samtidig så jeg at det kun var 1 vare igjen og skrev dem rolig av etter den første. Det er verdt å nevne at det faktisk fortsatt vil være blokkeringer her. 2 dokumenter vil ikke kunne avskrive saldoene samtidig; dette er nødvendig for den logiske integriteten til databasen, men for å løse applikasjonsproblemet i dette eksemplet er det neppe nyttig.

Nå skal vi prøve å rette opp situasjonen - i dokumentutførelseskoden skriver vi installasjonen av en eksklusiv kontrollert lås umiddelbart før vi leser saldoene:

Vel, nå som vi har funnet ut hvorfor låser trengs, gjenstår det bare å installere kontrollerte låser der de trengs: nemlig - kun der restkontroll utføres. Hvis en leder i databasen din har rett til å legge ut et dokument, uavhengig av om det er et produkt (penger) på lager eller ikke, hvorfor trenger du sperring da? Du kan rett og slett ikke installere dem, eller registrere dem og kommentere dem til bedre tider. Hvis du overvåker saldoer, er det som regel 3-4 registre, vel, maksimalt 10. Kontroll kan suspenderes både i generelle prosedyrer og funksjoner, og i moduler i RN-postsettet. Koden er ekstremt enkel, åpne syntaksassistenten og se:

Låse = NewDataLock;
LockElement = Lås. Legg til( "Akkumuleringsregister. Varer i varehus") ;
Låselement. SetValue("Kvalitet", Kataloger. Kvalitet. FindByCode("1" ) );
Låselement. Modus = DataLockMode. Eksepsjonell;
Låselement. DataSource = DocumentObject. Returbeholder;
Låselement. UseFromDataSource("Nomenklatur", "Nomenklatur");
Låselement. UseFromDataSource("Warehouse" , "Warehouse" );
Blokkering. Block() ;

Faktisk er alt umiddelbart klart - vi blokkerer "varer i varehus", setter 1 dimensjon eksplisitt, tar verdiene til de to andre fra datakilden - PM-dokumentet.

De som har lest bøker på 8.2, husker nok den "nye posteringslogikken" - når saldoene kontrolleres etter at dokumentbevegelser er registrert. Lurer du på hvorfor dette er? Men la oss tegne den samme platen på nytt slik at kontroll over balanser og blokkering vil være etter registrering av bevegelser:

Transaksjon 1 Transaksjon 2 Status for saldoer
Start | 1 PC
| Start 1 PC
| | 1 PC
Avskrivning fra saldoer | 0 stk
| Avskrivning fra saldoer -1 PC
Låse | -1 PC
Lese balanser Blokkeringsforsøk -1 PC
| Venter på blokk -1 PC
| Venter på blokk -1 PC
Fullføring Venter på blokk -1 PC
Låse -1 PC
Lese balanser -1 PC
| -1 PC
Avslag 0 stk

Forskjellen er ikke signifikant i utseende - vi får en ytelsesøkning på grunn av at det ved avskrivning av saldoer (skrive dem inn i databasen, noe som faktisk tar tid) ikke er noen blokkering ennå. Blokkeringen skjer senere på slutten av transaksjonen, hvor kontroll av negative saldoer utføres; dette tilfredsstiller fullstendig forretningslogikken til applikasjonen.

Når du vet hvorfor låser er nødvendig, kan du virkelig administrere dem basert på forretningsproblemene du løser. DBMS-er er utviklet basert på antakelsen om å sikre maksimal databeskyttelse. Hvis du for eksempel utfører banktransaksjoner, bør sperring være overalt og på maksimalt nivå. Det er bedre å blokkere unødvendige poster enn å la data være inkonsistente.

Selger du boller eller kulepenner trenger du neppe så mange blokkeringer. Gjennom defekter og feilvurdering på grunn av menneskelig skyld, taper du hundrevis av ganger mer enn du kunne hvis to brukere samtidig behandlet to identiske fraktdokumenter.

For å variere mellom slike forskjellige oppgaver, kom DBMS-er med isolasjonsnivåer. Ved å angi transaksjonsisolasjonsnivået kan du fortelle DBMS hvilke låser som skal pålegges i forskjellige tilfeller (når du skriver og når du leser i en transaksjon); i forskjellige tilfeller, S (du kan lese eller skrive) eller X (du kan verken lese eller skrive skrive) låser pålegges.

Så i automatisk modus vil du nesten alltid ha SERIALIZABLE isolasjonsnivået, som vil pålegge X-låser der det er nødvendig og der det ikke er nødvendig, noe som vil ødelegge livet ditt betydelig

Og i en administrert vil du ha READ COMMITED, som vil gjelde og umiddelbart frigjøre S-låsen når du leser, og X-låsen kun når du skriver. Det vanskeligste nivået. En raskt påført S-lås lar deg bare sjekke om en X-lås er plassert på disse dataene et sted, noe som sikrer at kun konsistente data leses, slik det er vanlig for et gitt isolasjonsnivå, og hvis du leste og fulgte handlingene anbefalt i forrige artikkel, da Det vil til og med være S-låser ved lesing, så på DBMS-nivå vil kun skriving blokkeres under skriving - noe som er riktig og nødvendig for datakonsistens.

Hva du gjør med administrerte låser er helt og holdent din avgjørelse. Men jeg vil anbefale å ikke skynde seg å installere dem. Jeg har møtt selskaper som hadde en automatisk blokkeringsmodus, og ordet "plaget av blokkering" ble hørt selv fra munnen til den daglige direktøren, og samtidig ble kontrollen av negative saldoer deaktivert....