Archive

Archive for the ‘SQL Server’ Category

Error 9002 después de un intento por encoger la base de datos


El día de hoy ha sido terrible. Resulta que el proyecto de GeoSEP que tengo está en un servidor de desarrollo compartido. Pero ya no hay espacio en disco duro. Me meto al servidor y menudo lío: solo 9MB de espacio disponible. Ni pex, tiempo de liberar espacio.

Entro a la dirección de SQL Server ($SQLSERVER\MSSQL10.MSSQLSERVER\MSSQL\DATA) y veo que mi base de datos tiene un log de 500MB. Pero además hay una base de datos cuyo MDF mide 3GB y su archivo log LDF mide 2GB! Así que aquí está el pan. Basta con hacer una reducción de ambas bases de datos para ganar 2.5GB nuevamente.

Así pues, abro el Management Studio y expando las bases de datos. Selecciono la mía y hago clic secundario y selecciono “Tasks->Shrink->Database”. Se ejecuta la transacción y listo, 500GB menos. Perfecto. Hago lo propio con la otra base de datos… ¡Y patatús! Resulta que en lugar de reducirse el archivo LDF, ¡éste comienza a aumentar de tamaño! de 2GB pasó a 2.5GB en unos segundos… y lanza error porque ya no hay espacio en disco duro. Me da el patatús.

¿De quién cuernos es esa base de datos? Investigo, y resulta que no es de nadie, ya no se usa. Pero no se puede desaparecer, hay que respaldarla. Bien. Voy al server de nuevo e intento hacerle un “detach” a la base de datos… y me lanza el siguiente error.

The transaction log for database ‘xxx’ is full. To find out why space in the log cannot be reused, see the log_reuse_wait

Me dá el patatús. Ni jota idea del por qué. Pero el mensaje dice que revise log_reuse_wait de la tabla sys.databases, así que hay voy. El campo log_reuse_wait_desc tiene el valor ‘LOG_BACKUP’, que no dice absolutamente nada. Vale, vamos a la documentación a buscar algo. Encuentro un artículo en MSDN que no da información útil.

Así que regreso a la base de datos. Intento hacer un respaldo y me sale el mismo error. Intento ver las propiedades, error. Intento hacer cualquier cosa, y error. Comienzo a perder la paciencia, así que salgo a comer para despejarme.

Regresando, a continuar. Comienzo a buscar en Google y los foros de MSDN, sin tener mucho resultado. Algunas soluciones proponen que se haga un detach/attach, pero es precisamente lo que no puedo hacer. Intento también volver a correr el comando para reducir la base de datos, y el mismo error.

Abro mi explorador y navego a la página de foros de MSDN. Localizo el foro para SQL Server, a ver si alguien me puede ayudar. Comienzo a redactar la pregunta, y cuando regreso al servidor para copiar el mensaje de error, noto algo que no había visto: “Microsoft SQL Server Error 9002”. ¡Ah, hay un código de error! Abro Google y a buscar. Y finalmente encontré una solución.

1. Ejecutar el procedimiento almacenado sp_resetstatus, así:

exec sp_resetstatus 'mi_basededatos'

2. Ejecutar el comando para recuperar una base de datos:

 DBCC DBRECOVER ('mi_basededatos')

Intento correr el detach… ¡y ahora sí funciona! ¡Uf! Me recargo en la pared, supongo que no ganaré el premio al mejor DBA del año. Pero bueno, ya quedó. Dejo un par de enlaces que me dieron la solución, por si alguien más con este problema los quiere leer.

Bueno, ahora sí, de vuelta al trabajo.

Realizar búsquedas de palabras fonéticamente similares usando Soundex

septiembre 22, 2010 6 comentarios

Realizar búsquedas es una cosa complicada, y un buen motor de búsquedas requiere redes neuronales, minería de datos y seguramente inteligencia artificial. Dicho eso, uno puede realizar consultas más sencillas sobre una base de datos.

Una de ellas, por supuesto, consiste en utilizar las clásicas consultas SQL usando el operador de igualdad, el operador LIKE, el operador BETWEEN, y otros por el estilo. Por ejemplo, supongamos que tengo una tabla Empleado que contiene tres campos: Nombre, Apellidos y Dirección. Si quiero hacer una búsqueda sobre Nombre, normalmente haría algo así:

select * from Empleado where Nombre like '%Fernando%'

Realizar esta consulta me regresaría todos los empleados cuyo nombre contenga a “Fernando”, por ejemplo, “Fernando Arturo” y “Juan Fernando”. Pero esta consulta oculta muchos problemas. Por ejemplo, supongamos que en lugar de “Fernando”, quiero buscar “Andrés”:

select * from Empleado where Nombre like '%Andrés%'

Por supuesto, esta consulta me regresa todos los de nombre “Andrés”… pero no me regresa los de nombre “Andres”, es decir, sin acento. Peor aún, por ejemplo, si buscamos a alguna “Jimena”, ya que puede haber registros con Gimena y Ximena. Y cuando desarrollamos aplicaciones empresariales, esto es un problema, porque los usuarios suponen que esto no será un impedimento. Y obvio, no querrán modificar toda su base de datos para revisar cuestiones gramaticales.

Siendo este el contexto, me gustaría comentar sobre un algoritmo de búsqueda por sonidos que SQL Server soporta, que ayuda a solucionar lo anterior. Pero para ello, necesitamos una breve historia…

[me reclino en la mecedora mientras enciendo un cigarrillo y agito la copa de coñac]

» Hace mucho tiempo cuando no había bases de datos ni computadoras ni electrónica, en la era oscura, cuando Thor buscaba a Jörmungandr y se podía ver a Freyja, vestida de blanco, pasear por los bosques de Midgard… ejem… bueno… quiero decir, que antes de las computadoras, los bibliotecarios, gente del registro civil y en general cualquier persona que tuviera que ordenar datos y realizar búsquedas se las veían negras para localizar información específica. En principio, un ciudadano iba a buscar, digamos, el acta de nacimiento de su padre, John. Sin embargo, John puede escribirse como John, Jon, Jhon, etcétera, por lo que a veces estas diferencias causaban que el dato en cuestión no se encontrara. Imagínate en idiomas como el español: realizar búsquedas incluye buscar con acentos, sin acentos, con H o si H, con Y o doble L… y un larguísimo etcétera.

» En aquellos días oscuros parecía que no habría forma de obtener la información que uno buscaba… parecía que el Ragnarök estaba cerca… Entonces a alguna mente en los Estados Unidos a inicios de siglo XX se le ocurrió diseñar un algoritmo que basara la búsqueda en similitudes fonéticas en lugar de alfabéticas… y dio como resultado un algoritmo para codificar nombres con la misma pronunciación, llamado Soundex. Este algoritmo se basa en codificar letras de sonidos similares, ignorar otras y al final reducir una palabra a cuatro letras. Dos palabras con sonidos iguales (como John y Jon) regresarán una codificación igual, mientras que si son semejantes (digamos, Fernando y Hernando) regresarán una codificación parecida(usualmente, coincidirán tres de las cuatro letras) pero no iguales.

» Soundex probó ser útil y permitió a la oficina de censos de EE.UU. realizar análisis precisos de los censos hechos entre 1890 y 1920. Probó ser tan útil que sobrevivió a la era oscura y llego a la era del Yggdrasil: ha sido incorporada en los motores de bases de datos modernos. De tal suerte que puedes utilizar el algoritmo Soundex en SQL Server para realizar una búsqueda por sonidos.

[abro los ojos, dejo la colilla del cigarrillo y vacío de un trago el resto del coñac]

Bueno, el punto es que SQL Server tiene una función llamada SOUNDEX que toma una cadena de texto y la codifica usando el algoritmo Soundex. Por ejemplo:

select soundex('casa'), soundex('caza'), soundex('cahsa')
go

regresa el siguiente resultado:

C200 C200 C200

Como casa, caza y cahsa se pronuncian igual, pues se regresa el mismo código. De igual forma:

select soundex('Fernando'), soundex('Hernando')
go

regresa:

F655 H655

Como puedes ver, los códigos son muy similares, pero no exactos. Así, tres de las cuatro letras coinciden, por lo que la aproximación debe ser buena, pero no exacta. Entonces, podemos ver que cuando comparamos dos términos, lo que nos interesa es la diferencia que éstos regresan, en un rango del 1 al 4 (1 si prácticamente no se parecen, 4 si se parecen demasiado). Afortunadamente, SQL Server provee una función llamada DIFFERENCE, que internamente hace uso de SOUNDEX y regresa un número del 1 al 4: en esencia, qué tanto se parecen los términos buscados. En efecto:

select difference('casa', 'caza')

regresa, sin sorpresas, un 4, mientras que

select difference('fernando', 'hernando')

regresa un 3. Así, una forma de realizar búsquedas pudiera ser haciendo uso de DIFFERENCE. Por ejemplo:

select nombre, apellidos, direccion
from empleado
where difference(nomrbe, 'fernando') > 2

Esta consulta te regresaría todos los “fernandos” de la tabla, pero también todos los “hernandos” y los “fehrnandos”.

Nota, sin embargo, que SOUNDEX y DIFFERENCE tienen sus puntos débiles. Después de todo, incluso Thor murió envenenado tras matar a Jörmungandr. Este algoritmo está muy bien para buscar nombres y palabras, pero no para buscar frases. Un soundex entre “En algún lugar de un gran país” y “país” te va a regresar códigos diferentes. De hecho, select difference(‘En algún lugar de un gran país’, ‘país’) te regresa apenas un 2. Así, mi recomendación sería utilizar este tipo de búsquedas sobre campos que contengan un solo nombre: por ejemplo, nombres de personas, apellidos, ciudades, países, etc.

Ah, por cierto. No olvides que el tema del idioma es muy importante, ya que por el asunto de la pronunciación, soundex se comporta de forma diferente en inglés que en español (por ejemplo, en inglés Y y J se pronuncian igual, mientras que en español se pronuncian diferente; análogamente, en español LL y Y son iguales mientras que en inglés son diferentes). Así que asegúrate que el idioma de tu base de datos sea el correcto, si vas a utilizar este algoritmo.

En fin, dicho lo anterior… la idea de este post es darte una alternativa más que puedas utilizar en tu desarrollo. Espero te sirva de algo. Ahí me cuentas cómo te fue.

Categorías:Apunte, SQL, SQL Server Etiquetas:

Error al restaurar base de datos: la clave del Registro BackupDirectory no está configurada correctamente.


El día de hoy llegué a la oficina a las nueve de la mañana. Desvelado, obviamente, ya que ayer hubo una sesión de Stargate SG-1, temporada cinco, aunque solo vi un par de capítulos mientras configuraba mi nueva máquina. Bueno, el chiste es que llegué desvelado, tuve que pasar por mi café y mi Pepsi Kick, y ya acá revisé el plan de actividades que tengo para el proyecto nuevo en el que estoy metido: la actualización tecnología del sitio GeoSEP de la Secretaría de Educación Pública. Y uno de los pendientes que tengo es el restaurar la antigua base de datos (es decir, la versión anterior) en el ambiente de pruebas.

Entonces, tras consumir mi Pepsi Kick y menear un poco la cabeza (al ritmo de un pegajoso “tan-tarán-tara-rararán”), tomé la base de datos del servidor de producción e hice una copia de seguridad. Pasé el archivo a mi máquina, abrí mi SQL Server Manager Studio y me conecté a la instancia local. Cree una nueva base de datos, vacía del todo, e intenté restaurar la base de datos con la que saqué de producción, sobreescribiendo cualquier configuración. Para mi sorpresa, me topé con el siguiente mensaje de error:

[3047] La clave del Registro BackupDirectory no está configurada correctamente. Esta clave debe especificar la ruta raíz en la que se almacenan los archivos de copia de seguridad en el disco cuando no se proporcionan nombres de ruta. Esta ruta también se utiliza para buscar archivos de reinicio de punto de comprobación para RESTORE.

Esto me sorprendió un poco, por lo que comencé a investigar. Al principio, pensé que era una cuestión de permisos, así que intenté hacer nuevos respaldos. Empero, el mensaje de error seguía mencionando a una llave del registro, por lo que me di cuenta que era más una cuestión interna. En efecto, el mensaje dice que es una llave del registro de Windows y que su valor se utiliza para copiar archivos durante una copia de seguridad. Así que su valor debería ser un directorio donde existieran permisos de escritura.

Solo quedaba un problema: buscar dónde demonios se encuentra la mentada llave. En primer lugar, HKEY_LOCAL_MACHINE\Software\Microsoft\Microsoft SQL Server\ es donde se encuentran todas las llaves de configuración general de SQL Server. Comencé a buscar en todas las subcarpetas y en ningún lugar encontré la mentada llave BackupDirectory. Vamos, hice una búsqueda completa en todo el registro y nada. Y sí, finalmente, después de buscar y algunos errores, di con el directorio: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL.1\MSSQLServer. Lo que hice fue crear la llave de tipo alfanumérico (REG_SZ) y ponerle de valor inicial un directorio cualquiera con permisos de escritura. Y lixto, eso solucionó el problema.

A ciencia cierta, no sé por qué mi registro no tenía esa llave. He de decir que la máquina con la que trabajo fue utilizara por alguien anteriormente, y no fue formateada, por lo que está llena de cosas. Quién sabe, en una de esas algo se echó a perder.

Pero bueno, esperemos que si te pasa este error, tengas la fortuna de cruzarte con este post y te sea más leve de lo que me fue a mí.

Auf wiedersehen!