您的位置:首页 > 其它

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

2016-05-26 11:27 956 查看
从客户那儿报来个问题,说是日志中显示,在执行一个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小时,也可,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: