0

奇怪的情况。

我尝试启动聊天应用程序。我使用 postgresql 9.3 和 tomcat 作为 Web 服务器。

当一个浏览器向另一个浏览器发送消息时会发生什么:

1 - Broswer A 向服务器发送消息(tomcat)

2 - Tomcat 将 msg 放入数据库并获取他的 id

INSERT INTO messages VALUES('first message') returning into MSGID id

3 - Tomcat 向浏览器 B 重新发送消息(websocket 接收者)

4 - 浏览器 B 发送系统答案:MSGID_READED

5 - Tomcat 更新数据库消息

UPDATE messages SET readtime = now() WHERE id = MSGID

一切正常,但有时在第 5 点更新时找不到 MSGID 的消息...

很奇怪,因为在第 2 点我得到了消息记录 ID,但在第 5 点,没有。

可能 postgresql 写得很慢并且这条记录不允许(不可见)来自并行数据库连接?

更新

我为我找到了解决方案,只需将 insert 放入 begin/exception/end 块中。

BEGIN
    INSERT INTO messages (...)
        VALUES (...)
        RETURNING id INTO MSGID;
EXCEPTION
    WHEN unique_violation THEN
     -- nothing
END;

更新 2

详细测试上述使用 BEGIN 块的更改没有影响。Javascript中的解决方案!我从其他线程发送了 websocket 消息,问题解决了!

// WebSocket send message function
// Part of code. so is a web socket
send = function(msg) {
    if (msg != null && msg != '') {
        var f = function() {
            var mm = m;
//            JCC.log('SENT: [' + mm + ']');
            so.send(mm);
        };
        setTimeout(f, 1);
    }
};
4

1 回答 1

0

好的,所以问题是通常作家不会阻止读者。这意味着您的第一个插入发生,第二个插入在第一个提交之前触发。这会在您的应用程序中引入竞争条件,从而引入您看到的问题。

您最好的问题是切换到可序列化的快照隔离或执行您已完成的操作并在插入时进行异常处理。一种或另一种方式最终导致必须处理的额外异常处理(如果可序列化,则有时可能会发生序列化失败异常,您可能必须等待它)。

在您的情况下,尽管 plpgsql 中的异常处理会降低性能,但您最好按照当前的方式进行操作,因为这样可以避免锁定问题并等待事务完成。

于 2013-12-06T03:44:19.070 回答