Btrieve es una base de datos desarrollada por Pervasive Software . La arquitectura de Btrieve ha sido diseñada teniendo en mente la gestión de registros. Esto significa que Btrieve solo se ocupa de las primitivas subyacentes de creación de registros, recuperación de datos, actualización de registros y eliminación de datos. Junto con MicroKernel Database Engine, utiliza ISAM (método de acceso secuencial indexado) como mecanismo de almacenamiento subyacente.
Btrieve es esencialmente una base de datos que utiliza claves e índices para organizar los datos . Sin embargo, la estructura del archivo en sí se construye en gran medida alrededor de unidades de datos más pequeñas, llamadas "páginas" en Btrieve. Aunque la estructura ha cambiado en las distintas versiones de Btrieve, la estructura del archivo todavía gira en torno a un Registro de Control de Archivo (FCR), que define la configuración de las páginas, y las páginas en el archivo Btrieve que contienen datos. Históricamente, Btrieve usaba "páginas físicas", o páginas que se ubicaban en posiciones fijas en el archivo. A partir de la versión 6.0, se comenzaron a usar "páginas lógicas", que se asignaban a tablas de asignación de páginas (PAT), lo que permitió a Btrieve cambiar su técnica de actualización de registros de lo que más tarde se conoció como "paginación previa a la imagen" a una técnica llamada "paginación en la sombra".
Btrieve está comprometido con la compatibilidad con versiones anteriores , ya que las versiones de Btrieve hasta la versión 6.15 usan un formato de archivo estándar y, hasta que se lanzó Btrieve 6.0, eran completamente compatibles con versiones anteriores. Btrieve 6.0 introdujo nuevas funciones y tuvo que romper la compatibilidad con versiones anteriores del software para implementar funciones más avanzadas. La API también siguió siendo compatible con versiones anteriores, y solo se eliminó una función (dividir archivos en medios separados). En un momento, el ex director ejecutivo de Btrieve , Ron Harris, declaró que "La API de la versión 1.0 aún es compatible con la versión 6.15, ¡y la vamos a mantener para siempre!" [1] : 11 .
Pervasive utilizó inicialmente el término "base de datos de navegación" para describir Btrieve, pero más tarde lo cambió a "base de datos transaccional". El uso del término base de datos de navegación era inusual porque una base de datos de navegación utiliza "punteros" y "rutas" para navegar entre registros de datos , y estos punteros están contenidos en el propio registro; ISAM, que es la estructura fundamental de Btrieve, utiliza una tabla de índice secundaria para almacenar estos punteros para disminuir los tiempos de búsqueda. Por lo tanto, los dos tipos de base de datos son diferentes, y pueden o no explicar por qué Pervasive comenzó a utilizar una terminología diferente para clasificar su base de datos. [a]
A partir de la versión 6.15, Pervasive comenzó a utilizar un nuevo método modular para separar el backend de la base de datos de la interfaz que utilizaban los desarrolladores. Separaron las operaciones básicas de la base de datos (como actualizar, escribir y eliminar registros) de los módulos Btrieve y Scalable SQL. Al separar el Micro-Kernel Database Engine (MKDE) de las otras funciones, permitió a los programadores utilizar varios métodos para acceder a la base de datos simultáneamente. Por ejemplo, se puede crear una aplicación utilizando la API Btrieve y otra aplicación que necesita acceder a los mismos datos puede utilizar un método totalmente diferente, como Scalable SQL. Debido a que los primitivos de registro se han separado de estos métodos, ambas aplicaciones pueden utilizar MKDE para acceder al mismo archivo de datos .
El motor de base de datos Micro-Kernel no está relacionado con los núcleos del sistema operativo microkernel .
El formato de archivo Btrieve está compuesto exclusivamente de páginas, que son los datos que se mueven entre la memoria y el medio de almacenamiento cuando el motor realiza una operación de E/S . Las versiones anteriores a la 6.0 solo utilizaban páginas de datos, páginas de índice y un registro de control de archivos (FCR). El archivo tenía un índice para realizar búsquedas que se vinculaba a páginas físicas. A partir de la versión 6.0, se empezaron a utilizar páginas lógicas , que son páginas que se asignan a páginas físicas (páginas en una ubicación fija en el archivo) en el disco mediante el uso de un conjunto de tablas de asignación de páginas (PAT).
El registro de control de archivos (FCR) contiene información importante sobre los archivos de la base de datos Btrieve. Contiene el tamaño de la página , la cantidad de páginas en uso actual, la cantidad de claves que pueden indexar el archivo, la cantidad de registros en el archivo y otros detalles. Después de la versión 6.0, se utilizaron dos FCR para redundancia. Se utiliza un campo de recuento de uso de 32 bits que existe en cada FCR para determinar qué FCR era válido para usar. Cada vez que se realiza una operación en un archivo, el campo se incrementa. El FCR con el recuento de uso más alto se convierte en el FCR válido. El FCR está bien descrito en ejemplos de fuentes de Jim Kyle. Con la introducción de la versión 8 de MKDE, se cambió la estructura de la página FCR. El tamaño de la página ahora se mueve dentro del FCR y no es un campo regular de 32 bits. Desde la versión 8, debe calcular el tamaño de la página tomando el campo de 32 bits en el desplazamiento 0x2A y multiplicándolo por 256.
Una tabla de asignación de páginas (PAT) asigna las páginas lógicas a las páginas físicas. Cada PAT es simplemente una página física ubicada en ubicaciones bien definidas. Al igual que las FCR, las PAT siempre aparecen en pares, y la copia válida actual se indica por tener un recuento de uso más alto. El primer par de PAT sigue inmediatamente a las dos primeras FCR y ocupa las páginas físicas 2 y 3. Le sigue una cantidad variable de otras páginas y, a su vez, un nuevo par de PAT sigue a esta. Cada PAT tiene una cantidad fija de punteros a páginas lógicas, y cada entrada que está vacía tiene un valor de cero.
La cantidad de registros lógicos que se pueden almacenar en el PAT está determinada por su tamaño de página. Cada puntero de página en las versiones 6.x y 7.x de MKDE ocupa 4 bytes de espacio, y el encabezado del PAT ocupa 8 bytes, por lo que la cantidad de páginas lógicas en el PAT se convierte en:
Con la introducción de la versión 8 de MKDE, el tamaño del encabezado de la página cambió y, por lo tanto, esta fórmula ya no se aplica, pero el principio sigue siendo el mismo.
Hasta la versión 6.0, se utilizaba la paginación previa a la imagen para realizar actualizaciones de registros. Implicaba la creación de un nuevo "archivo de preimagen" antes de realizar los cambios y, a continuación, las páginas del archivo de datos original se copiaban en este nuevo archivo de preimagen temporalmente. A continuación, el sistema realizaba los cambios en el archivo original. Si se interrumpía la actualización y solo se escribía la mitad de los datos en la página, el motor simplemente revertía la página copiando la página del archivo de preimagen nuevamente en la página dañada en el archivo de base de datos original; luego, se eliminaba el archivo de preimagen temporal. Los archivos de preimagen tenían la extensión .PRE, por lo que encontrar estos archivos en el sistema generalmente indicaba que una transacción no se había realizado correctamente y que la recuperación no había sido exitosa.
A partir de la versión 6.0, se utilizó la paginación de sombra en lugar de la creación de imágenes previas, y todavía se utiliza en la actualidad. En lugar de copiar la página en un archivo temporal, se encontró la siguiente ubicación física libre en el archivo de base de datos y la página se escribió en esta ubicación. Esta página se llama página de sombra porque aún no se ha escrito su ubicación en el PAT del archivo. Una vez que se completó la actualización de la página de sombra, se actualizó el PAT y se registró la entrada en el PAT de la siguiente página física disponible y actual en el archivo. Sin embargo, si se producía una falla del sistema mientras se realizaba la actualización de la página de sombra, el PAT no se actualizaría y, por lo tanto, el cambio se descartaría porque la entrada actual y siguiente no se actualizaron en el PAT.
El cambio de paginación previa a la imagen a paginación de sombra provocó cambios radicales en el formato de archivo que rompieron la compatibilidad entre versiones anteriores de Btrieve y la versión 6.x del producto.
Las páginas de secuencia de intercalación alternativa (ACS) son páginas que permiten ordenar los registros en un orden diferente. La intercalación es el ensamblaje de información escrita en un orden estándar. En el uso común, esto se denomina alfabetización, aunque la intercalación no se limita a ordenar las letras del alfabeto . Por ejemplo, una ACS podría permitir que el orden de clasificación ordene en orden sensible a mayúsculas y minúsculas y en orden no sensible a mayúsculas y minúsculas. Antes de la versión 6.0, solo se podía almacenar una ACS en el archivo; sin embargo, después del lanzamiento de la versión 6.0, se podía asociar más de una página ACS con un archivo en cualquier momento.
En los archivos de la versión 6.0 y posteriores, pueden existir más páginas físicas de las que se utilizan realmente. Esto se debe a que, con la paginación oculta, es posible que algunas páginas del sistema no tengan una entrada en el PAT. Estas páginas se marcan como páginas "extra" y se utilizan antes de que se asigne espacio para páginas nuevas.
En Btrieve, cada página es fija, pero un registro puede ser más grande que el tamaño de la página. Esto significa que, a menudo, los registros deben fragmentarse y distribuirse en muchas páginas diferentes. Con registros muy grandes, esto puede significar que pueden necesitarse cientos de páginas para almacenar el registro. Un enfoque de lista enlazada podría permitir esta fragmentación, pero el motor de Btrieve tendría dificultades para leer registros secuenciales. Por lo tanto, a partir de la versión 6.1, se utiliza una tabla en el archivo que almacena punteros a cada una de las páginas que componen el registro de datos. Esta tabla se denomina tabla de asignación de cola variable (VAT).
Btrieve utiliza un formato de árbol b para almacenar índices de registros en columnas de tablas particulares . El índice asigna cada conjunto de valores de columna indexados al conjunto de identificadores únicos para las filas que tienen esos valores de columna, lo que proporciona una forma rápida de encontrar las filas dentro de una tabla utilizando la columna indexada. Los árboles b son estructuras de datos de árbol y son muy eficientes como mecanismo para la recuperación rápida de datos. La desventaja de un árbol b es que los datos deben equilibrarse constantemente cuando se insertan en el árbol, por lo tanto, Btrieve solo almacena el índice de registro como árbol b para reducir la cantidad de tiempo que lleva insertar y actualizar registros. Se mantiene un árbol b separado para cada índice en el sistema, y la información del nodo raíz se mantiene en el FCR. En Btrieve 6.xa se puede crear un nuevo índice en el momento de la creación del archivo, o agregarlo y eliminarlo después de que se crea el archivo. Las páginas de índice también se crean a medida que se necesitan. Antes de Btrieve 6.0, los índices clave existentes no se podían eliminar, aunque se podían crear y eliminar índices complementarios según fuera necesario.
Btrieve permite valores de clave duplicados en un índice. Btrieve maneja claves duplicadas usando un método de duplicado vinculado o usando un método de duplicado repetitivo (esta terminología comenzó a usarse cuando se lanzó la versión 6.0). El método de duplicado vinculado usaba un par de punteros de registro en la página de índice para señalar el principio y el final de una lista doblemente vinculada de claves duplicadas. Esto significaba que el orden de las claves duplicadas en la lista estaba en el orden en que se ingresaron. El método de clave duplicada no usaba una lista vinculada, sino que hacía que todas las claves fueran únicas al crear una nueva clave de índice y agregar la dirección del puntero de registro al final de la clave. Esto significa que la clave se recupera a través de su orden de posición.
Cuando Btrieve necesitaba compartir archivos para obtener acceso a los registros, se podían utilizar dos tipos diferentes de modos de uso compartido de archivos: modo de uso compartido de archivos con un solo motor (SEFS) y modo de uso compartido de archivos con varios motores (MEFS). SEFS solo permitía que los clientes que accedían a ese motor modificaran la base de datos; otros clientes que accedían a un motor diferente no podían acceder a la base de datos. MEFS permite que diferentes clientes que se ejecutan en diferentes motores accedan a la base de datos.
Btrieve era capaz de gestionar transacciones concurrentes en la serie 6.x. Antes de Btrieve 6.0, el motor sólo podía realizar bloqueos a nivel de archivo o bloqueos exclusivos ; a partir de la versión 6.0, los registros se podían bloquear individualmente. El bloqueo a nivel de registro (o página) se conocía como bloqueo concurrente . Las ventajas eran obvias: más de un cliente podía acceder al archivo al mismo tiempo, siempre que no intentaran acceder al mismo registro, lo que generaba mejoras en el rendimiento. Además, otros clientes podían leer las páginas bloqueadas y no verían ningún cambio en un archivo involucrado en una transacción de escritura por parte de otro proceso que había bloqueado el registro.
El modo MEFS no admitía completamente el bloqueo simultáneo. Si un cliente iniciaba una transacción simultánea y luego intentaba realizar una operación de escritura en un registro, el motor Btrieve devolvía un código de estado 85 que indicaba que el archivo estaba bloqueado, aunque se estuviera utilizando un bloqueo simultáneo.
A partir de la versión 6.15 de Btrieve, se introdujo un nuevo tipo de transacción de base de datos denominada transacción del sistema , que se separó de las transacciones del usuario . Las transacciones del usuario son transacciones exclusivas y concurrentes, mientras que las transacciones del sistema son un conjunto de operaciones no transaccionales y/o transacciones del usuario. Las transacciones del sistema se utilizaban exclusivamente para la recuperación de datos por parte del MKDE. Si una falla del sistema causa corrupción de datos, cuando el MKDE se reinicia, detecta todos los archivos que tenían una transacción del sistema fallida e intenta recuperarlos. Sin embargo, como las transacciones del usuario podrían haberse perdido cuando se revirtió la última transacción del sistema, se podría configurar una opción que hiciera que el MKDE obligara a las transacciones del sistema que tenían transacciones del usuario a completarse cuando el motor recibiera una solicitud de "Finalizar operación".