俞席忠
摘要: 该文分析两个网络瘫痪事件,说明数据库并发控制对系统的运行效率起着至关重要的作用,对乐观锁和悲观锁进行分析,说明高并发网络环境下,数据库并发控制的选择。
关键词: 数据库; 并发控制; 乐观锁 ; 悲观锁
中图分类号:TP391文献标识码:A文章编号:1009-3044(2012)30-7172-03
第一个网络事件:小米手机网站第二轮开放购买时,网站瘫痪。
2012年1月4日消息 1月4日中午1点,小米手机第二轮开放购买。在开放购买后一个小时内,小米官方网站由于同时段访问人数过多出现宕机。对此,小米科技CEO雷军对于服务器无法负担访问人数过多,出现官网宕机事件表示歉意。雷军表示,“这次开放购买,服务器没有抗住,实在对不起各位!恳请各位谅解!”。
另一个网络事件:由于访问量过大,铁路售票网瘫痪.
2012年1月1日起,铁路部门开始调整售票时间,网络售票、电话订票、代售点、车站窗口等进行错时放售车票。但由于访问量过大,不少旅客在12306网购车票时,频频遭遇“系统忙”而无法访问。相比之下,电话订票比网购车票要更顺利些。记者亲历:折腾一个多小时订单没提交上。目前,网上购买火车票唯一官方网站就是铁道部下属的中国铁路客户服务中心网(www.12306.cn)。
什么原因导致网站瘫痪,是前端接口、是带宽、是网络架构,还是数据库并发出了问题。2012年初的这两个网络事件,引发了广大技术人员和专家的大讨论。本文将从数据库并发控制这个层面来研究网络效率与并发控制间的关系及它们间的优化处理。
1 网站瘫痪原因分析
小米网站平时的访问量不大,由于手机采用网上直销模式,使瞬时每分钟的并发量冲高导致服务DOWN机,小米手机运营经理钟雨菲贴出小米网站的数据解释:“给大家贴一个cnzz后台数据:15分钟内,小米官网,不含论坛,同时在线24万多人。做过网站运营的朋友都知道,这么多人同时在线对服务器的压力还是很大的”。
整体来说负载均衡的问题不大,问题根本不在前端服务器,前端都有良好的绶冲机制,加上只有读数据,没有写的操作。真正的原因集中在后端数据库并发跟不上来,因为一个用户要定购一台手机,首先要读(作一次selecet操作)库存表中剩余多少台这个字段,判断自已能否下单,若还有剩余,则向定购表中作一次插入操作(instert),最后向库存表更新剩余数(作一次update操作),可见数据库并发量过大,加上没作好并发控制的优化,是导致网站瘫痪的主要原因。主要是准备不足,前期没有作数据库并发压力测试一下,没有根据估计在线数设置一下限流,在相同的硬件条件下,通过数据库的并发控制优化和流量控制等软件的手段可以绶解并发数过多造成的网站响应慢的难题。小米公司在这个事件之后,对后台数据库的进行了彻底的优化并作了一些限流的措施,在2012年4月6日,在6分钟时间成功完成了10万台定购量。
2012年前7天,铁道部客户服务官方网站12306网日均点击次数已经超过了10亿次。众多专业人士认为,12306网站在线售票功能,其实就是个海量事务高速处理系统,这样一个系统,并不能简单地使用通用方案进行设计,但12306网站很可能是采用了Oracle通用数据库进行搭建,使用通用系统进行设计,在面对春运前夕的瞬间海量网络购票需求时,这个系统就变得极为脆弱。业内人士认为,问题不出在硬件上,而出在软件设计上。铁道部方面试图通过服务器的堆积,来解决软件设计的不足,但显然再强大的硬件也很难满足一个不完善的软件系统的极端处理请求。据悉,12306网目前正在进行后台调试,新一代客票系统将在既有客票系统的基础之上,提供全方位的信息咨询、丰富的售票渠道、多元化的支付方式、快捷的进出站,为铁路企业提供精细化的售票管理、智能化的售票组织、科学化的运力调配,并引入云计算技术,构建支撑超大规模并发交易。是否能真正解决,这要到2013年春运才看得出来,让我们试目以待吧。
从以上分析可以看出,数据库并发控制对系统的运行效率起着至关重要的地位。
2 数据库并发控制基本原理
数据库的并发控制能力是指在处理多个用户在同一时间内对相同数据同时进行访问的能力。一般的关系型数据库都具备这种能力,日常应用系统中也随处可见,例如火车的售票系统、银行数据库系统。
数据库并发处理时,常出现的问题有:
1)更新丢失:当多个事务同一条记录进新更新时,由于每个事务间没有通讯,事务间相对独立,就会产生更新丢失现象,例如A事务更新了一条记录的某个字段的值,接着B事务更新了此字段的值,此时A事务更新的值丢失。
2)脏读:一个事务正在修改记录数据,此时尚未提交,另一个事务读取了这些未提交的修改的记录数据,形成脏读。这里所指的修改记录,除了更新(Update)操作,还包括插入(Insert)和删除(Delete)记录操作。脏读的结果是:如果后面一个事务做回滚操作时,那么后一事务所做的修改内容,全部都会被撤销。这样前面一个事务读到的数据,就是脏数据。
下面举一个实例:在宾馆房间预订系统中。设计有一个预订表,向表中插入一条记录时,表示预订出了一个房间。
事务A:向预订表中插入一条记录,预订第20号房间。
事务B:执行查询未预定的房间命令,事务A已预订20号房间。所以20号房不会在空房列表中。
事务A:使用信用卡支付预订金,由于网络或其它原因,支付失败,导致事务回滚。插入到预订表中的预订记录被删除。事实上20号房间是空房。此时,事务B所得到空房列表,是不准确的。
3)不可重复读:在同一个事务中,重复读取数据时多次查询(select)操作时,所读取的数据,和前次读取的数据不一致,是不可重复读。例如新生报名系统,在编班时,新班人数是变化的数据,执行同一查询事务没有变化,得到的新班人数是不一样的。由于操作对象发生变化,而导致同一事务执行结果不一致,称为不可重复读。
4)幻读:事务A查询指定的条件的记录,之后别一事务B插入一条新记录,这条新记录满足事务A使用的查询条件。事务A再次使用相同的查询读取记录,此时可以查询到事务A刚插入的记录。这条记录被称为幻象,事务A查询操作,称之为幻读,因对事务A来说,这条的新出现的记录是件奇怪的事,象是幻觉一样。
举个例子来说明,在火车的售票系统中,有这样一个过程。
售票点通过网络从源数据库读出某车次的车票剩余张数为n(=100)。
B售票点通过网络从源数据库读出该车次的车票剩余张数也为n(=100)。
A售票点卖出一张该车次的车票,将1(99)写回源数据库。
B售票点也卖出一张该车次的车票,将1(99)写回源数据库。
这样就存在并发控制的问题,卖出了两张票,而数据库里面只有1条数据减少。这样,下次读取数据的时候,源数据就不准确了,从而会带来数据的错误。如果按照上面的操作顺序执行,A对源数据库的修改就被丢失。并发控制带来数据的不一致问题,被称为“数据库并发控制过程冲突”,在实际的测试过程中,我们必须对这样的冲突进行测试设计。我们主要是通过逻辑判定来设计测试用例。
刚才的例子就是一个典型。当事务A和B对同一个数据源进行修改,B提交的结果破坏了A提交的结果,导致A对数据库的修改失效。
不可重复读数据是指事务A在读取数据后,事务B对其进行了修改并执行了更新操作,当事务A无法再现前一次读取的结果。举个例子来说明:
事务A从数据库表中读出整数x=10,Y=20值进行求和运算z=x+Y=30。
事务B从相同的数据库中读出x值x=10,对x乘以5后写入原x值(x=X*5=50),提交事务B。
此时,事务A处理的结果是:z=x+Y=10-50<0,事务B对数据的操作已经影响了原来的结果。当多个事务在数据库中并发执行时,数据的一致性可能受到破坏。系统有必要控制各事务之间的相互作用,这是通过并发控制机制的多种机制中的一种来实现的。
避免事务“饿死”,授权加锁的条件:不存在在数据项Q上持有与M型锁冲突的锁的其他事务;不存在等待对数据项Q加锁且先于Ti申请加锁的事务。
常用的机制是各种封锁协议,时间戳排序,有效性检查,多版本机制。
数据封锁是需要时间开销的,对于访问量巨大的铁路客票系统和在线抢购等并发性要求极高的场合下,即可保证数据正确,又要得到最佳的并发效率,是值得研究的问题。
3 网络数据库在并发控制中的选择
对于互连网,数据库属于共享资源的一个重要组成部分,众多使用者可以同时使用数据库提供的各种数据服务。为了保证数据的一致性,早期的数据库系统,要求用户程序进行排队,即每一时刻只允许一个用户程序对数据库做存取操作,其他用户程序等待上一用户程序完成操作后,才能对数据库进行存取。数据库服务器的输出能力实际上是较强大的,面对一个用户的数据处理,数据库绝大多数的时间是处于闲置状态,别一方面,众多用户的数据请求已得到不到响应,要解决这一矛盾,现代数据库管理系统必须提供并发控制机制。并发控制机制的好坏是将关系到大型网络平台的数据吞吐能力,直接影响到网站的用户体验。
目前大型数据库系统的并发控制,主要是通过锁定的方式。不同的加锁方式用于不同的应用场合。根据业务逻辑关系,我们需要保证数据访问的排他性。通过一些并发机制保证数据在某个特定操作过程中不会被其它用户程序所修改,这就是所谓的“加锁”,目标数据锁定时,使其无法被其他用户程序修改。 目前常用两种加锁机制为:悲观锁(Pessimistic Locking)和乐观锁(Optimistic Locking)。
悲观锁认为你正在更新的记录,会被其它用户读取或更改的概率很高,因此当你的进程需要更改记录数据时,先进行锁定,禁止其它用户程序读取或更改,当你的进程完成更新后,解除锁定,其它用户程序才能正常读写。在一些实际应用程序中,例如生产管理系统,如果并发量不大,完全可以使用悲观锁定的方法,这种方法使用起来非常方便和简单。悲观锁很好的解决了数据读写的正确性,并由于加锁时间较长,使得并发性变差,在访问量很大时,用户体验将会是灾难性的。在系统的并发非常大的情况下,悲观锁定会带来非常大的性能问题,所以就要选择乐观锁定的方法。
乐观锁与悲观锁相反,乐观的认为对同一数据同时存取的概率极小,因而在数据库层次上的不加锁定机制,为了保证数据的正确性,乐观锁定采用在应用程序设计时,考虑在逻辑进行数据进行保护。在乐观锁机制中,增加了并发用户次数,大大提高了数据库的效率。
在高并发的环境下,使用多台电脑做均衡负载,但是数据库放在一台电脑上,那如何是这些并发保持数据都是统一的, 比如在用一时间,A用户调用1号设备修改记录,而A用户也在2号设备同样需要修改记录 ,现在的思路是在数据库电脑上做异步锁,所用的数据操作都会调用到这个锁,这个锁就是以用户的用户名来定义。
4 结束语
本文从数据库并发控制角度分析了大型网络平台在高负荷环境时锁定机制对网络效率的影响,提出解决数据一致性和高并发读写效率的思路。并发控制的方法非常丰富,远不止本文所提及的这些方法。在网络数据库应用中,并发控制的方法和实现途径多种多样。在选择时所依据的基本原则就是:数据一致性一定要合乎应用的需要,在此基础上,尽量提高并发度。
参考文献:
[1] 刘云生,郭芬,廖国琼.安全的乐观实时并发控制策略[J]. 微计算机应用,2006(4).
[2] 陈月峰.浅析数据库并发控制技术[J].科技信息,2009,(30).
[3] 戴志龙.浅谈高级数据库并发控制方法[J].科技经济市场,2010,(4) .
[4] 雷霖,熊伟,吴烨,景宁.基于语义的数据库并发控制研究进展[J].小型微型计算机系统,2011(12).