Wednesday, April 23, 2008

Oracle for Beginner: ORDB with Oracle (III)

In this third part of my articles about ORDB with Oracle, I just want to share about a simple example of implementation ORDB in Oracle based on class diagram UML. I want to show you about how to implement aggregation, association and inheritance in Oracle. Here is the class diagram:


Segitiga and Lingkaran class are child class from Bidang class (as parent class). Bidang class has association relationship with Warna class. This association is one direction that means Bidang class has a Warna's type attribute. First, we have to create Warna class:

create type warna as object(
r number(3),
b number(3),
g number(3),
member function getWarna return varchar
);
/

create type body warna as
member function getWarna return varchar is
begin
return 'Red=' || to_char(self.r) || ', Blue=' || to_char(self.b) || ', Green=' || to_char(self.g);
end;
end;
/


Warna class has 3 attributes, i.e. r for Red, b for Blue and g for Green, and 1 operation that will return a varchar for the color. Now, we can create Bidang that will have an attribute as an object for Warna class.

create type Bidang as object(
x number(3),
y number(3),
color warna,
member function getLuas return number,
member function getKeliling return number
) not final;
/

create type body Bidang as
member function getLuas return number is
begin
return 0;
end;
member function getKeliling return number is
begin
return 0;
end;
end;
/


Tuesday, April 01, 2008

Oracle for Beginner: ORDB with Oracle (II)

Continuing my last note, here we will try to use VARRAY() to make multiple value for a attribute of table. One of disadvantage of varray is we have to specify the maximum of element array that we want to save in it.

Here an example of how to create a varray type:

SQL> create type v_pengajar_t as varray(3) of pengajar_t;

Like previous example, we can create table which have one attribute with varray() type.

SQL> create table vkursus(
2 no_kursus char(5) primary key,
3 nama varchar(30),
4 pengajar v_pengajar_t
5 );

To insert new data, we can use statement below:

SQL> insert into vkursus values ('X01', 'Oracle', v_pengajar_t(pengajar_t('P01', 'Budi'), pengajar_t('P02', 'Wati')));

1 row created.

SQL> insert into vkursus values ('X02', 'ORDB with Oracle', v_pengajar_t(pengajar_t('P01', 'Budi'), pengajar_t('P03', 'Othie'), pengajar_t('P04','Indah')));

1 row created.

SQL> commit;


To make a query for varray, we can use table() function to create a virtual table from varray field. Here is an example:

SQL> select no_kursus, v.nama, p.nama
2 from vkursus v, table(v.pengajar) p;

NO_KU NAMA NAMA
----- ------------------------------ ------------------------------
X01 Oracle Budi
X01 Oracle Wati
X02 ORDB with Oracle Budi
X02 ORDB with Oracle Othie
X02 ORDB with Oracle Indah

Thursday, March 27, 2008

Oracle for Beginner: ORDB with Oracle (I)

If you want to learn about object relational database in Oracle, the first thing that you have to understand is object oriented concept itself. By the way, in what level of your understanding, let we learn about how to implement a simple Oracle's ORBMS.
In Oracle, there are object schema, .i.e., User Define Type (UDT). With this object, we can create any customize type, specially object type. Here is a example:

create or replace type pengajar_t as object (
pengajar_id char(5),
nama varchar(30)
)
/

With customize object type, we can use that as a attribute type for a table.

create table kursus (
kursus_id char(5) primary key,
nama_kursus varchar(50),
pengajar pengajar_t
);

If you want to insert or update for that table, here are an example for how to do that:

insert into kursus values ('K01', 'Air Blender', pengajar_t('X-01','Avatar'));
insert into kursus values ('K02', 'Kamehameha', pengajar_t('X-02','Goku'));
update kursus k set k.pengajar.nama = 'Gohan' where k.pengajar.pengajar_id ='X-02';

Sunday, March 23, 2008

OpenSource style for marketing

As you know, Open Source movement have changed the world to make their policies, either for organization or ourself. With this movement, everyone can became a programmer, a documentation maintainer, a tester, or may be only as a end user. I interested about how to make community, like Open Source, to make a marketing more powerful. With involving our customers, I believe that they will give their ideas (like wish list) to make our organization can give services better. I talk this with my client that one important thing to make their business can get the trust from their customers or partners is to make a good relationship with them. This is why CRM or PRM (Partner Relationship Management) concept arise on the surface.
How to build a customer community for our organization? Of course the most important thing to realize that is we have to give the best of our service to our partners. After that, we can use the Internet service to capture our customer requirements or needs. Indirectly, if our partner community is strong, they will promote our organization to others. This is a good strategy. And I believe that almost marketing manager had realize this way. But in Indonesia, specially for small-medium enterprise, still don't figure out about this. The big problem is the Internet penetration still low. Based on the APJII data, the Internet users in Indonesia at the end of 2005 was estimated around 1.6 million (I thing from 200 million population :D). I thing, we have to build and maintain many communities to develop their local small-business enterprise area to realize the Internet. Many names have arisen , like Internet goes to Village. I still figure out about the cheaper Internet access from villages. May be we can use mess wireless protocol to build local wireless communication with WiFi. Who knows...

Tuesday, February 12, 2008

Make My Desktop more fancy

I use fedora core 7 with Gnome and Beryl as the desktop management. To make my Beryl Desktop more fancy, I installed Mac4Lin Emerald Theme. This theme really make me more exciting to use Linux Desktop as my operating system in my notebook. To make my Linux Desktop to become most like a Tiger Mac X OS, I installed Avant Window Navigator too. With Avant, I have a fancy launch pad like Mac X OS in my Desktop. Very impressive.

In another thing, in my Linux box, I have installed VMWare Player that playing M$ Windows XP Home Edition (provided by compaq presario V1000 bundled) with SP2 for me. (I have tried VirtualBox to play Fedora Core 8). For my virtual M$ Windows, I want to make the desktop more like Fedora too, so I installed Fedora Transformation Packet. I think this theme is very impressive for my windows.

Here is the example of my desktop with Mac4Lin and Avant :

Monday, February 11, 2008

My Favorite mobile IM

At the first time when I changed my phone cell to N73, I have tried to fine a better IM application. First of all, I use mig33 (http://www.mig33.com) . But after a week, I didn't convenient with that. So, I tried to use shMessenger (http://www.shmessenger.ro/lang_en/index.jsp). This is a good mobile IM application, but unfortunately that application only support Yahoo! IM. I want to use an application with multiple IM protocol. Then, I found fring (http://www.fring.com). With early fring, I can use GTalk protocol, SIP, Fring, ICQ, but there were no Y! IM. But with the newest fring version (3.30), this application make me happy because they already support Y! IM protocol. So.. fring is the best mobile IM application for me. Right now. :D

Today (the day after I wrote this article), my friend has told me about another better Mobile IM application, i.e. Nimbuzz. Nimbuzz is j2me based application that support multi IM protocol and facebook. I have installed too and want to try it, may be this application can change my favorite, i.e. fring. Let me see...

After almost 2 months, I have decided to use Nimbuzz as my mobile messenger applications. :D Sorry fring.

Wednesday, November 21, 2007

Some Java OpenSource Projects

Everytime I need one or more Java packages or components, I always use sourceforge.net or freshmeat.net. Everyone know about this. This site is very useful for me either as system analyst or Java programmer.
Today, I have found a good site, i.e. Java Open Source, which provide a list of Java open source projects. May be you already know about this site, but for me I want to note at my blog to share with other.

Tuesday, October 09, 2007

SQL Tuning Advisor

This practice is based on http://www.oracle-base.com/articles/10g/AutomaticSQLTuning10g.php#sql_tuning_advisor.

SQL> conn / as sysdba
SQL> DECLARE
2 l_sql VARCHAR2(500);
3 l_sql_tune_task_id VARCHAR2(100);
4 BEGIN
5 l_sql := 'SELECT e.*, d.* ' ||
6 'FROM hr.employees e JOIN hr.departments d ON e.department_id = d.department_id ' ||
7 'WHERE NVL(employee_id, ''0'') = :empno';
8 l_sql_tune_task_id := DBMS_SQLTUNE.create_tuning_task (
9 sql_text => l_sql,
10 bind_list => sql_binds(anydata.ConvertNumber(100)),
11 scope => DBMS_SQLTUNE.scope_comprehensive,
12 time_limit => 60,
13 task_name => 'emp_dept_tuning_task',
14 description => 'Tuning task for an EMP to DEPT join query.');
15 DBMS_OUTPUT.put_line('l_sql_tune_task_id: ' || l_sql_tune_task_id);
16 END;
17 /

SQL> EXEC DBMS_STATS.delete_table_stats('HR', 'EMPLOYEES');

SQL> EXEC DBMS_SQLTUNE.execute_tuning_task(task_name => 'emp_dept_tuning_task');

In Enterprise Manager, click Advisor Central, you will see your sql tuning task completed. Click that name. In SQL Tuning result page, you can click View Recommendations button to view all of recommendations based on the query.

SQLAccess Advisor

SQL> conn / as sysdba
SQL> BEGIN
2 DBMS_ADVISOR.quick_tune(
3 advisor_name => DBMS_ADVISOR.SQLACCESS_ADVISOR,
4 task_name => 'test_quick_tune',
5 attr1 => 'SELECT * FROM hr.employees WHERE upper(last_name) = ''SMITH''');
6 END;
7 /

From Enterprise Manager, click Advisor Central. From the page, you can see test_quick_tune. Click that task name. In the page Result for Task, click the Recommendation tab. You will see a recommendation for tuning your index based on your query.

Using Segment Advisor

For each segment, Oracle will put a boundary (i.e. Highwater Mark) that will separate between used blocks and free blocks. Blocks below the high water mark (used blocks) have at least once contained data. This data might have been deleted. In normal DB operations, the high water mark only moves upwards, not downwards. If there is a lot of free space below the high water mark, one might consider to use alter table move statements. In another words, we have to shrink or compact the segment to move HWM downward. This condition will make full scan segment more faster.
We will try to use segment advisor to make our segment can be optimized based on the statistical data of our segment.

SQL> create table uji2 (id number(4), nilai varchar(1000));

Table created.

SQL> begin
2 for i in 1..10000 loop
3 insert into uji2 values (i, lpad('*', 1000, '*'));
4 end loop;
5 end;
6 /

PL/SQL procedure successfully completed.

SQL> update uji2 set data = null where mod(id, 5) = 0;

200 rows updated.

SQL> commit;

Commit complete.

SQL> set autotrace traceonly
(if you have any problems with this command, please refer to http://www.samoratech.com/tips/swenableautotrace.htm)

SQL> select count(*) from uji2;
(Summary)

SQL> alter table uji2 enable row movement;

Table altered.

SQL> alter table uji2 shrink space;

Table altered.

SQL> select count(*) from uji2;
(Summary)

Based on our practice, you can see that after shrink space, the amount of blocks that was reading have decreased, because the HWM was downwarded.

Now, we will use Segment Advisor from Enterprise Manager to get an advice about our segment.

SQL> create table uji2 (id int, data char(1000));

Table created.

SQL> insert into uji2 select object_id, lpad('*', 1000, '*')
2 from all_objects;

SQL> update uji2 set data = null where mod(id, 5) = 0;

Go to Enterprise Manager, and click Performance tab. In bottom section, click Advisor Central, and then click Segment Advisor. In Segment Advisor page, click Schema Objects, and click Next. Click Add button to add our table, i.e. uji2.

Click Next, and you can click Submit button directly. Here is example of the result :
Click the name of latest Segment Advisor task. In the page of Segment Advisor task, click Recomendataion Details.


Now, you can click Shrink button to make segment compact.

Wednesday, September 26, 2007

Default Temporary Tablespace

When I was teaching about temporary tablespace, I forgot about how to know where is the default temporary tablespace that is used in current Oracle database? After surfed arround the digital world, I have found some articles that give me a new knowledge. Here are the practice :

prompt> sqlplus /nolog
SQL> conn / as sysdba
SQL> col property_value format a20
SQL> select property_name, property_value from database_properties;

From above query, we can get all of database properties include default_temp_tablespace. If you want to change the default temporary tablespace, you can take a little steps below (my assumption is your database use OMF):

SQL> conn / as sysdba
SQL> create temporary tablespace temp1 datafile 20M;
SQL> alter database default temporary tablespace temp1;
SQL> select property_value from database_properties where property_name = 'DEFAULT_TEMP_TABLESPACE';

If you want to know about the temporary status and space information, you can query with this:
select * from v$tempfile;

Another FGA

When I tried to find more new thing about FGA (Fine Grained Audit), I found a simple practice to define a simple auditing based on a condition for a table. Here are the steps:

prompt> sqlplus /nolog
SQL> conn / as sysdba
SQL> execute dbms_fga.add_policy('HR', 'EMPLOYEES', 'EMPDEPT_POLICY', 'department_id > 90');
SQL> analyze table hr.employees compute statistics;
SQL> conn hr/hr
SQL> select first_name from employees where department_id = 20;
SQL> select first_name from employees where department_id = 100;
SQL> select distinct deparment_id from employees;
SQL> conn / as sysdba
SQL> select timestamp#, obj$name, policyname, scn, lsqltext from fga_log$;
SQL> execute dbms_fga.drop_policy('HR', 'EMPLOYEES', 'EMPDEPT_POLICY');

Wednesday, August 22, 2007

Oracle for Beginner: A Simple Audit

$ sqlplus /nolog
SQL> conn / as sysdba
SQL> alter system set audit_trail=db scope=spfile;
SQL> shutdown immediate;
SQL> startup
SQL> conn / as sysdba
SQL> select name, value from v$parameter where name like 'audit%';
SQL> @$ORACLE_HOME/rdbms/admin/cataudit.sql
SQL> audit connect by budsus whenever not successful;
SQL> conn budsus/sdasdasd
SQL> conn budsus/xhsjd
SQL> conn / as sysdba
SQL> desc aud$;
SQL> select * from aud$;

SQL> grant select, insert, update on hr.departments to budsus;
SQL> Audit Update, Delete, Insert On hr.departments By Access Whenever Successful;
SQL> conn budsus/xxx
SQL> insert into hr.departments values (... ... );
SQL> conn / as sysdba
SQL> col comment$text format a20
SQL> select statement, timestamp#, userid, comment$text from aud$ where userid='BUDSUS'
SQL> select * from select * from dba_common_audit_trail;
SQL> noaudit update, delete, insert on hr.departments;

Saturday, August 18, 2007

Oracle for Beginner: Knowing your Linux Kernel Parameter for Oracle

If you want to know about how to install Oracle 10g on your Linux, there are some interesting articles that may be can help you to inform step by step installation. Here are some of those:
From those guides, before installation is started, there are some kernel parameters that have to be setup in /etc/sysctl.conf files. Here are from Oracle-Base:
kernel.shmall = 2097152
kernel.shmmax = 2147483648
kernel.shmmni = 4096
# semaphores: semmsl, semmns, semopm, semmni
kernel.sem = 250 32000 100 128
fs.file-max = 65536
kernel.shm* are parameters that is used to configure shared memory in Linux. Shared memory is a system resource that is used for interprocess communication. With this technique, two or more processes share a single chunk of memory to communicate between them. Shared memory is allocated in segments.
  • shmall : define the maximum amount of shared memory that may be in use at any time on the system.
  • shmmax : define the maximum size of each shared memory segment (max. value is 4GB).
  • shmmni : define the maximum number of shared memory segments on the system.
Semaphore is an important mechanism for controlling access to resources. Oracle instance use semaphore to control access to shared memory. Here is the kernel parameter which is used to configure the semaphore:
# semaphores: semmsl, semmns, semopm, semmni
kernel.sem = 250 32000 100 128
  • semmsl: maximum number of semaphores per set.
  • semmns : total number of semaphores in the system.
  • semopm : maximum number of operations per semop call.
  • semmni : maximum number of semaphore sets.
fs.file-max is a file handle parameter that determines the maximum number of files that each process can open. Default value is 8192 and the maximum value is 65536.

For more information, please refer to puschtz and dba-oracle.com .

Monday, August 06, 2007

System 7 Simulation

If you want to look and try an old Mac Operating System, i.e. System 7, you can visit WebSE. This simulation is very good. They create it using Flash. Very Interactive. You have to try it.

My New Book


This month, my newest book has been released (in Bahasa Indonesia). In this book, I wrote about Oracle10g XE Database basic administration and talk about how to build an application to access Oracle10g XE Database in four computer languages, i.e. Java, PHP, Ruby on Rails and Oracle Application Express. In this book, I explained about how to build a program that access a BLOB data type in OracleXE database. For more detail, please visit beranda budsus.

Sunday, August 05, 2007

Oracle for Beginner: Create External Table

In Oracle 10g, there is a data pump module that handle almost moving data from database Oracle to another database or external storage. Except data pump, there is a oracle loader that can be used to create and access an external data file (csv) as a regular table. In this article we will try to create an external table with data pump and oracle loader. This is a very simple thing that you can do easily in Oracle 10g.

First, we will try to create external table with Oracle data pump module :

$ sqlplus /nolog
SQL> conn / as sysdba
SQL> create directory mylab as 'your/data/path';
SQL> create table dept(department_name)
2 organization external
3 (
4 type ORACLE_DATAPUMP
5 DEFAULT DIRECTORY mylab
6 LOCATION ('ware.exp')
7 )
8 AS select distinct department_name from hr.departments;

SQL> select * from dept;

Next, in same manner, we can access an external csv as a regular table in Oracle database using Oracle Loader:
  • Create a csv file. For example we will create kota.dat with the following values:
  • Jakarta,DKI
    Surabaya,Jawa Timur
    Semarang,Jawa Tengah
    Yogyakarta,DIY
    Malang,Jawa Timur
    Bandung,Jawa Barat

  • login to your database as sysdba, create a directory object as a map for your data directory, and create an external table:
$ sqlplus /nolog
SQL> conn / as sysdba
SQL> create directory mydata as 'your/data/path';
SQL> create table kota(kota varchar(50), propinsi varchar(50))
2 organization external
3 (type oracle_loader default directory mydata
4 access parameters
5 ( records delimited by newline
6 badfile mydata:'kota%a_%p.bad'
7 logfile mydata:'kota%a_%p.log'
8 fields terminated by ','
9 missing field values are null
10 (kota, propinsi)
11 )
12 location ('kota.dat') );

SQL> select * from kota;

I hope you can find a new experience with Oracle Database.

Fixing vmware-config on FC7

I just want to share about vmware-config (vmware player) error fixing when I tried to run it on my FC7 with kernel 2.6.22.1-41. This discussion is very helpful for me. I just want to rewrite again in my blog, so if I forget about this, I can just visit this my note.
  • download the patch from here.
  • follow these instructions :
    • cd /usr/lib/vmware/modules/source
    • cp vmnet.tar vmnet.tar.orig
    • tar xvpf vmnet.tar
    • zcat yourdownloaddir/patch-vmnet-for-linux-2.6.22.1.gz | patch -p4
    • rm vmnet.tar; tar cvf vmnet.tar vmnet-only
  • run /usr/bin/vmware-config.pl again. Now, I can configure my vmware network modul on vmware player clearly.
It's good thing that vmware-player can run very well on my FC7. Thanks.

Sunday, July 29, 2007

Oracle for Beginner: Fine Grained Access (FGA)

SQL> conn / as sydba
SQL> alter system set Event="28131 trace name context forever" scope=spfile;
SQL> shutdown immediate;
SQL> startup
SQL> conn / as sysdba
SQL> show parameter event;
SQL> create user test identified by oracle;
SQL> grant connect, resource, create any context, administer database trigger to test;
SQL> grant execute on dbms_rls to test;
SQL> conn test/oracle
SQL> create table manager(dep_id number(3) primary key, nama_manajer varchar(30));
SQL> create table karyawan(dep_id number(3), nama_kary varchar(30), primary key(dep_id, nama_kary) );
SQL> insert into manager values (10, 'BUDSUS');
SQL> insert into manager values (20, 'HR');
SQL> commit;
SQL> insert into karyawan values (10, 'ANI');
SQL> insert into karyawan values (10, 'WATI');
SQL> insert into karyawan values (20, 'ANTOK');
SQL> commit;
SQL> create table orders(id number(4) primary key, dep_id number(3), tgl date, karyawan varchar(30) default user);
SQL> insert into orders values (1, 10, '01-AUG-07', 'ANI');
SQL> insert into orders values (2, 10, '02-AUG-07', 'ANI');
SQL> insert into orders values (3, 10, '02-AUG-07', 'WATI');
SQL> insert into orders values (4, 20, '02-AUG-07', 'ANTOK');
SQL>

Here is the procedure that will be called when a user login to the database:

create or replace procedure set_testapp_role(
p_user varchar2 default sys_context('userenv', 'session_user')) is

--parameter berisi username,
--jika tidak diberikan, username akan diambil dari sys_context()
--yang mengembalikan user session saat ini

--v_ctx menyimpan nama application context.
v_ctx varchar2(16) := 'testapp_ctx';

v_is_manajer number;
v_dep_id number;
v_is_kary number;

begin
--set variabel application context "username" dengan user yang diberikan
dbms_session.set_context(v_ctx, 'username', p_user);

select count(*) into v_is_manajer from test.manajer where nama_manajer=p_user;
select count(*) into v_is_kary from test.karyawan where nama_kary=p_user;

--jika user adalah TEST,
-- maka beri role APP_OWNER.

if (p_user=sys_context('userenv','current_schema')) then
dbms_session.set_context(v_ctx,'rolename','APP_OWNER');
elsif (v_is_manajer=1) then
--jika user manajer, beri role APP_ADMIN dan ambil
--dep_id

select dep_id into v_dep_id from manajer where nama_manajer=p_user;

dbms_session.set_context(v_ctx,'rolename','APP_ADMIN');
dbms_session.set_context(v_ctx,'depid',v_dep_id);

elsif (v_is_kary=1) then
--jika user karyawan, beri role APP_USER
dbms_session.set_context(v_ctx,'rolename','APP_USER');
else
--jika user tidak berwewenang
dbms_session.set_context(v_ctx,'rolename','NOT_AUTHORIZED');
end if;
end;
/

We have to create a context to save some global variables :

create or replace context testapp_ctx using set_testapp_role;
/

We will call set_testapp_role procedure for each time a user login to database. To make that thing can run, we have to create a trigger that will be run for each time a login happened:

create or replace trigger test_logon_trigger after logon on database
begin
set_testapp_role;
end;
/

Here is a function that will return a condition string for a user session. It's mean, when a user is login to database and want to access ORDERS table, the system will make a restriction for each query from the active user:

create or replace function testapp_security_function (
p_schema varchar2, p_object varchar2) return varchar2 is
begin
if (sys_context('testapp_ctx','rolename')='APP_OWNER') then
--tidak ada kondisi yang diberkan
return '';

elsif (sys_context('testapp_ctx','rolename')='APP_ADMIN') then
--kondisi query dibatasi untuk data-data departemen dimana
--user sekarang sebagai manajernya (APP_ADMIN)
return 'dep_id=sys_context(''testapp_ctx'',''depid'')';

elsif ( sys_context('testapp_ctx','rolename')='APP_USER') then
--untuk role APP_USER
return 'karyawan=sys_context(''testapp_ctx'',''username'') and '||
'dep_id = (select dep_id from test.karyawan ' ||
'where nama_kary=sys_context(''testapp_ctx'',''username''))';

else
--untuk NOT_AUTHORIZED
return '1=2';
end if;
end;
/

Then, we add a new security policy to implement FGA :

declare
begin
DBMS_RLS.ADD_POLICY (
object_schema => 'TEST',
object_name => 'ORDERS', policy_name => 'TESTAPP_POLICY',
function_schema => 'TEST',
policy_function => 'TESTAPP_SECURITY_FUNCTION',
statement_types => 'SELECT,UPDATE,INSERT,DELETE',
update_check => TRUE,
enable => TRUE,
static_policy => FALSE);
end;
/

Let's try our FGA example:

SQL> conn / as sysdba
SQL> create user budsus identified by oracle;
SQL> grant connect to budsus;
SQL> create user ani identified by oracle;
SQL> grant connect to ani;
SQL> conn test/oracle
SQL> grant select, update, delete, insert on orders to budsus;
SQL> grant select, update, delete, insert on orders to ani;

SQL> conn ani/oracle
SQL> select * from test.orders;

ID DEP_ID TGL KARYAWAN
---------- ---------- --------- ------------------------------
1 10 01-AUG-07 ANI
2 10 02-AUG-07 ANI

SQL> insert into test.orders values (10,20,'03-AUG-07','ANI');
insert into test.orders values (10,20,'03-AUG-07','ANI')
*
ERROR at line 1:
ORA-28115: policy with check option violation
SQL> insert into test.orders values (10,10,'03-AUG-07','ANI');

1 row created.

SQL> conn budsus/oracle
Connected.
SQL> select * from test.orders;

ID DEP_ID TGL KARYAWAN
---------- ---------- --------- ------------------------------
1 10 01-AUG-07 ANI
2 10 02-AUG-07 ANI
3 10 02-AUG-07 WATI
10 10 03-AUG-07 ANI

Thursday, July 26, 2007

Oracle for Beginner: 'Snapshot too old' a simple practice

In Oracle, there is a undo tablespace (is controlled by undo_tablespace parameter) that is used by oracle to store old image of updated rows. With this tablespace, you can rollback to cancel the transaction. In a undo tablespace, there are some undo segments that is controlled by oracle automatically (it is recommended that undo_management init parameter has value AUTO). For each old row images will be retained at undo segment for 900 seconds (undo_retention parameter), after that the block for old images can be overwritten by another old row images. If the undo tablespace is too small to retain old row images, sometime you will get an error that will tell you about there is no enough space for undo data. Here is an example of that error:

ORA-30036: unable to extend segment by 8 in undo tablespace 'UNDOTBS_2'

The "snapshot too old" error can be happen if some old row images, that is used by another query for read consistency, have been overwritten. In this article, from another resources too, I would like to share about a simple practice to help us to understand about this error.

$ sqlplus /nolog
SQL> conn / as sysdba
SQL> create undo tablespace undotbs_2 datafile size 1M;

Tablespace created.

SQL> alter system set undo_tablespace='UNDOTBS_2';

System altered.

SQL> create user budsus identified by oracle quota 10M on users;
SQL> grant connect, create table, create any index to budsus;

Grant succeeded.
SQL> conn budsus/oracle
Connected.
SQL> create table siswa (id number(5), nama varchar(100));

SQL> create table dump(tmp varchar(100));

SQL> begin
2 for i in 1..5000 loop
3 insert into siswa values (i, 'siswa terbaru ' || i);
4 if mod(i, 100) = 0 then
5 insert into dump values ('teeeeeeeemmmmmmmmmppppppppp');
6 commit;
7 end if;
8 end loop;
9 commit;
10 end;

SQL> declare
2 cursor crs_siswa is select rowid, siswa.* from siswa where id < 250;
3 begin
4 for v_siswa in crs_siswa loop
5 update dump set tmp = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
6 update dump set tmp = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
7 update dump set tmp = 'ccccccccccccccccccccccccccccc';
8 update siswa set nama = 'siswa terupdate ' || v_siswa.id where v_siswa.rowid = rowid;
9 commit;
10 end loop;
11 end;
12 /
...
ORA-01555: snapshot too old: rollback segment number 15 with name "_SYSSMU15$" too small

SQL> conn / as sysdba;
SQL> alter system set undo_tablespace='UNDOTBS1';
SQL> drop tablespace undotbs_2;
SQL> drop table siswa;
SQL> drop table dump;
SQL> quit

Thanks.