Diario de SQL Server

Reinicio pendiente que no se quita reiniciando

Escrito por qwalgrande 27-04-2010 en General. Comentarios (0)

Esta FAQ no es exclusiva de SQL Server. Pasa también con Exchange y seguramente con otros productos. Cuando se inicia la instalación, la aplicación te advierte que existe un reinicio pendiente de alguna otra circunstancia y no deja continuar con la instalación. Sin embargo, por más que reinicies, sigue saliendo el warning.

 

Desesperante... Puede ser incluso peor, una instalación desatendida pueden entrar en un bucle continuo de reinicios o con sólo ejecutar el setup reiniciarse la máquina.

 

La solución al problema está perfectamente documentada aquí:

http://technet.microsoft.com/es-es/library/cc164360(EXCHG.80).aspx

 

Sí, Exchange. El resumen, busca esta clave en el registro de la máquina:

 

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations

 

Si existe, la eliminas y listo, ya puedes realizar la instalación. Ojo con hacerse trampas al solitario, si no has hecho ningún reinicio, no uses esto para ahorrártelo. Esta clave queda sin borrar por error, pero no se crea por capricho.

Obtención de contador sin identity

Escrito por qwalgrande 12-04-2010 en General. Comentarios (3)

Una problemática muy común ésta, y como tal podemos catalogarla como FAQ. Obtener un contador sin identity es una tarea bastante frecuente. Y suele hacerse mal, lo que genera muchos problemas de bloqueos en situaciones de concurrencia.

 

Empecemos con un ejemplo de lo que NO SE DEBE HACER:

 

declare @NuevoId int

select @NuevoId = max(Contador) + 1 from TablaDatos

insert TablaDatos values (@NuevoId, campo2, campo3,...)

 

En este ejemplo de lo NO SE DEBE HACER, se va a la tabla, se obtiene el mayor valor y se le añade uno. Eso significa, más que una fuente de bloqueos, un enorme tapón para la aplicación.

 

Pero no es el único problema que puede haber. También es muy frecuente que el contador se obtenga dentro de una transacción. En el fondo se puede implementar de numerosas formas, siempre que funcione, esto es, que no dé el mismo identificador dos veces, y se sigan dos reglas básicas: No involucrar a la tabla para la que se tiene que obtener el contador y obtener el número fuera de transacción.

 

Como decía, se pueden implementar muchos mecanismos. Expongo aquí uno muy simple basado en una tabla de números y en un procedimiento almacenado que encapsula la problemática, al que se le suministraría el nombre de la tabla, devolviéndote un nuevo valor.

 

La tabla:

 

CREATE TABLE [dbo].[CONTADORES](

[ID] [smallint] IDENTITY(1,1) NOT NULL,

[DES_TABLA] [varchar](255) NOT NULL,

[NUM_ID] [int] NOT NULL,

CONSTRAINT [PK_CONTADORES] PRIMARY KEY CLUSTERED

([ID] ASC))

 

El procedimiento:

 

 

/********************************************************************/

/* p_GetId : sp para la obtencin de nuevos ids */

/* Parametros: */

/* - @pTable_Name: Tabla para la que se solicita el id */

/* - @pNewId: Nuevo ID construido con el ID y las semillas (OUTPUT) */

/* */

/* Ejemplo de llamada: */

/* */

/* DECLARE @RC int, @NuevoId int */

/* */

/* EXEC @RC = dbo.p_GetId */

/* @pTable_Name = 'Ejemplo' */

/* ,@pNewId = @NuevoId OUTPUT */

/* */

/* select @RC Retorno, @NuevoId Nuevo_id */

/* */

/********************************************************************/

CREATE proc [dbo].[p_GetId]

@pTable_Name varchar(255),

@pNewId int OUTPUT as

set nocount on

declare @ret int

set transaction isolation level read uncommitted

if @@trancount > 0

begin

raiserror('Error: En transaccin.', 1, 16)

return -998

end

--Se consulta si el contador para la tabla ya existe en Contadores

if exists(select DES_Tabla from Contadores

where DES_Tabla = @pTable_Name)

begin --Si ya existe, se obtiene el siguiente valor del contador.

update Contadores set @pNewID = NUM_ID = NUM_ID + 1

from Contadores

where DES_Tabla = @pTable_Name

end

else

begin --Si no existe, se inserta el nuevo valor

select @pNewID = 1

insert Contadores (DES_Tabla, NUM_ID) values (@pTable_Name, @pNewID)

end

--Control de errores

select @ret = @@error

if @ret <> 0

begin

raiserror('Error en la obtencin de nuevo identificador', 1, 16)

set nocount off

return @ret

end

set nocount off

return 0

  

He incluido la sentencia que impedirá que se llame al procedimiento con una transacción de por medio. Es una medida de precaución quizá demasiado restringida, pero del todo eficaz ante la duda. Este procedimiento únicamente se ocupa de darle un número, no de lo que luego se hará con él. Así que pueden generarse huecos. Se puede implementar una gestión de huecos, pero eso será para otro post.

 

Otro mecanismo. Muy similar al uso de identity, utiliza una tabla con el mismo nombre en otro esquema para obtener el numerito:

 

create schema Maestros;

go

create proc Maestros.GeneraClave (@tabla Sysname,@valor int output)

with execute as owner -- cambialo por alguien con permisos para crear tablas

de forma dinmica

as

begin

declare @sql nvarchar(4000);

if not exists(select 1 from information_Schema.tables where table_name =

@tabla and Table_schema='Maestros')

begin

set @sql = 'CREATE TABLE Maestros.'+ quotename(@tabla) + ' (id int

identity(1,1)) ' ;

exec sp_executeSQL @sql

end

if @@trancount>0

save transaction @tabla

else

begin tran

set @sql=N'SET NOCOUNT ON; INSERT INTO Maestros.'+ quotename(@tabla) + '

DEFAULT VALUES; SELECT @Valor=Scope_identity() '

exec sp_executesql @sql, N' @valor int output', @valor output

rollback tran

end

go

declare @valor int

exec Maestros.GeneraClave 'Mi tabla1',@valor output

select @valor

select * from information_schema.tables where table_schema='Maestros'

go

-- sin problemas de inyeccin de cdigo.

declare @valor int

exec Maestros.GeneraClave 'Mi ] drop table Maestros.[Mi tabla1] -- ',@valor

output

select @valor

select * from information_schema.tables where table_schema='Maestros'

 

Y se podrían implementar otros muchos. Es importante recordar que es mucho más sencillo usar campos identity. Estos métodos deben quedar para cuando no se puede usar.

 

No puedo finalizar esta entrada sin mencionar al inspirador del primer método y autor del segundo, el Maestro Miguel Egea. Pásate por www.portalsql.com de vez en cuando, aprenderás. Y mucho.

 

¡Que nos suben los precios! ¡Y en plena crisis!

Escrito por qwalgrande 09-04-2010 en General. Comentarios (0)

En un par de semanas saldrá a la calle SQL Server 2008 R2. No viene con muchas novedades. Sin embargo, viene con dos nuevas ediciones, por encima de la edición Enterprise, antes Full Equipe, y ahora relegada a un segundo escalón.

Podéis encontrar detalles en http://www.microsoft.com/sqlserver/2008/en/us/R2-editions.aspx.

 

Lo de tener ediciones especializadas para OLPT y OLAP me parece un gran acierto. Pero limitar la edición Enterprise a únicamente 8 procesadores físicos quizá no lo sea tanto y más si tenemos en cuenta el "detallito" de que las nuevas ediciones Premium tendrán un coste (precio publicado en la misma página) por licencia de justo el doble (de 28.000$ por procesador en Enterprise se sube a  a 57.000$ por procesador en estas nuevas).

 

Afortunadamente, siguen sin considerar el multi-core como un factor licenciable, pero en cualquier caso, supone un aumento enorme de precio para empresas que precisen contar con servidores más potentes, para las que con 8 procesadores no es suficiente. Pues a esas justamente, es a las que se les disparará la tarifa.

 

La mayoría no poseemos una empresa que vaya a requerir de esas licencias, con lo que corremos el riesgo de pensar que, en fin, ese coste lo pagará la empresa para la que trabajo o mi cliente o ni siquiera eso. Pero dale una vuelta.

 

Luego, cuando esas mismas empresas vayan a negociar el precio global de licencias con Microsoft y tengan que reducir el número de horas de proyectos, las horas de formación, etc., para compensar el aumento por licencias, los mismos comerciales de MS se llevarán las manos a la cabeza...

 

Pero los perjudicados seremos aquellos que no pagamos el contrato, sólo lo utilizamos. Al final, a la empresa grande, la factura le saldrá por un monto total similar, el presupuestos es el que es. Si hay más en licencias, queda menos para todo lo demás. Si hay menos formación, son menos Workshops. Si se reduce el soporte, habrá que apechugar como se pueda sin esa ayuda. Que si el problema es de SQL Server, bueno, yo más o menos me puedo apañar, pero estas cosas se contratan casi siempre de forma global, con lo que si se rompe otra cosa aledaña, vete a saber.

 

Si trabajas en una consultora o en formación, a lo mejor esa empresa grande tiene que reducir costes de ahí para pagarle a Microsoft, y ya no te asigna ese contrato o te lo asigna de menos horas. Si estás buscando trabajo, esas consultoras no requerirán refuerzos, ya que, de hecho, puede hasta que sobren con los empleados que ya tienen.

 

En resumen, no me extrañaría que el aumento de la licencias lo acabemos pagando los profesionales.

 

Pero no quiero finalizar de una forma pesimista. Cada nueva versión supone una nueva oportunidad de negocio en muchos aspectos. Son nuevas funcionalidades que aprender, que ofrecer a los clientes, de las que hablar en los blogs, de las que leer en los blogs...

Fallo en la instalación de SQL Server (busca la carpeta "Setup Bootstrap")

Escrito por qwalgrande 02-04-2010 en General. Comentarios (2)

Esta sí es una FAQ con mayúsculas. La pregunta suele ser diferente, pero la respuesta no: busca la carpeta "Setup Bootstrap" en la máquina y revisa los logs de instalación. Son errores durante el proceso de instalación, ya sea del motor completo, de un parche o un service  pack. Se produce un error, la instalación muestra un mensaje (generalmente poco o nada concluyente) en el mejor de los casos, en otros, simplemente aquello se cierra y se acabó.

 

Existe una gran variedad de problemáticas que pueden estar entorpeciendo la instalación. Para iniciar el troubleshooting, hay que leer los logs que se generan en el proceso. Dan mucha información, en ocasiones tanta que es difícil encontrar algo en claro. Casi siempre es mejor leerlos de abajo arriba, ya que la instalación se corta por algún tipo de error, y hasta llegar allí, todo suele haber ido como la seda.

 

Otra cosa es que luego de esa lectura se pueda resolver lo que está fallando. Suelen ser errores confusos sobre claves de registro, ficheros .msi que no están, problemas de permisos, etc. Pero al menos tendremos muchas más información que un "La instalación encontró un problema y se cerrará.". Con un código de error, algo de experiencia y la valiosa ayuda de internet, puede que tengamos suerte.

 

Más información en http://msdn.microsoft.com/es-es/library/ms143702.aspx y en http://msdn.microsoft.com/es-es/library/ms144287.aspx. Y para obtener ayuda, aparte de abrir un caso de soporte, tenemos el foro.

 

En resumen, busca la carpeta "Setup Bootstrap" y revisa los logs, leyéndolos de abajo a arriba.  Si con lo que allí leas no logras solucionarlo, puedes abrir un caso de soporte o un hilo en el foro, indicando esos errores que encuentras en los ficheros de log.