Arquivo da tag: SQL Server

SharePoint 2013: Shredded storage

Olá SharePointers,

Hoje vou falar um pouco sobre Shredded storage e como o SharePoint se comporta utilizando esse recurso.

Antes de mais nada, vamos ao significado do verbo “Shred” que significa cortar, despedaçar, retalhar. Trazendo para o mundo do SharePoint, Shredded storage é uma grande melhoria na gestão de objetos binários (os “BLOBs” – que basicamente são arquivos como Planilhas do Excel, Documentos do Word, Vídeos, etc.).

Quem trabalha com o SharePoint desde as versões anteriores (pode ser a 2010 :D) sabe que versionamento, por exemplo, era um grande problema quando o ponto de vista era armazenamento. A cada alteração no documento, o SharePoint realizava uma cópia completa do arquivo e armazenava isso no banco de dados.

Agora, imaginem o seguinte cenário: Supondo que em arquivo de 10MB seja alterado 5 vezes por dia, logo, consumirá 50MB de espaço por dia.

É importante ressaltar que os softwares client da Microsoft (leia: o Pacote Office – Word, Excel, PowerPoint, etc.) já possuiam a tecnologia para que quando um arquivo aberto do SharePoint fosse salvo, somente o diferencial era enviado pela rede (over-the-wire, de volta ao SharePoint) e o SharePoint fazia o trabalho de fazer um “Merge” do arquivo original com o diferencial e salvar esse arquivo inteiro novamente.

O que mudou?

Com o SharePoint 2013 e a criação do Shredded storage (que utiliza o Cobalt –Sincronização de arquivos via SOAP – HTTP), esse BLOB que antes era armazenado em 1 linha do banco de dados SQL Server, agora é dividido em várias linhas. Quando um usuário faz a alteração em algum arquivo, o SharePoint é capaz de identificar qual registro foi alterado e alterar somente esse pedaço – bem reduzido – do arquivo, reduzindo o overhead de utilização de disco, estimada em 2x.

Isso funciona somente com arquivos do Office?

Não. A grande sacada é que funciona com qualquer tipo de arquivo. Não precisa ser do Office e nem muito menos a versão mais atual do Office. Qualquer arquivo se beneficiará dessa tecnologia.

 

Como ficou o armazenamento do BLOB?

Até a versão 2010, os documentos eram armazenados da seguinte forma: os metadados (propriedades do arquivo e do formato) e o stream contendo a representação binária do arquivo.

Com o SharePoint 2013, isso mudou! Temos uma tabela adicional no banco de dados de conteúdo (DocStreams) para armazenar cada pedaço do BLOB do arquivo e, ainda, temos um cache para otimizar a leitura do arquivo.

image

 

Para mais detalhes sobre o assunto, consultem as referências abaixo:

http://blogs.technet.com/b/wbaer/archive/2012/11/12/introduction-to-shredded-storage-in-sharepoint-2013.aspx

http://www.metalogix.com/blog/blog-article/13-03-18/Dispelling_the_Myths_of_Shredded_Storage_in_SharePoint_2013

http://www.microsoft.com/en-us/download/details.aspx?id=39719

SharePoint: Alterações no banco de dados

Olá SharePointers,

É muito comum ouvirmos falar que qualquer alteração nos bancos de dados do SharePoint resultam em perda da garantia do produto.

Mas, já pararam para pensar o que realmente acontece? Quais mudanças implicam na perda da garantia? O que deve ser feito em caso de alguém descobrir essas alterações?

Vamos lá:

Primeiro, vamos identificar o que não é suportado:

  • Adicionar triggers no banco de dados
  • Adicionar novos índices ou alterar os existentestables
  • Adicionar, modificar ou deletar qualquer chave primária ou estrangeira
  • Modificar ou deletar stored procedures
  • Chamar stored procedures diretamente, com exceção das descritas em SharePoint Protocols documentation

    (http://msdn.microsoft.com/en-us/library/cc339475.aspx)

  • Adicionar novas stored procedures
  • Adicionar, modificar ou deletar qualquer dado de qualquer tabela referente ao produto
  • Adicionar, modificar ou deletar qualquer coluna nas tabelas do produto
  • Fazer qualquer modificação ao schema do banco de dados
  • Adicionar tabelas em qualquer um dos bancos do produto
  • Trocar o collation do banco de dados
  • Rodar a stored procedure DBCC_CHECKDB WITH REPAIR_ALLOW_DATA_LOSS (Entretanto, rodar DBCC_CHECKDB WITH REPAIR_FAST e REPAIR_REBUILD é suportado, porque esses comandos só atualizam os índices do banco associado.)
  • Habilitar SQL Server change data capture (CDC)
  • Habilitar SQL Server transactional replication
  • Habilitar SQL Server merge replication
  •  

    Caso seja descoberto alguma dessas modificações (durante uma call com o suporte da Microsoft) você deverá fazer uma das ações abaixo:

    • Fazer um restore do banco de dados para a última versão que não contém essas modificações
    • Roll back em todas as modificações do banco de dados

     

    Embora todas essas modificações se refiram a alterações, operações de leitura também são proibidas.

    Qualquer operação de leitura programaticamente ou manual pode causar locks dentro do SQL Server e, com isso, resultar em queda de performance. Sendo assim, qualquer leitura ao banco de dados que não seja utilizando um artefato providenciado pelo time de desenvolvimento do SharePoint ou pelo time de suporte é considerado “não suportado” e são barreiras para que o time de suporte continue te atendendo.

    Para quem quiser ler mais sobre o assunto, acesse esse link: http://support.microsoft.com/kb/841057/en-us

    Abraços 😀

    Troubleshooting: Could not find stored procedure ‘sp_dboption’

    Olá SharePointers,

    Hoje estava montando um ambiente para testes de migração e encontrei um problema ao instalar o SharePoint Server 2007 SP2 com SQL Server 2012.

    O erro foi: Could not find stored procedure ‘sp_dboption’. Essa stored procedure foi descontinuada no SQL Server 2012 e, para que a instalação funcione, é necessário criá-la novamente, utilizando o código abaixo:

    USE [master]
    GO
    /****** Object: StoredProcedure [sys].[sp_dboption] Script Date: 12/08/2013 21:22:10 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE procedure [sp_dboption] — 1999/08/09 18:25
    @dbname sysname = NULL, — database name to change
    @optname varchar(35) = NULL, — option name to turn on/off
    @optvalue varchar(10) = NULL — true or false
    as
    set nocount on
    declare @dbid int — dbid of the database
    declare @catvalue int — number of category option
    declare @optcount int — number of options like @optname
    declare @allstatopts int — bit map off all options stored in sysdatqabases.status
    — that can be set by sp_dboption.
    declare @alloptopts int — bit map off all options stored in sysdatqabases.status
    — that can be set by sp_dboption.
    declare @allcatopts int — bit map off all options stored in sysdatqabases.category
    — that can be set by sp_dboption.
    declare @exec_stmt nvarchar(max)
    declare @fulloptname varchar(35)
    declare @alt_optname varchar(50)
    declare @alt_optvalue varchar(30)
    declare @optnameIn varchar(35)
    select @optnameIn = @optname
    ,@optname = LOWER (@optname collate Latin1_General_CI_AS)
    — If no @dbname given, just list the possible dboptions.
    — Only certain status bits may be set or cleared by sp_dboption.
    — Get bitmap of all options that can be set by sp_dboption.
    select @allstatopts=number from master.dbo.spt_values where type = ‘D’
    and name = ‘ALL SETTABLE OPTIONS’
    select @allcatopts=number from master.dbo.spt_values where type = ‘DC’
    and name = ‘ALL SETTABLE OPTIONS’
    select @alloptopts=number from master.dbo.spt_values where type = ‘D2’
    and name = ‘ALL SETTABLE OPTIONS’
    if @dbname is null
    begin
    select ‘Settable database options:’ = name
    from master.dbo.spt_values
    where (type = ‘D’
    and number & @allstatopts <> 0
    and number not in (0,@allstatopts)) — Eliminate non-option entries
    or (type = ‘DC’
    and number & @allcatopts <> 0
    and number not in (0,@allcatopts))
    or (type = ‘D2’
    and number & @alloptopts <> 0
    and number not in (0,@alloptopts))
    order by name
    return (0)
    end
    — Verify the database name and get info
    select @dbid = dbid
    from master.dbo.sysdatabases
    where name = @dbname
    — If @dbname not found, say so and list the databases.
    if @dbid is null
    begin
    raiserror(15010,-1,-1,@dbname)
    print ‘ ‘
    select ‘Available databases:’ = name
    from master.dbo.sysdatabases
    return (1)
    end
    — If no option was supplied, display current settings.
    if @optname is null
    begin
    select ‘The following options are set:’ = v.name
    from master.dbo.spt_values v, master.dbo.sysdatabases d
    where d.name=@dbname
    and ((number & @allstatopts <> 0
    and number not in (-1,@allstatopts)
    and v.type = ‘D’
    and (v.number & d.status)=v.number)
    or (number & @allcatopts <> 0
    and number not in (-1,@allcatopts)
    and v.type = ‘DC’
    and d.category & v.number <> 0)
    or (number & @alloptopts <> 0
    and number not in (-1,@alloptopts)
    and v.type = ‘D2’
    and d.status2 & v.number <> 0))
    return(0)
    end
    if @optvalue is not null and lower(@optvalue) not in (‘true’, ‘false’, ‘on’, ‘off’)
    begin
    raiserror(15241,-1,-1)
    return (1)
    end
    — Use @optname and try to find the right option.
    — If there isn’t just one, print appropriate diagnostics and return.
    select @optcount = count(*) ,@fulloptname = min(name)
    from master.dbo.spt_values
    where lower(name collate Latin1_General_CI_AS) like ‘%’ + @optname + ‘%’
    and ((type = ‘D’
    and number & @allstatopts <> 0
    and number not in (-1,@allstatopts))
    or (type = ‘DC’
    and number & @allcatopts <> 0
    and number not in (-1,@allcatopts))
    or (type = ‘D2’
    and number & @alloptopts <> 0
    and number not in (-1,@alloptopts)))
    — If no option, show the user what the options are.
    if @optcount = 0
    begin
    raiserror(15011,-1,-1,@optnameIn)
    print ‘ ‘
    select ‘Settable database options:’ = name
    from master.dbo.spt_values
    where (type = ‘D’
    and number & @allstatopts <> 0
    and number not in (-1,@allstatopts)) — Eliminate non-option entries
    or (type = ‘DC’
    and number & @allcatopts <> 0
    and number not in (-1,@allcatopts))
    or (type = ‘D2’
    and number & @alloptopts <> 0
    and number not in (-1,@alloptopts))
    order by name
    return (1)
    end
    — If more than one option like @optname, show the duplicates and return.
    if @optcount > 1
    begin
    raiserror(15242,-1,-1,@optnameIn)
    print ‘ ‘
    select duplicate_options = name
    from master.dbo.spt_values
    where lower(name collate Latin1_General_CI_AS) like ‘%’ + @optname + ‘%’
    and ((type = ‘D’
    and number & @allstatopts <> 0
    and number not in (-1,@allstatopts))
    or (type = ‘DC’
    and number & @allcatopts <> 0
    and number not in (-1,@allcatopts))
    or (type = ‘D2’
    and number & @alloptopts <> 0
    and number not in (-1,@alloptopts))
    )
    return (1)
    end
    — Just want to see current setting of specified option.
    if @optvalue is null
    begin
    select OptionName = v.name,
    CurrentSetting = (case
    when ( ((v.number & d.status) = v.number
    and v.type = ‘D’)
    or (d.category & v.number <> 0
    and v.type = ‘DC’)
    or (d.status2 & v.number <> 0
    and v.type = ‘D2’)
    )
    then ‘ON’
    when not
    ( ((v.number & d.status) = v.number
    and v.type = ‘D’)
    or (d.category & v.number <> 0
    and v.type = ‘DC’)
    or (d.status2 & v.number <> 0
    and v.type = ‘D2’)
    )
    then ‘OFF’
    end)
    from master.dbo.spt_values v, master.dbo.sysdatabases d
    where d.name=@dbname
    and ((v.number & @allstatopts <> 0
    and v.number not in (-1,@allstatopts) — Eliminate non-option entries
    and v.type = ‘D’)
    or (v.number & @allcatopts <> 0
    and v.number not in (-1,@allcatopts) — Eliminate non-option entries
    and v.type = ‘DC’)
    or (v.number & @alloptopts <> 0
    and v.number not in (-1,@alloptopts) — Eliminate non-option entries
    and v.type = ‘D2’)
    )
    and lower(v.name) = lower(@fulloptname)
    return (0)
    end
    select @catvalue = 0
    select @catvalue = number
    from master.dbo.spt_values
    where lower(name) = lower(@fulloptname)
    and type = ‘DC’
    — if setting replication option, call sp_replicationdboption directly
    if (@catvalue <> 0)
    begin
    select @alt_optvalue = (case lower(@optvalue)
    when ‘true’ then ‘true’
    when ‘on’ then ‘true’
    else ‘false’
    end)
    select @alt_optname = (case @catvalue
    when 1 then ‘publish’
    when 2 then ‘subscribe’
    when 4 then ‘merge publish’
    else quotename(@fulloptname, ””)
    end)
    select @exec_stmt = quotename(@dbname, ‘[‘) + ‘.dbo.sp_replicationdboption’
    EXEC @exec_stmt @dbname, @alt_optname, @alt_optvalue
    return (0)
    end
    — call Alter Database to set options
    — set option value in alter database
    select @alt_optvalue = (case lower(@optvalue)
    when ‘true’ then ‘ON’
    when ‘on’ then ‘ON’
    else ‘OFF’
    end)
    — set option name in alter database
    select @fulloptname = lower(@fulloptname)
    select @alt_optname = (case @fulloptname
    when ‘auto create statistics’ then ‘AUTO_CREATE_STATISTICS’
    when ‘auto update statistics’ then ‘AUTO_UPDATE_STATISTICS’
    when ‘autoclose’ then ‘AUTO_CLOSE’
    when ‘autoshrink’ then ‘AUTO_SHRINK’
    when ‘ansi padding’ then ‘ANSI_PADDING’
    when ‘arithabort’ then ‘ARITHABORT’
    when ‘numeric roundabort’ then ‘NUMERIC_ROUNDABORT’
    when ‘ansi null default’ then ‘ANSI_NULL_DEFAULT’
    when ‘ansi nulls’ then ‘ANSI_NULLS’
    when ‘ansi warnings’ then ‘ANSI_WARNINGS’
    when ‘concat null yields null’ then ‘CONCAT_NULL_YIELDS_NULL’
    when ‘cursor close on commit’ then ‘CURSOR_CLOSE_ON_COMMIT’
    when ‘torn page detection’ then ‘TORN_PAGE_DETECTION’
    when ‘quoted identifier’ then ‘QUOTED_IDENTIFIER’
    when ‘recursive triggers’ then ‘RECURSIVE_TRIGGERS’
    when ‘default to local cursor’ then ‘CURSOR_DEFAULT’
    when ‘offline’ then (case @alt_optvalue when ‘ON’ then ‘OFFLINE’ else ‘ONLINE’ end)
    when ‘read only’ then (case @alt_optvalue when ‘ON’ then ‘READ_ONLY’ else ‘READ_WRITE’ end)
    when ‘dbo use only’ then (case @alt_optvalue when ‘ON’ then ‘RESTRICTED_USER’ else ‘MULTI_USER’ end)
    when ‘single user’ then (case @alt_optvalue when ‘ON’ then ‘SINGLE_USER’ else ‘MULTI_USER’ end)
    when ‘select into/bulkcopy’ then ‘RECOVERY’
    when ‘trunc. log on chkpt.’ then ‘RECOVERY’
    when ‘db chaining’ then ‘DB_CHAINING’
    else @alt_optname
    end)
    if @fulloptname = ‘dbo use only’
    begin
    if @alt_optvalue = ‘ON’
    begin
    if databaseproperty(@dbname, ‘IsSingleUser’) = 1
    begin
    raiserror(5066,-1,-1);
    return (1)
    end
    end
    else
    begin
    if databaseproperty(@dbname, ‘IsDBOOnly’) = 0
    return (0)
    end
    end
    if @fulloptname = ‘single user’
    begin
    if @alt_optvalue = ‘ON’
    begin
    if databaseproperty(@dbname, ‘ISDBOOnly’) = 1
    begin
    raiserror(5066,-1,-1);
    return (1)
    end
    end
    else
    begin
    if databaseproperty(@dbname, ‘IsSingleUser’) = 0
    return (0)
    end
    end
    select @alt_optvalue = (case @fulloptname
    when ‘default to local cursor’ then (case @alt_optvalue when ‘ON’ then ‘LOCAL’ else ‘GLOBAL’ end)
    when ‘offline’ then ”
    when ‘read only’ then ”
    when ‘dbo use only’ then ”
    when ‘single user’ then ”
    else @alt_optvalue
    end)
    if lower(@fulloptname) = ‘select into/bulkcopy’
    begin
    if @alt_optvalue = ‘ON’
    begin
    if databaseproperty(@dbname, ‘IsTrunclog’) = 1
    select @alt_optvalue = ‘RECMODEL_70BACKCOMP’
    else
    select @alt_optvalue = ‘BULK_LOGGED’
    end
    else
    begin
    if databaseproperty(@dbname, ‘IsTrunclog’) = 1
    select @alt_optvalue = ‘SIMPLE’
    else
    select @alt_optvalue = ‘FULL’
    end
    end
    if lower(@fulloptname) = ‘trunc. log on chkpt.’
    begin
    if @alt_optvalue = ‘ON’
    begin
    if databaseproperty(@dbname, ‘IsBulkCopy’) = 1
    select @alt_optvalue = ‘RECMODEL_70BACKCOMP’
    else
    select @alt_optvalue = ‘SIMPLE’
    end
    else
    begin
    if databaseproperty(@dbname, ‘IsBulkCopy’) = 1
    select @alt_optvalue = ‘BULK_LOGGED’
    else
    select @alt_optvalue = ‘FULL’
    end
    end
    — construct the ALTER DATABASE command string
    select @exec_stmt = ‘ALTER DATABASE ‘ + quotename(@dbname) + ‘ SET ‘ + @alt_optname + ‘ ‘ + @alt_optvalue + ‘ WITH NO_WAIT’
    EXEC (@exec_stmt)
    if @@error <> 0
    begin
    raiserror(15627,-1,-1)
    return (1)
    end
    return (0) — sp_dboption

     

    Abraços! 😀

    SharePoint: SQL Server MAXDOP = 1 – é realmente necessário?

    Olá SharePointers,

    Hoje vou falar um pouco do MAXDOP (já ouviram falar?). MAXDOP é a propriedade no SQL Server que define o grau máximo de paralelismo (aka: Max Degree Of Parallelism) para as queries do SQL.

    A microsoft recomenda que, para instâncias do SQL dedicadas ao SharePoint, esse valor seja fixado com 1 para uma performance otimizada (Storage and SQL Server capacity planning and configuration (SharePoint Server 2010)). Muito embora, até a versão 2010 do SharePoint encontramos várias instalações com configurações diferentes desse valor, isso não era um “blocker”. Na versão 2013 do SharePoint, isso passou a ser um blocker de instalação. Veja abaixo:

    New-SPConfigurationDatabase : This SQL Server instance does not have the required "max degree of parallelism" setting of 1. Database provisioning operations will continue to fail if "max degree of parallelism" is not set 1 or the current account does not have permissions to change the setting. See documentation for details on manually changing the setting

    3225_MAXDOP_0_png-550x0

    Ainda de acordo com a Microsoft, o MAXDOP serve para mostrar para o SQL como aplicar o paralelismo, ou seja, se o MAXDOP estiver setado em 0 (valor default) o SQL detecta o melhor grau de paralelismo de acordo com a quantidade de CPUs disponíveis.

    Se estiver setado em 1, os “parallels plans” são desabilitados por default.

    Qualquer valor diferente disso serve para definir um grau específico.

     

    Mas então o SharePoint não utiliza paralelismo? Certo?

    ERRADO! Por questões de performance a melhor opção de performance é desabilitar esse recurso, mas, quando o SharePoint precisa, ele define Hints de paralelismo direto nas stored procedures (mais de 150 SP’s !!).

     

    Para mais informações sobre o assunto, acessem os links abaixo:

     

    Erro: the log scan number passed to log scan in database is not valid–SharePoint 2010 e SQL Server

    Olá SharePointers,

    Hoje passei por um problema assim:

    Ligava a máquina, abrir a Central Admin do SharePoint e aparecia o erro: Could not connect to configuration database.

    A primeira coisa que pensei foi em iniciar o Serviço de SQL Server do SharePoint. Cliquei em iniciar o serviço e deu erro.

    Olhando no Event Viewer, o erro abaixo estava logado:

    image

    No fim, a solução foi bem mais simples do que pensei.

     

    Para resolver o problema, você precisa entrar na pasta C:Program FilesMicrosoft Office Servers14.0DataMSSQL10.SHAREPOINTMSSQLTemplate Data e copiar os arquivos Model.mdf e ModelLog.ldf para a pasta C:Program FilesMicrosoft Office Servers14.0DataMSSQL10.SHAREPOINTMSSQLDATA.

    OBS: Esses caminhos são válidos quando você utilizou a instalação STAND ALONE do SharePoint. Caso contrário, você tem que ir na pasta da instância do seu SQL Server e copiar os arquivos da pasta Template Data para Data.

    Abraços e um feliz ano novo a todos Alegre!