3. Administración de bases de datos

3.1 DBMS

3.1.1 Definición

Es un sistema robusto que es capaz de emplear algoritmos de almacenamiento y recuperación de información para poder implementar un modelo de datos de manera física garantizando que todas las transacciones que se realizan con respecto a dichos datos sean "ácidas" (Atomicity, Consistency, Isolation, Duration).

 

3.1.2 Arquitectura de un manejador de bases de datos (DBMS)

Nota: Las partes utilizadas para ejemplificar la arquitectura se refieren a Oracle


Una base de datos en ejecución consta de 3 cosas:

 

Instancia de una bd en Oracle

 

Rotación de segmentos de rollback

Rotación de bitácoras de Redo

Ejemplo del esquema de una base de datos en Oracle

Utilización del Shared Pool

Ejemplo del control de transacción

3.1.3 Tipos de instancias de un DBMS

Online Transaction Processing (OLTP): compra/venta, telemarketing

Decision Support Systems (DSS): datawarehouse

 

3.1.4 Tipos de implementaciones

Por otro lado un dbms puede ser implantado de 2 formas:

Implantación Cliente-Servidor de un DBMS

Implantación 3 Tier de un DBMS

Finalmente, también se puede considerar la opción de crear clusters de máquinas o discos para poder brindar disponibilidad y escalabilidad. Existen 2 tipos de clusters:

SharedNothing:

 

ShareNothing Cluster

SharedDisk:

DiskShared Cluster

 

3.2 Administración de un DBMS real

3.2.1 MySQL

MySQL (pronunciado mai-es-quiu-el), es una manejador de bases de datos relacional bastante robusto, de código abierto bajo la licencia GPL el cual se ha convertido en el más popular hoy en día.

Su origen se debió a la búsqueda por parte de los fundadores de crear un manejador de bases de datos que fuera "rápido", todavía más rapido que mSQL. Así surgió MySQL, primero como un producto de la empresa y despúes como software de dominio público.

El nombre de My se debe probablemente a que la hija del cofundador Monty Widenius recibía ese sobrenombre, aunque a ciencia cierta nunca se ha revelado el origen. Por otro lado en el año 2002 MySQL tuvo un logo más original que el simple nombre, incluyendo un delfín, el cual a través de una encuesta en la página web recibió su nombre: "Sakila", de origen africano.

3.2.1.1 Por qué usar MySQL ?

 

Es importante resaltar que no se trata de una herramienta de juguete o aprendizaje, MySQL es un manejador que puede competir competir con sus famosas contrapartes comerciales: Oracle, DB2, Informix, Sybase.

Básicamente los motivos por los cuales se podría optar por usar MySQL en lugar de otro manejador serían:

3.2.1.2 Instalación Básica

MySQL posee varias versiones 3, 4 y 5 siendo la 3 la más estable y la 5 la más experimental

Los cambios en la versión 4 permiten tener mayor funcionalidad, teniendo por ejemplo queries anidados y búsquedas a texto completo.

MySQL posee 4 tipos de tablas (y en consecuencia de índices):

Index

Versión

MyISAM

Standard, Max

Heap Standard, Max

BerkeleyDB

Max

Innodb

Max

Tabla 3.1 Indexamiento en MySQL

 

MyISAM se basa en un indexamiento por bloques, Heap es una tabla que existe solo en memoria, mientras que BDB e InnoDB utilizan B-Trees.

Se puede observar que existen 2 variantes del software, la Standard y la Max; la diferencia radica en el soporte de transacciones que es posible en la versión Max gracias a los módulos de Berkeley DB e InnoDB incorporados en ella.

Es importante resaltar que aunque esta funcionalidad esta disponible no es la configuración por default, salvo que se indique lo contrario, siempre tipo de indexamiento por defecto será MyISAM.

El equipo MySQL recomienda bajar los binarios compilados por ellos para evitar cualquier tipo de problema, de manera que en la sección de "Database Server" se puede bajar el binario de la versión deseada.

Una vez descargado el software se procede a desempaquetarlo (.tgz, zip) o bien ejecutar el .exe correspondiente.

Dichos directorios contenidos en un directorio que por lo general lleva el mismo nombre 'mysql' contiene una estructura de la siguiente manera:

Antes de poder ejecutar el demonio (o guardián) del manejador, es conveniente realizar una configuración, para ello se tiene que editar alguno de los archivos .cnf, los cuales se encuentran ubicados en el directorio raíz de mysql o bien en el directorio support-files. El archivo elegido dependera de la configuración de la máquina (small, medium, large, huge), cada archivo provee información acerca de la memoria apropiada para cada configuración. La tabla 3.2 muestra un ejemplo de configuración para una arquitectura media.

Parte de la tarea de configuración es habilitar el soporte de InnoDB, configurando cada una de las variables de acuerdo a lo propuesto en 3.2, desde luego los aspectos más importantes serán los buffers

#Example mysql config file for medium systems.
#
# This is for a system with little memory (32M - 64M) where MySQL plays
# a important part and systems up to 128M very MySQL is used together with
# other programs (like a web server)
#
# You can copy this file to
# /etc/mf.cnf to set global options,
# mysql-data-dir/my.cnf to set server-specific options (in this
# installation this directory is /centia01/develop/database/mysql/var) or
# ~/.my.cnf to set user-specific options.
#
# One can in this file use all long options that the program supports.
# If you want to know which options a program support, run the program
# with --help option.
# The following options will be passed to all MySQL clients
[client]
#password = your_password
port = 3306
socket = /tmp/mysql.sock
# Here follows entries for some specific programs
# The MySQL server
[mysqld]
port = 3306
socket = /tmp/mysql.sock
skip-locking
set-variable = key_buffer=64M
set-variable = max_allowed_packet=256M
set-variable = table_cache=64
set-variable = sort_buffer=512K
set-variable = net_buffer_length=8K
set-variable = myisam_sort_buffer_size=16M
set-variable = max_connections=500
set-variable = interactive_timeout=604800
set-variable = wait_timeout=604800
log-bin
server-id = 1
set-variable=default_table_type=innodb
# Point the following paths to different dedicated disks
tmpdir = /var/tmp/ 
#log-update = /mysql/var/log-catarina
# Uncomment the following if you are using BDB tables
set-variable = bdb_cache_size=4M
set-variable = bdb_max_lock=10000
# Uncomment the following if you are using Innobase tables
innodb_data_file_path = ibdata1:30G:autoextend
innodb_data_home_dir = /mysql/innodb
innodb_log_group_home_dir = /mysql/innodb
innodb_log_arch_dir = /mysql/innodb
set-variable = innodb_mirrored_log_groups=1
set-variable = innodb_log_files_in_group=3
set-variable = innodb_log_file_size=5M
set-variable = innodb_log_buffer_size=16M
innodb_flush_log_at_trx_commit=1
innodb_log_archive=0
set-variable = innodb_buffer_pool_size=256M
set-variable = innodb_additional_mem_pool_size=256M
set-variable = innodb_file_io_threads=4
set-variable = innodb_lock_wait_timeout=50
#set-variable = innodb_force_recovery=3
[mysqldump]
quick
set-variable = max_allowed_packet=256M
[mysql]
prompt=(\u) [\d]>\_
no-auto-rehash
# Remove the next comment character if you are not familiar with SQL
#safe-updates
[isamchk]
set-variable = key_buffer=20M
set-variable = sort_buffer=20M
set-variable = read_buffer=2M
set-variable = write_buffer=2M
[myisamchk]
set-variable = key_buffer=20M
set-variable = sort_buffer=20M
set-variable = read_buffer=2M
set-variable = write_buffer=2M
[mysqlhotcopy]
interactive-timeout

Tabla 3.2 Archivo de Configuración my.cnf, my.ini

3.2.1.2 Arranque y Terminación

Arranque del manejador

Una vez configurado se puede iniciar el demonio del dbms a través del comando "mysqld" o alguna de sus variantes "safe_mysqld", "mysqld-max"

Esto se puede hacer desde cualquier terminal y se pueden pasar como parametros algunas de las mismas variables disponibles para configuración (en caso de necesitar alguna opción particular)

Terminación del manejador

Se puede hacer de 2 maneras

3.2.1.3 Creación de bases y cuentas de usuario

La tabla 3.3 muestra la manera en que cualquier usuario puede conectarse a la base llamada 'mysql' con el usuario 'root', para ello es indispensable contar con el password correspondiente; como se presentará más adelante la cuenta del super usuario 'root' se administra de manera similar que los demás usuario.

[digital@pcproal digital]$ mysql -u root -p mysql
Enter password: ****
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1 to server version: 4.1.0-alpha-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

(root) [mysql]>

Tabla 3.3 Conexión con el dbms

La tabla 3.4 muestra las tablas correspondientes a la base principal y que administra todos los usuarios, máquinas y bases permitidas en el manejador, recordando que se trata de un esquema relacional en el cual por ejemplo los usuarios se encuentran vinculados son bases de datos, de manera que no pueden existir problemas de seguridad al haber algun usuario malintencionado que pretenda modificar una base a la cual no tenga acceso.

 

(root) [mysql]> show databases;
+------------+
| Database   |
+------------+
| mysql      |
+------------+
1 rows in set (0.12 sec)

(root) [mysql]> show tables;
+-----------------+
| Tables_in_mysql |
+-----------------+
| columns_priv    |
| db              |
| func            |
| help_category   |
| help_relation   |
| help_topic      |
| host            |
| tables_priv     |
| user            |
+-----------------+
9 rows in set (0.10 sec)

Tabla 3.4 Tablas de administración del dbms

Para cada tabla se puede emplear el comando 'desc' o 'describe' para analizar la estructura de cada tabla y apreciar la relación que tiene con las demás.

Para dar de un alta un usuario, ejemplo de la tabla 3.5, se debe crear el usuario dentro de la tabla 'user', crear la base de datos y posteriormente asociar dicho usuario con la base en la tabla 'bd', todo lo anterior utilizando instrucciones de SQL tradicionales.

                                
(root) [mysql]> desc user;
+-----------------------+-----------------------------------+-------------------+------+-----+---------+-------+
| Field                 | Type                              | Collation         | Null | Key | Default | Extra |
+-----------------------+-----------------------------------+-------------------+------+-----+---------+-------+
| Host                  | varchar(60) binary                | binary            |      | PRI |         |       |
| User                  | varchar(16) binary                | binary            |      | PRI |         |       |
| Password              | varchar(45) binary                | binary            |      |     |         |       |
| Select_priv           | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Insert_priv           | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Update_priv           | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Delete_priv           | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Create_priv           | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Drop_priv             | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Reload_priv           | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Shutdown_priv         | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Process_priv          | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| File_priv             | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Grant_priv            | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| References_priv       | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Index_priv            | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Alter_priv            | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Show_db_priv          | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Super_priv            | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Create_tmp_table_priv | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Lock_tables_priv      | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Execute_priv          | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Repl_slave_priv       | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| Repl_client_priv      | enum('N','Y')                     | latin1_swedish_ci |      |     | N       |       |
| ssl_type              | enum('','ANY','X509','SPECIFIED') | latin1_swedish_ci |      |     |         |       |
| ssl_cipher            | blob                              | binary            |      |     |         |       |
| x509_issuer           | blob                              | binary            |      |     |         |       |
| x509_subject          | blob                              | binary            |      |     |         |       |
| max_questions         | int(11) unsigned                  | binary            |      |     | 0       |       |
| max_updates           | int(11) unsigned                  | binary            |      |     | 0       |       |
| max_connections       | int(11) unsigned                  | binary            |      |     | 0       |       |
+-----------------------+-----------------------------------+-------------------+------+-----+---------+-------+
31 rows in set (0.00 sec)

(root) [mysql]> desc db;
+-----------------------+-----------------+-------------------+------+-----+---------+-------+
| Field                 | Type            | Collation         | Null | Key | Default | Extra |
+-----------------------+-----------------+-------------------+------+-----+---------+-------+
| Host                  | char(60) binary | binary            |      | PRI |         |       |
| Db                    | char(64) binary | binary            |      | PRI |         |       |
| User                  | char(16) binary | binary            |      | PRI |         |       |
| Select_priv           | enum('N','Y')   | latin1_swedish_ci |      |     | N       |       |
| Insert_priv           | enum('N','Y')   | latin1_swedish_ci |      |     | N       |       |
| Update_priv           | enum('N','Y')   | latin1_swedish_ci |      |     | N       |       |
| Delete_priv           | enum('N','Y')   | latin1_swedish_ci |      |     | N       |       |
| Create_priv           | enum('N','Y')   | latin1_swedish_ci |      |     | N       |       |
| Drop_priv             | enum('N','Y')   | latin1_swedish_ci |      |     | N       |       |
| Grant_priv            | enum('N','Y')   | latin1_swedish_ci |      |     | N       |       |
| References_priv       | enum('N','Y')   | latin1_swedish_ci |      |     | N       |       |
| Index_priv            | enum('N','Y')   | latin1_swedish_ci |      |     | N       |       |
| Alter_priv            | enum('N','Y')   | latin1_swedish_ci |      |     | N       |       |
| Create_tmp_table_priv | enum('N','Y')   | latin1_swedish_ci |      |     | N       |       |
| Lock_tables_priv      | enum('N','Y')   | latin1_swedish_ci |      |     | N       |       |
+-----------------------+-----------------+-------------------+------+-----+---------+-------+
(root) [mysql]> insert into user (host,user,password) values ('%','carlos',password('lolo'));
Query OK, 1 row affected (0.07 sec)

(root) [mysql]> select * from user where user='carlos';
+------+--------+-----------------------------------------------+-------------+-------------+-------------+-------------+
| Host | User   | Password                                      | Select_priv | Insert_priv | Update_priv | Delete_priv |
+------+--------+-----------------------------------------------+-------------+-------------+-------------+-------------+
| %    | carlos | *87f0212af7420ce3e0b2b8992eb42dda4be54c9125b3 | N           | N           | N           | N           |
+------+--------+-----------------------------------------------+-------------+-------------+-------------+-------------+
1 row in set (0.00 sec)


(root) [mysql]> create database prueba;
Query OK, 1 row affected (0.00 sec)


(root) [mysql]> insert into db values ('%','prueba','carlos','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
Query OK, 1 row affected (0.00 sec)

(root) [mysql]> select * from db where user='carlos';
+------+--------+--------+-------------+-------------+-------------+-------------+
| Host | Db     | User   | Select_priv | Insert_priv | Update_priv | Delete_priv |
+------+--------+--------+-------------+-------------+-------------+-------------+
| %    | prueba | carlos | Y           | Y           | Y           | Y           |
+------+--------+--------+-------------+-------------+-------------+-------------+
1 row in set (0.09 sec)

(root) [mysql]> flush privileges;
Query OK, 0 rows affected (0.07 sec)

Tabla 3.5 Creación de una cuenta de usuario

3.2.1.4 Utilización de la base de datos

SQL

MySQL cumple con el estándar SQL92. Es importante resaltar que aunque no implementa todas las funciones que otros manejadores poseen, es posible realizar cualquier consulta usando los distintos tipos de joins o inclusive a través de tablas temporales.

[digital@pcproal digital]$ mysql -u carlos -p prueba
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3 to server version: 4.1.0-alpha-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

(carlos) [prueba]> show tables;
Empty set (0.00 sec)



(carlos) [prueba]> create table auser (id int primary key, last_name char(255),first_name char(255));
Query OK, 0 rows affected (0.07 sec)

(carlos) [prueba]> show tables;
+------------------+
| Tables_in_prueba |
+------------------+
| auser            |
+------------------+
1 row in set (0.00 sec)

(carlos) [prueba]> insert into auser values (1,'proal','carlos');
Query OK, 1 row affected (0.00 sec)


(carlos) [prueba]> select * from auser;
+----+-----------+------------+
| id | last_name | first_name |
+----+-----------+------------+
|  1 | proal     | carlos     |
+----+-----------+------------+
1 row in set (0.08 sec)

Tabla 3.6 Ejemplos de SQL

Creación de índices

La sintáxis de creación de índices no está considerada como un estándar, así que varía en cada dbms, ej.

create index index_name on table_name (atrib_1,..atrib_n);

En el caso partícular de MySQL toda llave primaria está asociada a un índice, así que no se requiere crear un índice adicional para dicho propósito.

Por otro lado si se crea un índice X que contiene a los atributos (a,b,c) ya no es necesario crear un índice para el caso de hacer una consulta que sólo involucre a (a) o (a,b) ya que se empleará el mismo índice X; para saber con certeza qué índices de están empleando en una consulta se puede recurrir a la expresión de 'explain'.


(carlos) [prueba]> create index iname on auser(last_name,first_name);
Query OK, 1 row affected (0.15 sec)
Records: 1  Duplicates: 0  Warnings: 0


(carlos) [prueba]> show index from auser;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| auser |          0 | PRIMARY  |            1 | id          | A         |           1 |     NULL | NULL   |      | BTREE      |         |
| auser |          1 | iname    |            1 | last_name   | A         |           1 |     NULL | NULL   | YES  | BTREE      |         |
| auser |          1 | iname    |            2 | first_name  | A         |           1 |     NULL | NULL   | YES  | BTREE      |         |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
3 rows in set (0.00 sec)

(carlos) [prueba]> explain select * from auser where last_name='aguilar';
+----+-------------+-------+------+---------------+-------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key   | key_len | ref   | rows | Extra                    |
+----+-------------+-------+------+---------------+-------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | auser | ref  | iname         | iname |     256 | const |    1 | Using where; Using index |
+----+-------------+-------+------+---------------+-------+---------+-------+------+--------------------------+
1 row in set (0.08 sec)

Tabla 3.7 Empleo de índices

Mantenimiento y monitoreo de la base

Actividad Comando
Revisar el estado de las tablas show table status;
Los procesos que están ejecutándose show processlist;

Variables con las que se está ejecutando la instancia

show variables;
Estado actual de innodb; show innodb status;

Respaldos

La manera usual de hacer un respaldo es usando el comando mysqldump, que posee muchas opciones que permiten duplicar todas las base, una base en particular, una tabla, solo los datos, solo la estructura, etc.

Para obtener un respaldo completo de una base

[digital@pcproal digital]$ mysqldump --opt -u carlos -p prueba > prueba.bak
Para restaurar un respaldo completo de una base
[digital@pcproal digital]$ mysql -u carlos -p prueba < prueba.bak

Otra manera de hacer respaldos es através del comando "select into" y restaurar los datos con "mysqlimport" o "load data infile".