Freitag, September 16, 2011

Row Cache Lock

Dieser Tage ist mir folgendes Phänomen begegnet: zu einer großen Tabelle existierte ein Index für die Spalten des Primary Keys, wobei der Primary Key selbst disabled war. Ohne intensiver darüber nachzudenken, hatte ich angenommen, dass die Aktivierung des PKs sich darauf beschränken würde, zu prüfen, ob ein passender Index exisitiert - aber offenbar ist anschließend noch mehr zu tun. Meine Vermutung war, dass ein weiterer FTS stattfinden müsste, aber ein Blick in v$session_longops konnte das nicht bestätigen. Genauer gesagt konnte v$session_longops gar nichts bestätigen oder widerlegen, da die Abfrage von der Session, in der die PK-Aktivierung lief, geblockt wurde. Das Verhalten lässt sich mit einem einfachen Test stabil reproduzieren (hier in 11.1.0.7):

-- Löschung und Neuanlage einer Testtabellen mit 10M rows
drop table big_t purge;

create table big_t
as
with
base_data
as
(
select rownum id1
  from dual
connect by level <= 1000000
)
,
mult
as
(
select rownum id2
  from dual
connect by level <= 10
)
select rownum id
     , 'aaaaaaaaa' col2
  from mult
     , base_data;

alter table big_t modify id not null;

create index big_t_idx on big_t(id);

alter table big_t add constraint big_t_pk primary key (id) disable;

alter table big_t enable constraint big_t_pk;

Tabelle wurde geändert.

Abgelaufen: 00:00:17.26

Ein gleichzeitiger Zugriff einer zweiten Session auf v$session_longops (nicht aber auf viele andere v$-Views) wird blockiert, und in einer dritten Session kann man dazu in v$session_wait folgende Informationen finden:

SID       SEQ# EVENT            
--- ---------- -----------------
140        110 row cache lock   

In Dion Chos (auch sonst sehr lesenswertem) Blog findet man eine Erläuterung dazu, wie man den holder eines row cache locks mit Hilfe von v$rowcache_parent ermitteln kann, aber in meinem Fall genügte ein Blick in v$session, um die blocking_session zu bestimmen. In der Dokumentation habe ich dafür zwar die Kurzbeschreibung "The session is trying to get a data dictionary lock" gefunden, aber keine grundsätzlichere Erklärung (kann auch sein, dass mein Suche nicht besonders systematisch war). Offenbar handelt es sich um ein Lock im dictionary cache, aber wieso es für den v$session_longops-Zugriff relevant ist aber nicht für Zugriffe auf ähnliche Objekte, kann ich nicht sagen.

Was ich immerhin herausgefunden habe, ist, dass die PK-Aktivierung ohne Verzögerung erfolgt, wenn der Index zur PK-Unterstützung als UNIQUE definiert ist, also:

create unique index big_t_idx on big_t(id);

Das ist durchaus einleuchtend - offenbar muss die Eindeutigkeit im Fall des non-unique Index erst explizit geprüft werden -, erklärt die Wirkung des "row cache lock" aber noch nicht. Wenn jemand mehr darüber weiß, würde ich mich über entsprechende Hinweise freuen.

Nachtrag 19.09.2011: Das row cache lock tritt offenbar auch bei der nachträglichen Definition eines NOT NULL Constraints auf.

Keine Kommentare:

Kommentar veröffentlichen