they are not unnecessary -- they are there in order to prevent someone from altering the structure of the table your transaction is now dependent on!
You might want to look at dba_locks which decodes the lock mode
ops$tkyte@ORA9IR2> create table t ( x int );
Table created.
ops$tkyte@ORA9IR2> update t set x = 0;
0 rows updated.
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> exec print_table( 'select * from dba_locks where session_id = (select sid from v$mystat where rownum=1)' );
.SESSION_ID : 10
.LOCK_TYPE : DML
.MODE_HELD : Row-X (SX)
.MODE_REQUESTED : None
.LOCK_ID1 : 36558
.LOCK_ID2 : 0
.LAST_CONVERT : 0
.BLOCKING_OTHERS : Not Blocking
-----------------
PL/SQL procedure successfully completed.
ops$tkyte@ORA9IR2> exec print_table( 'select * from v$lock where sid = (select sid from v$mystat where rownum=1)' );
.ADDR : 5B8A00C0
.KADDR : 5B8A00D4
.SID : 10
.TYPE : TM
.ID1 : 36558
.ID2 : 0
.LMODE : 3
.REQUEST : 0
.CTIME : 0
.BLOCK : 0
-----------------
PL/SQL procedure successfully completed.
It prevents other sessions from getting an exclusive lock on the table, nothing else really. Until you commit, you do in fact have an outstanding transaction against the table. We get that lock BEFORE the update happens -- in order to be certain that the update can in FACT happen (that there are no other locks preventing it from happening). This lock then prevents INCOMPATIBLE operations from taking place until we commit.
You might want to check out:
</code>
http://docs.oracle.com/cd/B10501_01/server.920/a96524/c21cnsis.htm#3138 <code>