Friday, August 22, 2008

SQL 2005 y los esquemas.

Para los que hicieron su migración de bases de datos de SQL 2000 a SQL 2005, usando el tradicional método de backup/restore, tienen que tomar en cuenta que al hacer la migración se crearon esquemas por cada rol y usuario en cada base de datos.

Esto podría estar bien para aquellos entornos en que manejen así la seguridad, pero podría crear ciertos "problemas" para los que no. Uno de ellos es que cada user al migrarse es el owner de su esquema y no se puede eliminar por lo mismo.

El error que marca es el siguiente: Msg 15138, Level 16, State 1, Line 1
The database principal owns a schema in the database, and cannot be dropped.

Por lo que es necesario que antes de querer eliminar el user, se cambie el owner del esquema o bien se elimine el esquema.

Cambiar el owner de un esquema es muy sencillo, solamente hay que ejecutar esto:
ALTER AUTHORIZATION ON SCHEMA::[nombre_del_esquema] TO DBO;

Es recomendable hacerlo, para evitar en una futura migración, en la que se borran y vuelven a crear los usuarios.

Un script que se puede utilizar para generar scripts que hagan el cambio de owner de todos los esquemas es el siguiente:

select 'ALTER AUTHORIZATION ON SCHEMA::['+ name + '] TO DBO;'
from sys.schemas where name not in ('dbo','sys','guest','INFORMATION_SCHEMA','db_accessadmin','db_backupoperator','db_datareader','db_datawriter','db_ddladmin','db_denydatareader','db_denydatawriter','db_owner','db_securityadmin')
and principal_id<>1 order by schema_id

Solamente hay que estar en cada una de las bases de datos y correr el script. Una vez que se haya hecho el cambio de owner en los esquemas, los esquemas se pueden eliminar o bien dejarlos en la base de datos.

Monday, August 18, 2008

Actualizando firmware de Smart Array E200i

Hace poco estaba actualizando el firmware en un servidor Proliant BL460c G1 de HP.

En una de esas actualizaciones, actualizé el firmware de la tarjeta controladora de los arreglos (Smart Array E200i Controller) de la versión 1.66 a la versión 1.78, lo hice usando el exe que viene para servidores Windows 2003 a 32 bits, todo transcurrió normalmente, me conecté por la ILO y me di cuenta que al iniciar el servidor marcó unos mensaje y no encontró los discos duros y se pasó a la parte del PXE, así que le di un reboot nuevamente y ya pudo iniciar Windows.

Pero, al iniciar marcaba este mensaje: "A firmware update is needed for the physical drive with product ID GD072ABAB3 connected to array controller [Embedded]. The recommended minimum firmware revision should be HPDA." Obviamente no podía dejar el servidor así, ya que se iba a reinstalar y no quería que esto ocasionara problemas en el futuro.

Así que bajé el archivo .iso de la página de HP, con todos los firmware, utilizé el 7-zip para descomprimir el iso (y así no tener que quemar un CD), puse los archivos del iso en el servidor, ejecuté el el archivo CDBrowser, dentro del folder /compaq/CDBrowser, mediante la página del HomePage del servidor, chequé el modelo de los discos duros, en este caso DG072ABAB3, y en la sección de Device ahi estaba el modelo (SAS 72 GB 10K drives DG072ABAB3), desde la misma herramienta ejecuté el instalador y reinicié el servidor.

Cuando se estaba reiniciando el servidor detectó que estaba pendiente hacer un upgrade de versión de los discos y me presentaba 3 opciones, actualizar el porcentaje del update, dejar el update para el siguiente restart o cancelarlo, yo dejé que solo se actualizara y al cabo de unos 2 minutos, el update terminó y desaparecieron los mensajes de Warning.

Esto para tener en cuenta en un upgrade de versión de firmware de la tarjeta controladora de HP, la versión puede quedar muy arriba que puede ser que sea necesario actualizar los disco, lo que yo recomendaría sería primero actualizar el firmware de los discos duros, para evitar este tipo de sorpresas.

Tuesday, August 12, 2008

Mas scripts de SMO-SQL 2005 y PowerShell.

En el último post expuse algunos scripts de PowerShell para obtener diferentes propiedades de los servidores SQL 2005. En este post voy a continuar explicando algunos otros que también son muy útiles en una política de Disaster Recover de SQL 2005.

El primer script servirá para obtener el script para recrear los usuarios de cada base de datos y agregarlos en su rol correspondiente.

param ( [string] $serverName )
$RutaScripts = "c\scripts\"
[void][reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
$MyScripter=new-object ("Microsoft.SqlServer.Management.Smo.Scripter")
$srv=New-Object "Microsoft.SqlServer.Management.Smo.Server" $serverName
$MyScripter.Options.FileName = $f
$MyScripter.Options.AppendToFile = $true
$MyScripter.Server=$srv


write-host "Obteniendo el script para recrear los usuarios..."
foreach($db in $srv.databases) {
$f = [System.IO.Path]::Combine($RutaScripts, $nombre + "_Usuarios_" + $db.name + ".sql")
if ($db.Name -ne "master" -and $db.Name -ne "model" -and $db.Name -ne "msdb" -and $db.Name -ne "tempdb") {
$MyScripter.options.IncludeDatabaseContext = $true
foreach ($User in $db.Users) {
if ($User.Name -ne "sys" -and $User.Name -ne "dbo" -and $User.Name -ne "INFORMATION_SCHEMA" -and $User.Name -ne "guest") {
$MyScripter.Options.IncludeIfNotExists = $true
$MyScripter.Options.ScriptDrops = $true
$MyScripter.Script($User) | Out-file $f -append
}
if ($User.Name -ne "sys" -and $User.Name -ne "dbo" -and $User.Name -ne "INFORMATION_SCHEMA" -and $User.Name -ne "guest") {
$MyScripter.options.IncludeDatabaseContext = $false
$MyScripter.Options.IncludeDatabaseRoleMemberships = $true
$MyScripter.Options.ScriptDrops = $false
$MyScripter.Script($User) | Out-file $f -append
out-file -filePath $f -inputobject "`n" -append
}
}
}
}

El siguiente script sirve para obtener un script con los permisos de cada base de datos:
param ( [string] $serverName )
$RutaScripts = "c\scripts\"
[void][reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
$MyScripter=new-object ("Microsoft.SqlServer.Management.Smo.Scripter")
$srv=New-Object "Microsoft.SqlServer.Management.Smo.Server" $serverName
$MyScripter.Options.FileName = $f
$MyScripter.Options.AppendToFile = $true
$MyScripter.Server=$srv


write-host "Obteniendo el script de permisos de cada base de datos..."
foreach($db in $srv.databases) {
if ($db.Name -ne "master" -and $db.Name -ne "model" -and $db.Name -ne "msdb" -and $db.Name -ne "tempdb") {
$f = [System.IO.Path]::Combine($RutaScripts, $nombre +"_permisos_" + $db.Name + ".sql")
out-file -filePath $f -inputobject "USE $db `nGO`n"
foreach ($permiso in $db.EnumObjectPermissions()| where {$_.Grantee.ToString() -ne 'public'} ) {
$var=[string]$permiso.PermissionState+" "+$permiso.PermissionType+" ON "+$permiso.Grantor+"."+$permiso.ObjectName+" TO "+$permiso.Grantee
out-file -filePath $f -inputobject $var -append
out-file -filePath $f -inputobject "GO" -append
}
}
}

En los siguientes posts estaré dando más tips para establecer políticas de Disaster Recovery para servidores SQL 2000 o 2005.

Friday, August 8, 2008

Utilizando PoweShell con SQL 2005 SMO.

Ultimamente he estado utilizando PowerShell para ir creando un procedimiento para un Disaster Recovery Plan de SQL. En las siguientes entradas iré posteando información sobre como ir haciendo pequeños scripts que nos ayudarán para la administración de servidores SQL y como una herramienta para un DR.

Primeramente es necesario bajar de la página de Microsoft el PowerShell 1.0 y tener instaladas las herramientas de SQL 2005.

Es recomendable bajar la documentación del PowerShell de la misma página de Microsoft, la página que tiene The Mak en Database Journal es muy útil para ir aprendiendo de SQL 2005 con PowerShell, les estaré dando algunos ejemplos prácticos de cómo se puede utilizar como una herramienta para asegurar que se tiene un servidor backup de SQL listo para entrar en operación.

Una de las cosas que se tienen que asegurar siempre en un servidor es tener un respaldo de la configuración del servidor y de las bases de datos, así que voy a empezar con algunos ejemplos para obtener scripts de los servidores SQL.

Para correr los scripts solamente hay que guardar los scripts siguientes como archivo .ps1 y pasar de parámetro el nombre del servidor SQL con el quieren trabajar, por ejemplo: .\script1 "myserver".

Script para Recrear todos los jobs configurados en el servidor:

param (
[string] $serverName
)
$RutaScripts = "c:\scripts\"
void][reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
$MyScripter=new-object ("Microsoft.SqlServer.Management.Smo.Scripter")
$MyScripter.Options.FileName = $f
$MyScripter.Options.AppendToFile = $true
$MyScripter.Server=$srv
$jobs=$srv.jobserver.jobs

write-host "Obteniendo el script para recrear los jobs..."
$f = [System.IO.Path]::Combine($RutaScripts, $nombre + "_jobs.sql")
out-file -filePath $f -inputobject "USE MASTER `nGO`n"
foreach ($job in $srv.jobserver.jobs) {
$MyScripter.Script($job) >> $f
out-file -filePath $f -inputobject "`n" -append
}

Con este script se obtiene en un archivo de texto todos los jobs configurados en el servidor, con este script se puede configurar un servidor de respaldo en segundos (solamente hay que cambiar la variable Enabled a 0)


Script para recrear todos los logins:
param (
[string] $serverName
)
$RutaScripts = "c:\scripts\"
void][reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
$MyScripter=new-object ("Microsoft.SqlServer.Management.Smo.Scripter")
$MyScripter.Options.FileName = $f
$MyScripter.Options.AppendToFile = $true
$MyScripter.Server=$srv
write-host "Obteniendo el script para recrear los logins..."
$f = [System.IO.Path]::Combine($RutaScripts, $nombre + "_logins.sql")
out-file -filePath $f -inputobject "USE MASTER `nGO`n"
foreach($login in $srv.logins) {
$MyScripter.options.IncludeDatabaseContext = $true
$MyScripter.Options.IncludeIfNotExists = $true
$MyScripter.Options.ScriptDrops = $true
$MyScripter.Script($login) | out-file $f -append

$MyScripter.Options.IncludeIfNotExists = $true
$MyScripter.Options.ScriptDrops = $false
$MyScripter.Script($login) | out-file $f -append
out-file -filePath $f -inputobject "`n" -append
}

Este script es muy útil también cuando se está configurando un servidor de respaldo, obtiene todos los logins configurados, solamente hay que sustituir el password por el correcto y quitar la línea del disable, ya que por default SQL 2005 crea los logins deshabilitados.

Script para recrear todos los backup devices:
param (
[string] $serverName
)
$RutaScripts = "c:\scripts\"
void][reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
$MyScripter=new-object ("Microsoft.SqlServer.Management.Smo.Scripter")
$MyScripter.Options.FileName = $f
$MyScripter.Options.AppendToFile = $true
$MyScripter.Server=$srv

out-file -filepath $ArchivoLog -inputobject "$hora Obteniendo el script para recrear los Backup Devices..." -append
write-host "Obteniendo el script para recrear los Backup Devices..."
$f = [System.IO.Path]::Combine($RutaScripts, $nombre + "_Backup_devices.sql")
out-file -filePath $f -inputobject "USE MASTER `nGO`n"

foreach($backup in $srv.backupdevices) {
$MyScripter.Script($backup) | out-file $f -append
out-file -filePath $f -inputobject "`n" -append
}

Con este script como se indica en la descripción se obtiene el script de todos los backup devices, con este script puedes instalar el servidor en segundos.

Script para recrear los linked servers:
param (
[string] $serverName
)
$RutaScripts = "c:\scripts\"
void][reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
$MyScripter=new-object ("Microsoft.SqlServer.Management.Smo.Scripter")
$MyScripter.Options.FileName = $f
$MyScripter.Options.AppendToFile = $true
$MyScripter.Server=$srv

write-host "Obteniendo el script para recrear los linked servers..."
$f = [System.IO.Path]::Combine($RutaScripts, $nombre + "_linked.sql")
out-file -filePath $f -inputobject "USE MASTER `nGO`n"

foreach($linked in $srv.linkedservers) {
$MyScripter.options.IncludeDatabaseContext = $true
$MyScripter.Options.IncludeIfNotExists = $true
$MyScripter.Options.ScriptDrops = $true
$MyScripter.Script($linked) | out-file $f -append

$MyScripter.Options.IncludeIfNotExists = $true
$MyScripter.Options.ScriptDrops = $false
$MyScripter.Script($linked) | out-file $f -append
out-file -filePath $f -inputobject "`n" -append
}
Con este script se genera un script con el que se pueden crear todos los linked server, ojo, hay que recteclear el password y una vez creados cambiar la seguridad, ya que por default SQL los crea con: "Be made using the login's current security context".

En las siguientes posts iré publicando otros scripts que son útiles tambien para recrear usuarios, permisos y otras cosas.

Primer Post.

Que tal,
En este blog estaré hablando de algunas cosas que suceden en el área de Informática, como puede ser algo de consejos para hacer tal o cual cosa con determinada herramienta o tal vez algo que haya aprendido recientemente y que quiera compartir con el mundo.

Principalmente estaré hablando de tecnología utilizada en las empresas en general, pero enfocada en servidores Windows y Linux.

Espero poco a poco ir aportando ideas y conocimiento en esta área, en la que nunca dejas de aprender cosas nuevas.