Hi Connor,
Thanks for your answer. As a bit of background, the problem is basically that there are two independent processes going on. One periodically polls the database and broadcasts any changes it finds. The other generates data snapshots on demand in order to provide an initial view, after which it can start listening to the stream of updates. Due to the asynchronous nature of these operations, there is a small chance of the results being delivered to the client out of order. Without attaching some kind of version number to the data I've got no way of saying which one is more up-to-date.
My initial thought was to take the maximum value of ora_rowscn for the set of rows I'm interested in as the version number, but it's possible for rows to be deleted from that set, so that max value would either not change or go backwards in that case.
Regarding your answer, while working through it I spotted the start_scnb and start_scnw columns in v$transaction. In my test this gave the same number as flashback_transaction_query.start_scn. Is there any reason I should use the value from flashback_transaction_query instead of v$transaction? It seems preferable to me to use v$transaction because I can query it from within the transaction itself.
As far as I can tell, the transaction start SCN is not exactly correlated to the serializable snapshot. Take the following example with two interleaved sessions.
Session 1 - Start the transaction. This is the point at which the 'snapshot' is generated.
SQL> set transaction isolation level serializable;
Transaction set.
Session 2 - Update the row, commit and exit.
SQL> set transaction isolation level serializable;
Transaction set.
SQL> update foo set value = 1;
1 row updated.
SQL> commit;
Commit complete.
SQL> select value, ora_rowscn from foo;
VALUE ORA_ROWSCN
---------- ----------
1 1896777079
SQL> exit
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
The row SCN of this update is 1896777079, so the snapshot SCN in session 1 must be less than this value.
Session 1 - Select from dbms_transaction to force it to create an entry in v$transaction.
SQL> select dbms_transaction.local_transaction_id from dual;
LOCAL_TRANSACTION_ID
--------------------------------------------------------------------------------
4.0.570818
Session 1 - Select from the test table. This is still showing the original value, unaffected by the change in session 2.
SQL> select value, ora_rowscn from foo;
VALUE ORA_ROWSCN
---------- ----------
0 1896776073
Session 1 - Select from v$transaction. The start SCN here is 1896777463. This is greater than the ora_rowscn we saw from session 2, so this cannot be the snapshot SCN because we have already seen that the change from session 2 is not visible.
SQL> select start_scnb, start_scnw from v$transaction;
START_SCNB START_SCNW
---------- ----------
1896777463 0
Note I also tried this using flashback_transaction_query and saw the same behaviour.
I guess this approach is probably not viable. I think I'm going to need to explicitly version data within the database. E.g., attach a trigger to the table of interest and every time something changes, increment a version number stored in a separate table.