1999年最后一个夜晚,许多人倒数的不只是烟花,还有全球的电脑会不会在午夜过后集体“算错日子”,将2000年错认为1000年。千年虫(Year 2000 Problem,Y2K)并非病毒,而是自20世纪中期以来无数程序的通病,也是资讯工程师常挂在嘴边的“技术债”(Technical Debt):程序先以权宜方式上线,日后再付出更多成本维护。
2000年反比1999年更早
要把危机说清楚,得先回到早期电脑如何记录时间。那时储存昂贵、程序空间有限,程序员编程时常把年份压缩成两位数字,如1988年记为“88”。
世纪交替时,麻烦便一并浮现。有些系统把“00”当成1900年,于是出现2000年反而比1999年更早的荒谬结果,电梯保养、手术排期、排队叫号都可能乱套。比如在计算公积金(CPF)申领资格时,若系统仍默认活在20世纪,答案就会整整偏差100年。处理贷款计息、保险理赔、护照与证件有效日期等,背后也是同一套日期逻辑。
手机应用可以一周上线,但政府、银行、航空系统背后往往仍有运行数十年的旧系统,平时运转如常,却可能在某个日期规则上暗藏隐患。千年虫的本质,是时间仍停在1999年以前的假设,分散在成千上万套程序里,没有单一病毒可杀,只有一张张待核对的清单。尤其在商业金融及银行界,许多关键系统当年用COBOL(Common Business-Oriented Language)等语言写在大型主机上,一跑就是几十年,如同大楼地下室里仍在运转的老水管,平时不显眼,接头锈蚀却可能在某一天同时漏水。
技术修补耗费数千亿美元
1990年代起,各国政府与企业开始逐一盘点和检查自家电脑系统,并展开跨国合作,商讨及实施检修千年虫的方案。
修补并没有统一答案。比较彻底的做法,是把电脑程序和数据库里的年份改成四位,再逐条测试计息、排程与报表,费时费钱。除了改程序,还有大量人力投入在清查旧档案,对照合约,重写说明文件,因为电脑里的日期往往与纸面合同、客户资料绑定在一起,一处改错可能牵动整条业务链。
因此,业内人士采用以下做法,其一是打“滑动窗口”(windowing)补丁,例如制定00至20代表2000至2020年,21至99则原封不动,仍代表1921至1999年。这种方法治标不治本,技术债并未消失,只是延期罢了。
其次,工程团队还会做“穿越测试”(rollover test),把系统时钟拨到1999年12月31日23时59分,观察跨过2000年那一刻是否宕机或算错;不少机构在新年前夜值守机房,只为确认世界翻页时系统仍醒着。航空、电力、金融、电信被优先处理,因为一处出错往往牵动整个条链。据Gartner等研究机构估计,全球技术修补费估计高达数千亿美元。
2000年元旦后,大规模停电、航班全面停飞等最坏情景并未普遍上演。但事后至今仍有争论:是本来就没那么严重,还是因为提前还债才避免违约?较公允的说法是,千年虫漏洞真实存在,而大规模修补行动显著降低了失控概率。2000年平安过关之后,先前的准备工作反而容易被说得夸大其词。成功往往无声,失败才会被记住。
对新加坡而言,风险不只来自本地写的程序,也来自跨境结算、国际银行网络、航材与港口系统,以及境外供应商提供的商用软件包。本地修好了,若对方系统仍出错,麻烦照样会沿数据线传来。当时国家电脑局(National Computer Board,NCB)牵头协调各政府部门与基础设施机构排查千年虫;新加坡金融管理局(Monetary Authority of Singapore,MAS)则推动银行、保险、证券业测试与应变,并曾准备跨年流动性安排,以防个别机构在世纪交替时出现短期资金紧张。海港与民航等与贸易相关的系统也被纳入排查,因为港口与航班一旦停摆,影响的不只是统计数字,而是现实生活中的货运与旅客行程。
2038年另一笔债到期
如今,许多程序换了一种记日子的办法:不从公元年月日记起,而是从1970年1月1日开始,数到今天一共过了多少秒。当年为了省空间,这个秒数常用一个容量有限的整数来存,大约能数到21亿秒出头,时钟便停在2038年1月19日清晨前后。
一旦数字叠满,就会像汽车里程表归零那样翻回去,电脑可能把当下误认作1901年12月的某日,或干脆读出一个负数。程序若用错误时间去判断备份是否过期,利息是否该结算,后果可能像连锁反应一样扩散,差之毫厘,谬以千里。早年写的后台程序,若未及时升级,到时可能出现宕机、资料错乱,或你明明能上网,手机却一再提示“证书已过期”却无法更新的怪现象。
人们把这称为“2038年问题”。当年图省事留下的设计,潜在的漏洞会在几十年后以另一种形式浮出水面。许多个人电脑与手机早已改用更宽裕的计数方式,但许多的嵌入设备、旧服务器与后台设备,仍可能留下隐患。
小知识
千年虫常被说成两位年份的误会,其实2000年还有另一道考题:闰年。公历里多数能被4整除的年份为闰年,天数多一天。然而,整百年份通常不算闰年,1900年因此没有2月29日;若再能被400整除,规则又放回来,2000年便真的有一天要被算进去。
不少旧程序只遵循“百年不闰”,却把2000年当成平年,或在2月29日算错相隔天数、贷款计息与排班。工程师还得核对2月份最后一天是否写对。2100年又将是不闰的整百年,提醒人们:日期算法写进程序后,不会像翻台历那样自己更新。
