MySQL ORDER BY 的实现分析

2009年4月22日 龙飞 没有评论

总的来说,在 MySQL 中的ORDER BY有两种排序实现方式,一种是利用有序索引获取有序数据,另一种则是通过相应的排序算法,将取得的数据在内存中进行排序。

下面将通过实例分析两种排序实现方式及实现图解:
假设有 Table A 和 B 两个表结构分别如下:

sky@localhost : example 01:48:21> show create table A\G
***************************
1. row ***************************
Table: A
Create Table: CREATE TABLE `A` (
`c1` int(11) NOT NULL default 0,
`c2` char(2) default NULL,
`c3` varchar(16) default NULL,
`c4` datetime default NULL,
PRIMARY KEY (`c1`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

sky@localhost : example 01:48:32> show create table B\G
***************************
1. row ***************************
Table: B
Create Table: CREATE TABLE `B` (
`c1` int(11) NOT NULL default 0,
`c2` char(2) default NULL,
`c3` varchar(16) default NULL,
PRIMARY KEY (`c1`),
KEY `B_c2_ind` (`c2`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

1、利用有序索引进行排序,实际上就是当我们 Query 的 ORDER BY 条件和 Query 的执行计划中所利用的 Index 的索引键(或前面几个索引键)完全一致,且索引访问方式为 rang、 ref 或者 index 的时候,MySQL 可以利用索引顺序而直接取得已经排好序的数据。这种方式的 ORDER BY 基本上可以说是最优的排序方式了,因为 MySQL 不需要进行实际的排序操作。

假设我们在Table A 和 B 上执行如下SQL:

sky@localhost : example 01:44:28> EXPLAIN SELECT A.* FROM A,B
-&
gt; WHERE A.c1 > 2 AND A.c2 < 5 AND A.c2 = B.c2 ORDER BY A.c1\G
***************************
1. row ***************************
id: 1
select_type: SIMPLE
table: A
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: NULL
rows: 3
Extra: Using where
***************************
2. row ***************************
id: 1
select_type: SIMPLE
table: B
type: ref
possible_keys: B_c2_ind
key: B_c2_ind
key_len: 7
ref: example.A.c2
rows: 2
Extra: Using where; Using index

我们通过执行计划可以看出,MySQL实际上并没有进行实际的排序操作,实际上其整个执行过程如下图所示:

2、通过相应的排序算法,将取得的数据在内存中进行排序方式,MySQL 比需要将数据在内存中进行排序,所使用的内存区域也就是我们通过 sort_buffer_size 系统变量所设置的排序区。这个排序区是每个 Thread 独享的,所以说可能在同一时刻在 MySQL 中可能存在多个 sort buffer 内存区域。

第二种方式在 MySQL Query Optimizer 所给出的执行计划(通过 EXPLAIN 命令查看)中被称为 filesort。在这种方式中,主要是由于没有可以利用的有序索引取得有序的数据,MySQL只能通过将取得的数据在内存中进行排序然后再将数据返回给客户端。在 MySQL 中 filesort 的实现算法实际上是有两种的,一种是首先根据相应的条件取出相应的排序字段和可以直接定位行数据的行指针信息,然后在 sort buffer 中进行排序。另外一种是一次性取出满足条件行的所有字段,然后在 sort buffer 中进行排序。

在 MySQL4.1 版本之前只有第一种排序算法,第二种算法是从 MySQL4.1开始的改进算法,主要目的是为了减少第一次算法中需要两次访问表数据的 IO 操作,将两次变成了一次,但相应也会耗用更多的 sort buffer 空间。当然,MySQL4.1开始的以后所有版本同时也支持第一种算法,MySQL 主要通过比较我们所设定的系统参数 max_length_for_sort_data 的大小和 Query 语句所取出的字段类型大小总和来判定需要使用哪一种排序算法。如果 max_length_for_sort_data 更大,则使用第二种优化后的算法,反之使用第一种算法。所以如果希望 ORDER BY 操作的效率尽可能的高,一定要主义 max_length_for_sort_data 参数的设置。曾经就有同事的数据库出现大量的排序等待,造成系统负载很高,而且响应时间变得很长,最后查出正是因为 MySQL 使用了传统的第一种排序算法而导致,在加大了 max_length_for_sort_data 参数值之后,系统负载马上得到了大的缓解,响应也快了很多。

我们再看看 MySQL 需要使用 filesort 实现排序的实例。

假设我们改变一下我们的 Query,换成通过A.c2来排序,再看看情况:

sky@localhost : example 01:54:23> EXPLAIN SELECT A.* FROM A,B
-&
gt; WHERE A.c1 > 2 AND A.c2 < 5 AND A.c2 = B.c2 ORDER BY A.c2\G
***************************
1. row ***************************
id: 1
select_type: SIMPLE
table: A
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: NULL
rows: 3
Extra: Using where; Using filesort
***************************
2. row ***************************
id: 1
select_type: SIMPLE
table: B
type: ref
possible_keys: B_c2_ind
key: B_c2_ind
key_len: 7
ref: example.A.c2
rows: 2
Extra: Using where; Using index

MySQL 从 Table A 中取出了符合条件的数据,由于取得的数据并不满足 ORDER BY 条件,所以 MySQL 进行了 filesort 操作,其整个执行过程如下图所示:

在 MySQL 中,filesort 操作还有一个比较奇怪的限制,那就是其数据源必须是来源于一个 Table,所以,如果我们的排序数据如果是两个(或者更多个) Table 通过 Join所得出的,那么 MySQL 必须通过先创建一个临时表(Temporary Table),然后再将此临时表的数据进行排序,如下例所示:

sky@localhost : example 02:46:15> explain select A.* from A,B
-&
gt; where A.c1 > 2 and A.c2 < 5 and A.c2 = B.c2 order by B.c3\G
***************************
1. row ***************************
id: 1
select_type: SIMPLE
table: A
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: NULL
rows: 3
Extra: Using where; Using temporary; Using filesort
***************************
2. row ***************************
id: 1
select_type: SIMPLE
table: B
type: ref
possible_keys: B_c2_ind
key: B_c2_ind
key_len: 7
ref: example.A.c2
rows: 2
Extra: Using where

这个执行计划的输出还是有点奇怪的,不知道为什么,MySQL Query Optimizer 将 “Using temporary” 过程显示在第一行对 Table A 的操作中,难道只是为让执行计划的输出少一行?

实际执行过程应该是如下图所示:

作者:Sky.Jian

链接:http://www.jianzhaoyang.com/database/mysql_order_by_implement

分类: mysql相关 标签: ,

MySQL内存使用-线程独享

2009年4月22日 龙飞 没有评论

对于任何一个数据库管理系统来说,内存的分配使用绝对可以算的上是其核心之一了,所以很多希望更为深入了解某数据库管理系统的人,都会希望一窥究竟,我也不例外。

从内存的使用方式MySQL 数据库的内存使用主要分为以下两类

  • 线程独享内存
  • 全局共享内存

今天这篇文章暂时先分析 MySQL 中主要的 “线程独享内存” 的。

在 MySQL 中,线程独享内存主要用于各客户端连接线程存储各种操作的独享数据,如线程栈信息,分组排序操作,数据读写缓冲,结果集暂存等等,而且大多数可以通过相关参数来控制内存的使用量。

线程栈信息使用内存(thread_stack):主要用来存放每一个线程自身的标识信息,如线程id,线程运行时基本信息等等,我们可以通过 thread_stack 参数来设置为每一个线程栈分配多大的内存。

排序使用内存(sort_buffer_size):MySQL 用此内存区域进行排序操作(filesort),完成客户端的排序请求。当我们设置的排序区缓存大小无法满足排序实际所需内存的时候,MySQL 会将数据写入磁盘文件来完成排序。由于磁盘和内存的读写性能完全不在一个数量级,所以sort_buffer_size参数对排序操作的性能影响绝对不可小视。排序操作的实现原理请参考:MySQL Order By 的实现分析

Join操作使用内存(join_buffer_size):应用程序经常会出现一些两表(或多表)Join的操作需求,MySQL在完成某些 Join 需求的时候(all/index join),为了减少参与Join的“被驱动表”的读取次数以提高性能,需要使用到 Join Buffer 来协助完成 Join操作(具体 Join 实现算法请参考:MySQL 中的 Join 基本实现原理)。当 Join Buffer 太小,MySQL 不会将该 Buffer 存入磁盘文件,而是先将Join Buffer中的结果集与需要 Join 的表进行 Join 操作,然后清空 Join Buffer 中的数据,继续将剩余的结果集写入此 Buffer 中,如此往复。这势必会造成被驱动表需要被多次读取,成倍增加 IO 访问,降低效率。

顺序读取数据缓冲区使用内存(read_buffer_size):这部分内存主要用于当需要顺序读取数据的时候,如无发使用索引的情况下的全表扫描,全索引扫描等。在这种时候,MySQL 按照数据的存储顺序依次读取数据块,每次读取的数据快首先会暂存在read_buffer_size中,当 buffer 空间被写满或者全部数据读取结束后,再将buffer中的数据返回给上层调用者,以提高效率。

随机读取数据缓冲区使用内存(read_rnd_buffer_size):和顺序读取相对应,当 MySQL 进行非顺序读取(随机读取)数据块的时候,会利用这个缓冲区暂存读取的数据。如根据索引信息读取表数据,根据排序后的结果集与表进行Join等等。总的来说,就是当数据块的读取需要满足一定的顺序的情况下,MySQL 就需要产生随机读取,进而使用到 read_rnd_buffer_size 参数所设置的内存缓冲区。

连接信息及返回客户端前结果集暂存使用内存(net_buffer_size):这部分用来存放客户端连接线程的连接信息和返回客户端的结果集。当 MySQL 开始产生可以返回的结果集,会在通过网络返回给客户端请求线程之前,会先暂存在通过 net_buffer_size 所设置的缓冲区中,等满足一定大小的时候才开始向客户端发送,以提高网络传输效率。不过,net_buffer_size 参数所设置的仅仅只是该缓存区的初始化大小,MySQL 会根据实际需要自行申请更多的内存以满足需求,但最大不会超过 max_allowed_packet 参数大小。

批量插入暂存使用内存(bulk_insert_buffer_size):当我们使用如 insert … values(…),(…),(…)… 的方式进行批量插入的时候,MySQL 会先将提交的数据放如一个缓存空间中,当该缓存空间被写满或者提交完所有数据之后,MySQL 才会一次性将该缓存空间中的数据写入数据库并清空缓存。此外,当我们进行 LOAD DATA INFILE 操作来将文本文件中的数据 Load 进数据库的时候,同样会使用到此缓冲区。

临时表使用内存(tmp_table_size):当我们进行一些特殊操作如需要使用临时表才能完成的 Order By,Group By 等等,MySQL 可能需要使用到临时表。当我们的临时表较小(小于 tmp_table_size 参数所设置的大小)的时候,MySQL 会将临时表创建成内存临时表,只有当 tmp_table_size 所设置的大小无法装下整个临时表的时候,MySQL 才会将该表创建成 MyISAM 存储引擎的表存放在磁盘上。不过,当另一个系统参数 max_heap_table_size 的大小还小于 tmp_table_size 的时候,MySQL 将使用 max_heap_table_size 参数所设置大小作为最大的内存临时表大小,而忽略 tmp_table_size 所设置的值。而且 tmp_table_size 参数从 MySQL 5.1.2 才开始有,之前一直使用 max_heap_table_size。

上面所列举的 MySQL 线程独享内存仅仅只是所有线程独享内存中的部分,并不是全部,选择的原则是可能对 MySQL 的性能产生较大的影响,且可以通过系统参数进行调节。

由于以上内存都是线程独享,极端情况下的内存总体使用量将是所有连接线程的总倍数。所以各位朋友在设置过程中一定要谨慎,切不可为了提升性能就盲目的增大各参数值,避免因为内存不够而产生 Out Of Memory 异常或者是严重的 Swap 交换反而降低整体性能。

作者:Sky.Jian
链接:http://www.jianzhaoyang.com/database/mysql-memory-thread-private

分类: mysql相关 标签:

华为交换机的端口限速

2009年4月21日 龙飞 没有评论

最近在电信idc的宽频流量有点涨,所以想把一些非关键应用的流量通过端口限速限制一下。
限速的这台交换机是S5024G,其实大部分华为交换机都通用,只是细粒度不一样用得时候 ? 看看单位值就行。

操作步骤:
进入交换机console

<S5024G-1>system-view
Enter system view, return to user view with Ctrl+Z.
[S5024G-1]interface GigabitEthernet0/2
[S5024G-1-GigabitEthernet0/2]line-rate ?
INTEGER<1-1000> Target rate(Mbps)

这里line-rate单位是Mbps,直接输入数字1-1000就代表1Mbps-1000Mbps,我们限制为50Mbps。

[S5024G-1-GigabitEthernet0/2]line-rate 50

这里要注意 line-rate 只能对交换机端口的出流量进行限速。
如果要对端口入流量限速的话就必须要用traffic-limit方式,使用traffic-limit则必须要用acl匹配。

[S5024G-1]acl number 4000
[S5024G-1-acl-link-4000]rule permit ingress any egress any

然后再在端口里面添加traffic-limit,这里对入方向限速50Mbps

[S5024G-1-GigabitEthernet0/2]traffic-limit inbound link-group 4000 50 exceed drop

这样就ok了。

iis下面php getenv(‘HTTP_X_FORWARDED_FOR’)取不到ip

2009年4月16日 龙飞 没有评论

环境是win2003 iis6 php(isapi)
应用是个dz,最近在上了cdn后发现用户过来的ip都是squid服务器的地址,看了下dz的源代码

1
2
3
4
5
6
7
8
9
if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
	$onlineip = getenv('HTTP_CLIENT_IP');
} elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
	$onlineip = getenv('HTTP_X_FORWARDED_FOR');
} elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
	$onlineip = getenv('REMOTE_ADDR');
} elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
	$onlineip = $_SERVER['REMOTE_ADDR'];
}

对比了下另外一台linux的机器发现是可以取到的。
于是用_SERVER["HTTP_X_FORWARDED_FOR"]试了试是可以取到用户ip的,难道在windows下面不能用getenv?
最后略微修改了下dz的代码搞定了

1
2
3
4
5
6
7
8
9
10
11
if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
	$onlineip = getenv('HTTP_CLIENT_IP');
} elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
	$onlineip = getenv('HTTP_X_FORWARDED_FOR');
} elseif($_SERVER["HTTP_X_FORWARDED_FOR"] && strcasecmp($_SERVER["HTTP_X_FORWARDED_FOR"], 'unknown')) {
	$onlineip = $_SERVER["HTTP_X_FORWARDED_FOR"];
} elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
	$onlineip = getenv('REMOTE_ADDR');
} elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
	$onlineip = $_SERVER['REMOTE_ADDR'];
}
分类: php相关, windows相关 标签:

电信EVDO 3G无线宽带试用

2009年4月15日 龙飞 1 条评论

其实半个多月前就体验过EVDO了,同事去采访发布会的时候带回来过一个,那次纯粹就是安装上网流程化体验了下,记得是个华为的设备。

这次单位领导正好把以前的老的cmda上网卡去换了个回来,由于老婆童装店里也正在考虑搞个无线上网省的装宽带了,所以带回来试了试信号顺便试用下。

这次的拿回来的2个是中兴 AC560的设备,东西蛮好看就个u盘大小,上面除了uim卡插槽外还有个tf卡插槽,能当读卡器用,貌似还有2喇叭。做工不错
image
由于有了上次安装的经验,所以直接就像u盘那样插进usb口,电脑提示发现新硬件,其实是个u盘,里面就是上网卡的驱动,现在这设计蛮好的省的光盘了。一路驱动装完后出现了拨号界面,直接选3G,顺利上网,连接速率3.1M。
image image
选择本地服务器测试了下载和上传速度,用的ftp单线程,下载峰值200kb出头,平均在100kb上下,上传峰值80多kb,平均在50kb上线。上传和下载基本处于上下波动状态忽高忽低,没有一刻是稳定的。下载的同时上传会对下载速度有一些影响。

浏览网页,qq等操作那是和adsl基本无异,速度飞快,比以前1x快不知道多少倍。

试用感觉良好,连接目前看来很稳定,可以考虑作为宽带替代方案,就是不知道费用如何。

分类: 只谈心情 标签:

iptables在防火墙应用方面的简单教程(第2版)

2009年4月13日 龙飞 没有评论

#首先全部允许数据包通过,防止默认丢包的话下面删除规则造成数据包全部丢掉
#允许所有进来的包
iptables -P INPUT ACCEPT
#允许所有出去的包
iptables -P OUTPUT ACCEPT

#初始化iptables 清空所有规则和组
#删除所有规则
iptables -F
#删除所有组
iptables -X

#这里才是正式开始配置iptables
#创建新的定义firewall_in
iptables -N firewall_in

#指定firewall_in组应用到INPUT chain,类似于应用组
iptables -A INPUT -j firewall_in

#指定firewall_in组应用到FORWARD chain,类似于应用组。
iptables -A FORWARD -j firewall_in

#这里开始增加规则,这里例子里规则都是添加到firewall_in组
#localhost数据包全部允许通过
iptables -A firewall_in -i lo -j ACCEPT

#所有已经建立连接的数据包全部通过
iptables -A firewall_in -m state –state RELATED,ESTABLISHED -j ACCEPT

#所有地址开放tcp 80端口
iptables -A firewall_in -p tcp -m tcp –dport 80 -j ACCEPT

#ping数据包允许每秒通过1个
iptables -A firewall_in -p icmp -m limit –limit 1/s –limit-burst 10 -j ACCEPT

#向10.1.1.0/255.255.255.0网段开放eth0网卡上面并且目的ip地址为10.1.1.1的22端口(这是一个功能示例:网卡、协议类型、源地址组、目的地址、目的端口都有体现)
iptables -A firewall_in -i eth0 -p tcp -m tcp -s 10.1.1.0/255.255.255.0 -d 10.1.1.1 –dport 22 -j ACCEPT

#下面这2行是ftp server的pasv模式开放示例,因为ftp的pasv模式端口是随机打开的所以需要另外设置ftp server的pasv端口范围为60000-60004
iptables -A firewall_in -p tcp -m tcp -s 10.1.1.2 –dport 21 -j ACCEPT
iptables -A firewall_in -p tcp -m tcp -s 10.1.1.2 –dport 60000:60004 -j ACCEPT

#丢弃不符合规则的其它tcp和udp数据包,如果处于调试的最好先不要用这2行,万一规则错了就麻烦了
iptables -A firewall_in -p tcp -m tcp -j DROP
iptables -A firewall_in -p udp -m udp -j DROP

#清除规则匹配数据包计数信息
iptables -Z

#禁止所有进来的包,iptables是从上往下匹配的,如果有符合的话就结束匹配了,这里丢弃和上面规则里面的丢弃相比更加彻底。
#同样如果处于调试的最好先不要用这2行,万一规则错了就麻烦了
iptables -P INPUT DROP

#应许所有出去的包,这个防火墙只是简单的进行入站包的过滤,如果需要出站包也要过滤话可以给OUTPUT chain单独一个组然后把参考上面把出站规则写到对应的组里
iptables -P OUTPUT ACCEPT

#最后保存iptables,这样重启后也能应用
/etc/init.d/iptables save

虽然iptables可以通过命令进行修改插入和删除操作,但是这里极不推荐新手这样来修改iptables,我推荐大家是把我上面的这样的命令(去掉注释)保存下来,一方面是做好记录,另一方面在下次修改的时候可以很方便的修改文本,然后把命令全部粘贴进命令行就行。

另外查看目前iptables的内容指令:
iptables -L -vn

分类: linux相关 标签:

Update Manager 主机扫描更新提示patch metadata for xxxx missing解决

2009年4月10日 龙飞 没有评论

Update Manager是一款VMware VirtualCenter插件,可以对esx和vm操作系统 进行在线补丁更新。

前两天看到esx已经出3.5 u4了,所以今天抽空打算升级一下的,启用Update Manager,设置更新内容下载补丁都蛮正常,结果在对esx主机进行 scan for updates(扫描更新) 的时候出错。事件里面提示patch metadata for xxxx missing. please download updates metadata first.

去官网kb补习了一下,说这种情况一般是esx无法连上vc的um造成的。常见的可能性就是:
1是esx的防火墙没开8080的out规则
2是vc的机器上可能有多个ip或者网卡,恰好um给esx的ip或者vc的hostname esx连接不上。

所以解决方法首先就是打开esx 防火墙的访问外部8080端口
用ssh登入上esx(注意root用户默认是无法ssh登陆的)先su到root权限执行下面指令:
/usr/sbin/esxcfg-firewall -o 8080,tcp,out,updatemanager

如果安装vc的时候选择的http端口不是8080请做相应修改。

然后在vc主机上在服务里停掉VMware Update Manager Service,在进入Update Manager目录修改文件:
C:\Program Files\VMware\Infrastructure\Update Manager\vci-integrity.xml

找到
<HostConfig>
下面的
<PatchDepotUrl/>
改为
<PatchDepotUrl>http://192.168.0.1:8080/vci/hostupdates/hostupdate</PatchDepotUrl>

其中192.168.0.1就是esx能ping通并且访问到的vc的ip地址,8080端口为安装vc的时候选择的http端口。

然后再启动VMware Update Manager Service,这时应该需要在vc里面重新启用下Update Manager。然后再对esx主机进行扫描更新就可以通过了。

官方对于这个问题的kb:

http://kb.vmware.com/kb/1004914

http://kb.vmware.com/kb/1004330

mysql 5.0的mysqldump导入导出

2009年4月8日 龙飞 没有评论

以前写过个4.0的,现在机器上都是5.0的了,也不知道兼容不兼容4.0的参数,所以干脆看着help重新写了个

我这的环境都是gbk所以下面是以gbk为例子
导出:

1
mysqldump --user="xxx" --password="xxx" --force --quick --skip-opt --create-options --add-drop-table --default-character-set=gbk db1 >db1.sql

其中–force 代表忽略错误,如果导出的数据要导入mysql 4.0的话加个参数–compatible=mysql40

导入:

1
mysql -u"xxx" -p"xxx" --default-character-set=gbk db1 <db1.sql
分类: mysql相关 标签: ,

display_errors设置无效永远off故障一例

2009年4月7日 龙飞 1 条评论

就我这台跑博客的机器,nginx-0.7.37 + php 5.2.8(fastcgi)出现个极度诡异的现象,就是无论php.ini怎么设置display_errors,永远无错误信息显示,觉得不是我搞错文件或者其它问题,别的配置都有效,就是display_errors 设置为on 进phpinfo一看还是off,昏倒,怎么最近老是碰到问题撒,只能log到文件看出错信息。同样的环境在另外一台机器确实好的
最后检查来检查去发现php-fpm.conf里面还有个关于display_errors的设置改成1就搞定了

分类: php相关 标签:

一次netapp2050机头故障的修复经历

2009年4月3日 龙飞 没有评论

今天吃饭前,上网管机,惊现存储监控的页面上面闪红灯,紧急赶往机房一看,一台netapp2050的机头a处于关机状态,于是连机头b查看,机头b的cf status状态是FAS2050B has taken over FAS2050A. 目前存储处于机头b接管状态。

于是又输了几条命令查看了下机头b的状态,当输入stats show 之后,没有出现命令行,ctrl+c也无法退出到命令行,断开终端重连输入用户名和密码后还是处于无命令行状态,顿时抓狂。

联系了下售后,决定先找机头a当机原因,起出机头a,由于机头a处于Waiting for giveback状态(ctrl+c重启后autoboot还是这样),无命令行,web也无法进去,直接用nfs连也无法通过。

到此为止,基本情况就是这样,机头a处于Waiting for giveback等待状态,需要机头b进行giveback才能回到正常工作状态,但是进行这个操作必须在机头b进行命令操作,但是机头b无论串口还是telnet都无法出现命令行。
:???:
抓狂了一阵后,忽然想到rsh可以直接写命令进去,试了下
rsh 10.10.1.1 -l root:root rdfile /etc/log/messages

果然有戏,把机头a的日志给读了出来了,一看原来nvram的电池检测到问题,自动关机了
Thu Apr 2 20:00:27 CST [FAS2050A: kern.shutdown:notice]: System shut down because : “NVRAM BATTERY FAILURE”.

把日志发给售后,netapp那边一开始说发配件换电池把,后来又打电话说无法判断是电池还是充电模块问题,干脆换机头把。 :shock: …说等会给我确定送货时间,我一琢磨下一工作日岂不是要4天后才能搞定了 :evil:
等了一会,售后又打电话过来说netapp那边分析下来应该属于固件版本太低的问题,这个版本固件可能有点bug,电池是应该好的,让我直接giveback。 :???:

没办法客服的话总是要听的,rsh 10.10.1.2 -l root:root cf giveback 结果提示
Partner not waiting for giveback, giveback cancelled.
To do a giveback without checking for partner readiness, please either set optio
n “cf.giveback.check.partner” to “off” before doing “cf giveback” again, or do ”
cf giveback -f”.

The first choice disables checking for all future “cf giveback”, until it’s turn
ed back to “on”. The second choice is good for this giveback only.

客服说我插拔过机头用cf giveback -f,咱照做,果然有反应了
在机头b上面cf status,目前状态是
FAS2050B has taken over FAS2050A, giveback in progress.
giveback is in module “snapmirror”, 118 of 131 modules.

一阵等待后,提示ready for giveback,终于真不容易。。。。
继续 cf giveback
哗啦啦一堆信息滚过之后终于
Cluster enabled,2个机头都up了

最后按照客服提示options autosupport.doit 2000669538 导出一份autosupport报告发了过去。
客服说下周安排过来升级固件。

流水账就此结束,幸亏发现的及时,没有造成什么后果,这次经历之后我乖乖的还是把autosupport邮件名单添加了一份我的手机邮地址,可怜每个星期天半夜要被骚扰一次了。

分类: 硬件相关 标签: