This is my 13 post. So I’ve decided to make some digression. Usually number 13 is considered as unhappy. It seems not a rule for me. This year 13 is my happy number. On 13th January I’ve signed new job contract. It was just about 13:15 (or might be it was exactly at 13:13). What is more interesting, sum of digits in that date (13-01-2006) is equal to 13 (1+3+0+1+2+0+0+6=13). Number of building I’m now working in is also 13. As for now I’m quite happy in my new job.
Also according to Walter Schneider 13 is definitely happy number. I’ve observed that for me the unhappiest day in month is 26th. In fact it is 2*13. When I use Walters method to it gives me: 26 => 40 (2*2+6*6) => 16 => 37 => 58 => 89 => 145 => 42 => 20 => 4. So 26 is unhappy number and it confirms my observations :).
More on Happy Numbers in Wikipedia.
Cheers, Paweł
Search Oracle Blogs
Saturday, September 30, 2006
Flashback Table and Materialized View – not working together
I must say that I like Flashback features very much. This is very useful option and should be used more often. But sometimes you might hit some obstacles. One of them is Materialized view. When You want to issue FLASHBACK TABLE statement on table that has materialized view it does not work.
Lets try:
Lets try:
SQL> create table a_fb 2 (id number primary key, text char(200)) enable row movement; Table created. SQL> create materialized view log on a_fb with rowid; Materialized view log created.Now insert some data:
SQL> insert into a_fb select object_id, object_name 2 from all_objects where rownum <= 100; 100 rows created. SQL> commit; Commit complete. SQL> select sys.dbms_flashback.get_system_change_number, 2 min(id), max(id), count(*) 3 from a_fb; GET_SYSTEM_CHANGE_NUMBER MIN(ID) MAX(ID) COUNT(*) ------------------------ ---------- ---------- ---------- 568668 258 1069 100ok. Lets insert more data and then try to flashback to above SCN.
SQL> insert into a_fb select object_id, object_name 2 from all_objects where rownum <= 100 3 and object_id not in(select id from a_fb); 100 rows created. SQL> commit; Commit complete. SQL> select sys.dbms_flashback.get_system_change_number, 2 min(id), max(id), count(*) 3 from a_fb; GET_SYSTEM_CHANGE_NUMBER MIN(ID) MAX(ID) COUNT(*) ------------------------ ---------- ---------- ---------- 568704 258 1257 200And now flashback:
SQL> flashback table a_fb to scn 568668; Flashback complete.It seems that Materialized view log is not a problem. Moreover when FLASHBACK TABLE is executed new rows are inserted to Materialized view log. You can check it issuing this select:
select count(*) from MLOG$_A_FB;Now lets try to create materialized view
SQL> create materialized view a_fb_mv 2 REFRESH FAST ON COMMIT with rowid 3 as 4 select id, text, rowid a_rowid from a_fb; Materialized view created. SQL> select sys.dbms_flashback.get_system_change_number, 2 min(id), max(id), count(*) 3 from a_fb; GET_SYSTEM_CHANGE_NUMBER MIN(ID) MAX(ID) COUNT(*) ------------------------ ---------- ---------- ---------- 568852 258 1069 100Lets add some data and roll back to that SCN
SQL> insert into a_fb select object_id, object_name 2 from all_objects where rownum <= 100 3 and object_id not in(select id from a_fb); 100 rows created. SQL> commit; Commit complete. SQL> select sys.dbms_flashback.get_system_change_number, 2 min(id), max(id), count(*) 3 from a_fb; GET_SYSTEM_CHANGE_NUMBER MIN(ID) MAX(ID) COUNT(*) ------------------------ ---------- ---------- ---------- 568893 258 1257 200Lets see what we have in Materialized view:
SQL> select sys.dbms_flashback.get_system_change_number, 2 min(id), max(id), count(*) 3 from a_fb_mv; GET_SYSTEM_CHANGE_NUMBER MIN(ID) MAX(ID) COUNT(*) ------------------------ ---------- ---------- ---------- 568895 258 1257 200
Problem
Try to flashback:SQL> flashback table a_fb to scn 568852; flashback table a_fb to scn 568852 * ERROR at line 1: ORA-08194: Flashback Table operation is not allowed on materialized viewsYou cannot flashback table if there is materialized view defined on it. But materialized view log is not a problem. I must say that I do not see any reason for that. If materialized view log is generated during flashback operation why materialized view is not updated according to that log?
Workaround
This is quite simple. You just have to drop materialized view and issue flashback table statement:SQL> drop materialized view a_fb_mv; Materialized view dropped. SQL> flashback table a_fb to scn 568852; Flashback complete. SQL> select sys.dbms_flashback.get_system_change_number, 2 min(id), max(id), count(*) 3 from a_fb; GET_SYSTEM_CHANGE_NUMBER MIN(ID) MAX(ID) COUNT(*) ------------------------ ---------- ---------- ---------- 569009 258 1069 100Now you need only to recreate dropped materialized view.
Related articles:
Thursday, September 21, 2006
ORA_ROWSCN continuation…
In my previous post I was wondering how SCN is assigned to ROW or Block. I couldn’t find explanation in Oracle Documentation. But I’ve found this document written by Jonathan Lewis. You should read this! I’m little afraid about 'best guess' technology.
By the way you can also read article about undocumented userenv('commitscn') written in May 1999. When I first saw it I thought it might be replaced by ORA_ROWSCN.
So I’ve try this:
If You have some spare time, I recommend to read this post: Is it crazy to feel guilty about success? and from Eddie Awad blog: SYS_OP_MAP_NONNULL, REVERSE, LNNVL, NVL, NVL2, COALESCE
Cheers, Paweł
By the way you can also read article about undocumented userenv('commitscn') written in May 1999. When I first saw it I thought it might be replaced by ORA_ROWSCN.
So I’ve try this:
SQL> create table t (n1 number, text varchar2(10)) ROWDEPENDENCIES; Table created. SQL> insert into t values (userenv('commitscn'), 'T1'); 1 row created. SQL> select ora_rowscn, n1 commitscn, text from t; ORA_ROWSCN COMMITSCN TEXT ---------- ---------- ---------- 4621851 T1 SQL> declare 2 pragma autonomous_transaction; 3 begin 4 insert into t values (userenv('commitscn'), 'TAuto'); 5 commit; 6 end; 7 / PL/SQL procedure successfully completed. SQL> select ora_rowscn, n1 commitscn, text from t; ORA_ROWSCN COMMITSCN TEXT ---------- ---------- ---------- 4621851 T1 4621852 4621851 TAuto SQL> commit; Commit complete. SQL> select ora_rowscn, n1 commitscn, text from t; ORA_ROWSCN COMMITSCN TEXT ---------- ---------- ---------- 4621854 4621853 T1 4621852 4621851 TAutoSo for sure ORA_ROWSCN and userenv('commitscn') is not the same. I must say that I’m even more confused.
If You have some spare time, I recommend to read this post: Is it crazy to feel guilty about success? and from Eddie Awad blog: SYS_OP_MAP_NONNULL, REVERSE, LNNVL, NVL, NVL2, COALESCE
Cheers, Paweł
Sunday, September 17, 2006
ORA_ROWSCN behavior: bug or feature?
ORA_ROWSCN is pseudo column that gives SCN (System Change Number) for transaction that was modifying record. Lets take a closer look. First create table:
Now lets take a look what will happen for table with ROWDEPENDENCIES on.
What about Index Organized Tables:
2. We can see that SCN is assigned at commit. Does commit tackles all blocks modified by transaction? For short transaction it is not a problem, as blocks probably are still in buffer. But large transactions that generate lot of redo, and there are few check points during transaction time should not change this blocks. That means that block should have only transaction id, and oracle translates this transaction id to SCN.
Cheers, Paweł
CREATE TABLE A_TABLE (ID NUMBER, TEXT CHAR(2000));Then feed table with some data:
SQL> declare 2 procedure auto_commit 3 is pragma autonomous_transaction; 4 begin commit; end; 5 begin 6 for i in 1..10 loop 7 insert into a_table select rownum, rownum from dual connect by level <=10; 8 auto_commit; 9 end loop; 10 end; 11 /Procedure auto_commit is used to force change of SCN. Take a look what we have in table:
SQL> select ora_rowscn, count(*) from a_table 2 group by ora_rowscn; ORA_ROWSCN COUNT(*) ---------- ---------- 4589308 24 4589313 16 4589293 15 4589297 24 4589302 21We ran INSERT statement 10 times and we get 5 different SCN’s in table. None of them has exactly 10 rows. This is because table was created with default setting: NOROWDEPENDENCIES, and SCN is kept on block level. Every and each row in block has the same SCN. Lets commit this transaction:
SQL> commit; Commit complete. SQL> select ora_rowscn, count(*) from a_table 2 group by ora_rowscn; ORA_ROWSCN COUNT(*) ---------- ---------- 4589363 100Now all rows haveexactly the same SCN.
Now lets take a look what will happen for table with ROWDEPENDENCIES on.
CREATE TABLE A_TABLE_ROW (ID NUMBER, TEXT CHAR(2000)) ROWDEPENDENCIES;Insert some data:
SQL> declare 2 procedure auto_commit 3 is pragma autonomous_transaction; 4 begin commit; end; 5 begin 6 for i in 1..10 loop 7 insert into A_TABLE_ROW select rownum, rownum from dual connect by level <=10; 8 auto_commit; 9 end loop; 10 end; 11 /Query table:
SQL> select ora_rowscn, count(*) from A_TABLE_ROW 2 group by ora_rowscn; ORA_ROWSCN COUNT(*) ---------- ---------- 100Now ORA_ROWSCN is NULL for uncommitted transaction. This is very interesting.
SQL> commit; Commit complete. SQL> select ora_rowscn, count(*) from A_TABLE_ROW 2 group by ora_rowscn; ORA_ROWSCN COUNT(*) ---------- ---------- 4590773 100What will happen when updating:
SQL> update A_TABLE_ROW set id = id where rownum <20; 19 rows updated. SQL> select ora_rowscn, count(*) from A_TABLE_ROW 2 group by ora_rowscn; ORA_ROWSCN COUNT(*) ---------- ---------- 19 4590773 81We can conclude that data in active transaction have NULL ORA_ROWSCN for tables with ROWDEPENDENCY.
What about Index Organized Tables:
CREATE TABLE A_TABLE_IOT (ID NUMBER primary key, TEXT CHAR(2000)) organization index;Generate data:
SQL> declare 2 procedure auto_commit 3 is pragma autonomous_transaction; 4 begin commit; end; 5 begin 6 for i in 1..10 loop 7 insert into A_TABLE_IOT select i*10+rownum, rownum from dual connect by level <=10; 8 auto_commit; 9 end loop; 10 end; 11 / PL/SQL procedure successfully completed. SQL> select ora_rowscn, count(*) from A_TABLE_IOT 2 group by ora_rowscn; ORA_ROWSCN COUNT(*) ---------- ---------- 100For IOT with NOROWDEPENDENCIES we still get NULLs for ORA_ROWSCN.
Questions:
1. Why we have such differences in implementation of ORA_ROWSCN?2. We can see that SCN is assigned at commit. Does commit tackles all blocks modified by transaction? For short transaction it is not a problem, as blocks probably are still in buffer. But large transactions that generate lot of redo, and there are few check points during transaction time should not change this blocks. That means that block should have only transaction id, and oracle translates this transaction id to SCN.
Cheers, Paweł
Thursday, September 14, 2006
Avoiding Deadlocks: SKIP LOCKED
After reading Tim's article on Deadlocks, I've recalled solution that can help avoid deadlocks in some situations.
Assume that in our application we have to choose few (say 5) documents from pool to assign to users for processing. Usually we can use just update statement like that:
Cheers, Paweł
Assume that in our application we have to choose few (say 5) documents from pool to assign to users for processing. Usually we can use just update statement like that:
UPDATE documents SET doc_state = 'ASSIGNED', doc_user = USER WHERE doc_state = 'TO PROCESS' AND rownum <= 5;But this can cause some waits in highly loaded environments where this statement is run often. To overcome that we can use SKIP LOCKED clause:
BEGIN FOR r IN (SELECT id FROM documents WHERE doc_state = 'TO PROCESS' AND rownum <= 5 FOR UPDATE SKIP LOCKED) LOOP UPDATE documents SET doc_state = 'ASSIGNED', doc_user = USER WHERE id = r.id; END LOOP; END;In this statement we do not suffer from waits, and we get up to 5 rows assigned to current user.
Cheers, Paweł
Wednesday, September 13, 2006
Binary Days
As addition to may previous post lets see other Binary days, where day number is power of 2.
BTW. Does anybody know if is it possible to turn off these automatic <br /> tags in beta blogger?
Paweł
SQL> select rownum-1 power_of2 2 , to_char(trunc(sysdate,'YYYY')-1+power(2,rownum-1), 3 'DD-MON-YYYY DAY') magic_day 4 from dual connect by level <=9; POWER_OF2 MAGIC_DAY ---------- --------------------------------------------------------- 0 01-JAN-2006 SUNDAY 1 02-JAN-2006 MONDAY 2 04-JAN-2006 WEDNESDAY 3 08-JAN-2006 SUNDAY 4 16-JAN-2006 MONDAY 5 01-FEB-2006 WEDNESDAY 6 05-MAR-2006 SUNDAY 7 08-MAY-2006 MONDAY 8 13-SEP-2006 WEDNESDAY 9 rows selected.Interesting coincidence - there are only 3 days of week: SUNDAY, MONDAY and WEDNESDAY.
BTW. Does anybody know if is it possible to turn off these automatic <br /> tags in beta blogger?
Paweł
Tuesday, September 12, 2006
Row Generators
You probably now all these methods to generate rows.
I've decided to choose the best method.
My criterias are:
My Results, all times in seconds
Cheers, Paweł
- Maximum Speed
- Without limitations
- Easy of use
declare v_start_time timestamp; v_end_time timestamp; v_max_number integer; v_max_gen integer; begin v_max_number := 1000; v_max_gen := 0; v_start_time := systimestamp; for r in (QUERY_HERE) loop v_max_gen := r.r; end loop; v_end_time := systimestamp; dbms_output.put_line('Max gen = '||v_max_gen); dbms_output.put_line('Time = '||(v_end_time-v_start_time)); end;Where QUERY_HERE was one of:
ALL_OBJECTS | select rownum r from all_objects where rownum <= v_max_number |
2*ALL_OBJECTS | select rownum r from all_objects, all_objects where rownum <= v_max_number |
group by cube | select rownum r from (select 1 from dual group by cube(1,2,3,4,5,6,7,8,9,10,11,12,13,14)) where rownum <= v_max_number |
level | select level r from dual connect by level <= v_max_number |
PL/SQL Function | select rownum r from table(rowgen(v_max_number)) |
where function was created using:
CREATE OR REPLACE TYPE numtab_type IS TABLE OF NUMBER; CREATE or replace FUNCTION rowgen(pin_nor IN NUMBER) RETURN numtab_type DETERMINISTIC PIPELINED AS BEGIN FOR i IN 1..pin_nor LOOP PIPE ROW(i); END LOOP; RETURN; END rowgen; / |
Method/Rows | 1000 rows | 10000 rows | 1000000 rows | Comment |
ALL_OBJECTS | 0.1 | (*) | (*) | (*) only 5292 rows generated. We cannot generate big number of rows |
2*ALL_OBJECTS | 0.2 | 0.7 | 66.2 | |
group by cube | 0 | 0.1 | > 5 min | Number of elements in cube clause vary on how big numbers we want get. For big numbers it is slow and not flexible in setting. |
level | 0 | 0.1 | 2.8 | |
PL/SQL Function | 0 | 0.1 | 2.2 | We have to create Type and Function |
Conclusion
If we consider speed, we should use one of two methods: level or PL/SQL Function. When we also consider the Easy of use we have only one solution select level r from dual connect by level <= v_max_numberCheers, Paweł
Sunday, September 10, 2006
Kubica 3rd in F1 race
Well Done
Polish driver Robert Kubica in his 3rd race in Formula 1 took 3rd place on Monza in Italy. This is really BIG SUCCESS as he is driving Formula 1 car for few weeks in races only.
Well done Robert. Keep it that way...
Polish driver Robert Kubica in his 3rd race in Formula 1 took 3rd place on Monza in Italy. This is really BIG SUCCESS as he is driving Formula 1 car for few weeks in races only.
Well done Robert. Keep it that way...
Rolling Back the DDL
Assume You were asked if You can rollback changes in tables in Oracle database, You would answer that it is not possible. DDL always makes commit before and after statement.
But wait a minute: there is solution for that. In 10g we have Flashback feature. This feature can be extremely useful when you are running application patch on database.
You can use this scenario:
Moreover you can use Restore Point while upgrading database 10g R1 to 10g R2. It can be very time saving in case of failure during upgrade process.
Restore Points can be also usefull in application testing process. You can define restore point, run test procedures, save results, restore to to saveponit and test again ...
To check if that you have set restore point you can run query:
Cheers, Paweł
- issue command to set restore point:
CREATE RESTORE POINT before_patch GUARANTEE FLASHBACK DATABASE;
- apply application patch
- test system after patch
- if ok, release restore point:
DROP RESTORE POINT before_patch;
- if something go wrong, flashback to restore point:
SHUTDOWN DATABASE; STARTUP MOUNT; FLASHBACK DATABASE TO RESTORE POINT before_patch;
Moreover you can use Restore Point while upgrading database 10g R1 to 10g R2. It can be very time saving in case of failure during upgrade process.
Restore Points can be also usefull in application testing process. You can define restore point, run test procedures, save results, restore to to saveponit and test again ...
To check if that you have set restore point you can run query:
select * from v$restore_point;Hope you will find it useful,
Cheers, Paweł
Related articles:
Wednesday, September 06, 2006
Visual SourceSafe - Invalid DOS Path
I hate wrong error messages. I hate messages that lead me in wrong direction. Yesterday I've spend too much time on resolving problem with VSS. I had to add new user to VSS. Pretty simple task.
I've started and bang: "Invalid DOS PATH \\server\vss\project\users"
I've checked path - it's OK.
Double checked. Again the same error.
I've checked my privileges - Full access.
I've made local copy of VSS repository - still the same problem.
It's time to search for solution on Internet.
Few click, and I've got it: no template.ini file in \\server\vss\project\users catalog.
So, I've copied ss.ini of one user to template.ini, removed unneeded lines, and task completed.
Full description of solution.
Whenever you are programming, please, make sure that error messages are meaningful to users. Try to give as many details as possible, it will help to solve problem.
Cheers, Paweł
I've started and bang: "Invalid DOS PATH \\server\vss\project\users"
I've checked path - it's OK.
Double checked. Again the same error.
I've checked my privileges - Full access.
I've made local copy of VSS repository - still the same problem.
It's time to search for solution on Internet.
Few click, and I've got it: no template.ini file in \\server\vss\project\users catalog.
So, I've copied ss.ini of one user to template.ini, removed unneeded lines, and task completed.
Full description of solution.
Whenever you are programming, please, make sure that error messages are meaningful to users. Try to give as many details as possible, it will help to solve problem.
Cheers, Paweł
Sunday, September 03, 2006
Successful Programmer
At begging I would propose to read 7 Secrets of Successful programmers. I agree with all those suggestions. I would only change order:
Cheers, Paweł
- Expect the unexpected and deal with it
- Scope functions and variables appropriately
- Keep your functions and subroutines simple
- Layout code to increase legibility
- Name your variables to aid readability
- Code for human consumption
- Comment often and comment well
Cheers, Paweł
About Blog and Me
Hi All Readers!
I'm a Software Engineer with many years of experience in developing computer software. I'm mostly working on software that uses Database Systems. In past I was using dBase and Clipper. Since 1996 it is Oracle. I was working on all version since Oracle 7.3 and on many platforms: Novel, Sun Solaris, IBM AIX, Compaq Tru64, Windows.
On this blog I want to share my knowledge and experience with all visitors. I hope You will find some interesting and useful topics here. I'll be writing about my current problems and solutions, tricks I use in everyday work, bugs and workarounds, and thinks that are interesting to me, and You might find interesting too.
Cheers, Paweł
Subscribe to:
Posts (Atom)