SVS 没有尽头

SVS is SQL & Visual Studio
随笔 - 9, 评论 - 8, 引用 - 0

导航

工具

关于

做技术的路没有尽头,你只能看到前方几公里,但是更远的地方总是看不太清,当远处的景色渐渐清晰,回首看,有我们深深的足迹。兄弟们,上路吧,前方还有更多的难关,也有更美的景色。

每月存档

广告



访客

SQL Server 2008 New Feature- Filestream

昨天SQL Server 2008发布了,很多用户目前还没有用上SQL 2005,产品真是太快了,看样子学习的步伐也要加快了。这2天看了看SQL 2008的新功能,发现和05的版本相比功能是增加了一些,但是没有什么本质上的区别,只不过对于某些特殊的应用场景有了很好的优化。其中在数据类型上提供了几个新的数据类型,这里我们就先聊聊Filestream。
其实对于很多开发人员来说如何存储BLOB的数据一直就是一个麻烦的事情。原来可选方案只有2中,将BLOB保存在SQL Server中的Image或者Text数据类型中,2进制数据放到SQL的数据文件中;另外就是将数据放到文件系统上,然后将文件的地址保存在数据库中。这2中方法各有利弊。在文件系统中的2进制数据在管理上相对比较麻烦,因为要保证对于数据的修改必须在文件系统和数据库中同时完成,或者可以说需要在一个事务中完成,这里还要注意的就是文件系统可不支持Transaction,而且这些文件也无法收到保护,其他用户可能会误操作删除文件。保存在数据库中的主要问题是性能,因为所有对于这些BLOB字段的操作也会占用Cache,而且这些Cache其实很难复用,有些浪费了,另外在BLOB字段中的数据长度最大只能有2G。
FileStream就可以解决这些问题,Let’s go. Do it.
首先我们先需要在数据库引擎上开启FileStream Access,默认是禁用的。在Feb的CTP中 BOL上有一个地方写错了,@enable_level=2,我查了一下这个值的范围在0-2,BOL上写的是3,需要更正。
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
exec sp_filestream_configure@enable_level=2;
GO
RECONFIGURE;
GO
 
然后需要shutdown 数据库,重新启动服务
接下来就是创建数据库并指定Filestream的文件组,同时创建表。
create database FSPhoto
on
primary
(name=PhotoData,FILENAME='D:\Code\SQLDB\PHOTO.mdf'),
FileGroup FileStreamGroup1 Contains
Filestream(Name=PhotoFile,FILENAME='D:\Code\SQLDB\Photo')
log on(Name=PhotoLog,FILENAME='D:\Code\SQLDB\PHOTO.ldf')
go
use FSPhoto
go
create table Photos
(
ID uniqueidentifier RowGuidCol not null unique,
Name nvarchar(50) not null,
FS varbinary(max) filestream null
)
go
接下来我们就开始使用了。你可以先去相应的文件夹看看,系统会创建出一些目录和文件,里面的.hdr文件是个系统文件,不要使用工具将其打开。
在Insert的时候我们通常需要提供一个展位符,这样我们才能获取相应文件在系统中的句柄,这点和之前版本中的Textptr函数差不多。
declare @id uniqueidentifier
select @id=NEWID()
insert photos values(@id,'aaa.jpg',cast('' as varbinary(max)))
select @id
这里要注意的是’’和null是不一样的,null不会再文件系统中创建文件也就是在后面我们无法获取句柄,而’’是创建了空文件,文件是空的但是有句柄。
select FS.PathName() from Photos where id =@id
你就可以看到这个文件的路径。
因为这个路径是受到SQL Server保护的,我们有那个File类无法获取。所以需要使用一个函数
[DllImport("sqlncli10.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern SafeFileHandle OpenSqlFilestream(string FilestreamPath,
            UInt32 DesiredAccess,
            UInt32 OpenOptions,
            byte[] FilestreamTransactionContext,
            UInt32 FilestreamTransactionContextLength,
            Int64 AllocationSize);
使用这个函数去访问文件。除了这个函数之外还有一个重要的语句
select GET_FILESTREAM_TRANSACTION_CONTEXT()
这个语句就是可以将OpenSqlFilestream函数的操作与SQL的操作绑定在一个transaction中。这样就可以了。剩下的操作就是用构造一个FileStream类然后在构造函数中将OpenSqlFilestream的结果传入,然后就简单了。

posted on 2008-03-14 15:08:03 by Sun.wei  评论(0) 阅读(2734)

在Transaction Replication环境中BLOB字段数据的处理

好久没有写技术的Blog了,幸好开心给我提供了这个空间能和大家多多的交流,废话少说,直接进入主题。
最近做了一个关于SQL的项目,用户对于高可用性要求相当的高,在这个项目上基本上把SQL Server 2005能用到的高可用技术都用上了,主要就是Cluster+Mirroring+LogShipping+Replication,当然这些也都是根据不同的子系统对于可用性要求的SLA来设计的,其中比较复杂和麻烦的是设计Replication。
其实从Replication的角度来说,最常用的就是这个Transaction Replication,其基本的原理就是先基于BCP做一套相应发布数据的快照,后续的就是启动Log Reader Agent来读取发布数据库的事务日志,然后将操作传递到分发服务器上,再有分发服务器推送给订阅服务器,过程虽然不是很复杂,但是需要调整的参数是相当的多。
在这个方案中主要遇到了2个小问题,一个是关于BLOB字段的复制,另外一个就是对于同步数据时一个特殊的需求,这个我在下一次会具体说明。
BLOB的字段在很多应用上会用到,很多人在开发应用的时候都与Image和文档的数据都是保存在文件系统上,这样做是最简单的,但是查询起来就会比较麻烦了,放到数据库中可以使用SQL的Full Text Search,这样检索文档中的信息就会比较容易了。但是问题在于如何将一个大的文档保存到数据库上。我们通常的做法是创建一个BLOB的字段,在SQL Server中可以使用Image、Text、varbinary(max)等,很多人还在使用SQL2000上的模式,也就是使用Image和Text。在使用Image和Text的时候主要是会使用WriteText、UpdateText、TextPtr这3个函数,然后将从文件读到流分割后批量写入的SQL中,当然注意一点这些函数在SQL的后续版本中可能会删除,用其他的函数代替。还有一点就是最好能将分割的数据长度设置为8060,这样插入的速度可以更快一些。回到主题上吧,在Transaction Replication的环境中原有的这种方式就会出问题,问题出在Transaction上。如果不将插入图片的所有操作设计为一个Transaction中,每一个操作都会是一个独立的事务复制到订阅端,在订阅端执行的时候TextPtr函数的结果是不同的。如果在一个Transaction中,其实就是将这边的操作做为一个整体复制到了订阅端,这样才能保证指针位置的正确性。

posted on 2008-03-11 09:18:05 by Sun.wei  评论(0) 阅读(1789)

Powered by: Joycode MVC Blogger System