我正在使用 Node.js 开发一个简单的服务。它接收上传的文件,将它们存储在磁盘上并在 Oracle 表上记录一些元数据。我正在使用 db-oracle
包和连接池,遵循这篇文章:http://nodejsdb.org/2011/05/connection-pooling-node-db-with-generic-pool/
但是,我注意到我插入的数据仅在连接池通过调用其disconnect()
方法关闭空闲连接后才发送到Oracle 数据库。
有没有办法在向我的客户端发送“OK”信号之前刷新数据?它现在的工作方式是,我的 web 服务或 Oracle 本身的崩溃会导致数据丢失,而我的服务的客户端不会知道这件事。我实际上通过在一些上传后终止我的应用进程来测试这个,数据确实丢失了。
这是代码的简化版本:
var express = require('express');
var app = module.exports = express.createServer();
app.post('/upload', handleUpload);
app.listen(4001, function(){
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
});
function handleUpload(req, res) {
res.contentType('application/xml');
var buf = '';
req.on('data', function(chunk) { buf += chunk; });
req.on('end', function() {
saveUpload(req, res, buf);
});
}
function saveUpload(req, res, buf) {
if (buf.length == 0)
return sendError(res, 'No data supplied', 422);
var payload = new Buffer(buf, 'base64');
files.save(payload, function(err, savedFile) {
if (err)
return sendError(res, 'Error while saving', 500);
var obj = { ip: req.connection.remoteAddress, location: savedFile.path,
created_at: new Date(), updated_at: new Date() };
var fields = ['IP', 'LOCATION', 'CREATED_AT', 'UPDATED_AT'];
var values = fields.map(function(v) { return obj[v.toLowerCase()] });
pool.acquire(function(err, conn) {
if (err)
return sendError(res, err, 500);
var q = conn.query().insert('FILES', fields, values);
q.execute(function(err, result) {
pool.release(conn);
if (err)
return sendError(res, err, 500);
if (result.affected < 1)
return sendError(res, 'Error saving the record', 500);
// The next statement sends the final result to the client.
// However, the new record was not yet flushed to the database.
res.end('<ok />');
});
});
});
}
function sendError(res, err, code) {
console.log(err);
res.send('<error>' + err + '</error>', code || 500);
}
作为一种变通方法,我尝试实现一个虚假的连接池并释放所有已获取的连接,但现在我的应用正在死去,并显示消息:pure virtual method calledAbort trap: 6
这是假的连接池:
var fakePool = {
acquire: function(callback) {
new oracle.Database(config.database).connect(function(err, server) {
callback(err, this);
});
},
release: function(conn) {
conn.disconnect();
}
};
需要说明的是,我不关心假连接池,它只是一个肮脏的解决方法。我希望能够在向我的客户端发送“OK”消息之前将数据刷新到 Oracle。
顺便说一句,我还在他们的 Github 上开了一张票:https://github.com/mariano/node-db-oracle/issues/38
最佳答案
您显然错过了事务提交。
node-db 不需要公开提交 API,因为在大多数 RDBMS(包括 Oracle)中,COMMIT 是一个有效的查询。由于包允许执行任意查询,提交/回滚应该使用简单的 execute()
代码应该修改如下:
pool.acquire(function(err, conn) {
if (err)
return sendError(res, err, 500);
var q = conn.query().insert('FILES', fields, values);
q.execute(function(err, result) {
if (err || result.affected < 1 ) {
pool.release(conn);
return sendError(res, err, 500);
}
conn.query().execute("commit", function(err,result) {
if (err) {
pool.release(conn);
return sendError(res, err, 500);
}
res.end('<ok />');
pool.release(conn);
});
});
});
关于oracle - db-oracle 没有刷新数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10809476/