Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

1,什么是合并复制。
将多个节点的数据变化合并起来同步到多个节点,保证节点数据一致。
在同步表中增加字段rowguid标识更改的行ID,在表增加触发器,插入更新存rowguid入到MSmerge_contents表内,删除存放在MSmerge_tombstone表内,
引用:http://searchsqlserver.techtarget.com/tip/How-merge-replication-works-in-SQL-Server
2,合并复制如何操作。

http://www.codeproject.com/Articles/28951/SQL-Server-2005-Merge-Replication-Step-by-Step-Pro

3,合并复制相关表。

http://blogs.msdn.com/b/repltalk/archive/2010/02/23/collection-of-merge-replication-best-practices.aspx

书籍:pro sqlserver2005 replication

http://books.google.com.hk/books?id=aup_ppJfgMcC&printsec=frontcover#v=onepage&q&f=false

4,查询没有复制分发的表
SELECT type_desc,name
FROM sys.objects
WHERE name NOT IN(
    SELECT name
    FROM sysmergearticles)
AND CHARINDEX('MS',name)<=0
AND CHARINDEX('sys',name)<=0
AND CHARINDEX('_',name)<=0
AND type_desc IN('SQL_SCALAR_FUNCTION','SQL_STORED_PROCEDURE','SQL_TABLE_VALUED_FUNCTION','USER_TABLE','VIEW')
ORDER BY type_desc,name


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

–查找表约束
SELECT OBJECT_NAME(c.object_id),c.name,d.name
FROM sys.default_constraints d
JOIN sys.columns c ON d.parent_column_id = c.column_id AND d.parent_object_id = c.object_id
WHERE d.parent_object_id = OBJECT_ID(N’bdAllocateGroup’) –AND c.name = ‘msrepl_tran_version’;


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
–开连接
CREATE USER [zinnova] FOR LOGIN [zinnova]
GO
 
–开表
GRANT SELECT ON OBJECT::dbo.mdOrderStatus TO zinnova;
GO
 
–查看 SQL 2005 用户被赋予的权限
exec sp_helprotect @username = 'zinnova'
 
–查看用户角色
select DbRole = g.name, MemberName = u.name, MemberSID = u.sid
from sys.database_principals u, sys.database_principals g, sys.database_role_members m
where g.principal_id = m.role_principal_id
and u.principal_id = m.member_principal_id
order by 1, 2

–对象的取得所有权与控制的权限区别
–经测试:取得所有权的权限可以deny,而控制权限忽略deny


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

1,存储空间
char(36):存储空间是36个字节,
Uniqueidentifier是16个字节,原因(如:F9274DE1-322D-46FF-A5E9-20670FFF661B,每个都是16进制,共有32个,而每个16进制数可用4位表示(2^4),故guid()是128位,一个字节是8位,那么guid()共用128/8=16个字节存储):

2,Uniqueidentifier格式必须是32个16进制+4个-,那么位数少于36或者字母中出现非a-f就会报错,如
0EC75E6B-7434-485E-BCEA-2130651861DD可用Uniqueidentifier存储,但0HC75E6B-7434-485E-BCEA-2130651861DD就不行。
故在兼容性方面,char(36)可存储<=36的所有字符,而Uniqueidentifier只能存储32个16进制+4个-. 故:在现在存储空间价格便宜的情况下,在兼容方面,推荐char(36)


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

/*在修改列类型时,提示有依赖,如下。现提供AlterColumnType存储过程用来复制表依赖关系。
ALTER TABLE dbo.bmdCustomerTel ALTER COLUMN CustomerID INT
消息 5074,级别 16,状态 1,第 1 行
索引'IX_bmdCustomerTel_2' 依赖于 列'CustomerID'。
消息 4922,级别 16,状态 9,第 1 行
由于一个或多个对象访问此列,ALTER TABLE ALTER COLUMN CustomerID 失败。
*
--主键:SELECT TABLE_NAME,COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME='表名'

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[AlterColumnType]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[AlterColumnType]
GO

/*修改列类型时,自动查找相关索引,删除再重建*/
CREATE PROCEDURE [dbo].[AlterColumnType]
@TableName VARCHAR(50),
@ColumnName VARCHAR(50),
@NewColumnType VARCHAR(1000)
AS

SELECT t.object_id,ix.type_desc,t.name TableName,IX.index_id,ix.name indexName,s.name SchemeName INTO #
FROM SYS.tables t
JOIN SYS.indexes IX ON t.[object_id] = IX.[object_id]
JOIN SYS.schemas s ON S.[schema_id] = t.[schema_id] --表架构名
WHERE t.object_id = object_id(@TableName)
AND EXISTS( --拥有此列的索引
SELECT 1 FROM sys.index_columns cl
JOIN sys.columns c ON cl.column_id = c.column_id AND c.object_id = cl.object_id
WHERE c.name = @ColumnName AND cl.index_id = ix.index_id AND cl.object_id = t.object_id )

DECLARE cur_dx CURSOR FOR
SELECT ' DROP INDEX ' + QUOTENAME(indexName) + ' ON ' + QUOTENAME(SchemeName) + '.' + QUOTENAME(TableName) --t.name,ix.name,ix.type_desc,cl.name
FROM # t

UNION ALL

SELECT ' ALTER TABLE ' + @TableName + ' ALTER COLUMN '+ @ColumnName + ' ' + @NewColumnType

UNION ALL

SELECT ' CREATE ' + type_desc collate Chinese_PRC_CI_AS_WS + ' INDEX ' + QUOTENAME(indexName) + ' ON ' + QUOTENAME(SchemeName) + '.' + QUOTENAME(TableName)
+ '(' + STUFF( --索引列,复合索引
(SELECT ',' + CONVERT(NVARCHAR(100),cl.name)
FROM sys.index_columns c
JOIN sys.columns cl ON cl.column_id = c.column_id AND c.object_id = cl.object_id
WHERE c.object_id = t.object_id AND index_id = t.index_id
ORDER BY key_ordinal
FOR XML PATH('')),
1,1,'') + ')'
FROM # t

DECLARE @sql NVARCHAR(max)
OPEN cur_dx
FETCH cur_dx INTO @sql
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC sp_executesql @sql
RAISERROR('Executed:%s',10,1,@sql) WITH NOWAIT
--PRINT @SQL
FETCH cur_dx INTO @sql
END
CLOSE cur_dx
DEALLOCATE cur_dx

DROP TABLE #

/pre>


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

利用:1,mssql job运行。2,链接服务器,3,mssql 邮件发送

例:

DECLARE @LastRun VARCHAR(10)

SELECT @SyncDate = SyncDate FROM dbo.SyncTable

WHERE TableName = ‘JobLogMonitor’

IF @@ROWCOUNT = 0 BEGIN RETURN END

SET @LastRun = CONVERT(VARCHAR(10),@SyncDate,112)

DECLARE @Receivers varchar(1000)

SET @receivers = ‘wukun@lvshou.com;liqihua@lvshou.com;zhengxuesong@lvshou.com’

DECLARE @table VARCHAR(max),@body VARCHAR(max),@COUNT INT

SET @COUNT = 0 SET @SyncCount = 0

–2.201

SET @table = ‘



SELECT @table = @table + ‘

‘+ ‘

‘+ ‘

‘+ ‘



FROM server.msdb.dbo.sysjobhistory sjh(NOLOCK)

JOIN server.msdb.dbo.sysjobs sj(NOLOCK) ON sjh.job_id = sj.job_id

JOIN server.msdb.dbo.sysjobsteps sjt(NOLOCK) ON sjh.step_id = sjt.step_id AND sjh.job_id = sjt.job_id

WHERE run_status =0

AND msdb.dbo.agent_datetime(run_date,run_time)> @LastRun

ORDER BY run_date

SET @COUNT = @@ROWCOUNT

IF @COUNT > 0

BEGIN

SET @SyncCount = @SyncCount + @COUNT

SET @table = @table + ‘

‘ + CONVERT(VARCHAR(10),ROW_NUMBER() OVER (ORDER BY run_date))+ ‘ job名称:’ + CASE(ISNULL(sj.NAME,”))WHEN ” THEN ‘ ’ ELSE sj.NAME END +

步骤:’ + CASE(ISNULL(sjt.step_name,”))WHEN ” THEN ‘ ’ ELSE sjt.step_name END + REPLICATE(‘ ’,4) + ‘执行时间:’ + CASE(ISNULL(sjh.run_date,”))WHEN ” THEN ‘ ’ ELSE CONVERT(VARCHAR(50),sjh.run_date,120) END +

错误消息:’ + CASE(ISNULL(sjh.message,”))WHEN ” THEN ‘ ’ ELSE sjh.message END +

执行SQL:’ + CASE(ISNULL(sjt.command,”))WHEN ” THEN ‘ ’ ELSE sjt.command END +



SET @body = dbo.getHTML(@table)

–SELECT @body

EXEC msdb.dbo.sp_send_dbmail

@profile_name = ‘LogMonitor’,

@recipients = @receivers,

@body_format = ‘HTML’,

@body = @body,

@subject = ‘Job执行错误[201]‘;

END


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

CREATE TABLE tmp ([USER] NVARCHAR(MAX) )
BULK INSERT tmp FROM N’C:\aaa\数据.txt’


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

脱机数据库删除后,与联机数据删除不同的一点是,它不会自动删除与数据库关联的mdf,ldf文件,即此时若建立一同名数据库,会因数据库文件已经存大而弹出错误信息


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

sp_procoption [ @ProcName = ] ‘procedure’
, [ @OptionName = ] ‘option’
, [ @OptionValue = ] ‘value’

备注
启动过程必须位于 master 数据库中,并且不能包含 INPUT 或 OUTPUT 参数。启动时恢复了 master 数据库后,即开始执行存储过程。

参数
[ @ProcName = ] ‘procedure’
为其设置选项的过程的名称。 procedure 的数据类型为 nvarchar(776),无默认值。

[ @OptionName = ] ‘option’
要设置的选项的名称。option 的唯一值为 startup。

[ @OptionValue = ] ‘value’
指示是将选项设置为开启(true 或 on)还是关闭(false 或 off)。value 的数据类型为 varchar(12),无默认值。

返回代码值
0(成功)或错误号(失败)

权限
要求具有 sysadmin 固定服务器角色的成员身份。


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

EXEC GetTableScript 'frmuser'

CREATE PROCEDURE GetTableScript 
@TableName VARCHAR(50)
AS 

--To get table script
declare @Id int, @i int, @i2 int,@Sql varchar(max),@Sql2 varchar(max), @f1 varchar(5), @f2 varchar(5), @f3 varchar(5), @f4 varchar(5), @T varchar(5)
    select @Id=object_id(@TableName), @f1 = char(13) + char(10), @f2 = '    ', @f3=@f1+@f2, @f4=',' + @f3
    
    if not(@Id is null)
    BEGIN
    declare @Data table(Id int identity primary key, D varchar(max) not null, ic int null, re int null, o int not null);
    
    -- Columns
    with c as(
        select c.column_id, Nr = row_number() over(order by c.column_id), Clr=count(*) over(),
            D = quotename(c.name) + ' ' +
                case when s.name = 'sys' or c.is_computed=1 then '' else quotename(s.name) + '.' end +
                case when c.is_computed=1 then '' when s.name = 'sys' then t.Name else quotename(t.name) end +
                case when c.user_type_id!=c.system_type_id or c.is_computed=1 then ''
                    when t.Name in ('xml', 'uniqueidentifier', 'tinyint', 'timestamp', 'time', 'text', 'sysname', 'sql_variant', 'smallmoney', 'smallint', 'smalldatetime', 'ntext', 'money',
                                    'int', 'image', 'hierarchyid', 'geometry', 'geography', 'float', 'datetimeoffset', 'datetime2', 'datetime', 'date', 'bigint', 'bit') then ''
                    when t.Name in('varchar','varbinary', 'real', 'numeric', 'decimal', 'char', 'binary')
                        then '(' + isnull(convert(varchar,nullif(c.max_length,-1)), 'max') + isnull(','+convert(varchar,nullif(c.scale, 0)), '') + ')'
                    when t.Name in('nvarchar','nchar')
                        then '(' + isnull(convert(varchar,nullif(c.max_length,-1) / 2), 'max') + isnull(','+convert(varchar,nullif(c.scale, 0)), '') + ')'
                    else '??'
                    end + 
                case when ic.object_id is not null then ' identity(' + convert(varchar,ic.seed_value) + ',' + convert(varchar,ic.increment_value) + ')' else '' end +
                case when c.is_computed=1 then 'as' + cc.definition when c.is_nullable = 1 then ' null' else ' not null' end +
                case c.is_rowguidcol when 1 then ' rowguidcol' else '' end +
                case when d.object_id is not null then ' default ' + d.definition else  '' end
        from sys.columns c
        inner join sys.types t
        on t.user_type_id = c.user_type_id
        inner join sys.schemas s
        on s.schema_id=t.schema_id
        left outer join sys.computed_columns cc
        on cc.object_id=c.object_id and cc.column_id=c.column_id
        left outer join sys.default_constraints d
        on d.parent_object_id=@id and d.parent_column_id=c.column_id
        left outer join sys.identity_columns ic
        on ic.object_id=c.object_id and ic.column_id=c.column_id
        where c.object_id=@Id
        
    )
        insert into @Data(D, o)
        select '    ' + D + case Nr when Clr then '' else ',' + @f1 end, 0
        from c where NOT D IS NULL 
        order by column_id
    
    -- SubObjects
    set @i=0
    while 1=1
        begin
        select top 1 @i=c.object_id, @T = c.type, @i2=i.index_id
        from sys.objects c 
        left outer join sys.indexes i
        on i.object_id=@Id and i.name=c.name
        where parent_object_id=@Id and c.object_id>@i and c.type not in('D')
        order by c.object_id
        if @@rowcount=0 break
        if @T = 'C' 
            insert into @Data 
            select @f4 + 'check ' + case is_not_for_replication when 1 then 'not for replication ' else '' end + definition, null, null, 10
            from sys.check_constraints where object_id=@i
        else if @T = 'Pk'
            insert into @Data 
            select @f4 + 'primary key' + isnull(' ' + nullif(lower(i.type_desc),'clustered'), ''), @i2, null, 20
            from sys.indexes i
            where i.object_id=@Id and i.index_id=@i2
        else if @T = 'uq'
            insert into @Data values(@f4 + 'unique', @i2, null, 30)
        else if @T = 'f'
            begin
            insert into @Data 
            select @f4 + 'foreign key', -1, @i, 40
            from sys.foreign_keys f
            where f.object_id=@i
            
            insert into @Data 
            select ' references ' + quotename(s.name) + '.' + quotename(o.name), -2, @i, 41
            from sys.foreign_keys f
            inner join sys.objects o
            on o.object_id=f.referenced_object_id
            inner join sys.schemas s
            on s.schema_id=o.schema_id
            where f.object_id=@i
            
            insert into @Data 
            select ' not for replication', -3, @i, 42
            from sys.foreign_keys f
            inner join sys.objects o
            on o.object_id=f.referenced_object_id
            inner join sys.schemas s
            on s.schema_id=o.schema_id
            where f.object_id=@i and f.is_not_for_replication=1
            end
        else
            insert into @Data values(@f4 + 'Unknow SubObject [' + @T + ']', null, null, 99)
        end

    insert into @Data values(@f1+')', null, null, 100)
    
    -- Indexes
    insert into @Data
    select @f1 + 'create ' + case is_unique when 1 then 'unique ' else '' end + lower(s.type_desc) + ' index ' + 'i' + convert(varchar, row_number() over(order by index_id)) + ' on ' + quotename(sc.Name) + '.' + quotename(o.name), index_id, null, 1000
    from sys.indexes s
    inner join sys.objects o
    on o.object_id=s.object_id
    inner join sys.schemas sc
    on sc.schema_id=o.schema_id
    where s.object_id=@Id and is_unique_constraint=0 and is_primary_key=0 and s.type_desc != 'heap'
    
    -- columns
    set @i=0
    while 1=1
        begin
        select top 1 @i=ic from @Data where ic>@i order by ic 
        if @@rowcount=0 break
        select @i2=0, @Sql=null, @Sql2=null
        while 1=1
            begin
            select @i2=index_column_id, 
                @Sql = case c.is_included_column when 1 then @Sql else isnull(@Sql + ', ', '(') + cc.Name + case c.is_descending_key when 1  then ' desc' else '' end end,
                @Sql2 = case c.is_included_column when 0 then @Sql2 else isnull(@Sql2 + ', ', '(') + cc.Name + case c.is_descending_key when 1  then ' desc' else '' end end
            from sys.index_columns c
            inner join sys.columns cc
            on c.column_id=cc.column_id and cc.object_id=c.object_id
            where c.object_id=@Id and index_id=@i and index_column_id>@i2
            order by index_column_id
            if @@rowcount=0 break
            end
        update @Data set D=D+@Sql +')' + isnull(' include' + @Sql2 + ')', '') where ic=@i
        end
        
    -- references
    set @i=0
    while 1=1
        begin
        select top 1 @i=re from @Data where re>@i order by re
        if @@rowcount=0 break
        
        select @i2=0, @Sql=null, @Sql2=null
        while 1=1
            begin
            select @i2=f.constraint_column_id, 
                @Sql = isnull(@Sql + ', ', '(') + c1.Name,
                @Sql2 = isnull(@Sql2 + ', ', '(') + c2.Name
            from sys.foreign_key_columns f
            inner join sys.columns c1
            on c1.column_id=f.parent_column_id and c1.object_id=f.parent_object_id
            inner join sys.columns c2
            on c2.column_id=f.referenced_column_id and c2.object_id=f.referenced_object_id
            where f.constraint_object_id=@i and f.constraint_column_id>@i2
            order by f.constraint_column_id
            if @@rowcount=0 break
            end
        update @Data set D = D + @Sql + ')'  where re=@i and ic=-1
        update @Data set D = D + @Sql2 + ')'  where re=@i and ic=-2
        end;
    
    -- Render
    with x as(
        select id=d.id-1, D=d.D + isnull(d2.D,'')
        from @Data d
        left outer join @Data d2
        on d.re=d2.re and d2.o=42
        where d.o=41
        
    )
    update @Data
        set D=d.D+x.D
    from @Data d
    inner join x
    on x.id=d.id
    
    delete @Data where o in(41, 42)
    
    select @Sql = 'create table ' + quotename(s.name) + '.' + quotename(o.name) + '(' + @f1
    from sys.objects o
    inner join sys.schemas s
    on o.schema_id = s.schema_id
    where o.object_id=@Id
    
    set @i=0
    while 1=1
        begin
        select top 1 @I=Id, @Sql = @Sql + D from @Data order by o, case when o=0 then right('0000' + convert(varchar,id),5)  else D end, id
        if @@rowcount=0 break
        delete @Data where id=@i
        end
    END
    SELECT @Sql

引自:http://www.cnblogs.com/unruledboy/archive/2011/12/05/SQLMon2.html


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

视图创建之后,若表结构发生改变,此时视图是不改变的,需要刷新视图才可。
exec sp_refreshview ‘VR_bswGoods’


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

复制:将数据传输到其他服务器上存储,做备份。
镜像:主服务器数据库挂了,另一台自动成为主服务器运行,
日志:可控制的镜像。
集群:主服务器挂了,另一台自动成为主服务器运行,并不仅限于数据库。

明细:引自http://hi.baidu.com/jaimy_jie/blog/item/6e099ed52f42a4d250da4b24.html

一, 数据库复制

SQL Server 2008数据库复制是通过发布/订阅的机制进行多台服务器之间的数据同步,我们把它用于数据库的同步备份。这里的同步备份指的是备份服务器与主服务器进行 实时数据同步,正常情况下只使用主数据库服务器,备份服务器只在主服务器出现故障时投入使用。它是一种优于文件备份的数据库备份解决方案。

SQL Server的复制分为种:

1. 快照发布:

发布服务器按预定的时间间隔向订阅服务器发送已发布数据的快照。每隔一段时间将订阅数据库中的相应表中的数据全部删除,然后将自己相应表中的全部插到订阅数据库中

使用快照复制本身是最合适的:
1)很少更改数据。
2)在一段时间内允许具有相对发布服务器已过时的数据副本。
3)复制少量数据。
4)在短期内出现大量更改。

在数据更改量很大,但很少发生更改时,快照复制是最合适的。 例如,如果某销售组织维护一个产品价格列表且这些价格每年要在固定时间进行一两次完全更新,那么建议在数据更改后复制完整的数据快照。 对于给定的某些类型的数据,更频繁的快照可能也比较适合。 例如,如果一天中在发布服务器上更新相对小的表,但可以接受一定的滞后时间,则可以在夜间以快照形式传递更改。

发布服务器上快照复制的连续开销低于事务复制的开销,因为不用跟踪增量更改。 但是,如果要复制的数据集非常大,那么若要生成和应用快照,将需要使用大量资源。 评估是否使用快照复制时,需要考虑整个数据集的大小以及数据的更改频率。

2. 事务发布:

在订阅服务器收到已发布数据的初始快照后,发布服务器将事务流式传输到订阅服务器。

事务复制通常从发布数据库对象和数据的快照开始。 创建了初始快照后,接着在发布服务器上所做的数据更改和架构修改通常在修改发生时(几乎实时)便传递给订阅服务器。 数据更改将按照其在发布服务器上发生的顺序和事务边界应用于订阅服务器,因此,在发布内部可以保证事务的一致性。

以下各种情况下适合采用事务复制:
1). 希望发生增量更改时将其传播到订阅服务器。
2). 从发布服务器上发生更改,至更改到达订阅服务器,应用程序需要这两者之间的滞后时间较短。
3). 应用程序需要访问中间数据状态。 例如,如果某一行更改了五次,事务复制将允许应用程序响应每次更改(例如,激发触发器),而不只是响应该行最终的数据更改。
4).发布服务器有大量的插入、更新和删除活动。
5).发布服务器或订阅服务器不是 SQL Server 数据库(例如,Oracle)。

默认情况下,事务发布的订阅服务器应视为只读,因为更改将不会传播回发布服务器。 但是,事务复制确实提供了允许在订阅服务器上进行更新的选项

3. 具有可更新订阅的事务发布:

在 SQL Server 订阅服务器收到已发布数据的初始快照后,发布服务器将事务流式传输到订阅服务器。来自订阅服务器的事务被应用于发布服务器。

4. 合并发布:

在订阅服务器收到已发布数据的初始快照后,发布服务器和订阅服务器可以独立更新已发布数据。更改会定期合并。Microsoft SQL Server Compact Edition 只能订阅合并发布。

与事务复制相同,合并复制通常也是从发布数据库对象和数据的快照开始, 并且用触发器跟踪在发布服务器和订阅服务器上所做的后续数据更改和架构修改。 订阅服务器在连接到网络时将与发布服务器进行同步,并交换自上次同步以来发布服务器和订阅服务器之间发生更改的所有行。

合并复制通常用于服务器到客户端的环境中。 合并复制适用于下列各种情况:
1). 多个订阅服务器可能会在不同时间更新同一数据,并将其更改传播到发布服务器和其他订阅服务器。
2). 订阅服务器需要接收数据,脱机更改数据,并在以后与发布服务器和其他订阅服务器同步更改。
3). 每个订阅服务器都需要不同的数据分区。
4). 可能会发生冲突,并且在冲突发生时,您需要具有检测和解决冲突的能力。
5). 应用程序需要最终的数据更改结果,而不是访问中间数据状态。 例如,如果在订阅服务器与发布服务器进行同步之前,订阅服务器上的行更改了五次,则该行在发布服务器上仅更改一次来反映最终数据更改(也就是第五次更改的值)。

合并复制允许不同站点自主工作,并在以后将更新合并成一个统一的结果。 由于更新是在多个节点上进行的,同一数据可能由发布服务器和多个订阅服务器进行了更新。 因此,在合并更新时可能会产生冲突,合并复制提供了多种处理冲突的方法

复制的缺点: 表有主键,而且表结构日后不能更改,如果架构稳定也是不错的,如果有很多张表那就比较麻烦了

复制方法及过程:

http://www.cnblogs.com/dudu/archive/2010/08/26/1808540.html

http://www.cnblogs.com/killkill/archive/2009/07/17/1525733.html

http://dufei.blog.51cto.com/382644/84645

http://www.cnblogs.com/wangdong/archive/2008/10/24/1318740.html

二,数据库镜像:

数据库镜像:

优点是系统能自动发现主服务器故障,并且自动切换至镜像服务器。

缺点是配置复杂,镜像数据库中的数据不可见(在SQL Server Management Studio中,只能看到镜像数据库处于镜像状态,无法进行任何数据库操作,最简单的查询也不行。想眼见为实,看看镜像数据库中的数据是否正确都不行。只 有将镜像数据库切换主数据库才可见)

相对于日志传送,数据库镜像显然更高一级。在最简单的形式下,它其实与日志传送的工作原理相似,但是生产服务器发送事务到镜像服务器的频率要高得多,这意味着更新速度也要快很多。

  对于数据库镜像来说,故障转移功能也是需要手动完成。但是你可以添加第三个SQL Server,称为witness。Witness可以作为一个普通的SQL Server,但是一直留意着其它两个镜像服务器。当主镜像发生故障,witness可以让第二个镜像接管操作,类似一种自动的故障转移。

  在故障转移时,任何进行中的客户端事务都将重新启动,而由于在这一过程中仍然存在着延迟,镜像服务器也不能保证百分之百不丢失数据。

三,数据库日志传输:

作为高可用性的最低级形式,日志传送(log shipping)本质上是SQL Server复制功能的一种延伸

允许解决方案提供商创建多个数据库副本。日志传输能够将次数据库日志副本同步发送到SQL Server实例上。然后这些日志会在次服务器上重放,从而保持数据库副本是最新的。

  有一些解决方案提供商使用日志传输作为克服数据库镜像缺点的方法。数据库镜像是很好的技术,但是它只允许我们实现一个数据库副本。镜像可以接近实时的方式进行,所以数据库修改可以快速地写到次数据库上。如果客户数据库损坏或数据库记录意外删除,那么这可能会造成问题。

  日志传输有两个主要的优点。首先,解决方案提供商能够实现一种延迟,这样日志就不会即时重放。这是很重要的,因为如果主(或镜像)数据库出现问题,日志可以在重放之前拦截,因此可以防止问题扩散。

  日志传输第二个主要的优点是它支持实现多个数据库副本。有一些单位使用日志传输作为在备份数据中心维护数据库副本的方法,这能够防止主数据中心出现问题时发生数据丢失。

   虽然日志传输通过是作为数据库镜像的补充措施,但是它是一种独立的技术,它可以不依赖于镜像技术而独立使用。

http://www.searchdatabase.com.cn/showcontent_11708.htm

四,故障转移集群

集群技术是微软可用性的最高级形式,它需要你设置一个Windows集群。

  在集群中并不会涉及传输以及镜像,取而代之,两台或更多的电脑将会彼此连接在一个共享的外部存储器中,通常是存储区域网络(SAN)。数据库文件就存放在这个共享存储器上,同样设置的SQL Server实例都运行在集群节点上。

  集群中的所有节点中,实际上只有一个节点是一直处在活动状态的,如果这个节点发生故障,其它的节点将启动相应的SQL Server实例,并连接共享存储器的数据文件。而整个故障转移过程往往只有几秒钟时间,对于任何给定的SQL Server实例,Windows集群技术都可以确保客户端始终注视活动的节点。

  集群技术非常复杂,但它是实现高可用的最高效技术。与前面介绍的两个功能相比,集群依赖于一个单一的数据库文件集。如果这些文件损坏了,故障转移也不能起作用了,因为故障转移的实例同损坏的文件是一样的。而使用镜像与日志传送,你可以对文件进行实时拷贝,因此不必担心文件损坏的问题。SQL Server中,文件遭到损坏的情况很少发生,因此我认为集群应该还是一个不错的选择。

缺点的。其中一个重要的问题是故障恢复的实现是非常昂贵的。Microsoft只在那些通过Windows Server认证的硬件上才支持故障恢复。 另一个问题是它要求使用共享存储


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
go N :执行批语句N次

Create Table #Temp(SerialNo int identity Primary key, Product varchar(500))
go
 
Declare @Product varchar(500)
SET @Product='Mouse'
insert into #Temp(Product)
select @Product

GO 20

select * from #Temp
drop Table #Temp


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

磁盘负责三方面,一个将数据写入到日志文件ldf中,然后在check point后写入到mdf, 接着就是大量的读操作。
先写入ldf,是因为sql server的预写日志机制引起的,此机制保证了数据在写入到mdf中前,一定会在ldf中保留一份,这样以后恢复等操作都可进行,故可以说,影响写性能的主要是写入到ldf中的操作。磁盘一边负责随机取数据,一边负责写入数据,磁头转来变去,性能低下,而将ldf文件放在不同的磁盘中,就独立了写操作。
注意:磁盘应是物理上的。

Other logical drive will not benefit because ultimately, it’s the same drive controller and the same physical disc. Hence, if the heads are busy doing random reads for a logical drive D, they won’t be able to perform serial writes on logical drive E on the same physical drive.

Hence, the log should be given the priviledge of it’s own separate physical drive.
引自:
Performance Best practice – Transaction log must on a different drive. But WHY?
Write-Ahead Transaction Log


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

当 SET NOCOUNT 为 ON 时,不返回计数(表示受 Transact-SQL 语句影响的行数)。当 SET NOCOUNT 为 OFF 时,返回计数。

即使当 SET NOCOUNT 为 ON 时,也更新 @@ROWCOUNT 函数。

当 SET NOCOUNT 为 ON 时,将不向客户端发送存储过程中每个语句的 DONE_IN_PROC 消息。使用由 SQL Server 2005 提供的实用工具执行查询时,其结果会防止在 Transact-SQL 语句(例如 SELECT、INSERT、UPDATE 和 DELETE)的末尾显示 nn rows affected。

如果存储过程中包含的一些语句并不返回许多实际数据,则该设置由于大量减少了网络流量,因此可显著提高性能。

SET NOCOUNT 设置是在执行或运行时设置,而不是在分析时设置。


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
1, INFORMATION_SCHEMA.COLUMNS :存储列定义,包含列类型,长度等信息。
2,INFORMATION_SCHEMA.PARAMETERS:存储过程参数信息。
如:查询行长度:
select
c.table_name,
count(*) columns,
sum(
case data_type
when 'binary' then character_maximum_length
when 'varbinary' then character_maximum_length
when 'char' then character_maximum_length
when 'varchar' then character_maximum_length
when 'nchar' then character_maximum_length
when 'nvarchar' then character_maximum_length
when 'bigint' then 8
when 'int' then 4
when 'uniqueidentifier' then 16
when 'datetime' then 8
when 'bit' then 1
when 'image' then 16
when 'text' then 16
when 'ntext' then 16
end) as avgLen
 from INFORMATION_SCHEMA.COLUMNS c join INFORMATION_SCHEMA.Tables t
ON c.Table_Schema=t.Table_Schema AND c.Table_Name=t.Table_Name
WHERE t.TABLE_TYPE='BASE TABLE' AND c.TABLE_NAME NOT IN('dtproperties','sysdiagrams')
--AND table_name like '%log'
group by c.table_name
order by avgLen desc
go


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

聚集索引叶级别除了保持键值外,还包含所有数据
非聚集索引叶级别只有需要的键值及书签,以“文件号:页号:槽号”的格式定位
查看索引存储:
–打开3604,信息发送到控制台
DBCC TRACEON(3604)
–查看表索引对应的页数明细
DBCC IND (‘brm_lvjian_new’, ‘frmuser’, -1);
–查看页上的数据信息
DBCC PAGE (brm_lvjian_new, 1, 586958, 1);
在Memory Dump下存储着信息。

不过非聚集索引并不一定比聚集索引快,但where条件,select字段都是复合索引字段时,因索引
空间较小,比件聚集索引查找快一些。
如:在frmUser表中DepartmentID上建立非聚集索引
执行:
SELECT departmentid
FROM frmuser
WHERE DepartmentId = 4

SELECT *
FROM frmuser
WHERE DepartmentId = 4

发现前者通过索引查找一步到位,而后者在索引查找后,因还要取其它值,故还要根据索引页键值中的引用,去数据页取值
这提示:SELECT中的字段少一些速度会更快,一是若字段在一索引内,就避免了去数据页的检索,二是避免了大量数据的I/O操作。
复合索引与对字段分别建索引的区别:
1,复合索引整体空间比分别建索引要小。
2,若查询语句对索引内字段查询,复合索引直接得到位置,而分别建索引需要分别查出再连接
并且当SELECT字段也在索引内时,复合索引会直接得出,而分另建索引则需要去数据页重新取。


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

SELECT objectpropertyex (OBJECT_ID(‘VR_bswGoods’), ‘IsView’)
IsSystemTable
IsUserTable
IsView
IsTable
IsTableFunction
IsTrigger


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
引用:http://technet.microsoft.com/zh-cn/library/cc966540(en-us).aspx
Sql Server速度变慢问题主要由三个方面引起,可从这三个方面入手分析问题
  1,资源瓶颈:CPU、I/O、内存等。
  2,临时表瓶颈:tempdb各个数据库共用,资源紧张时会引起性能降低。
  3,用户比较耗时的sql查询。

一,CPU瓶颈分析。瓶颈症状:打开perfmon, 监视 processor:% Processor Time若长期>80%,或者任务管理器,说明可能是CPU原因。
1,分析是否是查询语句引起
 这里涉及一个动态视图:sys.dm_exec_query_stats,返回每条查询语句运行的时间
关键栏位有:
 1)sql_handle:表示包含查询的批查询或存储过程的标记,若sql_handle相同,代表查询在同个批处理或同一个存储过程内。可将此值传入    sys.dm_exec_sql_text中获取查询语句。同个存储过程或批处理语句的sql_handle相同,如何分辨是哪个查询语句得到了执行,
可用statement_start_offset、statement_end_offset来查出此查询语句的真容。
2)statement_start_offset:查询在其批查询或持久化对象文本中的开始位置
3)statement_end_offset:查询在其批查询或持久化对象文本中的结束位置
4)execution_count: 计划自上次编译以来所执行的次数。
5)total_worker_time:此计划自编译以来执行所用的 CPU 时间总量(以微秒为单位报告,但仅精确到毫秒)。
6)last_execution_time:上次开始执行计划的时间。
故分析耗CPU语句方法可得出:

--若返回的dbname,objectname为空,代表是动态sql语句,不是存储过程
SELECT 
    dbname,ObjectName,Sql,
    SUM([总消耗CPU 时间(ms)]) [总消耗CPU 时间(ms)],
    SUM([运行次数])[运行次数],[查询语句],[所在存储过程],
    SUM([平均消耗CPU 时间(ms)])[平均消耗CPU 时间(ms)]    
    FROM (
    SELECT TOP (50)
        qs.total_worker_time/qs.execution_count/1000. as [平均消耗CPU 时间(ms)],
        total_worker_time/1000 AS [总消耗CPU 时间(ms)],execution_count [运行次数],
       
        dbo.SQLSig(SUBSTRING(qt.text,qs.statement_start_offset/2+1, --利用sqlsig函数进行参数化,以屏蔽传来的参数,使之标准化
            (case when qs.statement_end_offset = -1
            then DATALENGTH(qt.text)
            else qs.statement_end_offset end -qs.statement_start_offset)/2 + 1),4000)
        as [查询语句], qt.text [所在存储过程],
        qt.dbid, dbname=db_name(qt.dbid),
        qt.objectid,object_name(qt.objectid,qt.dbid) ObjectName
    FROM sys.dm_exec_query_stats qs
    cross apply sys.dm_exec_sql_text(qs.sql_handle) as qt
    ORDER BY [平均消耗CPU 时间(ms)] DESC
    )M
    GROUP BY [查询语句],[所在存储过程],dbid, dbname,objectid,ObjectName
    ORDER BY [平均消耗CPU 时间(ms)] DESC

注:测试sys.dm_exec_query_stats 时可先清除缓存DBCC FREEPROCCACHE 再执行查询语句分析。

2,分析是否是重新编译引起,重新编译比较费时。
1)perfmon:

    SQL Server: SQL Statistics: Batch Requests/sec :每秒钟接收的请求数

    SQL Server: SQL Statistics: SQL Compilations/sec:每秒钟的编译数

    SQL Server: SQL Statistics: SQL Recompilations/sec:每秒钟的重新编译数

2)profile:SP:Recompile / SQL:StmtRecompile.
3)sys.dm_exec_query_stats 有一个栏位plan_generation_num,计划编译次数,可用此来分析最常编译的计划。
select top 25
    plan_generation_num,
    SUBSTRING(qt.text,qs.statement_start_offset/2+1,
        (case when qs.statement_end_offset = -1
        then DATALENGTH(qt.text)
        else qs.statement_end_offset end -qs.statement_start_offset)/2 + 1)
        as stmt_executing,
    qt.text,
    execution_count,
    sql_handle,
    dbid,
    db_name(dbid) DBName,
    objectid,
    object_name(objectid,dbid) ObjectName
from sys.dm_exec_query_stats as qs
    Cross apply sys.dm_exec_sql_text(sql_handle) qt
where plan_generation_num >1
--AND qs.last_execution_time >='2011-08-28 10:00' 限定时间
order by plan_generation_num desc



二,内存瓶颈分析。瓶颈症状:打开perfmon, 监视 Paging File: %Usage长期>80%。Paging File:Usage: 分页空间使用百分率

三,I/O瓶颈分析:症状:计数器PhysicalDisk:%Disk Time >80% , Avg.Disk Queue Length:>2
1,%Disk Time :所选磁盘驱动器忙于为读或写入请求提供服务所用的时间的百分比。
Avg. Disk Queue Length 指读取和写入请求(为所选磁盘在实例间隔中列队的)的平均数。
不过,若出现上述情况,也可以是内存不足引起。

2,sys.dm_exec_query_stats 有栏位total_logical_writes:此计划自编译后在执行期间所执行的逻辑写入总次数。total_logical_reads:此计划自编译后在执行期间所执行的逻辑写入总次数。
故查询最耗I/O的语句为:

select top 50
(total_logical_reads/execution_count) as [平均逻辑读取次数],
(total_logical_writes/execution_count) as [平均逻辑写入次数],
(total_physical_reads/execution_count) as [平均对象读取次数],
 Execution_count 运行次数,
substring(qt.text,r.statement_start_offset/2+1,
(case when r.statement_end_offset = -1
then datalength(qt.text)
else r.statement_end_offset end - r.statement_start_offset)/2+1) [运行语法]
from sys.dm_exec_query_stats  as r
    cross apply sys.dm_exec_sql_text(r.sql_handle) as qt
--WHERE r.last_execution_time >='2011-08-28 10:00' 限定时间
order by
 (total_logical_reads + total_logical_writes) Desc

四,tempdb瓶颈。空间资源耗尽引起。
查询:
Select
    SUM (user_object_reserved_page_count)*8 as user_objects_kb,
    SUM (internal_object_reserved_page_count)*8 as internal_objects_kb,
    SUM (version_store_reserved_page_count)*8  as version_store_kb,
    SUM (unallocated_extent_page_count)*8 as freespace_kb
From sys.dm_db_file_space_usage
Where database_id = 2
其中:freespace_kb  要足够大才可。



Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

1,Query Notification:当用户访问的数据改变时,会主动通知前台程序,避免了以往的轮询机制。
2,Event Notification:在用户执行DDL或DML语言后,需要立刻处理的商业逻辑可以通过触发器来完成,但由于触发器执行时会与上述语句绑在一个事务中,因此会拖慢系统响应时间,利用Event Notification可以借由队列积累需求,在系统不忙碌时执行这些需求。
3,当CPU,内存,I/O,带宽等使用率持续超过80%时,表示此系统已达临界门槛,此后系统整体性能必定急速下滑。
4,用户端硬件差也有可能拖慢整个系统,原因:当用户要了一大堆数据,但它没有能力立刻处理完这些服务器源源不断传来的网络包,因此Sql Server对该用户的网络输出缓存区也就塞满了数据,此时并不影响其他用户,但当缓存区满时,扫描数据的工作也将暂停,这时扫描数据所持有的锁不能释放,导致其它用户可能被锁定。
5,因为磁盘是通过磁性和机械臂的运行来访问数据,因此效率远低于CPU和RAM等通过电子运行的速度。
6,学习资料:http://technet.microsoft.com/en-us/sqlserver/bb331794.aspx
http://www.microsoft.com/technet/prodtechnol/sql/2005/tsprfprb.mspx