SQL Server 2005 和 2008 有几个关于高可用性的选项,如日志传输、副本和数据库镜像。所有这些技术都能够作为维护一个备用服务器的手段,同时这个数据库可以在你原先的主数据库出问题时上线并作为新的主服务器。然而,你必须记住的是将备用服务器替换上线只是完成了一半的故障修复工作。
要保证你的应用正常工作,在数据库外部还有许多注意事项。这其中包括登录信息、数据库用户、调度任务、DTS 和 SSIS 包、可执行文件、系统数据库中的对象、同名数据库、链接服务器等等。
有时这些细小的依赖只有在你进行一个数据库故障恢复时才会发现,这样你又不得不花费大量时间进行调试和评估导致这个问题的根源。此外,你还必须让第二台服务器和应用尽可能快地上线以减少停机时间。因此,提前做设置是非常重要的。
当涉及到高可用性和SQL Server 的灾难恢复规划时,你应该谨记我本人所喜欢的一个拉丁谚语 ——Si vis pacem, para bellum,它的意思翻译过来就是“如果你想要得到和平,那就得先作好战争准备。”记住这一点后,让我们来看看一些可能会遇到的问题。我也将建议几个预先可以完成的任务,以确保数据库故障恢复过程快速有效地完成。
SQL Server 登录信息与数据库用户
你的故障恢复服务器应该备份所有的登录信息和数据库用户,包括密码。登录信息可以在任何时候创建,但是如果你使用日志传输或数据库镜像,你的数据库将处理恢复状态,这样你只有在它们重新上线后才能完成恢复过程。
使用 Windows 认证,可以很容易地将登录信息映射到数据库用户。然而,如果你使用的是 SQL 认证,那么你需要手动地在你从另一个服务器获得的数据库上重新建立登录信息与数据库用户的连接。因此,你在迁移数据库时会丢失登录信息和数据库用户之间的连接。
当你在第二台服务器上恢复数据库后,运行这些代码:
USE YourDatabaseName
EXEC sp_change_Users_Login ‘UPDATE_ONE’, YourDBUserName, YourLogin
保持登录信息同步的另一个方法是遵循 Microsoft Knowledge Base 上关于 在 SQL Server 实例之间传输登录信息和密码 的文章的步骤。这篇文章阐述了如何使用原始的 SID 脚本化登录信息。当在故障恢复数据库服务器上创建这些登录信息时,登录信息与数据库用户之间的连接会被保存,这样你就不必运行上面的脚本修复孤立的用户。
SQL Server 2005 相对于 2000 的进步非常大,特别是有了免费的 SQL Server 2005 Express 版本以后,就可以免费使用了。但是 2005 有个比较麻烦的就是找不到跟 2000 一样的服务管理器了。停止运行服务显得有些麻烦,每次都要进配置管理器进行操作,很不方便。
不过不怕,有了这个小工具以后你就可以拥有跟 2000 一样的服务管理器了。启动和停止 SQL Server 服务方便很多。提醒:本程序需要 .NET 2.0 运行环境。
点击下载
前两天我们介绍了一种新的存储无限级分类方法,但是读出分类的时候怎么实现树形显示呢?方法很简单,我们自己定义一个树形的数据结构,然后根据数据库存储的节点的深度来插入到树里面,当然显示的时候需要用递归来显示一下,不过这里的递归只是在内存里面递归,效率是相当高的。
2008-11-17 更新为不使用树结构,使用排序和深度来做文章。
在数据库读出数据的时候直接按照 LID 来进行 ASC
排序就可以了,默认的排列顺序就是按照树走的,大家可以插入一些数据,并读取一下就可以很明了的看到顺序了,插入树循环的时候只需要对深度进行运算就可以了。
下面我只写出了一些关键地方的代码,具体的代码自己试着多写写在纸上多画画应该就明白了。
另外就是想说下,这种分类算法只适用于一般的树形分类,并不适用于插入数据比较频繁的树形结构,比如说无限次回复的评论,无限次回复的评论有另外一种更适合的算法。
新的方法:
Response.Write(”
“);
Response.Write(”
由于数据库存储的数据都是以平面方式存储,所以目前大部分论坛和其他程序都是用递归来展现层次数据的,如果分类的层次十分深的话那么使用的递归次数相当可观,对性能的影响也非常大。最近要做一个分类信息的平台就遇到这个问题了,那么如何实现快速的展现分层数据呢?MYSQL 的开发者帮我们想到了一个算法,这个算法目前唯一的问题就是尚未实现分类排序,我们可以通过右值的反向排序实现先入先出的排序。在这里我们需要了解的是如何用 SQL Server 来实现,我们就以省市县数据库为例来实现:
如图所示我们将一个树节点的左右各编上号码,就可以看出一些规律,山西的左右值为(8,17),那么所有左值大于8,右值小于17的节点都是属于山西的子节点。稷山先的左右值为(14,15),那么他的所有父节点就是左值小于14,右值大于15的节点,怎么样,用这个方法实现的无限级分类性能绝对是顶呱呱的。一次查询就可以查出属于某个节点的数据以及他子节点的数据。这个算是我见过性能最高的无限级分类算法。其他算法跟这个对比基本没有任何优势。
我们先建立一个数据表,结构如下图(LID 为左值,RID 为右值,Tree 为节点深度,Name 和 ID 就不多说了,节点的索引和名称)
我们可以使用下面的存储过程来获得一个节点和其子节点:
CREATE PROCEDURE CLSP_ZoneSelect
(
@Root INT,
@Tree INT
)
AS
SELECT Z.ID,Z.Tree,Z.Name
FROM CL_ZoneData AS Z,CL_ZoneData AS P
WHERE P.ID = @Root
AND Z.LID >= P.LID AND Z.RID <= P.RID
AND (@Tree = 0 OR Z.Tree <= P.Tree + @Tree)
ORDER BY Z.LID ASC
GO
我们可以用下面这个存储过程来在一个节点下插入新的子节点:
CREATE PROCEDURE CLSP_ZoneInsert
(
@Root INT,
@Name NVARCHAR(50)
)
AS
DECLARE @RID AS INT,@NID AS INT,@Tree AS INT
SET @RID = 1
SET @NID = 0
SET @Tree = 1
IF @Root = 0
BEGIN
SELECT TOP 1 @RID = RID + 1
FROM CL_CateData ORDER BY RID DESC
END
ELSE
BEGIN
SELECT @RID = RID, @Tree = Tree + 1
FROM CL_ZoneData WHERE ID = @Root
END
IF @Root = 0 OR @RID > 1
BEGIN
UPDATE CL_ZoneData SET RID = RID + 2 WHERE RID >= @RID
UPDATE CL_ZoneData SET LID = LID + 2 WHERE LID > @RID
INSERT INTO CL_ZoneData(LID,RID,Tree,Name)
VALUES (@RID,@RID + 1,@Tree,@Name)
SET @NID = SCOPE_IDENTITY()
END
SELECT @NID
GO
删除一个节点可以用下面的存储过程:
CREATE PROCEDURE CLSP_ZoneDelete
(
@ID INT
)
AS
DECLARE @LID AS INT, @RID AS INT, @WID AS INT, @DID AS INT
SET @DID = 0
SELECT @DID = ID, @LID = LID, @RID = RID, @WID = RID - LID + 1 FROM CL_ZoneData WHERE ID = @ID
IF @DID != 0
BEGIN
DELETE FROM CL_ZoneData WHERE LID BETWEEN @LID AND @RID
UPDATE CL_ZoneData SET RID = RID - @WID WHERE RID > @RID
UPDATE CL_ZoneData SET LID = LID - @WID WHERE LID > @RID
END
SELECT @DID
GO