-
Notifications
You must be signed in to change notification settings - Fork 7.6k
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
mysql长时间没数据,可能导致canal与mysql的连接读操作永远阻塞 #188
Comments
目前设计时依赖于MySQL数据库的空闲链接超时机制,默认是8小时会断开链接,你的链接失效是指半开链接么?这个客户端能获取到EOFException |
这个问题在我自己的测试环境中很容易重现,mysql版本:5.5.14 wait_timeout设为8小时,canal版本1.0.22,如果mysql半个小时无数据更新,canal就无法读取新的bin-log,重启canalServer后就正常了。难道跟数据库的配置有关系,还是其他原因?期望能得到指导。 |
PS:CanalServer没有任何的错误日志,不好分析问题。。。 |
暂时性解决方案,可以开启下心跳SQL. 这问题还真没遇到过 |
mysql的slave连接master读数据的默认超时时间(slave_net_timeout)是3600s(时间太长),超时后重建连接,参考http://dev.mysql.com/doc/refman/5.6/en/replication-options-slave.html#sysvar_slave_net_timeout mysql5.5后好像引入了master/slave之间的heartbeat binlog event,master没binlog event空闲一段时间后(超过MASTER_HEARTBEAT_PERIOD)就发送给slave heartbeat事件。参考: MASTER_HEARTBEAT_PERIOD的默认配置是slave_net_timeout/2,默认是1800s,时间都太长了。 @tianshazzq 可以测试下这些参数试试。 canal程序想要支持默认配置、不出问题,最好还是像开头说的那样自己控制超时时间、连接空闲一段时间(比如最多1min?)后重新建连接。 |
mysql与canl-server的tcp连接闪断,canl-server并不知情,导致后续的binlog无法通知到canal-server,这个怎么破? |
建议开启canal心跳设置,会定时更新数据库来产生心跳binlog,如果指定时间没收到心跳信息可以尝试重建链接 |
mysql到canal的连接异常了,比如mysql宕机这种情况,canal是被动接收数据的,自然是不会知道任何链路是否正常的状态;关键是canal是否实现了空闲后有无重连的机制或者mysql异常重连?如若实现了配置哪个参数? |
canal基于被动监听式的是没法感知socket被server断开的,最重要还是开启心跳binlog,或者升级mysql5.6(mysql针对空闲链接会定时发送心跳binlog事件来维持tcp链接) |
在Mysql宕机后重启这种情况下面的,开启心跳没什么用吧?我们需要在canal中实现mysql这个参数slave_net_timeout所需要实现的功能。 |
@agapple 把数据库断开时间改成了2分钟,并且开启了心跳检查。长时间(2分钟以上)没有数据后新插入数据,canal server会获取不到 (过不定时间后canal server又能获取到数据10~30分钟不等)。debug看心跳数据都是能正常收发。日志里没有任何异常输出 detecing configcanal.instance.detecting.enable = true |
mysql与canl-server的tcp连接闪断,canl-server并不知情,导致后续的binlog无法通知到canal-server,这个怎么破?这个问题你怎么解决的,我现在也遇到了这个问题 @githubcjh |
刚刚踩到一个坑,canal.instance.memory.buffer.size设置过小,导致主库执行大事务时,canal堵住 |
buffer.size建议设置>1024 |
确实有这个问题,不知道楼主解决了这个问题么? 改为inputstream是可以的,sotimeout生效了,但是长时间没有数据,inputstream 阻塞在read那里时不会响应thread.interrupt(),event parser那里需要做一些改动先close socket再调用thread.interrupt(),但是总感觉这个方法和canal的nio设计有些矛盾。但是问题是现实存在的。虽然是nio但是读的时候用的是阻塞的模式 |
buffer size能解决这个问题?? |
解决方案就是在读取mysql binlog变更的地方加个超时就好,不然就只能依赖tcp的keeplive机制;我不太懂java,已经没用这一套了,自己开发了一套。 |
SocketChannel.read(buffer)此方法的确不会报超时异常(https://stackoverflow.com/questions/2866557/timeout-for-socketchannel-doesnt-work#answer-9150513),目前本人使用1.0.24版本,暂时将DirectLogFetcher使用的SocketChannel转为ReadableByteChannel,可使socket timeout 生效,抛出SocketTimeoutException。 |
@vamdt BioSocketChannelPool.java,基于原生Socket操作,soTimeout参数验证也可以生效 |
@agapple OK,暂时使用体验上感觉1.0.24更稳,等1.0.26正式发布再试试看BIO的。 |
推荐v1.1.1版本,基于原生Socket的bio操作,增加了超时重连机制 |
canal从mysql读binlog事件时,建的连接设置了读超时时间: channel.socket().setSoTimeout(this.soTimeout); ,soTimeout用了30s。
读binlog事件时,用了SocketChannel.read(buffer)方法,soTimeout对这个SocketChannel的read方法无效,永远不会超时,参考http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4614802。
如果mysql有一段时间没数据(比如一个小时),这个连接失效了(可能因为防火墙问题,参考http://www.tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html的2.4. 虽然设置了channel.socket().setKeepAlive(true),但是linux系统默认的keepalive配置时间太长、不起作用。),但canal还在永远阻塞read。
所以是不是用sock.socket().getInputStream()这个来read比较好,如果在soTimeout内没读到数据,就超时了,强制重新建立连接。
The text was updated successfully, but these errors were encountered: