Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 为什么节点模块中定义的变量在两个用户之间共享_Mysql_Node.js_Memory_Pm2 - Fatal编程技术网

Mysql 为什么节点模块中定义的变量在两个用户之间共享

Mysql 为什么节点模块中定义的变量在两个用户之间共享,mysql,node.js,memory,pm2,Mysql,Node.js,Memory,Pm2,我使用pm2集群模式运行节点API服务器,该服务器将与mysqlDB服务器通信 在modulex.js中,我有如下代码: 让insertMappingQuery=`; ... ... const constructInsertMappingQuery=()=>{ insertMappingQuery+=` 将忽略插入消息映射(消息id、联系人id) 值(`+消息id+`、`+联系人id+`+`);`; } 当用户发送消息时,函数将调用模块x,并为其消息执行上述代码(比如message_id=

我使用pm2集群模式运行节点API服务器,该服务器将与mysqlDB服务器通信

在module
x.js
中,我有如下代码:


让insertMappingQuery=`;
...
...
const constructInsertMappingQuery=()=>{
insertMappingQuery+=`
将忽略插入消息映射(消息id、联系人id)
值(`+消息id+`、`+联系人id+`+`);`;
}

当用户发送消息时,函数将调用模块x,并为其消息执行上述代码(比如message_id=1

将忽略插入消息映射(消息id、联系人id)
值(1,一些_id);
然后另一个用户发送一条消息,并执行代码,比如说message_id=2,但是查询如下所示:

将忽略插入消息映射(消息id、联系人id)
值(1,一些_id);
将忽略插入消息映射(消息id、联系人id)
值(2,一些_id);
所以基本上,当用户2发送消息时,这个查询将包含用户1已经执行的内容因此用户一将插入其记录两次。

这种情况并非总是发生,但它经常发生(我会说30%到50%),而且我找不到任何发生这种情况的模式

用户不必同时做,可能会有一些时差(几分钟甚至几小时)

这可能与内存中未清除的变量有关吗?还是某种内存泄漏


我不明白两个不同的用户如何共享一个变量。

显然,我不知道
要求
调用模块将缓存并重用它。因此,该模块中的全局变量也将被缓存

因此,这里最好的解决方案是避免使用全局变量并重新构造代码。但是,如果您需要快速解决方案,您可以使用:

delete require.cache[require.resolve('replaceWithModulePath')]
示例:

让一些需要模块x的函数=()=>{
删除require.cache[require.resolve('./x')];
常数x=要求('./x');
}

请记住,
require
缓存模块,所有后续的
require
调用都被赋予相同的内容,因此请编写一些导出函数或类的内容,这样您就可以安全地调用/实例化一些内容,而不必共享变量

例如:

const db=require(`your/db/connector`);
常量映射器={
addToMessageMapping:异步函数(messageId、contactId){
常量查询=`
将忽略插入消息映射(消息id、联系人id)
值(${message\u id},${contact\u id});
`;
...
返回db.run(查询);
},
...
}
module.exports=映射器;
当然,这也可能是一个类,或者它甚至可能是一个直接的函数-唯一改变的是如何使它运行,而不与任何其他调用函数冲突

现在,此代码的使用者只需相信以下内容没有副作用:

const mapper=require('mapper.js');
const express、app等,无论什么=。。。
....
app.post(`/api/v1/mappings/message/:msgid`),(req,res,next)=>{
const post=getpostparamesusualway();
mapper.addToMessageMapping(req.params.msgId,post.contactId)
.然后(()=>next());
.catch(错误=>next(错误));
},…,更多中间件,…,(请求,请求)=>{
res.render(`blah.html`,{…});
});
还请注意,模板字符串的存在是为了通过将字符串与
+
连接来防止字符串合成,关键是它们可以将
${…}
放在它们内部,并将模板放在“那些花括号中的任何内容”(变量、函数调用、任何JS)中

(它们的第二个功能是,您可以在它们前面加上函数名,该函数将作为模板操作的一部分运行,但不是很多人每天都需要它。
${…}
模板化?每天数千次)


当然还有最后一点:看起来您正在创建原始SQL,这总是一个坏主意。对您正在使用的任何数据库库使用准备好的语句:它支持它们,并且意味着任何用户输入都是安全的。现在,有人可以在你的API上发布消息id为
);删除表消息\u映射--完成:你的桌子不见了。有趣的时刻。

这个问题到处都是,但最直接的观察结果是:如果你不想让用户共享变量,不要在服务API调用的路由之外声明它们。使用,这样您就不需要手动查阅和增加内容,并且只在请求上下文中创建查询,而不是在全局级别。您好@Mike'Pomax'Kamermans,很抱歉,我忘了提到
message\u id
是外键,所以我在自动增加表中的主键方面没有问题。你能详细说明一下声明变量吗?据我所知,在模块(文件)内、任何代码块外声明变量将使它们仅对该模块具有全局性。“当用户发送消息时,函数将调用模块x”=将所有变量作用于该函数,而不涉及任何其他内容。这意味着传递诸如会话、db连接等的函数参数,并且只在该函数内声明特定于请求的变量(并进一步传递这些变量)。可能相关:每次使用
require
时,节点模块都被缓存和共享,而不是作为“单独的副本”被要求,因此如果在某个地方有
const a=require('whatever')
,而在另一个地方有
const b=require('whatever')
,它们指向相同的位置thing@Mike“Pomax”Kamermans,谢谢你的提示和快速回复。我不知道
require
cac