时间:2021-07-01 10:21:17 帮助过:2人阅读
前段时间把公司的主数据库切了,分成业务库和报表库,业务库向报表库进行实时的Replication。这个项目的上线提升了系统的性能和可维护性,现在把设计时的考量和所做的工作重新回顾一下,作为备忘。
项目起源
在日常的开发过程中,功能总是先于性能被考虑。只有当用户抱怨系统性能时,我们才开始头痛医头,脚痛医脚地来解决这些性能问题。
公司的CRM和ERP系统叫作Olite,完全是我们组开发的。从无到有,功能不断扩展,原先只有CRM模块,后来加入了ERP模块,Accounting功能和Report功能。近来出现的情况是当某些用户跑一个大Report时,正在进行业务操作的用户感觉系统响应非常慢。通过对系统的性能监视发现,在这些时刻,数据库中产生了大量的锁,同时服务器上出现了CPU和内存资源消耗的尖峰。
系统结构
性能问题源于系统的整体结构和发展过程。Olite系统的Application是基于.NET平台的Web Form程序,数据库为SQL Server 2005。其主体结构如下图所示:
其Application端包括两个网站:OliteBase和OliteReport,但连接的都是同一个数据库。
Olite的Application端其实很薄,而把大量的业务逻辑包装在存储过程中,放在数据库端来运行。
这种结构在起初性能很好,而且提供给用户的Report是实时的业务数据。但随着提供的业务模块,特别是Report的增多(Report对应的存储过程连接的表多,计算量大,输出的结果集大),数据库就成为了瓶颈。
首先,我们做了存储过程的优化,通过创建Trace捕获性能差的存储过程,并对其进行优化。我们这么做了一段时间,但获得的收效并不大。我们在优化以往存储过程的同时,随着系统新功能的上线,又有新的存储过程进入需要优化的列表中。
其次,修改数据库设计,其中包括修改表结构和优化索引。在系统局部重构表结构与关系对于性能的提升还是比较明显的,但这样的修改会造成Application端的大量修改,工作量大,风险大,所以不能大规模实施。对于索引优化又存在矛盾,业务模块(OliteBase)要求数据库中的索引不要太多,以支持高效的插入、修改和删除,而报表模块(OliteReport)则希望在数据库中有更多的索引,以支持高效读。
最后,我们还试图提供晚一天的Report服务,来分流主数据库的压力。每天通过把前一天的备份数据库恢复在另一台服务器上,并在此服务器上提供OliteReport2站点,给用户提供Report服务。但用户并不喜欢使用OliteReport2,原因分析下来有3个方面:其一,有时用户确实需要实时的Report。其二,OliteReport能存储用户的Report条件,而OliteReport2由于每天都会被刷新,无法保留这些条件。其三,用户更习惯打开原来的Report链接。
项目需求
上述的各种优化方案都没有根本性的解决系统的性能问题。在这种的背景下我们有了把报表数据库与业务数据库分离的想法。
此项目的需求:
1. 提高用户对整个系统性能的感受,Report模块不要影响到业务模块的运行。
2. 用户可以和原先一样使用Report模块,即不增加新的Report站点。
3. 用户可以和原先一样存储填写的Report条件,以供重复使用。
4. 尽可能提供最小延时的Report。
需求1是这个项目的主要目标,需求2、3、4是尽可能保证项目所带来的改变对用户是透明的。
方案选择
对于原来的系统结构,其Application端已经是两个独立的站点OliteBase和OliteReport。所以只要把OliteBase和OliteReport的数据库进行分离,在分离后的两数据库间进行数据的同步就行了。这里的关键在于如何进行数据库间的同步。
微软提供了很多种数据同步的选择:1.集群;2.Log Shipping;3.Replication;4.Mirror;5.Integration Service。
微软提供的这些方案中大部分都是用于做数据库的高可用性的,而我们的项目是以高性能为目标的。为了满足我们自己的需求,应选择那种方案,并做哪些修改呢?
1.集群
这是第一个被我们否决的方案。配置SQL Server数据库集群,对硬件有较多限制,而且配置相对其他方案复杂。我们的项目总共的服务器资源就两台,除原先主数据库服务器外,另一台是虚拟机。
2.Log Shipping
Log Shipping把主数据库的日志传送到从数据库,并在从数据库上进行回放来保证主、从数据库间数据的一致,从数据库为只读。Log Shipping而且还有配置简单的特点,开始时是我们的一个候选方案,但在进一步的实验过程中发现了两个问题。第一、Log Shipping可设置的时间间隔最小单位为分钟。第二、当从数据库进行日志回放时,连接此数据库的连接需要被断开。其中第二个问题是难以容忍的,这个方案也被淘汰了。
3.Replication
Replication的原理和Log Shipping有些相似,但其提供了更多的灵活性。Replication可以只多主数据库的一些表、函数或存储过程进行,甚至可以对某些符合条件的记录进行。除此之外,其复制出来的数据库可写,而且复制的最小时间间隔可配置为concurrent(测试下来的时间延迟为秒级别),而且其配置也较为简单。经过一些实验,我们最后选择了它。后面会对其原理和配置进一步讨论。
4.Mirror
Mirror是SQL Server 2005提供的强大的高可用性方案。其镜像数据库不能直接读取,这和我们的需求场景不符合,所以被否了。
5.Integration Service
Integration Service具有最大的灵活性,其可以为数据仓库进行数据抽取,转换和装载。但使用Integration Service需要有大量的开发与测试工作,所以我们也没选用。
Replication方案细分
Replication方案又可以分为Snapshot Replication, Transactional Replication, Peer-2-Peer Replication, Merge Replication。
Snapshot Replication:一般用于对于数据库的一次性的完全复制。
Transactional Replication:用于主数据库向从数据库的单向复制。
Peer-2-Peer Replication:能进行二个或多个数据库之间的互相复制,即从数据库也能向主数据库复制,这个功能很强大,但可能会引起冲突,需要特别关注保证各库的数据完整性。
Merge Replication:可以把多个数据库中的数据进行合并后,复制到目标数据库。
对于我们的需求,我们选用了最单纯的Transactional Replication。
Transactional Replication原理
在Transactional Replication中有3个角色:Publisher(发布者), Distributor(分发者), Subscriber(订阅者)。其逻辑图如下:
在进行增量的Transactional Replication之前,Subscriber需要进行初始化,使其包含和Publisher一样的表结构和初始数据。
Transactional Replication启动之后,Distributor上的Log Reader Agent会将读取Publisher的Log信息,并分拣出被标识为replication的INSERT, UPDATE, DELETE语句。此后复制这些Transaction到Distributor,并写入distribution数据库。最后Distribution Agent把Distributor上的Transaction运送到Subscriber进行重放。
注意:在图中Distribution Agent运行在Distributor上,这是在push(推)模式下的情况。可以配置为pull(拉)模式,Distribution Agent将运行在Subscriber上。
更多关于Transactional Replication的原理可参考:
http://msdn.microsoft.com/en-us/library/ms151706(SQL.90).aspx
项目中的配置与考量
在前文的系统结构小节,给出了原先的系统结构。我们希望通过这次的项目得到如下所示的系统结构:
OliteReport能连接到一个由主数据库复制出的单独数据库上,这样这两个库之间的锁就被隔离了。同时主数据库与从数据库安排在两台服务器上(项目中我们把复制出的数据库放在了一台虚拟机上),那么CPU资源与内存资源的消耗也被隔离了。需要注意的是图中OliteReport除了主要的读操作外,还有少量的写操作(这是因为用户可以存储Report条件)。我们把这些写指回主数据库,从数据库在下一时刻的复制中得到这些数据。
在Transactional Replication中有三个逻辑角色,而项目中只有两台服务器。我们如何来安排这三个逻辑角色呢?
我们是选用Push模式还是Pull模式呢?
另一个需要考虑的问题是复制些什么?
还有一个需要考虑的是如何进行从数据库的初始化?
Transactional Replication有些什么前提条件?
如何来配置Transactional Replication?
后期维护
如何监视Replication的性能与异常?
如何进行以后的Release?
总结与设想
此项目已经上线,基本达到了需求所提出的目标,但这只是开始,优化后的结构给将来系统的扩展提供了一个基础。
SQL Server性能调优——报表数据库与业务数据库分离
标签: