Database Reference
In-Depth Information
When we
COMMIT
, all that is left to happen is the following:
A System Change Number (SCN) is generated for our transaction. In case you are not familiar
•
with it, the SCN is a simple timing mechanism Oracle uses to guarantee the ordering of
transactions and to enable recovery from failure. It is also used to guarantee read-consistency
and checkpointing in the database. Think of the SCN as a ticker; every time someone
COMMIT
s,
the SCN is incremented by one.
•
LGWR
writes all of our
remaining
buffered redo log entries to disk and records the SCN in
the online redo log files as well. This step is actually the
COMMIT
. If this step occurs, we have
committed. Our transaction entry is “removed” from
V$TRANSACTION
—this shows that we have
committed.
•
All locks recorded in
V$LOCK
held by our session are released, and everyone who was
enqueued waiting on locks we held will be woken up and allowed to proceed with their work.
•
Some of the blocks our transaction modified will be visited and “cleaned out” in a fast mode if
they are still in the buffer cache.
Block cleanout
refers to the lock-related information we store
in the database block header. Basically, we are cleaning out our transaction information on
the block, so the next person who visits the block won't have to. We are doing this in a way that
need not generate redo log information, saving considerable work later (this is discussed fully
in the next chapter).
As you can see, there is very little to do to process a
COMMIT
. The lengthiest operation is, and always will be, the
activity performed by
LGWR
, as this is physical disk I/O. The amount of time spent by
LGWR
here will be greatly reduced
by the fact that it has already been flushing the contents of the redo log buffer on a recurring basis.
LGWR
will not buffer
all of the work you do for as long as you do it. Rather, it will incrementally flush the contents of the redo log buffer in
the background as you are going along. This is to avoid having a
COMMIT
wait for a very long time in order to flush all of
your redo at once.
So, even if we have a long-running transaction, much of the buffered redo log it generates would have been
flushed to disk, prior to committing. On the flip side is the fact that when we
COMMIT
, we must typically wait until
all
buffered redo that has not been written yet is safely on disk. That is, our call to
LGWR
is by default a
synchronous
one.
While
LGWR
may use asynchronous I/O to write in parallel to our log files, our transaction will normally wait for
LGWR
to
complete all writes and receive confirmation that the data exists on disk before returning.
■
oracle 11
g
release 1 and above have an asynchronous wait. however, that style of commit has limited
general-purpose use. Commits in any end-user-facing application should be synchronous.
Note
Now, earlier I mentioned that we were using a Java program and not PL/SQL for a reason—and that reason is a
PL/SQL commit-time optimization. I said that our call to
LGWR
is by default a synchronous one and that we wait for it
to complete its write. That is true in Oracle 12c Release 1 and before for every programmatic language
except PL/SQL
.
The PL/SQL engine, realizing that the client does not know whether or not a
COMMIT
has happened in the PL/SQL
routine until the PL/SQL routine is completed, does an asynchronous commit. It does not wait for
LGWR
to complete;
rather, it returns from the
COMMIT
call immediately. However, when the PL/SQL routine is completed, when we return
from the database to the client, the PL/SQL routine will wait for
LGWR
to complete any of the outstanding
COMMIT
s. So,
if you commit 100 times in PL/SQL and then return to the client, you will likely find you waited for
LGWR
once—not 100
times—due to this optimization. Does this imply that committing frequently in PL/SQL is a good or OK idea? No, not
at all—just that it is not
as bad an idea
as it is in other languages. The guiding rule is to commit when your logical unit
of work is complete—not before.
Search WWH ::
Custom Search