På min primære produktions-RAC-database ser jeg perioder med langsommelighed, og den dominerende ventehændelse, hele systemet, er "markør:pin S vent på X". Arrangementet kommer og går, men jeg ser det fra tid til anden. Så jeg var nødt til at finde bunden af det her. Bemærk, at dette ikke er et RAC-problem. Denne hændelse kan også nemt ses på enkeltforekomstdatabaser. Når jeg ser dette på flere forekomster af min Oracle RAC-database, skyldes det, at jeg har flere sessioner fra den samme applikation spredt ud blandt forekomsterne, som alle gør det samme, og derfor har alle det samme problem.
For det første, hvad handler ventebegivenheden om? Enhver af "cursor:"-venterne er flaskehalse i den delte pool i SQL-området. For lang tid siden var denne del af den fælles pool beskyttet af låse. Men som det er tilfældet med mange områder af den delte pool, bruger Oracle nu mutexes. Med ændringen i beskyttelsesmekanismen har vi nu nye ventebegivenheder.
I tilfælde af denne særlige ventehændelse har vi en markør, der ønsker en delt pin, men som skal vente på en anden session for at frigive dens eksklusive mutex. En markør forsøger at blive analyseret. Men det kan ikke parses, fordi en anden session holder på den samme mutex.
Der er tre hovedårsager til sessioner, der venter på denne begivenhed.
- Høj hårde parses
- Et stort antal versioner af SQL-sætningen
- Bugs
Desværre er der en række fejl relateret til denne ventebegivenhed. De fleste af dem, jeg har set, er rettet i 11.2.0.4 eller 12.1.0.1, så hvis du halter bagud i versioner, kan du overveje at opgradere til en af de nyere Oracle-versioner.
Så lad os se, om vi kan gennemgå et eksempel for at bestemme årsagen til problemet. For at gøre det brugte jeg følgende forespørgsel:
select s.inst_id as inst, s.sid as blocked_sid, s.username as blocked_user, sa.sql_id as blocked_sql_id, trunc(s.p2/4294967296) as blocking_sid, b.username as blocking_user, b.sql_id as blocking_sql_id from gv$session s join gv$sqlarea sa on sa.hash_value = s.p1 join gv$session b on trunc(s.p2/4294967296)=b.sid and s.inst_id=b.inst_id join gv$sqlarea sa2 on b.sql_id=sa2.sql_id where s.event='cursor: pin S wait on X';
Når jeg kører dette i en af mine produktions-RAC-databaser, får jeg følgende output:
INST BLOCKED_SID BLOCKED_USER BLOCKED_SQL_ID BLOCKING_SID BLOCKING_USER BLOCKING_SQL_ID ---- ----------- ------------ -------------- ------------ ------------- --------------- 4 723 USER12345 cn7m7t6y5h77g 1226 USER12345 cn7m7t6y5h77g 4 723 USER12345 cn7m7t6y5h77g 1226 USER12345 cn7m7t6y5h77g 4 723 USER12345 cn7m7t6y5h77g 1226 USER12345 cn7m7t6y5h77g 4 723 USER12345 cn7m7t6y5h77g 1226 USER12345 cn7m7t6y5h77g 4 1226 USER12345 cn7m7t6y5h77g 1796 USER12345 cn7m7t6y5h77g 4 1226 USER12345 cn7m7t6y5h77g 1796 USER12345 cn7m7t6y5h77g 4 1226 USER12345 cn7m7t6y5h77g 1796 USER12345 cn7m7t6y5h77g 4 1226 USER12345 cn7m7t6y5h77g 1796 USER12345 cn7m7t6y5h77g
Den første ting at bemærke er, at mutex kun er inden for denne instans for Oracle RAC-databaser. For enkeltforekomstdatabaser vil forespørgslen ovenfor stadig fungere. For Oracle RAC vil outputtet fra denne forespørgsel vise, hvilken instans der har problemet.
I eksemplet ovenfor har vi session 723 blokeret af session 1226. Session 1226 er yderligere blokeret af session 1796. Bemærk, at alle tre sessioner udsender den samme forespørgsel med SQL ID cn7m7t6y5h77g .
Nu hvor vi kender SQL ID'et, kan vi nemt forespørge V$SQL for at bestemme SQL-sætningen involveret i problemet. Jeg brugte denne forespørgsel til at få flere oplysninger.
select sql_id,loaded_versions,executions,loads,invalidations,parse_calls from gv$sql where inst_id=4 and sql_id='cn7m7t6y5h77g';
Outputtet fra at forespørge V$SQL er som følger:
SQL_ID LOADED_VERSIONS EXECUTIONS LOADS INVALIDATIONS PARSE_CALLS ------------- --------------- ---------- ---------- ------------- ----------- cn7m7t6y5h77g 1 105 546 308 3513
Vi kan nu se, at denne forespørgsel kun har 1 version i SQL-området. Så med det samme har vi elimineret et af de potentielle problemområder. I et fremtidigt blogindlæg vil jeg diskutere forespørgsler med et stort antal versioner i SQL-området. Men det er ikke vores problem i dag, så vi fortsætter.
Det burde være tydeligt ud fra ovenstående, at der er et meget højt antal parse-kald. Forespørgslen er kun blevet udført 105 gange, men er blevet parset 3513 gange. Yikes! Det høje tal, hvis invalidering er, har sandsynligvis også noget at gøre med dette.
I dette eksempel har vi nu en god idé om, hvad problemet er. Dette er et applikationsproblem. Applikationen overparser forespørgslen. Så vi sender dette tilbage til udvikling og graver i applikationskoden. De sædvanlige årsager til overparsing skal undersøges.
Hvis antallet af versioner var lavt, og overdreven parsing/ugyldiggørelser/indlæsninger ikke var et problem, ville jeg mistænke en fejl og indsende en SR til Oracle Support.