【问题标题】:PostgreSQL's XMIN in Oracle & MySQLPostgreSQL 在 Oracle 和 MySQL 中的 XMIN
【发布时间】:2017-10-07 05:58:10
【问题描述】:

我正在尝试在 Oracle 和 MySQL 上获取此代码的等效项

if(vardbtype.equals("POSTGRESQL")){
            Long previousTxId = 0L;
            Long nextTxId = 0L;

            Class.forName("org.postgresql.Driver");
            System.out.println("----------------------------");

            try(Connection c = DriverManager.getConnection("jdbc:postgresql://localhost:5432/"+ vardbserver, vardbuser, vardbpassword);
                 PreparedStatement stmts = c.prepareStatement("SELECT * FROM "+ vardbname +" where xmin::varchar::bigint > ? and xmin::varchar::bigint < ? ");
                 PreparedStatement max = c.prepareStatement("select max(xmin::varchar::bigint) as txid from "+ vardbname)
                ) {
                c.setAutoCommit(false);

                while(true) {
                    stmts.clearParameters();

                    try(ResultSet rss = max.executeQuery()) {
                        if(rss.next()) {
                            nextTxId = rss.getLong(1);
                        }
                    }
                    stmts.setLong(1, previousTxId);
                    stmts.setLong(2, nextTxId + 1);
                    try(ResultSet rss = stmts.executeQuery()) {
                        while(rss.next()) {
                            String message = rss.getString("MESSAGE");
                            System.out.println("Message = " + message);
                            TextMessage mssg = session.createTextMessage(message);
                            System.out.println("Sent: " + mssg.getText());
                            producer.send(mssg);
                        }
                        previousTxId = nextTxId;
                    }
                    Thread.sleep(batchperiod2);
                }
            }
        }

基本上,代码用于获取数据库表中的内容并将其发送到 ActiveMQ。并且当表格更新时,它将发送刚刚更新的内容(而不是发送过去发送的内容)。但此代码仅适用于 PostgreSQL

然后我打算创建一个“if”函数。所以我可以使用另一个数据库来获取数据(Oracle 和 MySQL)。

我想我必须更改此代码吧?

 try(Connection c = DriverManager.getConnection("jdbc:postgresql://localhost:5432/"+ vardbserver, vardbuser, vardbpassword);
             PreparedStatement stmts = c.prepareStatement("SELECT * FROM "+ vardbname +" where xmin::varchar::bigint > ? and xmin::varchar::bigint < ? ");
             PreparedStatement max = c.prepareStatement("select max(xmin::varchar::bigint) as txid from "+ vardbname)
            ) {

【问题讨论】:

    标签: java mysql sql oracle postgresql


    【解决方案1】:

    此脚本在表格中查找间隔,并输出自上次循环以来插入的所有消息。

    PostgreSQL 存储了插入记录的事务编号,因此可以用来查找新插入的记录(尽管我不确定是否可以保证新事务的编号比以前的所有事务都高)假设)。

    其他 DBMS 没有此伪列。所以你必须在你的表中有一个时间戳列并使用它来代替。您必须更改两个查询以及代码以匹配数据类型(我想 java.sql.Timestamp 而不是 Long,但我不是 Java 人)。

    【讨论】:

    • 谢谢您的回复顺便说一句,在这种情况下,我只有 1 列将选择每行内的内容,它没有时间戳列...
    • 我的意思是:你必须创造一个。否则,您将无法识别新旧内容。
    • 两者都是伪列。 Postgre的XMIN存放插入事务号;因此,对于不能更改的行,它是一个固定值。该脚本假设这个增加(我不知道这个假设是否有效)并建立在这个假设之上。 Oracle 的ROWID 存储行的物理位置。这不是固定的,但可以在重新定位行时更改。
    • 所以:您需要一些列来指示插入顺序。人们通常会为此使用时间戳列。递增的 ID 也是可能的(如来自 Oracle 序列)。我什至不知道脚本对XMIN 的假设是否正确。反正Oracle和其他DBMS反正没有这样的列,所以你必须创建一个。如果你不能,那么你必须在你的脚本中有一个所有记录的数组,并将它们与每个循环的表中的所有记录进行比较,我认为这是毫无疑问的。因此,如果您无法添加列,则需要完全不同的方法。
    • 如前所述,如果插入顺序对您很重要,那么您必须更改表格并添加相应的列。但是,在您的情况下,插入顺序可能并不重要。您想要了解的只是新的插入。您通常会为此使用触发器和日志表。每次插入记录时,触发器都会创建一个日志记录。然后脚本读取日志,输出数据并删除日志条目。
    【解决方案2】:

    Thorsten 回答的一些补充想法。

    首先,xmin 是一个系统列,即 iirc,存储在磁盘的行标题中。它由写入更新。我还没有遇到交易ID不增加的情况。但是,必须有一些环绕点。我认为您最好使用一个触发器,该触发器将事务 id 存储在另一个表中以便出于这个原因进行处理(并使用它来处理事情)。

    对于 Oracle 和 MySQL,底层存储有很大的不同,我不知道如何直接做到这一点。

    如果您想要一个通用解决方案,您需要一个队列表,您可以在其中使用触发器插入等待的副本,然后在您的工作人员中从中选择/删除。这在 MySQL 上可能比在 PostgreSQL 上工作得更好,而对于 Oracle,您希望寻找面向索引的表。如果 autovacuum 无法跟上,请提出更多问题或聘请顾问。

    经过进一步研究

    InnoDB 提供了一个类似的DB_TRX_ID 列。请注意,如果您正在运行 MySQL,您不能假设您有此列,因为 MySQL 具有不同的表存储引擎,而且并非所有引擎都支持事务。所以这是一个重要的限制。

    我无法在 Oracle 上找到类似的专栏。

    【讨论】:

    • 老实说,我从我的演讲中得到了这个任务:|
    • 深入了解 MySQL 和 Oracle 的存储。我实际上并不认为在 Oracle 中使用 InnoDB 或面向索引的表是可能的。否则在堆表中可能是可能的,因为在堆表中数据库必须有某种方法来找出哪些行是可见的。
    • 基本上我想获取表中只有 1 列的每一行。但是如果表更新了,它会得到只更新的行...
    • 在 MySQL 上,我在使用 InnodB 时能够找到一列。不确定甲骨文。您将需要深入了解他们如何处理多版本。
    猜你喜欢
    • 2019-07-15
    • 2010-09-18
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    • 2016-12-27
    • 1970-01-01
    • 1970-01-01
    • 2011-07-29
    相关资源
    最近更新 更多