Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ bug ]如果sql语句过长,mongodb 执行sql会不成功,我已经复现 #1552

Closed
czxin788 opened this issue May 27, 2022 · 30 comments · Fixed by #1556
Closed

[ bug ]如果sql语句过长,mongodb 执行sql会不成功,我已经复现 #1552

czxin788 opened this issue May 27, 2022 · 30 comments · Fixed by #1556

Comments

@czxin788
Copy link
Contributor

czxin788 commented May 27, 2022

1、问题
image

2、重现步骤
我看了源码,知道了archery执行mongodb sql的原理:
sql/engines/mongo.py

 cmd = "{mongo} --quiet -u {uname} -p '{password}' {host}:{port}/{auth_db} <<\\EOF\ndb=db.getSiblingDB(\"{db_name}\");{slave_ok}printjson({sql})\nEOF".format(
                        mongo=mongo, uname=self.user, password=self.password, host=self.host, port=self.port,
                        db_name=db_name, sql=sql, auth_db=auth_db, slave_ok=slave_ok)

于是,我手工执行命令,进行复现,发现是语句太长,mongo执行sql会报错,如下:

mongo --quiet -u root -p '123456' 192.168.1.xx:27017/admin <<EOF
db=db.getSiblingDB("czx");printjson(db.t1.insertMany(
        [{"optionKey":"HE","value":"1","describe":"xxxxxxx","_id":"6cc0ss9ac96cd51d3cc7cb","templateId":"6f4fxxxxx441-8431-389e85ded92d"},{"optionKey":"HE","value":"2","describe":"xxxxx","_id":"dc483316bde04c2ab21bc0c9e0f62d34","templateId":"6f4fxxxx62d-4441-8431-389e85ded92d"},{"optionKey":"ACN1","value":"0","describe":"无","_id":"82697d363abb40c8b697e4826d59f55d","templateId":"6xxx1-8431-389e85ded92d"},{"optionKey":"ACN1","value":"1","describe":"xxxx","_id":"01aeb6e16fc9471393868a367710dde2","templateId":"6f4f518d-262d-4441-8431-389e85ded92d"},{"optionKey":"ACN1","value":"2","describe":"xxx","_id":"7f33637e5fd14f52aa22c07fcbc025d1","templateId":"6fxxxxx2d-4441-8431-389e85ded92d"},{"optionKey":"ACN1","value":"3","describe":"xxxx","_id":"3dbc0b296865447f9290c5844a45d8a9","templateId":"6xxxx431-389e85ded92d"},{"optionKey":"IFSTY","value":"1","describe":"xxxx","_id":"c924ff912eb1487880e7218f5e9deb64","templateId":"6fxxxxxe85ded92d"},{"optionKey":"IFSTY","value":"2","describe":"xxx","_id":"581bf44c93bf4e6687f831f4bd147a19","templateId":"6f4f518d-262d-4441-8431-389e85ded92d"},{"optionKey":"IFSTY","value":"3","describe":"xxx","_id":"3181a73b77cb4c5dbd1f26daf01a8b90","templateId":"6f4fxxxx389e85ded92d"},{"optionKey":"FM1","value":"1","describe":"xxxx","_id":"23d8d285497548f9aaa3470aef7bb39a","templateId":"6f4xxxxx389e85ded92d"},{"optionKey":"FM1","value":"2","describe":"xxx","_id":"fde22d3e4fd24fb9a0b2e088aa312968","templateId":"6f4xxxxe85ded92d"},{"optionKey":"FM","value":"1","describe":"10","_id":"b0b48ae8c0a04a5499ffade80ee7fbd4","templateId":"6f4f518d-262d-4441-8431-389e85ded92d"},{"optionKey":"FM","value":"2","describe":"11","_id":"04d44ea232164279b7b824ffdd29b13c","templateId":"6f4xxx89e85ded92d"},{"optionKey":"FM","value":"3","describe":"12","_id":"4293d60a3b3f4ded8c960e9021827a6d","templateId":"6f4f518d-262d-4441-8431-389e85ded92d"},{"optionKey":"RS","value":"1","describe":"xx","_id":"239a4d074eaa4cf9a1e7af54430605b2","templateId":"6f4f51xxxx5ded92d"},{"optionKey":"RS","value":"2","describe":"xxxxx","_id":"11126db03a2c4b3e8bd8d86691a29c09","templateId":"6f4fxxxe85ded92d"},{"optionKey":"BMD","value":"1","describe":"≥-1.0(xxxx)","_id":"19948ee083ae446dbb506408580cef52","templateId":"6f4f518d-xxxxx389e85ded92d"},{"optionKey":"BMD","value":"2","describe":"-1.0— -2.5(xxx)","_id":"ea7b41a355054edd90e72f66b0455584","templateId":"6f4f51xxxxx-389e85ded92d"},{"optionKey":"BMD","value":"3","describe":"≤-2.5(xxxx)","_id":"78e200491c5e461da487f37aa4126120","templateId":"6f4f518xxxxx1-389e85ded92d"},{"optionKey":"PRI","value":"1","describe":"0","_id":"2f0ca97f465a4f198fd642a1777e6e0a","templateId":"6f4fxxxx389e85ded92d"},{"optionKey":"TERM","value":"1","describe":"xxxx","_id":"b67a241e6575498bb9685420ac29bb46","templateId":"6f4fxxxx85ded92d"},{"optionKey":"TERM","value":"2","describe":"xxxx,xxxx","_id":"4ae50cf37d794133865bc3e33cc5c5e6","templateId":"6f4f518d-262d-4441-8431-389e85ded92d"},{"optionKey":"TERM","value":"3","describe":"xxxx","_id":"e16450fcd2a6492f9c0ad693a7a91b4d","templateId":"6f4xxxx9e85ded92d"},{"optionKey":"TERM","value":"4","describe":"xxxx","_id":"baa09ff12c4e4debb2b508a90058f420","templateId":"6f4fxxx85ded92d"},{"optionKey":"TERM","value":"5","describe":"xxx","_id":"5b36860bda7b4598b9bfb56ef7af78e2","templateId":"6f4f5xxxxded92d"},{"optionKey":"TERM","value":"5","describe":"xxxx","_id":"4b36860bda7b4598b9bfb56ef7af78e2","templateId":"xxxxxxx"},{"optionKey":"TERM","value":"5","describe":"xxxx","templateId":"xxxxxxx"},{"optionKey":"TERM","value":"5","describe":"xxxx","templateId":"xxxxxxx"},{"optionKey":"TERM","value":"5","describe":"xxxx","templateId":"xxxxxxx"},{"optionKey":"TERM","value":"5","describe":"xxxx","templateId":"xxxxxxx"},{"optionKey":"TERM","value":"5","describe":"xxxx","templateId":"xxxxxxx"}] ))
EOF

上面的命令执行后就会报如下错误:

2022-05-27T21:12:58.394+0800 E  QUERY    [js] uncaught exception: SyntaxError: "" literal not terminated before end of script :
@(shell):2:4073
2022-05-27T21:12:58.397+0800 E  QUERY    [js] uncaught exception: SyntaxError: unexpected token: string literal :
@(shell):1:7

如果把上面的sql,去掉一组,比如去掉{"optionKey":"TERM","value":"5","describe":"xxxx","templateId":"xxxxxxx"},就能正常执行了,如下:

mongo --quiet -u root -p '123456' 192.168.1.xx:27017/admin <<EOF
db=db.getSiblingDB("czx");printjson(db.t1.insertMany(
        [{"optionKey":"HE","value":"1","describe":"xxxxxxx","_id":"6cc0fbad794445389ac96cd51d3cc7cb","templateId":"6f4fxx1-xxxxxd92d"},{"optionKey":"HE","value":"2","describe":"xxxxx","_id":"dc483316bde04c2ab21bc0c9e0f62d34","templateId":"6f4f5xxxx2d-4441-8431-389e85ded92d"},{"optionKey":"ACN1","value":"0","describe":"无","_id":"82697d363abb40c8b697e4826d59f55d","templateId":"6f4xxx262d-4441-8431-389e85ded92d"},{"optionKey":"ACN1","value":"1","describe":"xxxx","_id":"01aeb6e16fc9471393868a367710dde2","templateId":"6f4xxxx-262d-4441-8431-389e85ded92d"},{"optionKey":"ACN1","value":"2","describe":"xxx","_id":"7f33637e5fd14f52aa22c07fcbc025d1","templateId":"6f4f5xxx2d-4441-8431-389e85ded92d"},{"optionKey":"ACN1","value":"3","describe":"xxxx","_id":"3dbc0b296865447f9290c5844a45d8a9","templateId":"6fxxxd-262d-4441-8431-389e85ded92d"},{"optionKey":"IFSTY","value":"1","describe":"xxxx","_id":"c924ff912eb1487880e7218f5e9deb64","templateId":"6f4fxxx-262d-4441-8431-389e85ded92d"},{"optionKey":"IFSTY","value":"2","describe":"xxx","_id":"581bf44c93bf4e6687f831f4bd147a19","templateId":"6f4f51xxxd-4441-8431-389e85ded92d"},{"optionKey":"IFSTY","value":"3","describe":"xxx","_id":"3181a73b77cb4c5dbd1f26daf01a8b90","templateId":"6f4fxxxx-262d-4441-8431-389e85ded92d"},{"optionKey":"FM1","value":"1","describe":"xxxx","_id":"23d8d285497548f9aaa3470aef7bb39a","templateId":"6f4fxxx-262d-4441-8431-389e85ded92d"},{"optionKey":"FM1","value":"2","describe":"xxx","_id":"fde22d3e4fd24fb9a0b2e088aa312968","templateId":"6f4f51xxxx262d-4441-8431-389e85ded92d"},{"optionKey":"FM","value":"1","describe":"10","_id":"b0b48ae8c0a04a5499ffade80ee7fbd4","templateId":"6f4f518xxxx-4441-8431-389e85ded92d"},{"optionKey":"FM","value":"2","describe":"11","_id":"04d44ea232164279b7b824ffdd29b13c","templateId":"6f4f51xxxx2d-4441-8431-389e85ded92d"},{"optionKey":"FM","value":"3","describe":"12","_id":"4293d60a3b3f4ded8c960e9021827a6d","templateId":"6f4f518xxxx2d-4441-8431-389e85ded92d"},{"optionKey":"RS","value":"1","describe":"xx","_id":"239a4d074eaa4cf9a1e7af54430605b2","templateId":"6f4f518dxxxxd-4441-8431-389e85ded92d"},{"optionKey":"RS","value":"2","describe":"xxxxx","_id":"11126db03a2c4b3e8bd8d86691a29c09","templateId":"6fxxxx8d-262d-4441-8431-389e85ded92d"},{"optionKey":"BMD","value":"1","describe":"≥-1.0(xxxx)","_id":"19948ee083ae446dbb506408580cef52","templateId":"6f4f518d-262d-4441-8431-389e85xxxx2d"},{"optionKey":"BMD","value":"2","describe":"-1.0— -2.5(xxx)","_id":"ea7b41a355054edd90e72f66b0455584","templateId":"6f4f518d-xxxxxx9e85ded92d"},{"optionKey":"BMD","value":"3","describe":"≤-2.5(xxxx)","_id":"78e200491c5e461da487f37aa4126120","templateId":"6f4f518d-262dxxxxx5ded92d"},{"optionKey":"PRI","value":"1","describe":"0","_id":"2f0ca97f465a4f198fd642a1777e6e0a","templateId":"6f4xxxxx9e85ded92d"},{"optionKey":"TERM","value":"1","describe":"xxxx","_id":"b67a241e6575498bb9685420ac29bb46","templateId":"6f4f518d-262d-4441-8431-389e85ded92d"},{"optionKey":"TERM","value":"2","describe":"xxxx,xxxx","_id":"4ae50cf37d794133865bc3e33cc5c5e6","templateId":"6f4f51xxxxxx85ded92d"},{"optionKey":"TERM","value":"3","describe":"xxxx","_id":"e16450fcd2a6492f9c0ad693a7a91b4d","templateId":"6f4f518d-262dxxxxx5ded92d"},{"optionKey":"TERM","value":"4","describe":"xxxx","_id":"baa09ff12c4e4debb2b508a90058f420","templateId":"6f4f518d-262xxxxxxx89e85ded92d"},{"optionKey":"TERM","value":"5","describe":"xxx","_id":"5b36860bda7b4598b9bfb56ef7af78e2","templateId":"6f4f518d-26xxxxxx9e85ded92d"},{"optionKey":"TERM","value":"5","describe":"xxxx","_id":"4b36860bda7b4598b9bfb56ef7af78e2","templateId":"xxxxxxx"},{"optionKey":"TERM","value":"5","describe":"xxxx","templateId":"xxxxxxx"},{"optionKey":"TERM","value":"5","describe":"xxxx","templateId":"xxxxxxx"},{"optionKey":"TERM","value":"5","describe":"xxxx","templateId":"xxxxxxx"},{"optionKey":"TERM","value":"5","describe":"xxxx","templateId":"xxxxxxx"}] ))
EOF

执行结果如下,说明执行成功了:

{
	"acknowledged" : true,
	"insertedIds" : [
		"6cc0fbad794445389ac96cd51d3cc7cb",
               ...........................
		ObjectId("6290cffcd69bd88868731c28")
	]
}

3、请问,对于上面的问题,应该怎么处理好呢。

@fancy-lee
Copy link
Contributor

因为用的是mongo自己带的shell工具执行,确实会有这个问题。临时处理的办法就是自己写一个脚本执行过长的语句,或者用数据库工具执行,或者把语句切小一点。因为这种情况不是很多,所以一直没有去改进解决。如果你有更好的思路也可以分享一下

@czxin788
Copy link
Contributor Author

czxin788 commented May 28, 2022

我想到的版办法是,遇到insertmany,archery自动转为insertone,变成一行一行地执行

@fancy-lee
Copy link
Contributor

你说的这种情况只是超过行数的其中一种情况,这种case by case的解决方法,治标不治本

@czxin788
Copy link
Contributor Author

czxin788 commented May 30, 2022

那就利用脚本的方法。
1、archery把获取到的每条sql存到archery服务器上的一个js文件里面;
2、archery执行js脚本

 mongo --quiet -uroot -p '123456' 192.168.1.xx:27017/admin <<EOF
db=db.getSiblingDB("czx");load('/data/db/a.js')
EOF
load("/data/db/scripts/myjstest.js")

3、这样就可以应对任何类型的sql语句过长的问题了

@czxin788
Copy link
Contributor Author

我提交了一个pr,我这边测试可以用,有时间帮我看看 @fancy-lee
#1556

@fancy-lee
Copy link
Contributor

你用你之前报错的语句试了没有问题?

@czxin788
Copy link
Contributor Author

试了,没问题

@fancy-lee
Copy link
Contributor

这样有一个问题就是,执行命令返回结果的看不到了

@czxin788
Copy link
Contributor Author

czxin788 commented May 31, 2022

嗯,还真是,什么原因,能解决吗
修改前:
image

修改后:
image

@czxin788
Copy link
Contributor Author

czxin788 commented May 31, 2022

我发现我们遇到这种长sql场景还挺多的
image

@fancy-lee
Copy link
Contributor

我觉得可以捕获一下这个长度的错误,再去按你这样方法处理会更合理一点

@czxin788
Copy link
Contributor Author

我还是不知道怎么做,你有时间改写一下吗,我学习一下

@fancy-lee
Copy link
Contributor

也可以提前判断一下行的字符数,超过了就用load的方法

@czxin788
Copy link
Contributor Author

czxin788 commented May 31, 2022

这也是个方法,同时治标不治本。
原来用load方法,执行结果只显示个true

PRIMARY> load('a.js')
true

而直接用命令执行的话,就会有详细的回显信息

 PRIMARY>db.t1.insertMany(
     [{"optionKey":"HE","value":

执行结果
{
	"acknowledged" : true,
	"insertedIds" : [
		"6cc0ss9ac96cd51d3cc7cb",
		"dc48331xxxxxxxxx0f62d34",
		"82697d36xxxxxx7e4826d59f55d",

..............................
 ]
}
...............

@nick2wang
Copy link
Collaborator

参考一下这种方式执行:

mongo  --quiet ...... < /tmp/abc.js

@czxin788
Copy link
Contributor Author

你这个方法可以,但是怎么指定库执行js脚本

@nick2wang
Copy link
Collaborator

nick2wang commented May 31, 2022

mongo --quiet host:port/db_name ...... < /tmp/abc.js
或者文件首行加上db=db.getSiblingDB(db_name)或use db_name,都是一样的

@czxin788
Copy link
Contributor Author

可以了,你这个方法挺不错,我一会改一下脚本试试:

 cat a.js 
use czx;
db.t1.insert({"_id":"1111","name":"aa"});
 mongo --quiet -u root  -p '123456' 192.168.1.xx:27017/admin  < a.js 
switched to db czx
WriteResult({ "nInserted" : 1 })
mongo --quiet -u  root -p '123456' 192.168.1.xxxx:27017/admin  < a.js 
switched to db czx
WriteResult({
	"nInserted" : 0,
	"writeError" : {
		"code" : 11000,
		"errmsg" : "E11000 duplicate key error collection: czx.t1 index: _id_ dup key: { _id: \"1111\" }"
	}
})

@fancy-lee
Copy link
Contributor

mongo --quiet -u root -p '123456' 127.0.0.1:27017/root < a.js
2022-05-31T14:14:47.835+0800 E QUERY [thread1] Error: Authentication failed. :
DB.prototype._authOrThrow@src/mongo/shell/db.js:1441:20
@(auth):6:1
@(auth):1:2

exception: login failed

这种方法还是会有长度问题

@czxin788
Copy link
Contributor Author

是的,我也发现了,但是load方法没事

@fancy-lee
Copy link
Contributor

用管道也不行

@czxin788
Copy link
Contributor Author

绝绝子

@czxin788
Copy link
Contributor Author

mongo --quiet --eval 'db.t1.insertMany({})'

好像这样可以

@nick2wang
Copy link
Collaborator

mongo源码写死了shell单命令最大4096 bytes,看来是绕不过了,想想其他办法吧
https://github.com/mongodb/mongo/blob/6220cd6acadf334edee5168e4729c79c85327345/src/mongo/shell/linenoise.cpp#L145

@czxin788
Copy link
Contributor Author

czxin788 commented May 31, 2022

我有了一个方法,你看行吗

 cat a.js
var rs = db.t1.insertMany([{"optionKey":"............
printjson(rs);

image

参考文档:https://www.thinbug.com/q/53714996

@czxin788
Copy link
Contributor Author

就是执行结果有点长
image

@nick2wang
Copy link
Collaborator

结果长没事,可以默认显示一部分,点展开再显示全部

@czxin788
Copy link
Contributor Author

好主意,我又提了一下pr,有时间帮忙review一下

@fancy-lee
Copy link
Contributor

棒棒的,我试了一个也没有问题,可以输出结果,不过还是建议判断一下长度,超过再执行load,这样也可以减少读写文件操作,然后直接printjson(db.t1.insertMany([{"optionKey":"............)感觉理简洁

@czxin788
Copy link
Contributor Author

czxin788 commented Jun 1, 2022

已改,见PR

@hhyo hhyo closed this as completed in #1556 Jun 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants