在ActiveRecord::StatementInvalid昨天的 4 小时内,我们看到MySQL 服务器出现零星错误。从那以后这些错误就没有发生过。
奇怪的是,SQL 语句似乎已被破坏:一个随机字符或更多向后或向前移动 2 个字节。例如,"Unknown table 'erades'"对于一个grades表的查询。这不仅限于表名:列名、SQL 关键字和值都在这些查询中受到影响。
错误消息示例:
.->,:表'[数据库名称].id'不存在:SELECT [..] FROM [..] INNER JOIN [..] ON [..] = `[table name]`.`id`。 .
`->b:不正确的表名'topic_setsb ON':SELECT [..] FROM [..] INNER JOIN `topic_sets` ON ...
s->q:'field list'中的未知列'aqsigned_[redacted]'
U->W:您的 SQL 语法有错误;[..] 'NWLL GROUP BY ...
8->附近::您的 SQL 语法有错误;[..] near ':887)' at line 1: SELECT [..] WHERE [..] IN (48846, 48901, 48887)
由于 MySQL 可能只报告语句中的第一个错误,我无法确定每个语句的确切损坏次数。消息中包含的完整 SQL 查询似乎是客户端保存的语句的副本,并且消息的该部分没有损坏。
在某些情况下,我无法从错误消息中判断出哪个字符可能已损坏,例如“在第 1 行的 '' 附近使用的正确语法”,并且并非所有损坏都与字节移位有关。这可能来自无法打印的字符,或者可能插入/删除了字符。
有一个有点陈述被损坏的方式固定的模式,但似乎没有一个明确的规则。例如,将有 10-20 次出现 10-20 次相同语句以相同方式损坏的模式,但这些模式之间损坏的位置各不相同。
我可以从 RDS 控制台获取的错误日志是空的。在该时间段内没有报告 AWS 服务降级。
我们的异常跟踪工具总共报告了 143 个错误。它们来自 4 个乘客工作人员,2 个在同一个 EC2 实例上,另外两个在另一个 EC2 实例上。这些工作人员的错误计数分布:1、41、42、50。这大约是发生这种情况的 4 小时内服务的请求总数的 0.001%。
对于每个工作人员来说,错误发生在涓涓细流中:每个人报告这些错误大约 5 分钟,每隔几秒到 2-3 分钟就会发生 1-2 个错误——除了只有 1 个错误的那个。
有些查询针对主数据库,有些针对副本数据库。
时间线
instance A launch 2018-11-13 12:00 UTC
instance A process P errors 2018-11-13 13:40-13:43 UTC
instance A process Q errors 2018-11-13 14:22-14:26 UTC
instance A shutdown 2018-11-13 20:00 UTC
instance B launch 2018-11-13 15:00 UTC
instance B process R errors 2018-11-13 15:39-15:40 UTC
instance B process S errors 2018-11-13 17:39-17:43 UTC
instance B shutdown 2018-11-13 23:00 UTC
Run Code Online (Sandbox Code Playgroud)
一位熟人承认他们在同一天在 AWS 中看到了同样的错误,并参考了这个 关于网络级数据损坏的演讲[1]:它谈到了网络交换机如何在重新路由时重新计算数据包的以太网 CRC重路由过程可能会产生一个“有效”的CRC,而TCP校验和怎么也有漏洞。(kevinchen.co 的文字说明)。
[1] !!Con 2017:数据中心腐败!TCP 可能无法保证您的数据安全!通过埃文琼斯
他们的建议是使用 TLS 进行所有通信,因为 TLS 层将无法解密损坏的字节。
我还发现这个页面描述了 CRC 和校验和的限制。这个serverfault 问题中有一个类似的错误,原因也与网络有关。
我越来越相信这些错误是由网络级别的错误引起的。
以太网/TCP 理论是否与我描述的错误行为一致?我不确定一次只有一个进程是否可能看到此错误,尽管我认为如果交换机决定根据源 - 目标端口对以不同方式处理数据包,则可能会发生这种情况,因为每个连接都将使用不同的端口。
如果这实际上是一个 XY 问题,我很乐意重新定义这个问题。
注意:我已经向AWS 论坛发布了一个请求,以确认/调查这是来自 AWS 基础设施的东西。在这里,在 serverfault 中,我有兴趣了解假设的合理性以及它如何表现出我看到的(或没有看到的)行为。
这是在合理范围之内,很难得出任何结论。您列出的位翻转在 8 位对齐时是一致的。虽然看到整个消息会很有趣,因为(可能)网络帧中还必须进行其他翻转才能挫败 CRC/校验和。
就“同一台机器上只有一些工作人员报告错误”而言,可能是 - 工作人员之间的负载不相等,这只是每个进程生成的流量字节数的影响,或者如果工作人员确实保持持久连接,你只是输掉了路径选择中的机会游戏。即,在沿途某个地方存在多个活动链接的情况下,报告错误的工作人员碰巧拥有散列到错误链接的连接。(请注意,对于 L2 (lacp/bond) 和 L3 (ECMP) 而言,散列 (srcip、srcport、dstip、dstport) 用于链接选择并不罕见)。对于寿命较短的连接来说也是可能的,尽管现在这种可能性越来越小。AWS 也完全有可能对其网络有更深奥的路径选择,这也可以解释这一点。
我通常会有点粗糙并寻找其他确凿的证据,例如来自操作系统、网卡和交换机/路由器的校验和错误计数器,尽管我倾向于说您对某些实例的拆分没有问题,而其他实例作为良好的佐证证据确实存在问题。
翻转图案:
00101110 .
00101100 ,
00000010 xor
01100000 `
01100010 b
00000010 xor
01110011 s
01110001 q
00000010
01010101 U
01010111 W
00000010 xor
00111000 8
00111010 :
00000010 xor
Run Code Online (Sandbox Code Playgroud)