Atualmente meu notebook (também conhecido como desktop porque a bateria já era) não tem muita capacidade de suportar alguns testes,,, (Acer Aspire 5050 – AMD Turion 1 core, 1.9GB RAM, 35GB HD),,,
Então tentei fazer uma coisa interessante,,,, criar um banco e apontar os arquivos para meu storage (QNAP TS-110),,,
Tenho 2 instâncias de SQL instaladas nesse note, 1 SQL Server 2008 R2 e 1 SQL Server 2005.
Claro que no 2008 R2 funcionou e no 2005 não…
Ai lembrei que para o SQL 2005 (e para o 2008 sem ser R2) criar uma base em local UNC eu precisava habilitar a trace flag 1807. Feito isso conseguir criar a base sem problema.
Achei interessante relembrar isso, pois vai que uma hora qualquer alguém precisa, ou para fazer um LAB ou por falta de espaço (meu caso) você sempre tem uma alternativa… e muita gente nem lembra dessa possibilidade…
Mesmo que saiba o que fazer, é importante treinar para situações complicadas…
É melhor fazer muita tentativa em erro em um ambiente controlado do que no ambiente de produção,,, certo?
Então,,, antes de mais nada… eu sei que você sabe,,, mas não custa nada relembrar,,,
NUNCA FAÇA ISSO EM PRODUÇÃO !!!
Bom,,, com isso em mente,,, vamos começar,,,
1. Vamos criar uma base:
CREATE DATABASE [corrompeu] GO
2. Vamos alterar o modo de recovery da base:
alter database corrompeu set recovery full GO
3. Agora vamos colocar uma tabela:
use corrompeu GO
create table vendas ( vendasID int identity, clienteID int default convert(int, 100000 * RAND()), vendaData datetime default getdate(), vendaTotal money ) GO
4. Adicionamos um índice pra dar gosto…
create clustered index vendaCI on vendas (vendasID) GO
5. Colocamos uns dados,,,
set nocount ON GO
declare @conta INT select @conta = 0 while (@conta < 50000) begin insert into vendas (vendaTotal) values (100*RAND()) select @conta = @conta +1 end GO
7. E vamos fazer uns backups
use master GO
backup database corrompeu to disk = ‘d:\db01\local\corrompeu_1.bak’ with init go
backup log corrompeu to disk = ‘d:\db01\local\corrompeu_2.trn’ go
8. Bom,,, com os backups feitos,,, vamos ver as páginas que foram criadas,,,
dbcc ind (‘corrompeu’,‘vendas’,1) GO
9. Escolha uma página e coloque no lugar do XXXXX
DBCC TRACEON (3604) GO dbcc page(‘corrompeu’,1,XXXXX,3)
Você deve ver alguma coisa do tipo:
A página que eu escolhi foi a 1:493. Meu vendasID vai do registro 24256 até 245000.
Agora começa a ficar legal….
10. Vamos colocar a base offline:
alter database corrompeu set offline GO
11. Agora um simples cálculo…
select 493*8192 GO
Temos o número em decimal da localização da página no arquivo .mdf
12. Com esse número vamos utilizar um editor Hexadecimal para achar a linha dentro do arquivo .mdf.
Dentro do editor de Hexadecimal, abra o arquivo .mdf (neste caso D:\DB01\Corrompeu.mdf).
Clique em “Localizar” e escolha “Ir Para”.
Escolha a opção “DEC”, digite ou cole o resultado do cálculo acima e depois cliente em “HEX”, ele vai converter o valor para Hexadecimal.
clique em “OK”
Altere a linha onde o cursor esta piscando para 00 (zero-zero), ela vai ficar em vermelho.
Salve o arquivo.
13. Agora dentro do SQL vamos voltar com a base online:
alter database corrompeu set online GO
14. Usando o DBCC CHECKDB, vamos ver se a base está realmente corrompida…
Legal,,, temos uma base corrompida…
15. vamos tentar um select na tabela,,, e olha lá o erro,,,
Bom,,, legal… temos uma base corrompida,,, e agora?
Agora fica legal… o objetivo é deixar a base operacional sem perder informação… imagine que essa é sua base de produção e justamente essa tabela é a folha de pagamento,,, olha que legal…
Uma dica: tentei fazer o processo de restore no SQL Server Denali CTP 1 e não consegui restaurar apenas a página, tive que remover ela e reinserir os dados através de outra base, fiz o mesmo processo de restore apenas da página no SQL Server 2008 R2 e funcionou sem problema.
Se alguém precisar de ajuda é só deixar o comentário…
ATUALIZAÇÃO:
Segue o link do SkyDrive com a base, backup e o script desse exemplo:
Existe um número bem legal de comandos DBCC que não fazem nada de mais a não ser checar consistencia no banco de dados. Eu coloque alguns no script abaixo. O primeiro comando é o único considerado mais “perigoso”, isso causará um grande stress no sistema de I/O enquanto efetua a limpesa do cache. Dependendo do workload, isso pode levar alguns minutos, e durante o processo ele pode impactar a performance.
-- A Small Collection of Useful DBCC Commands
-- Glenn Berry
-- August 2010
-- http://glennberrysqlperformance.spaces.live.com/
-- Twitter: GlennAlanBerry
-- Clears out contents of buffer cache
-- Use caution before doing this on a production system!
DBCC DROPCLEANBUFFERS;
-- Clears procedure cache on entire Continue reading Uma pequena coleção de comandos DBCC→
Nesse post vou falar como movimentar os arquivos de um banco de dados de uma unidade/diretório para outra unidade/diretório.
Ai você pensa:
“Pra que? Já sei como faz isso. Não tem nenhuma novidade.” ou
“Aaahh,,, isso é facil, uso o bom e velho backup/restore ou o detach/attach…”
Isso é verdade, não tem nenhuma grande novidade em fazer a movimentação mas, ai vem a parte divertida, pra que fazer do método fácil se podemos fazer do método interessante?
1.- Backup/Restore
Se executarmos o bom e velho backup/restore, no momento do restore podemos alterar o caminho onde os arquivos irão ser gravados, isso é simples.
Apenas precisaremos executar o processo de backup que, dependendo do tamanho da base, pode demorar alguns minutos ou até umas horas. Além de ter que ter um espaço para armazenar o backup ou executá-lo através de uma unidade de backup.
2.- Detach/Attach
Usando o Detach ganhamos algum tempo, você vai apenas mover os arquivos de log e dados para outro lugar e anexar a base novamente.
O problema disso é se você usar o Service Broker ou até o Mirror, você terá que refazer o processo.
3.- Alter Database (o “método interessante”)
Esse “método” a seguir cria uma procedure para executar a movimentação do banco para outro local usando o Alter database, mas é possível executá-lo em diversos bancos como vou demonstrar:
Vamos criar 2 bases de dados para testar:
create database banco1
create database banco2
Agora execute o scritp abaixo para criar a procedure que irá executar a movimentação dos arquivos:
IF ( OBJECT_ID(‘dbo.sp_MoveDatabase’) IS NOT NULL )
begin
DROP PROCEDURE dbo.sp_MoveDatabase
end
GO
as
Begin
declare @DbTable table (lkey int identity (1,1) primary key, dbname nvarchar(100))
declare @FileTable table (lkey int identity (1,1) primary key, [name]nvarchar(100), physical_name nvarchar(1000), [type] int )
declare @sql nvarchar(4000)
declare @count int, @RowNum int
declare @DbName nvarchar(100)
declare @OldPath nvarchar(1000)
declare @Type int
declare @LogicalName nvarchar(100)
declare @ParmDefinition nvarchar(1000)
declare @FileName nvarchar(100)
declare @NewPath nvarchar(1000)
declare @ShowAdvOpt int
declare @XPCMD int
set nocount on;
if right(@DbList,1) = ‘,’
Begin
print ‘DbList must NOT end with “””‘
return
End
declare @MyString NVARCHAR(100)
declare @Pos INT
declare @NextPos INT
declare @String NVARCHAR(4000)
declare @Delimiter NVARCHAR(1)
set @String = @DbList
set @Delimiter = ‘,’
SET @String = @String + @Delimiter
SET @Pos = charindex(@Delimiter,@String)
WHILE (@pos <> 0)
BEGIN
SET @MyString = substring(@String,1,@Pos – 1)
insert into @DbTable (dbname) values (LTRIM(RTRIM(@MyString)))
SET @String = substring(@String,@pos+1,len(@String))
SET @pos = charindex(@Delimiter,@String)
END
set @ShowAdvOpt = cast(( select [value] from sys.configurations where [name] = ‘show advanced options’) as int)
set @XPCMD = cast(( select [value] from sys.configurations where [name] = ‘xp_cmdshell’) as int)
if right(@NewDataFolder,1)<> ‘\’ or right(@NewLogFolder,1)<>’\’
Begin
print ‘new path”s must end with \’
return
end
EXEC sp_configure ‘show advanced option’, ‘1’
RECONFIGURE
exec sp_configure ‘xp_cmdshell’ , ‘1’
RECONFIGURE
print ‘NewMdfFolder is ‘ + @NewDataFolder
print ‘NewLdfFolder is ‘ + @NewLogFolder
SET @RowNum = 1
SET @count = (select count(*) from @DbTable)
while @RowNum <= @count
Begin
select @DbName = DBName from @DbTable
where lKey = @RowNum
set @sql = ‘select name, physical_name, type from ‘ + @DbName + ‘.sys.database_files’
insert into @FileTable
exec sp_executesql @sql
— Derruba todas as conexoes configurando como single user with immediate
set @sql= ‘ALTER DATABASE [‘ + @DbName + ‘] SET SINGLE_USER WITH ROLLBACK IMMEDIATE’
print ”
print ‘Executando linha -‘ + @sql
exec sp_executesql @sql
— configura db off line
set @sql = ‘ALTER DATABASE [‘ + @DbName + ‘] SET OFFLINE;’
print ”
print ‘Executando linha – ‘ + @sql
exec sp_executesql @sql
select * from @FileTable
while @@rowcount > 0
begin
select top 1 @OldPath = physical_name, @Type = [type], @LogicalName = [name] from @FileTable
–move arquivos files
set @FileName = (SELECT REVERSE(SUBSTRING(REVERSE(@OldPath), 0, CHARINDEX(‘\’, REVERSE(@OldPath), 1))))
if @type = 0
begin
set @NewPath = @NewDataFolder + @FileName
end
else
begin
set @NewPath = @NewLogFolder + @FileName
end
set @Sql = ‘EXEC master..xp_cmdshell ”MOVE “‘ + @OldPath + ‘” “‘ + @NewPath +'””’
print ”
print ‘Executando linha -‘ + @sql
exec sp_executesql @sql
— altera caminho dos arquivos
set @sql = ‘ALTER DATABASE ‘ + @DbName + ‘ MODIFY FILE (NAME = ‘ + @LogicalName + ‘, FILENAME = “‘ + @NewPath + ‘”)’
exec sp_executesql @sql
delete from @FileTable where [name] = @LogicalName
select * from @FileTable
end –while
set @sql = ‘ALTER DATABASE [‘ + @DbName + ‘] SET ONLINE;’
print ”
print ‘Executing line -‘ + @sql
exec sp_executesql @sql
SET @RowNum = @RowNum + 1
— aceita multi user novamente.
set @sql= ‘ALTER DATABASE [‘ + @DbName + ‘] SET MULTI_USER’
print ”
print ‘Executing line -‘ + @sql
exec sp_executesql @sql
end
exec sp_configure ‘xp_cmdshell’ , @XPCMD
Os diretórios de destino já devem estar criados, caso você execute a procedure sem criar o destino o script vai alterar o caminho da base e não vai movimentar os arquivos e quando ela foi trazida online ela vai apresentar erro.
** ATENÇÃO 2 **
Esse script é do tipo “Vai filhão”, quando ele for executado todos os usuários conectados serão desconectados sem dó nem piedade, todas as transações que eles estiverem executando serão dropadas. As conexões apenas poderão ser reestabelecidas após o termino da movimentação.
Para executar a procedure execute-a da seguinte forma:
Se tudo der certo, as bases banco1 e banco2 estarão seus novos destinos.
let's make things better
Manage Cookie Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional
Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes.The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.