Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
oracle_locking_latches_mutexes [2019/10/25 08:28] – [Latches] andonovj | oracle_locking_latches_mutexes [2021/01/07 18:48] (current) – [Enqueues] andonovj | ||
---|---|---|---|
Line 21: | Line 21: | ||
Latches are lightweight serialization control structure devices. WoW that was a lot of terms used here :) So let's explain it a little bit: | Latches are lightweight serialization control structure devices. WoW that was a lot of terms used here :) So let's explain it a little bit: | ||
- | * lightweight - Meaning they don't cause a lot of overhead to support. They are generally around 100-200 bytes of data in the SGA | + | * lightweight - Meaning they don't cause a lot of overhead to support. They are generally around 100-200 bytes of data in the SGA and they hold between 150-200 instructions) |
* Serialization - Meaning they can process only one request at a time | * Serialization - Meaning they can process only one request at a time | ||
* Control - They control access the shared resources (Library caches objects mostly: cursors and etc.) | * Control - They control access the shared resources (Library caches objects mostly: cursors and etc.) | ||
Line 37: | Line 37: | ||
Latch usually start as immediate and then transform into willing to wait, but that is a story for another time :) | Latch usually start as immediate and then transform into willing to wait, but that is a story for another time :) | ||
- | In a nutshell, Latch is a combination of memory location in the SGA (around 100-200 bytes big) and CPU atomic capability of checking and changing the value in that location. They can be held only by one process and all else has to wait. It is also import to notice that the latch structure doesn' | + | In a nutshell, Latch is a combination of memory location in the SGA (around 100-200 bytes big) and CPU atomic capability of checking and changing the value in that location. They can be held only by one process and everybody |
+ | It is also import to notice that the latch structure doesn' | ||
The logic of the latch is: | The logic of the latch is: | ||
Line 50: | Line 51: | ||
- If not then go back to the top and try again—for a couple of thousand attempts | - If not then go back to the top and try again—for a couple of thousand attempts | ||
- | We were speaking of what latches are and how to obtain then. But what really they protect. Well Latches protect shared resources, mostly library caches objects, such as cursors. Library objects and objects in general, in Oracle, are chained into linked lists, that is a structure which keeps the location of all members. Meaning that each member knows the location of the next member. | + | We were speaking of what latches are and how to obtain then. But what really they protect. Well Latches protect shared resources, mostly library caches objects, such as cursors. Library objects and objects in general, in Oracle, are chained into linked lists, that is a structure which keeps the location of all members. |
+ | |||
+ | Meaning that each member knows the location of the next member. | ||
Each linked list has a hash bucket (function) which acts as a quick search option. So if we want to know if a certain cursor is in a certain linked list we check the hash value of our select through the "hash bucket" | Each linked list has a hash bucket (function) which acts as a quick search option. So if we want to know if a certain cursor is in a certain linked list we check the hash value of our select through the "hash bucket" | ||
+ | |||
In Oracle <=10g and even in early 11g. A lot of hash buckets and their linked lists were protected by a single latch. Of course that create a lot of contention even for a simple selects. | In Oracle <=10g and even in early 11g. A lot of hash buckets and their linked lists were protected by a single latch. Of course that create a lot of contention even for a simple selects. | ||
+ | |||
You can observer graphical representation of that structure: | You can observer graphical representation of that structure: | ||
- | Graphical representation of how latch is working can be seen below: | ||
{{ : | {{ : | ||
Line 61: | Line 65: | ||
Latches are good control structures but they have their flows. For example if the session fails to get the latch it will spin couple thousand times before going to sleep, That spinning is causing CPU time which can be spend for other more " | Latches are good control structures but they have their flows. For example if the session fails to get the latch it will spin couple thousand times before going to sleep, That spinning is causing CPU time which can be spend for other more " | ||
- | It is worth mentioning that latches aren't used so much in newer Oracle version: >=11g. They were replacing | + | It is worth mentioning that latches aren't used so much in newer Oracle version: >=11g. They were replaced |
+ | |||
+ | Latch present a contrast with enqueues which always protect structures which has some disk based equivalent such as database objects, data blocks or table rows. | ||
+ | Another significant difference between latch and enqueue In latches there is no ordered queue of waiters like in enqueues. Latch waiters may either use timers to wake up and retry or spin (only in multiprocessors). Since all waiters are concurrently retrying (depending on the scheduler), anyone might get the latch and conceivably the first one to try might be the last one to get. | ||
+ | |||
+ | |||
+ | We can check all the latches as follows: | ||
+ | |||
+ | < | ||
+ | SQL> column name format A32 truncate heading "LATCH NAME" | ||
+ | SQL> column pid heading " | ||
+ | SQL> | ||
+ | column name format A32 truncate heading "LATCH NAME" | ||
+ | column pid heading " | ||
+ | select c.name, | ||
+ | a.immediate_gets, | ||
+ | from v$latch a, v$latchholder b, v$latchname c | ||
+ | where a.addr = b.laddr(+) | ||
+ | and a.latch# = c.latch# | ||
+ | order by a.latch#; | ||
+ | |||
+ | LATCH NAME | ||
+ | -------------------------------- ---------------- ---------- ---------- ---------- -------------- ---------------- ---------- | ||
+ | PC and Classifier lists for WLM 0000000060001008 | ||
+ | post/wait queue 000000006000AA50 | ||
+ | hot latch diags 000000006000AAF0 | ||
+ | event stats latch 000000006000AB90 | ||
+ | test excl. non-parent l0 | ||
+ | test excl. parent l0 | ||
+ | test excl. parent2 l0 000000006000AD70 | ||
+ | test shared non-parent l0 000000006000AE10 | ||
+ | test excl. non-parent lmax | ||
+ | test excl. parent2 lmid cln 000000006000AF50 | ||
+ | ------------------------------------------------------------------------------------------------------------------------------- | ||
+ | </ | ||
+ | |||
+ | Let's further examine the most gets/ | ||
+ | |||
+ | < | ||
+ | SQL> SET LINESIZE 200 | ||
+ | SET VERIFY OFF | ||
+ | |||
+ | SELECT * | ||
+ | FROM | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | FROM | ||
+ | WHERE name = 'cache buffers chains' | ||
+ | AND misses > 0 | ||
+ | ORDER BY gets DESC) | ||
+ | WHERE rownum < 11;SQL> SQL> SQL> | ||
+ | |||
+ | LATCH NAME | ||
+ | -------------------------------- ---------------- ---------- ---------- ---------- | ||
+ | cache buffers chains | ||
+ | cache buffers chains | ||
+ | cache buffers chains | ||
+ | cache buffers chains | ||
+ | cache buffers chains | ||
+ | cache buffers chains | ||
+ | cache buffers chains | ||
+ | cache buffers chains | ||
+ | cache buffers chains | ||
+ | cache buffers chains | ||
+ | </ | ||
+ | |||
+ | From that we can see that latch child with addr: ' | ||
+ | |||
+ | < | ||
+ | ACCEPT address PROMPT "Enter ADDR: " | ||
+ | |||
+ | COLUMN owner FORMAT A15 | ||
+ | COLUMN object_name FORMAT A30 | ||
+ | COLUMN subobject_name FORMAT A20 | ||
+ | |||
+ | SELECT * | ||
+ | FROM | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | 1,' | ||
+ | 2,' | ||
+ | 3,' | ||
+ | 4,' | ||
+ | 5,' | ||
+ | 6,' | ||
+ | 7,' | ||
+ | 8,' | ||
+ | 9,' | ||
+ | 10,' | ||
+ | 11,' | ||
+ | FROM x$bh bh, | ||
+ | | ||
+ | WHERE o.data_object_id = bh.obj | ||
+ | AND hladdr IN (SELECT addr | ||
+ | | ||
+ | | ||
+ | and addr=' | ||
+ | ORDER BY tch DESC); | ||
+ | |||
+ | |||
+ | HLADDR | ||
+ | ---------------- --------------- ------------------------------ -------------------- ----------------------- ---------- ---------- ---------- ---------- ------------------ ------- | ||
+ | 00000015C2E1CDF8 XCREW | ||
+ | 00000015C2E1CDF8 XCREW | ||
+ | 00000015C2E1CDF8 XCREW | ||
+ | 00000015C2E1CDF8 XCREW | ||
+ | 00000015C2E1CDF8 XCREW | ||
+ | 00000015C2E1CDF8 XCREW | ||
+ | 00000015C2E1CDF8 SCHEDOPS | ||
+ | 00000015C2E1CDF8 XCREW | ||
+ | 00000015C2E1CDF8 XCREW | ||
+ | 00000015C2E1CDF8 XCREW | ||
+ | 00000015C2E1CDF8 XCREW | ||
+ | </ | ||
+ | |||
+ | |||
+ | We can also search for the most misses: | ||
+ | |||
+ | < | ||
+ | SQL> SELECT | ||
+ | addr, | ||
+ | sleeps | ||
+ | FROM | ||
+ | v$latch_children c, | ||
+ | v$latchname n | ||
+ | WHERE | ||
+ | n.name=' | ||
+ | c.latch# | ||
+ | sleeps > 100 | ||
+ | ORDER BY sleeps | ||
+ | | ||
+ | |||
+ | ADDR | ||
+ | ---------------- ---------- | ||
+ | 00000015C31212F8 | ||
+ | 00000015C32020B8 | ||
+ | 00000015E27150D0 | ||
+ | 0000001602639EC0 | ||
+ | 00000016025F30C0 | ||
+ | 0000001602E696C0 | ||
+ | 0000001602291140 | ||
+ | 00000015E2B82650 | ||
+ | 00000015C2EA0138 | ||
+ | </ | ||
+ | |||
+ | And of course we can see what is behind that latch: ' | ||
+ | |||
+ | < | ||
+ | |||
+ | SQL> COLUMN owner FORMAT A15 | ||
+ | COLUMN object_name FORMAT A30 | ||
+ | COLUMN subobject_name FORMAT A20 | ||
+ | |||
+ | SELECT * | ||
+ | FROM | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | 1,' | ||
+ | 2,' | ||
+ | 3,' | ||
+ | 4,' | ||
+ | 5,' | ||
+ | 6,' | ||
+ | 7,' | ||
+ | 8,' | ||
+ | 9,' | ||
+ | 10,' | ||
+ | 11,' | ||
+ | FROM x$bh bh, | ||
+ | | ||
+ | WHERE o.data_object_id = bh.obj | ||
+ | AND hladdr IN (SELECT addr | ||
+ | FROM | ||
+ | WHERE name=' | ||
+ | and addr=' | ||
+ | ORDER BY tch DESC); | ||
+ | SQL> SQL> SQL> SQL> | ||
+ | |||
+ | HLADDR | ||
+ | ---------------- --------------- ------------------------------ -------------------- ----------------------- ---------- ---------- ---------- ---------- ------------------ ------- | ||
+ | 00000015C2EA0138 XCREW | ||
+ | 00000015C2EA0138 XCREW | ||
+ | 00000015C2EA0138 SCHEDOPS | ||
+ | 00000015C2EA0138 XCREW | ||
+ | 00000015C2EA0138 IOCC ACTIVEMQ_ACKS | ||
+ | 00000015C2EA0138 SCHEDOPS | ||
+ | 00000015C2EA0138 XCREW | ||
+ | 00000015C2EA0138 XCREW | ||
+ | 00000015C2EA0138 IOCC ACTIVEMQ_ACKS | ||
+ | 00000015C2EA0138 IOCC ACTIVEMQ_ACKS | ||
+ | 00000015C2EA0138 SCHEDOPS | ||
+ | 00000015C2EA0138 IOCC ACTIVEMQ_ACKS | ||
+ | 00000015C2EA0138 IOCC ACTIVEMQ_ACKS | ||
+ | 00000015C2EA0138 IOCC ACTIVEMQ_ACKS | ||
+ | 00000015C2EA0138 IOCC ACTIVEMQ_ACKS | ||
+ | 00000015C2EA0138 SCHEDOPS | ||
+ | 00000015C2EA0138 SCHEDOPS | ||
+ | </ | ||
+ | |||
+ | |||
+ | =====KGL Locks & Pins===== | ||
+ | |||
+ | |||
+ | =====Mutexes===== | ||
+ | Mutexes are very similar to latches, in a such a way that they also are lightweighted serializable control structures. Furthermore, | ||
+ | |||
+ | The mutex usually have around 28 bytes and have around 30-35 instructions. Furthermore, | ||
+ | Furthermore, | ||
+ | |||
+ | Also, it is import to notice that a latch is taken by process, while mutexes is taken by a session. Since a process can have many sessions (shared server), a mutex will not allow a deadlock by a single process. | ||
+ | |||
+ | If you have to compare latches to Mutexes, they are pretty similar, just mutexes are protecting way smaller groups of objects than latches and they are way smaller. They have the same logic: "If I can change the value of the mutex then I can do something with the objects it protects" | ||
+ | |||
+ | Mutexes usually protect Cursors and there are quite a lot of them. We can check the mutexes for cursors as follows: | ||
+ | |||
+ | < | ||
+ | SQL> select MUTEX_IDENTIFIER, | ||
+ | |||
+ | MUTEX_IDENTIFIER MUTEX_TYPE | ||
+ | ---------------- ---------- ---------- ----------- ---------------- | ||
+ | 2036683327 Cursor Pin | ||
+ | 2257295401 Cursor Pin | ||
+ | 1698288247 Cursor Pin | ||
+ | 2941537973 Cursor Pin | ||
+ | 1154347790 Cursor Pin | ||
+ | 1154347790 Cursor Pin | ||
+ | 1184750592 Cursor Pin | ||
+ | 1184750592 Cursor Pin | ||
+ | | ||
+ | </ | ||
+ | |||
+ | This query shows us the amount of gets and misses per mutex. Don't forget that each time a mutex is missed, it will try again or go to sleep. We can check the actual plan as follows: | ||
+ | |||
+ | < | ||
+ | SQL> select sql_id, sql_text, version_count from v$sqlarea where hash_value=345957031; | ||
+ | |||
+ | SQL_ID | ||
+ | ------------- ------------------------------ ------------- | ||
+ | 2ff8mkna9xsp7 select item_daily_uno , | ||
+ | aily_uno ,rank , | ||
+ | eat_category ,seat_class ,seat | ||
+ | _no ,rest_begin ,rest_end ,las | ||
+ | t_update | ||
+ | here chain_daily_uno=: | ||
+ | |||
+ | </ | ||
+ | |||
+ | From the code it is visible, that this query is being executed A LOT of times and this can lead to contentions with that mutex: | ||
+ | |||
+ | < | ||
+ | > set linesize 800 | ||
+ | set pages 20000 | ||
+ | col SAMPLE_TIME for a30 | ||
+ | col event for a30 | ||
+ | col blocking_session for a10 | ||
+ | col WAIT_CLASS for a15 | ||
+ | col BLOCKING_SESSION_SERIAL# | ||
+ | col BLOCKING_SESSION_SERIAL# | ||
+ | col SQL_CHILD_NUMBER for 99999 | ||
+ | select snap_id, | ||
+ | from dba_hist_active_sess_history | ||
+ | where snap_id between | ||
+ | group by snap_id, | ||
+ | order by count(*); | ||
+ | 23920 cursor: pin S wait on X 1729 | ||
+ | 23917 cursor: pin S wait on X 1850 | ||
+ | 23922 cursor: pin S wait on X 2135 | ||
+ | 23919 cursor: pin S wait on X 2573 | ||
+ | 23918 cursor: pin S wait on X 2629 | ||
+ | 23916 cursor: pin S wait on X 2918 | ||
+ | 23914 cursor: pin S wait on X 2967 | ||
+ | 23914 latch free | ||
+ | 23915 cursor: pin S wait on X 3077 | ||
+ | |||
+ | |||
+ | </ | ||
+ | =====Enqueues===== | ||
+ | Enqueues are your standard locks and they come in several tyes: | ||
+ | * TX: Transaction lock: | ||
+ | * * mode 6: data modification, | ||
+ | * * mode 4: setting tablespace to read only, foreign key enforcement, | ||
+ | * TM: Table modification (or locking a referenced table when the foreign key is not indexed) | ||
+ | * UL: Lock used by user applications, | ||
+ | * CF: Control file: actions accessing the control file, like: log switch, redo archiving, and backup | ||
+ | * ST: Space Transaction: | ||
+ | * TT: Temporary tablespace: parallel tablespace operations | ||
+ | * CI: Cross-instance: | ||
+ | * HV: Parallel direct-path insert |