简体   繁体   English

插入数量超过20时Oracle数据库更改通知不起作用

[英]Oracle database change notification not working when inserts qty exceeds 20

public class Register {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private DCNListener listener;


    private OracleConnection oracleConnection = null;
    private DatabaseChangeRegistration dcr = null;
    private Statement statement = null;
    private ResultSet rs = null;


    @PostConstruct
    public void init() {
        this.register();
    }


    private void register() {


        Properties props = new Properties();
        props.put(OracleConnection.DCN_NOTIFY_ROWIDS, "true");
        props.setProperty(OracleConnection.DCN_IGNORE_DELETEOP, "true");
        props.setProperty(OracleConnection.DCN_IGNORE_UPDATEOP, "true");

        try {

            oracleConnection = (OracleConnection) dataSource.getConnection();

            dcr = oracleConnection.registerDatabaseChangeNotification(props);
            statement = oracleConnection.createStatement();
            ((OracleStatement) statement).setDatabaseChangeRegistration(dcr);

            rs = statement.executeQuery(listenerQuery);

            while (rs.next()) {

            }

            dcr.addListener(listener);

            String[] tableNames = dcr.getTables();
            Arrays.stream(tableNames)
                    .forEach(i -> log.debug("Table {}" + " registered.", i));

        } catch (SQLException e) {
            e.printStackTrace();
            close();
        }

    }
}

My Listener: 我的听众:

public class DCNListener implements DatabaseChangeListener {

    @Override
    public void onDatabaseChangeNotification(DatabaseChangeEvent databaseChangeEvent) {

        TableChangeDescription[] tableChanges = databaseChangeEvent.getTableChangeDescription();

        for (TableChangeDescription tableChange : tableChanges) {

            RowChangeDescription[] rcds = tableChange.getRowChangeDescription();

            for (RowChangeDescription rcd : rcds) {

                RowOperation op = rcd.getRowOperation();
                String rowId = rcd.getRowid().stringValue();

                switch (op) {

                    case INSERT:
                        //process
                        break;

                    case UPDATE:
                        //do nothing
                        break;

                    case DELETE:
                       //do nothing
                        break;

                    default:
                        //do nothing
                }

            }

        }
    }
}

In my Spring boot application, I have an Oracle DCN Register class that listens for INSERTS in an event table of my database. 在我的Spring启动应用程序中,我有一个Oracle DCN Register类,该类在数据库的事件表中侦听INSERTS。 I am listening for insertion new records. 我正在听插入新记录。

In this Event table, I have different types of events that my application supports, lets say EventA and EventB. 在此事件表中,我有应用程序支持的不同类型的事件,比如说EventA和EventB。

The application gui allows you to upload in bulk these type of events which translate into INSERT into the oracle database table I am listening to. 应用程序gui允许您批量上传这些类型的事件,这些事件会转换为INSERT到我正在侦听的oracle数据库表中。

For one of the event types, my application is not capturing the INSERT ONLY when it is 20 or more events uploaded in bulk, but for the other event type, I do not experience this problem. 对于其中一种事件类型,当它批量上传20个或更多事件时,我的应用程序不会捕获INSERT,但是对于另一种事件类型,我没有遇到此问题。

So lets say user inserts eventA any number < 20, my application captures the inserts. 因此,假设用户插入eventA任何数字<20,我的应用程序都将捕获插入。 But if the number of eventA inserts exceeds 20, it does not capture. 但是,如果eventA插入的数量超过20,则不会捕获。

This is not the case for eventB which works smoothly. 对于eventB情况并非如此,它可以正常运行。 I'd like to understand if I'm missing anything in term of registration and anything I can look out for maybe in the database or what the issue could be here? 我想了解我是否在注册方面缺少任何东西,或者我可以在数据库中寻找的任何东西,或者这里可能出什么问题?

You should also look for the ALL_ROWS event from: 您还应该从以下位置查找ALL_ROWS事件:

EnumSet<TableChangeDescription.TableOperation> tableOps = tableChange.getTableOperations();
if(tableOps.contains(TableChangeDescription.TableOperation.ALL_ROWS)){
  // Invalidate the cache
}

Quote fromt the JavaDoc: 引用JavaDoc:

The ALL_ROWS event is sent when the table is completely invalidated and row level information isn't available. 当表完全无效并且行级别信息不可用时,将发送ALL_ROWS事件。 If the DCN_NOTIFY_ROWIDS option hasn't been turned on during registration, then all events will have this OPERATION_ALL_ROWS flag on. 如果在注册过程中未打开DCN_NOTIFY_ROWIDS选项,则所有事件都将打开此OPERATION_ALL_ROWS标志。 It can also happen in situations where too many rows have changed and it would be too expensive for the server to send the list of them. 如果更改的行太多,也可能发生这种情况,并且服务器发送这些行的列表过于昂贵。

https://docs.oracle.com/en/database/oracle/oracle-database/12.2/jajdb/oracle/jdbc/dcn/TableChangeDescription.TableOperation.html#ALL_ROWS https://docs.oracle.com/zh_CN/database/oracle/oracle-database/12.2/jajdb/oracle/jdbc/dcn/TableChangeDescription.TableOperation.html#ALL_ROWS

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM