Skip to Main Content

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Mike.

Asked: March 13, 2001 - 10:06 am UTC

Last updated: January 15, 2016 - 2:14 am UTC

Version: 8.1.7

Viewed 1000+ times

You Asked

There is a table named t_state, I created a snapshot log for it (see below). I'd like to know what the column change_vector$$ is.

SQLWKS> desc MLOG$_T_STATE
Column Name Null? Type
------------------------------ -------- ----
COUNTRY VARCHAR2(3)
STATE VARCHAR2(4)
SNAPTIME$$ DATE
DMLTYPE$$ VARCHAR2(1)
OLD_NEW$$ VARCHAR2(1)
CHANGE_VECTOR$$ RAW(255)

--------------
What I did here is insert a row and then update it.

SQLWKS> select * from MLOG$_T_STATE
2>
COU STAT SNAPTIME$ D O CHANGE_VECTOR$$
tst MF 01-JAN-00 I N FE
tst MF 01-JAN-00 D O 00
tst MR 01-JAN-00 I N FF
3 rows selected.

Thanks


and Tom said...

It is a change vector describing what columns have been modified. The size of the vector is a function of the number of columns. If you goto:
</code> http://asktom.oracle.com/~tkyte/hexdec/index.html <code>
I have a base conversion routine there, usful for dumping the binary format of the vector.

consider this example. I update each column in turn and fetch out the vector and display it. It can be used to see which columns were updated:

ops$tkyte@DEV816> create table t
2 ( x int primary key,
3 c0 int, c1 int, c2 int, c3 int, c4 int,
4 c5 int, c6 int, c7 int, c8 int, c9 int,
5 c10 int, c11 int, c12 int, c13 int, c14 int,
6 c15 int, c16 int, c17 int, c18 int, c19 int );

Table created.

ops$tkyte@DEV816>
ops$tkyte@DEV816> insert into t(x) values ( 1);

1 row created.

ops$tkyte@DEV816>
ops$tkyte@DEV816> create snapshot log on t;

Materialized view log created.

ops$tkyte@DEV816> set serveroutput on format wrapped;
ops$tkyte@DEV816> declare
2 l_str varchar2(255);
3 begin
4 for i in 0 .. 19
5 loop
6 execute immediate
7 'update t set c' || i || ' = 1';
8
9 select change_vector$$ into l_str
10 from mlog$_t;
11
12 dbms_output.put_line
13 ( to_char(i,'99') || ' = ' || l_str || ' ' ||
14 lpad(to_bin( to_number(l_str,'xxxxxx') ),32,'0') );
15 delete from mlog$_t;
16 end loop;
17 update t set c1 = 2, c4 = 3, c10 = 12, c11 = 2, c18=0;
18 select change_vector$$ into l_str
19 from mlog$_t;
20
21 dbms_output.put_line
22 ( to_char(0,'99') || ' = ' || l_str || ' ' ||
23 lpad(to_bin( to_number(l_str,'xxxxxx') ),32,'0') );
24 end;
25 /
0 = 040000 00000000000001000000000000000000
1 = 080000 00000000000010000000000000000000
2 = 100000 00000000000100000000000000000000
3 = 200000 00000000001000000000000000000000
4 = 400000 00000000010000000000000000000000
5 = 800000 00000000100000000000000000000000
6 = 000100 00000000000000000000000100000000
7 = 000200 00000000000000000000001000000000
8 = 000400 00000000000000000000010000000000
9 = 000800 00000000000000000000100000000000
10 = 001000 00000000000000000001000000000000
11 = 002000 00000000000000000010000000000000
12 = 004000 00000000000000000100000000000000
13 = 008000 00000000000000001000000000000000
14 = 000001 00000000000000000000000000000001
15 = 000002 00000000000000000000000000000010
16 = 000004 00000000000000000000000000000100
17 = 000008 00000000000000000000000000001000
18 = 000010 00000000000000000000000000010000
19 = 000020 00000000000000000000000000100000
0 = 483010 00000000010010000011000000010000

PL/SQL procedure successfully completed.


Rating

  (5 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Problem on snapshot log

Eka, June 16, 2003 - 11:39 pm UTC

Tom, thanks for answering my previous questions. You are very helpful.
I have some problem with snapshot log. I try to search on your site but i can't found similar problem.
I experienced this a couple times : when i update a table, the snapshot logs for that table is not updated.
for example, i update table invoice, but when i query mlog$_invoice, it shows no rows. Not every table behave like that.
To solve the problem, i should drop snapshot log, recreate it again, and doing a complete refresh on the snapshot site.
Tom, how can that happen? and how i prevent it so it won't happen again?
Thank you very much.

Tom Kyte
June 17, 2003 - 7:22 am UTC

umm, have you noticed that the target table isn't getting the updates -- if so, file a bug (that would be a bug). If not -- if the changes always get made, let it be.

You are looking at the logs, did you look at the real snapshots and see if they got the changes or not. if they did not, please file a bug.

did you commit?

Reader, June 17, 2003 - 8:56 am UTC

Please make sure that your transaction commits only then snapshot log will have entries. I am sure you would have checked.

problem with snapshot log

Eka, June 18, 2003 - 1:15 am UTC

The real snapshot was not updated. Actually, i found this problem because my report which running on snapshot site showed old data (not up to date). Then i tried to do an update on master table and i found that snapshot log still showed empty rows, even when i commit the update.
All tables in the same master replication group behave this way, but another tables belong to another master replication group are fine.
Unfortunately, i can not reproduce this error, it happens eventually, and rarely. I recall it happen three times since i setup snapshot replication, a couple months ago.

More on change_vector$$

Carsten, May 02, 2008 - 10:32 am UTC

Although the mapping of the bit field to columns is not documentated (and therefor this shouldn't be used in any production code), with some try and error you will see that:

select mt.x, DMLTYPE$$, uc.column_name
from mlog$_t mt, user_tab_cols uc
where uc.table_name='T'
and bitand(to_number(regexp_replace(change_vector$$,'^(..)(..)?(..)?(..)?(..)?(..)?(..)?(..)?$','\8\7\6\5\4\3\2\1'),'xxxxxxxxxxxxxx'),power(2,uc.internal_column_id))+0>0

will display the column names that have been changed (tested with 10.2.0.1.0 and 10.2.0.2.0).
The bytes are in little endian order (lowest first), that is why I am using a regex_replace to turn them around, which will only work for 63 column tables...so there might be a better way to evaluate this.

Anyway, it was useful for me to trace some table changes without writing my own trigger with lots of "if :old.columnname!=:new.columnname"





More on change_vector$$

MichaƂ Kaczmarczyk, January 14, 2016 - 6:59 pm UTC

The following query gives which columns were modified in the table according to the entry in snapshot log. Should work also when there are more than 63 columns, although the method is still undocumented.

select mt.x, DMLTYPE$$, uc.column_name
from mlog$_t mt, user_tab_cols uc
where uc.table_name='T'
and bitand(to_number(substr(change_vector$$,1+2*trunc(uc.internal_column_id/8),2),'xx'),power(2,mod(uc.internal_column_id,8))) > 0
Chris Saxon
January 15, 2016 - 2:14 am UTC

Thanks for the input, although our standard disclaimer - we might change (no pun intended) the change_vector$$ from release to release for whatever reasons we may think of :-)

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library