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

MyCat Prepared Statement Id溢出Bug #2598

Closed
chank opened this issue Sep 27, 2020 · 8 comments
Closed

MyCat Prepared Statement Id溢出Bug #2598

chank opened this issue Sep 27, 2020 · 8 comments

Comments

@chank
Copy link

chank commented Sep 27, 2020

MyCat Prepared Statement Id溢出:

2020-09-20 20:26:08.114  INFO [$_NIOREACTOR-5-RW] (io.mycat.server.handler.ServerPrepareHandler.execute(ServerPrepareHandler.java:155)) - preparestatement  execute id:-2146423296
2020-09-20 20:26:08.114  INFO [$_NIOREACTOR-6-RW] (io.mycat.server.handler.ServerPrepareHandler.close(ServerPrepareHandler.java:183)) - preparestatement  close id:-2146423298

原因分析:
MyCat Prepared Statement Id是实例(进程)级别递增,只有重启MyCat Prepared Statement Id才会从0开始(MySQL Driver约定的Prepared Statement Id只有32位):
https://github.com/MyCATApache/Mycat-Server/blob/https/github.com/MyCATApache/Mycat-Server/tree/Mycat-server-1.6.76-test/src/main/java/io/mycat/server/handler/ServerPrepareHandler.java#L80
https://github.com/MyCATApache/Mycat-Server/blob/https/github.com/MyCATApache/Mycat-Server/tree/Mycat-server-1.6.76-test/src/main/java/io/mycat/backend/mysql/BufferUtil.java#L55

但MySQL Server的Prepared Statement Id是在连接(线程)级别递增的,重新连接Prepared Statement就会从0开始:
https://github.com/mysql/mysql-server/blob/8.0/sql/sql_class.h#L2169

因此,MyCat对Prepared Statement Id的生成没有与MySQL Server保存一致,请问是否能保持一致?

@junwen12221
Copy link
Collaborator

@funnyAnt

@chank
Copy link
Author

chank commented Sep 29, 2020

使用的是:Mycat-server-1675-release 这个版本,1.7好像解决了这个问题,但为什么还没有发布?

@funnyAnt
Copy link
Collaborator

funnyAnt commented Oct 1, 2020

@chank 这个故障我来确认下

@funnyAnt
Copy link
Collaborator

funnyAnt commented Oct 2, 2020

@chank 问题已经修复。

分析:

Prepare交互流程:
  • 1、客户端prepare--->mycat 生成statementId-->客户端接收statementId
  • 2、客户端execute(带statementId,参数)--->mycat 根据statementId查询到prepare语句-->mycat执行--->结果返回客户端
问题原因:
  • java int是32位,long是64位;mysql协议里面定义的statementId是32位。
  • mycat使用AtomicLong生成statementId,当该值不停递增超过32位时,返回给客户端包里面的statementId值位数存在丢失,导致客户端获取到statementId值和mycat存储的值不一致。于是当客户端execute时,mycat收到客户端statementId就会报找不到对应的prepare语句错误。

修复方法:

  • 将AtomicLong 改成AtomicInteger

@chank
Copy link
Author

chank commented Oct 4, 2020

@funnyAnt @junwen12221 你只是改为AtomicInteger的话还是会溢出的,应该要将static去掉,将递增改为连接级别的

junwen12221 added a commit that referenced this issue Oct 8, 2020
#2598  修复Prepared Statement Id溢出Bug
@funnyAnt
Copy link
Collaborator

@chank

  • integer 类型溢出,变为负数,不影响从全局的 Map<String, PreparedStatement> pstmtForSql 中以这个值作为key取PreparedStatement值。
  • 原始代码里面使用static ,我想是因为考虑不用频繁地new对象。

@chank
Copy link
Author

chank commented Oct 12, 2020

@funnyAnt 请问什么时候可以发布啊?

@chank
Copy link
Author

chank commented Oct 16, 2020

@funnyAnt @junwen12221

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

No branches or pull requests

3 participants