ORA-01555: snapshot too old: rollback segment number with name "" too smal

從客戶那兒報來個問題,說是日誌中顯示,在執行一個sql時拋出 error info 如下:
java.sql.SQLException: ORA-01555: snapshot too old: rollback segment number 2 with name "_SYSSMU2$"
too small


搜索了一下,總算是對這個error有了一點點了解。下面是一篇介紹 ORA-01555 的文章:


Oracle 讀一致及塊清除的內部機制(read consistency and block cleanouts)
Oracle always enforces statement-level read consistency. This guarantees that the data returned by a single query is consistent with respect to time when the query began. Therefore, a query never sees the data-changes made by transactions that commit during the course of execution of the query.
Oracle uniquely identifies any given point in time by a set of numbers called the System Change Numbers (SCN). So SCN can be defined as the state of the database at any one given point in time. To produce read-consistency, Oracle marks the current SCN as the query enters the execution phase. The query can only see the snapshot of the records as they were at the time of marked SCN.
Oracle uses rollback segments to reconstruct the read-consistent snapshot of the data. Whenever a transaction makes any changes, a snapshot of the record before the changes were made is copied to a rollback segment and the data block header is marked appropriately with the address of the rollback segment block where the changes are recorded. The data block also maintains the SCN of the last committed change to the block.
[ Oracle 爲保證讀一致性,一個查詢語句在執行過程中數據是從 snapshot 取的,從而忽略查詢執行過程中其他事務對數據的修改。而 snapshot 是在回滾段中管理的。每當有事務修改了一些數據,DB就會將這些修改前的數據快照存在回滾段data block中。]


ORA-01555 的產生原因及解決方法 
As the data blocks are read on behalf of the query, only blocks with lower SCN than the query SCN will be read. If a block has uncommitted changes of other transactions or changed data with more recent SCN, then the data is reconstructed using the saved snapshot from the rollback segments. In some rare situations, if RDBMS is not able to reconstruct the snapshot for a long running query, the query results in an ORA-01555 error.
[ 查詢每次只讀取回滾段中比自己的SCN號(查詢開始時賦予)小的數據塊(這些塊在查詢執行過程中沒有被修改過)。如果其中某個數據塊的數據被修改了(SCN號大),則回滾段中的相應快照需要重建。在某種情況下,如果某個查詢執行時間過長導致快照重建失敗,就會發生ORA-01555錯誤????(啥意思)


A rollback segment maintains the snapshot of the changed data as long as the transaction is still active (commit or rollback has not been issued). Once a transaction is committed, RDBMS marks it with current SCN and the space used by the snapshot becomes available for reuse. 
[ 事務 inactive 後,snapshot 所在的空間被釋放(可以被覆蓋)。???那豈不是說如果某些數據在查詢時被其他事務修改了,就會有ora-01555的問題???
不過,DB中有一個參數(UNDO_RETENTION)可以指定 snapshot 維持的時間,如果查詢執行時間超過這個參數,且當前回滾段不夠用,snapshot 所在的空間也會被佔用。 ]


Therefore, ORA-01555 will result if the query is looking for the snapshot which is so old that rollback segment information could not be found because of wrap around or overwrite.
[ 就是說,導致ORA-01555的原因其實就是:快照在該查詢執行過程中被修改了(清除或者覆蓋)。 ]


SITUATIONS WHERE ORA-01555 ERRORS COMMONLY OCCUR:
1. Fewer and smaller rollback segments for a very actively changing database
If the database has many transactions changing data and commiting very often, then the chance of reusing the space used by a committed transaction is higher. A long running query then may not be able to reconstruct the snapshot due to wrap around and overwrite in rollback segments. Larger rollback segments in this case will reduce the chance of reusing the committed transaction slots.


2. Corrupted rollback segment
If the rollback segment is corrupted and could not be read, then a statement needing to reconstruct a before image snapshot will result in the error.


3. Fetch across commit
This is the situation when a query opens a cursor, then loops through fetching, changing, and committing the records on the same table. In this scenerio, very often an ORA-01555 can result. 
Let's take the following example to explain this:
A cursor was opened at SCN=10. The execution SCN of the query is then marked as SCN=10. Every fetch by that cursor now needs to get the read-consistent data from SCN=10. The user program is now fetching x numbers of records, changing them, and committing them. Let's say they were committed with SCN=20. If a later fetch happens to retrieve a record which is in one of the previously committed blocks, then the fetch will see that the SCN there as 20. Since the fetch has to get the snapshot from SCN=10 it will try to find it in the rollback segments. If it could rollback sufficiently backwards as previously explained, then it could reconstruct the snapshot from SCN=10. If not, then it will result in an ORA-01555 error.
Committing less often which will result in larger rollback segments will REDUCE the probability of getting 'snapshot too old' error.


4. Fetch across commits with delayed block clean out
To complicate things, now we see how delayed block clean outs play an important role in getting this error.
When a data or index block is modified in the database and the transaction committed, Oracle does a fast commit by marking the transaction as committed in the rollback segment header but does not clean the datablocks that were modified. The next transaction which does a select on the modified blocks will do the actual cleanout of the block. This is known as a delayed block cleanout.
Now, take the same scenario as described in previous section. But instead of assuming one table, let us assume that there are two tables in question. i.e: the cursor is opened and then in a loop, it fetches from one table and changes records in another, and commits. Even though the records are getting committed in another table it could still cause ORA-01555 because cleanout has not been done on the table from which the records are being fetched.
For this case, a full table scan before opening and fetching through the cursor will help.



Summary:
Fetches across commits as explained in last two cases are not supported by ANSI standard. According to ANSI standard a cursor is invalidated when a commit is performed and should be closed and reopened. Oracle allows users to do fetch across commits but users should be aware that it might result in ORA-01555.
Related DB configuration:
UNDO_RETENTION
UNDO_RETENTION specifies (in seconds) the low threshold value of undo retention. For AUTOEXTEND undo tablespaces, the system retains undo for at least the time specified in this parameter, and automatically tunes the undo retention period to satisfy the undo requirements of the queries. For fixed- size undo tablespaces, the system automatically tunes for the maximum possible undo retention period, based on undo tablespace size and usage history, and ignores UNDO_RETENTION unless retention guarantee is enabled.


The setting of this parameter should account for any flashback requirements of the system. Automatic tuning of undo retention is not supported for LOBs. The RETENTION value for LOB columns is set to the value of the UNDO_RETENTION parameter.
The UNDO_RETENTION parameter can only be honored if the current undo tablespace has enough space. If an active transaction requires undo space and the undo tablespace does not have available space, then the system starts reusing unexpired undo space. This action can potentially cause some queries to fail with a "snapshot too old" message.


Solution:

ALTER SYSTEM SET undo_retention=10800 SCOPE=BOTH; (設爲3小時)   實際我設成了1小時,也可,視實際情況而定!


轉載自:http://hi.baidu.com/hihengsheng/blog/item/80d22a53db5d622943a75b3e.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章