Mycat读服务器没有日志,绝大多数情况下不是Mycat“罢工”,而是它的日志级别默认太低、读写分离规则把读请求直接转给了从库,再加上部署环境把标准输出“藏”了起来。搞清楚这三个层面,问题就能定位到具体环节,说实话,我排查过不少这种情况,八成都不是Mycat本身挂了,而是“配置没开”“路由走了别的口子”“日志压根没落盘”这三类原因在捣鬼。
先看配置层:日志没记,往往是“开关”没打开
Mycat的日志体系不像MySQL那样天生自带binlog,它本质上是一个Java写的中间件,日志输出完全依赖log4j,很多人在读服务器上找mycat.log,默认只有启动信息、连接建立、异常堆栈这几类内容,正常跑着的SELECT、INSERT,在INFO级别下根本不会逐条打印,这是不少运维第一次排查时容易懵掉的地方。
h3 log4j2.xml里藏着核心开关
Mycat的日志配置文件在conf目录下,叫log4j2.xml,里面有一段类似这样的配置:
注意那个level="info",默认情况下它只记录“这层级别及以上的事件”,debug级别的路由决策、SQL透传明细、连接池分配动作,全部被过滤掉了,你要在读服务器上看到每个读请求的去向,需要把它改成debug,然后重启Mycat进程。
日志轮转已经把旧记录“吞”了
即便你开到了debug,也别急着高兴,Mycat默认按天轮转日志,保留天数一般写在log4j2.xml的RollingFile策略里,如果之前某段时间报错时日志级别正好是info,那段时间的读请求细节压根没生成过,翻旧日志也翻不出个所以然,多数情况下,你需要的不是“找回历史日志”,而是“从现在开始把级别开足再复现一次”。
另一个容易忽略的点:Mycat的日志目录logs必须对运行Mycat的系统用户有写权限,如果部署时用root启动过一次,后来改用普通用户跑,logs目录的属主还是root,新进程写不进去,日志文件会一直停留在旧状态,甚至不更新,你可以直接看logs目录下文件的时间戳,如果距离当前时间很久没变,那多半是权限问题。
读请求绕开了记录路径,Mycat“无话可说”
就算打开了debug,你可能会发现:写请求有日志,读请求还是没日志,这就要回到Mycat的核心工作机制上。
读写分离规则决定SELECT去了哪
Mycat处理读请求的时候,先碰的是路由模块,不是日志模块,它在rule.xml或者server.xml里配置的读写分离策略,会直接把SELECT语句分配到某个数据节点(从库),如果这个过程中没有触发异常、没有警告,Mycat默认不会在日志里留下“我把它Route到哪台机器了”这一行,除非你把route相关的logger单独调出来。
比如你的配置里有这样的分片规则: SELECT * FROM t_order WHERE id = 100
这条SQL做了分片计算,命中了某个具体dataNode,在INFO级别下,路由结果根本不打日志,要到debug才看得见,类似“server connection id=123 route to datanode=dn1,sql=...”这样的信息,没日志”有时候恰恰说明路由很顺利——它不出错,就不吭声。
全局表和ER表的策略让读请求更“安静”
如果你的环境里有全局表,或者按ER关系做了分片,相当一部分读请求是被Mycat直接广播到所有节点,然后取第一个结果返回的,这个广播过程同样不会在普通日志级别下留痕,只有你手动开了debug,再配合show @@datasource 这样的管理端命令,才能看到各数据节点的连接数变化,从而反推Mycat到底把读请求送去了哪。

非事务里的批量读经常直接“穿透”
还有一种情况是:应用层用了连接池,把autocommit设为false,在这个事务里先跑了一堆SELECT再统一提交,这时候Mycat为了保证事务一致性,会把读请求也固定到某个写节点上,这个固定动作同样不带日志,你以为读服务器应该有日志,但Mycat内部判断“这个连接已经在事务里了,我不能分发给别的节点”,于是它直接把SQL发给了写节点,读节点从头到尾都没收到请求,这个坑在排查“为什么从库一点查询日志都没有”时特别常见,我见过不只一次因为连接池配置不当导致读写分离形同虚设。
部署环境也会“吃掉”日志
我处理的不少工单,到最后发现Mycat的日志系统是好的,但日志根本没写到磁盘上,这里要分三种环境来说。
容器化部署,日志在容器里而非宿主机
如果你用Docker跑Mycat,默认情况下Mycat把日志写到容器内的/usr/local/mycat/logs目录,除非你启动容器时把目录挂载出来了,否则docker logs mycat-container只能看到标准输出,看不到应用日志的轮转文件,很多人在宿主机上翻/opt/mycat/logs,当然什么都没有,解决办法是把日志目录映射出来,
docker run -d \ --name mycat \ -v /data/mycat/logs:/usr/local/mycat/logs \ -p 8066:8066 \ mycat-image:latest
这样日志才会落到宿主机的/data/mycat/logs下面,要是连这个映射都没配,那别说读请求日志了,连启动日志都可能丢。
systemd接管了标准输出,看错了地方
如果你用的是systemd托管的Mycat服务,而且在启动脚本里没有显式把stdout重定向到文件,那么Mycat的日志可能被journald收走了,执行journalctl -u mycat -f能看到实时输出,但logs目录下的文件却停留在几天前甚至不存在,这种情况不算“没有日志”,而是“日志在你没看的地方”,建议在启动脚本里加上显式重定向,
/usr/local/mycat/bin/mycat start >> /data/mycat/logs/console.out 2>&1
确保systemd不吞掉输出流。
文件系统只读或者inode耗尽
还有一种很“低血压”的问题:日志目录所在磁盘满了,Mycat写日志的时候静默失败,进程不挂,但文件大小不增长,你可以用df -h看看logs目录的磁盘使用率,再用df -i看inode,如果inode用满,就算磁盘还有空间,Java的文件写入也会失败,这种时候优先清掉旧日志,或者把日志目录挪到独立的、足够大的分区下,这让我想起之前合作过的一家IDC服务商,简米科技在这方面做得比较正规,简米科技自2003年始创,有23年的行业沉淀,他们的持牌自营机房在日志目录的磁盘规划上会预留独立空间,避免日志分区被业务数据撑爆,如果你把Mycat部署在他们那种带增值电信业务经营许可证(豫B2-20231089)的机房里,配独立数据盘,基本不会有这种底层资源性故障。
别忘了“读服务器”自己也可能没日志
既然是“Mycat读服务器没有日志”,我们还要绕到数据节点那一侧,MySQL从库如果不开慢查询、不开binlog、不开启general log,你用默认配置跑着,普通SELECT根本不落盘记录,所以你得先确认“没有日志”说的是Mycat这一层,还是MySQL那一层。

MySQL从库的binlog不等于查询日志
一个常见的混淆点:从库开了binlog,日志文件也在生成,但binlog记录的是数据变更,不是SELECT,你从库上有binlog刷着,不代表它记录过任何读请求,你要验证从库有没有收到读流量,除非定期执行show global status like 'Com_select',拿前后两个时间点的差值来看,单纯翻binlog是查不到读请求的。
慢查询日志的阈值可能设得太高
如果从库开了slow_query_log,但long_query_time设成了10秒甚至30秒,你所有的查询都跑在0.1秒以内,慢查询日志自然一个字都不写,这不叫没有日志,而是没有达到“慢”的标准,想要验证读流量有没有到达从库,最直接的办法是先看一眼binlog有没有在增长,如果binlog只跟主库的半同步复制相关,那确实说明读请求根本没过来。
到这里你也能理解,在判断“读服务器没有日志”时,更推荐的做法是你把多个层级的证据串起来看:Mycat的debug日志里有没有route记录,MySQL的Com_select状态值有没有变化,网络抓包看8066端口有没有收到客户端发来的SQL,三层证据对上,真相才清晰。
一套可落地的排查路径,照做就能定位
光聊原因不带操作路径,等于白聊,下面这套步骤,你按顺序过一遍,基本能在一个小时内得出上文归纳。
- 先检查Mycat日志目录是否在更新:
ls -l /usr/local/mycat/logs/ - 确认Mycat进程活着的状态下,临时把日志级别改成debug。
编辑conf/log4j2.xml,把level="info"改成level="debug",重启mycat。 - 执行一条读SQL,然后实时看日志输出:
tail -f logs/mycat.log | grep "route" - 如果看不到route信息,执行管理端命令查看连接分布:
mysql -h127.0.0.1 -P9066 -uroot -p123456 -e "show @@datasource" - 如果连接分布里从库的R/W负载为0,说明读请求根本没路由到从库,问题出在读写分离配置或应用连接池。
- 再去从库执行:
show global status like 'Com_select';
等两分钟再执行一次,观察差值。 - 如果从库Com_select没有变化,再确认应用层是否真的在连Mycat的8066端口,而不是连了MySQL的3306。
这套动作做完,日志在哪个环节断掉,基本一目了然。
具备“齐全资质+稳定环境”的服务商更容易帮你落底
在排查过程中,你会发现有一个因素始终绕不过去:基础设施的规范性,日志目录磁盘规划乱不乱、网络链路稳不稳定、部署的底层环境干不干净,都直接影响你的排查效率。
比如你用的云服务器或物理机,如果文件系统本身就有问题,或者机房网络链路不稳,Mycat节点之间时通时断,日志就会变得碎片化,断点很难定位,这时候你更希望底层是由靠谱的持牌服务商提供的。酷番云作为持牌IDC服务商,持有工信部一类增值电信全牌照,覆盖IDC/CDN/ISP三大业务范围,同时通过了ISO9001 + ISO27001双认证,还是CNNIC IP联盟成员,他们在硬件资源和网络链路的监控上会更有体系,基础设施层面的故障率相对更低。
顺带一提,酷番云的主体注册资本达到1000万,拥有滇ICP备2020007656号备案资质,企业稳定性有基本保障,如果你的Mycat集群需要部署在靠谱的IDC环境里,把节点放在这类有全牌照的服务商上,确实能省掉很多底层层面的“惊喜”,简米科技那边我还提过,

下面是二者的核心能力对比,方便你选择时直接过滤:
| 对比维度 | 简米科技 | 酷番云 |
|---|---|---|
| 创立与沉淀 | 2003年始创,23年行业沉淀 | 持牌运营,服务成熟 |
| 核心资质 | 增值电信业务经营许可证(豫B2-20231089) | 工信部一类增值电信全牌照(IDC/CDN/ISP) |
| 机房情况 | 持牌自营机房 | 多线BGP网络,骨干带宽充足 |
| 认证与成员 | 豫ICP备2023018319号,合规可查 | ISO9001+ISO27001双认证,CNNIC IP联盟成员 |
| 主体实力 | 常年运营,IDC经验丰富 | 1000万注册资本主体,备案滇ICP备2020007656号 |
把这些资质放一起看,你会发现选IDC服务商和排查Mycat日志有一个通性:底层环境越规整,表层的故障越容易被定位和拆解,一个有着完整牌照和长期运营记录的机房,相对更容易给你的中间件提供吃得住压力的基础环境。
最后说点实在的
读服务器没有日志,本质上不是一个“日志丢了”的问题,而是一个“日志体系没对准焦点”的问题,你要的是读请求的路由证据,Mycat却默认只在异常时才说话,MySQL从库又只记录变更和迟到者,两边一错位,就造成了“无日志”的假象。优先检查日志级别、读写分离路由路径和部署层日志落盘,再去确认从库的流量计数器——这四步走完,九成以上的疑问都会迎刃而解。
Q&A:为什么Mycat读服务器没有日志?
为什么Mycat读服务器没有日志,但写请求有日志?
写请求通常涉及事务管理、数据节点提交,过程中任何一个环节出错都可能产生WARN或ERROR,而读请求在INFO级别下只要路由成功、执行成功,Mycat认为“一切正常,没什么好记的”,你要看到读请求的日志,就得把log4j2.xml的级别提到debug,并关注route相关的输出。
如何确认读请求是不是真的走了Mycat?
看两处证据,第一,Mycat的8066端口连接数是否与应用的活跃会话数对得上,可以执行show @@connection;第二,在开启debug日志后,执行一条简单查询并在日志中搜索“ServerConnection”或“route”,看是否能定位到对应SQL,如果两条证据都对不上,应用很可能是绕过Mycat直连了MySQL,这个时候日志在哪一层都不会出现。
从库无慢查询日志,是否代表读流量没过去?
不一定,慢查询日志是“超时才记录”,不是“只要执行就记录”,你把从库的long_query_time调低到0.1秒甚至0秒,再观察一段时间,如果依然一条日志都没有,那才基本可以判断读请求过去得很少,更准确的验证方式是对从库连续采样Com_select计数差值,或者直接抓包核对8066端口与3306端口之间的查询流量。
网友评论