I. Introduction▲
Issue de l'époque lointaine (au moins 10 ans !) ou il n'était pas aisé de faire cohabiter une grosse masse d'informations sur de nombreux raw devices, ventilés sur de non moins nombreux disques, la gestion des fichiers de données sous Sybase ASE peut paraître quelque peu complexe au néophyte.
Le prix à payer à ce jour est une mauvaise compréhension de la complexité de la gestion des espaces de stockage du DBA Junior, et la mécompréhension de l'inexistence de deux spécificités existant déjà dans d'autres SGBDR :
- L'inexistence d'une clause AUTOEXTENT lors de la création de devices ;
- L'incapacité de réduire la taille d'un device ayant été trop largement taillé (cf. autre article du même auteur).
Cet article à pour but d'apporter une solution à la soi-disant impossibilité qu'à ASE d'autoétendre ses devices.
II. L'explication historique▲
Sybase ASE (anciennement Sybase SQL Server) permettait en fait de définir avant tout ses espaces de stockage, puis de tailler dans lesdits espaces les segments nécessaires à chaque base de données.
Il faut garder en mémoire que jusqu'en version 11.9, le seul système de stockage supporté en production était le raw device. Il permettait d'assurer une intégrité des accès disques à ASE (en évitant tout cache OS). Ce raw device était généralement créé par l'administrateur système, et non pas par l'administrateur de la base. Une fois cet espace créé, sa taille ne pouvait varier… ce qui explique que l'autoextension ou la réduction du fichier ne pouvait être une option au niveau de l'instance ASE.
Nous avions donc une application claire de ce que Codd souhaitait : une dissociation claire et nette de la partie logique (base de données, tables) et de la partie physique (devices, fichiers sur disques…).
Ce qui différencie donc ASE de la plupart de ses concurrents, et ce qui explique certaines contraintes, c'est que l'on y crée des devices neutres. Ce n'est qu'à l'affectation de zones que l'on détermine leur contenu, et que le contenu peut être variable. C'est d'ailleurs pour cela que le stockage des informations sur les devices se fait dans la table sysdevices de master, puis que c'est ensuite une table de liens master..sysusages qui stocke le partage des devices de sysdevices avec les dbid de sysdatabases.
Microsoft a cassé cette logique dès la version 2000 en rapatriant les informations de stockage dans la base elle-même, et en dissociant fortement les fichiers de données (.mdb) et ceux du journal de transactions (.ldb).
Si l'on se base sur un modèle contraignant, évitant ainsi les écueils, on peut automatiser les choses.
III. Simulation d'autoextension : un exemple▲
En fait, il suffit de jouer avec la procédure stockée sp_thresholdaction qui n'est rien d'autre qu'un configurateur de seuils d'alerte pour les segments.
Basons-nous sur le modèle contraignant suivant :
- Une base est propriétaire de ses propres fichiers (pas de fichiers partagés entre bases) ;
- Le journal de transaction est toujours dissocié ;
- On crée arbitrairement trois types de segments qui auront eux aussi leur(s) propre(s) ; fichier(s)
- Chaque segment utilise l'entièreté de son device associé.
Il faut avant tout créer une procédure stockée de seuil qui augmentera la taille des devices et des segments au moment critique. Son positionnement dans master est nécessaire à cause de la commande disk remap.
use
master
go
create
procedure
dbo.sp_auto_db_etend
(
@dbname
varchar
(
30
), @segment_name
varchar
(
30
), @space_left
int
, @status
int
)
as
begin
declare
@v_size
varchar
(
5
)
declare
@v_device
varchar
(
30
)
declare
@v_type
varchar
(
5
)
declare
@v_sql
varchar
(
200
)
if
@segment_name
=
'default'
select
@v_device
=
@dbname
+
'_D01'
, @v_size
=
'100M'
, @v_type
=
''
else
if
@segment_name
=
'system'
select
@v_device
=
@dbname
+
'_D01'
, @v_size
=
'100M'
, @v_type
=
''
else
if
@segment_name
=
'indexsegment'
select
@v_device
=
@dbname
+
'_I01'
, @v_size
=
'100M'
, @v_type
=
''
else
if
@segment_name
=
'logsegment'
select
@v_device
=
@dbname
+
'_L01'
, @v_size
=
'50M'
, @v_type
=
'LOG'
else
begin
raiserror
20001
'Type de segment non géré'
return
-
1
end
disk
resize name
=
@v_device
, size =
@v_size
select
@v_sql
=
'alter database '
+
@dbname
+
' '
+
@v_type
+
' ON '
+
@v_device
+
'='''
+
@v_size
+
''''
print
@v_sql
exec
(
@v_sql
)
return
0
end
go
La procédure stockée suivante automatise la création d'une base de données selon les critères spécifiques et détermine le seuil critique.
user
master
go
create
procedure
sp_auto_db_cree
(
@v_dbname
varchar
(
30
))
as
begin
declare
@v_sql
varchar
(
200
)
declare
@v_path
varchar
(
200
)
declare
@v_file
varchar
(
200
)
declare
@v_seg
varchar
(
30
)
declare
@v_num_dev
int
declare
@v_max_dev
int
/* Contrôle de la préexistence de la base */
if
exists
(
select
name
from
sysdatabases
where
name
=
@v_dbname
)
begin
raiserror
20001
"La base existe déjà"
return
-
1
end
/* Contrôle du nombre de devices configurés */
select
@v_max_dev
=
value from
sysconfigures
where
name
=
'number of devices'
select
@v_num_dev
=
count
(*
) from
sysdevices
if
@v_max_dev
<
@v_num_dev
+
3
-- manque de structures mémoire pour les devices
begin
select
@v_num_dev
=
@v_max_dev
+
3
exec
sp_configure
'number of devices'
, @v_num_dev
end
/* Creation des devices specifiques */
select
@v_path
=
left
(
phyname , datalength
(
phyname )-
10
) from
master..sysdevices
where
name
=
'master'
select
@v_seg
=
@v_dbname
+
'_D01'
, @v_file
=
@v_path
+
@v_dbname
+
'_DATA01.dat'
disk
init name
=
@v_seg
, physname=
@v_file
, size=
'100M'
select
@v_seg
=
@v_dbname
+
'_I01'
, @v_file
=
@v_path
+
@v_dbname
+
'_INDEX01.dat'
disk
init name
=
@v_seg
, physname=
@v_file
, size=
'100M'
select
@v_seg
=
@v_dbname
+
'_L01'
, @v_file
=
@v_path
+
@v_dbname
+
'_LOG01.dat'
disk
init name
=
@v_seg
, physname=
@v_file
, size=
'50M'
/* Creation de la base */
select
@v_sql
=
'create database '
+
@v_dbname
+
' on '
+
@v_dbname
+
'_D01=''100M'' log on '
+
@v_dbname
+
'_L01=''50M'''
exec
(
@v_sql
)
select
@v_sql
=
'alter database '
+
@v_dbname
+
' on '
+
@v_dbname
+
'_I01=''100M'''
exec
(
@v_sql
)
/* Attribution des segments */
select
@v_sql
=
@v_dbname
+
'..sp_addsegment ''indexsegment'', '
+
@v_dbname
+
', '
+
@v_dbname
+
'_I01'
exec
(
@v_sql
)
select
@v_sql
=
@v_dbname
+
'..sp_dropsegment ''default'', '
+
@v_dbname
+
', '
+
@v_dbname
+
'_I01'
exec
(
@v_sql
)
select
@v_sql
=
@v_dbname
+
'..sp_dropsegment ''system'', '
+
@v_dbname
+
', '
+
@v_dbname
+
'_I01'
exec
(
@v_sql
)
/* Délimitation des seuil d'alerte */
select
@v_sql
=
@v_dbname
+
'..sp_addthreshold '
+
@v_dbname
+
', system, 5120, sp_auto_db_etend'
exec
(
@v_sql
)
select
@v_sql
=
@v_dbname
+
'..sp_addthreshold '
+
@v_dbname
+
', default, 5120, sp_auto_db_etend'
exec
(
@v_sql
)
select
@v_sql
=
@v_dbname
+
'..sp_addthreshold '
+
@v_dbname
+
', indexsegment, 5120, sp_auto_db_etend'
exec
(
@v_sql
)
select
@v_sql
=
@v_dbname
+
'..sp_addthreshold '
+
@v_dbname
+
', logsegment, 5120, sp_auto_db_etend'
exec
(
@v_sql
)
return
0
end
go
Certains choix ont été faits afin de simplifier la démonstration :
- localisation des devices dans un répertoire unique, à savoir celui hébergeant le device master : en termes de performances, il serait judicieux de choisir des disques distincts pour les divers segments ;
- création arbitraire d'un device de 100M (50M pour les logs) ;
- augmentation arbitraire d'un device de 100M (50M pour les logs) ;
- trois segments distincts (data/system, log et index).
Il sera cependant aisément possible d'améliorer la procédure en « piochant » les informations modifiables via une table de configuration.
Cette solution n'est pas optimale : elle a cependant le mérite de donner les pistes nécessaires à la résolution de cette problématique.
IV. Références▲
- Diagramme des tables système de Sybase ASE
- Documentationde Sybase ASE