This is about one problem I have, and there's also a patch attached which might be good to incorporate into future version of Bacula.

I'm in the middle of migrating Bacula database from PostgreSQL to MySQL, and got into kind of trouble because of different constraints on the columns in those two databases.

The job table has columns poolid and filesetid defined as NOT NULL in MySQL, but there is no such constraint in PostgreSQL. Also, Bacula utilizes foreign keys with MySQL, but not with PostgreSQL. Simmilary, sqlite and sqlite3 backends also utilize foreign keys. While I was running on PostgreSQL, I got some entries in job table with those columns set to NULL. Of course, migration is failing on those.

The jobs in question seems to be either restores or failed jobs:

bacula=# select jobid, type, jobstatus from job where poolid is null or filesetid is null;
jobid | type | jobstatus
-------+------+-----------
 1040 | R    | T
  373 | R    | T
   98 | B    | C
   97 | B    | R
   99 | B    | C
  100 | B    | C
  101 | B    | C
 1146 | B    | R
(8 rows)

Two 'R' jobs are also failed/canceled jobs (for whatever reason, Bacula never marked them as such).

Should existance of these rows in database be considered bug in Bacula? When using SQLite or MySQL (if InnoDB engine is used), inserting those rows into database would fail anynow (as well as thousands of other rows in file table that depend on them).

Now, I guess I could simply delete those, and also all rows from other tables that reference these rows (file, jobmedia, basefiles, and unsavedfiles). My wild guess is that if I used MySQL initially, those rows wouldn't exist anyhow (inserts would fail). Anyhow, looking at the file table, there's about 32,000 rows that I'll need to delete... Hopefully I'm not going to nuke anything too usefull...

However, regardless of this problem I have, it might be good move to utilize same features on all database backends (as long as they support them), which would basically mean adding foreign key constrains to PostgreSQL data definitions (yeah, it might slow database inserts a bit). I've included a patch that does this. The patch might look bigger than it really is, since I needed to reorder table creation. Basically, all it does is adding foreign keys to the places where they are defined in other backends (used MySQL backend as reference). I haven't made an update script, since updating PostgreSQL tables to start using foreign keys might require deletion of live data from database (I'll leave it to someone with more internal knowledge of Bacula).

When we are at patching... How about adding ON DELETE CASCADE to table definitions (wherever foreign keys are used)? This would make some stuff much easier (for example, the task that is now in front of me) if database backend supports foreign keys (sqlite and postgresql do, mysql depending on version and storage engine used).


----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.

--- bacula-1.38.2/src/cats/make_postgresql_tables.in.orig	2006-02-09 13:16:04.000000000 -0600
+++ bacula-1.38.2/src/cats/make_postgresql_tables.in	2006-02-09 13:50:54.000000000 -0600
@@ -24,29 +24,61 @@
 
 CREATE INDEX path_name_idx on path (path);
 
-CREATE TABLE file
+CREATE TABLE pool
 (
-    fileid	      serial	  not null,
-    fileindex	      integer	  not null  default 0,
-    jobid	      integer	  not null,
-    pathid	      integer	  not null,
-    filenameid	      integer	  not null,
-    markid	      integer	  not null  default 0,
-    lstat	      text	  not null,
+    poolid	      serial	  not null,
+    name	      text	  not null,
+    numvols	      integer	  not null default 0,
+    maxvols	      integer	  not null default 0,
+    useonce	      smallint	  not null default 0,
+    usecatalog	      smallint	  not null default 0,
+    acceptanyvolume   smallint	  not null default 0,
+    volretention      bigint	  not null default 0,
+    voluseduration    bigint	  not null default 0,
+    maxvoljobs	      integer	  not null default 0,
+    maxvolfiles       integer	  not null default 0,
+    maxvolbytes       bigint	  not null default 0,
+    autoprune	      smallint	  not null default 0,
+    recycle	      smallint	  not null default 0,
+    pooltype	      text			    
+      check (pooltype in ('Backup','Copy','Cloned','Archive','Migration','Scratch')),
+    labeltype	      integer	  not null default 0,
+    labelformat       text	  not null,
+    enabled	      smallint	  not null default 1,
+    scratchpoolid     integer default 0 references pool,
+    recyclepoolid     integer default 0 references pool,
+    NextPoolId	      integer default 0 references pool,
+    MigrationHighBytes BIGINT DEFAULT 0,
+    MigrationLowBytes  BIGINT DEFAULT 0,
+    MigrationTime      BIGINT DEFAULT 0,
+    primary key (poolid)
+);
+
+CREATE INDEX pool_name_idx on pool (name);
+
+CREATE TABLE fileset
+(
+    filesetid	      serial	  not null,
+    fileset	      text	  not null,
     md5 	      text	  not null,
-    primary key (fileid)
+    createtime	      timestamp without time zone not null,
+    primary key (filesetid)
 );
 
-CREATE INDEX file_jobid_idx on file (jobid);
-CREATE INDEX file_fp_idx on file (filenameid, pathid);
+CREATE INDEX fileset_name_idx on fileset (fileset);
 
---
--- Possibly add one or more of the following indexes
---  if your Verifies are too slow.
---
--- CREATE INDEX file_pathid_idx on file(pathid);
--- CREATE INDEX file_filenameid_idx on file(filenameid);
--- CREATE INDEX file_jpfid_idx on file (jobid, pathid, filenameid);
+CREATE TABLE client
+(
+    clientid	      serial	  not null,
+    name	      text	  not null,
+    uname	      text	  not null,
+    autoprune	      smallint	  default 0,
+    fileretention     bigint	  not null,
+    jobretention      bigint	  not null,
+    primary key (clientid)
+);
+
+create unique index client_name_idx on client (name);
 
 CREATE TABLE job
 (
@@ -55,7 +87,7 @@
     name	      text	  not null,
     type	      char(1)	  not null,
     level	      char(1)	  not null,
-    clientid	      integer,
+    clientid	      integer	  not null references client,
     jobstatus	      char(1)	  not null,
     schedtime	      timestamp   without time zone not null,
     starttime	      timestamp   without time zone,
@@ -67,8 +99,8 @@
     jobbytes	      bigint	  not null default 0,
     joberrors	      integer	  not null default 0,
     jobmissingfiles   integer	  not null default 0,
-    poolid	      integer,
-    filesetid	      integer,
+    poolid	      integer	  not null references pool,
+    filesetid	      integer	  not null references fileset,
     purgedfiles       smallint	  not null default 0,
     hasbase	      smallint	  not null default 0,
     primary key (jobid)
@@ -76,42 +108,43 @@
 
 CREATE INDEX job_name_idx on job (name);
 
-CREATE TABLE fileset
+CREATE TABLE file
 (
-    filesetid	      serial	  not null,
-    fileset	      text	  not null,
+    fileid	      serial	  not null,
+    fileindex	      integer	  not null  default 0,
+    jobid	      integer	  not null  references job,
+    pathid	      integer	  not null  references path,
+    filenameid	      integer	  not null  references filename,
+    markid	      integer	  not null  default 0,
+    lstat	      text	  not null,
     md5 	      text	  not null,
-    createtime	      timestamp without time zone not null,
-    primary key (filesetid)
+    primary key (fileid)
 );
 
-CREATE INDEX fileset_name_idx on fileset (fileset);
+CREATE INDEX file_jobid_idx on file (jobid);
+CREATE INDEX file_fp_idx on file (filenameid, pathid);
 
-CREATE TABLE jobmedia
-(
-    jobmediaid	      serial	  not null,
-    jobid	      integer	  not null,
-    mediaid	      integer	  not null,
-    firstindex	      integer	  not null default 0,
-    lastindex	      integer	  not null default 0,
-    startfile	      integer	  not null default 0,
-    endfile	      integer	  not null default 0,
-    startblock	      bigint	  not null default 0,
-    endblock	      bigint	  not null default 0,
-    volindex	      integer	  not null default 0,
-    copy	      integer	  not null default 0,
-    stripe	      integer	  not null default 0,
-    primary key (jobmediaid)
-);
+--
+-- Possibly add one or more of the following indexes
+--  if your Verifies are too slow.
+--
+-- CREATE INDEX file_pathid_idx on file(pathid);
+-- CREATE INDEX file_filenameid_idx on file(filenameid);
+-- CREATE INDEX file_jpfid_idx on file (jobid, pathid, filenameid);
 
-CREATE INDEX job_media_job_id_media_id_idx on jobmedia (jobid, mediaid);
+CREATE TABLE Storage (
+   StorageId SERIAL,
+   Name TEXT NOT NULL,
+   AutoChanger INTEGER DEFAULT 0,
+   PRIMARY KEY(StorageId)
+   );
 
 CREATE TABLE media
 (
     mediaid	      serial	  not null,
     volumename	      text	  not null,
     slot	      integer	  not null default 0,
-    poolid	      integer	  not null,
+    poolid	      integer	  not null references pool,
     mediatype	      text	  not null,
     labeltype	      integer	  not null default 0,
     firstwritten      timestamp   without time zone,
@@ -137,7 +170,7 @@
     maxvolfiles       integer	  not null default 0,
     maxvolbytes       bigint	  not null default 0,
     inchanger	      smallint	  not null default 0,
-    StorageId	      integer		   default 0,
+    StorageId	      integer	  not null default 0 references storage,
     mediaaddressing   smallint	  not null default 0,
     volreadtime       bigint	  not null default 0,
     volwritetime      bigint	  not null default 0,
@@ -148,7 +181,25 @@
 
 create unique index media_volumename_id on media (volumename);
 
- 
+CREATE TABLE jobmedia
+(
+    jobmediaid	      serial	  not null,
+    jobid	      integer	  not null references job,
+    mediaid	      integer	  not null references media,
+    firstindex	      integer	  not null default 0,
+    lastindex	      integer	  not null default 0,
+    startfile	      integer	  not null default 0,
+    endfile	      integer	  not null default 0,
+    startblock	      bigint	  not null default 0,
+    endblock	      bigint	  not null default 0,
+    volindex	      integer	  not null default 0,
+    copy	      integer	  not null default 0,
+    stripe	      integer	  not null default 0,
+    primary key (jobmediaid)
+);
+
+CREATE INDEX job_media_job_id_media_id_idx on jobmedia (jobid, mediaid);
+
 CREATE TABLE MediaType (
    MediaTypeId SERIAL,
    MediaType TEXT NOT NULL,
@@ -156,18 +207,11 @@
    PRIMARY KEY(MediaTypeId)
    );
 
-CREATE TABLE Storage (
-   StorageId SERIAL,
-   Name TEXT NOT NULL,
-   AutoChanger INTEGER DEFAULT 0,
-   PRIMARY KEY(StorageId)
-   );
-
 CREATE TABLE Device (
    DeviceId SERIAL,
    Name TEXT NOT NULL,
-   MediaTypeId INTEGER NOT NULL,
-   StorageId INTEGER NOT NULL,
+   MediaTypeId INTEGER NOT NULL REFERENCES mediatype,
+   StorageId INTEGER NOT NULL REFERENCES storage,
    DevMounts INTEGER NOT NULL DEFAULT 0,
    DevReadBytes BIGINT NOT NULL DEFAULT 0,
    DevWriteBytes BIGINT NOT NULL DEFAULT 0,
@@ -183,52 +227,6 @@
    );
 
 
-CREATE TABLE pool
-(
-    poolid	      serial	  not null,
-    name	      text	  not null,
-    numvols	      integer	  not null default 0,
-    maxvols	      integer	  not null default 0,
-    useonce	      smallint	  not null default 0,
-    usecatalog	      smallint	  not null default 0,
-    acceptanyvolume   smallint	  not null default 0,
-    volretention      bigint	  not null default 0,
-    voluseduration    bigint	  not null default 0,
-    maxvoljobs	      integer	  not null default 0,
-    maxvolfiles       integer	  not null default 0,
-    maxvolbytes       bigint	  not null default 0,
-    autoprune	      smallint	  not null default 0,
-    recycle	      smallint	  not null default 0,
-    pooltype	      text			    
-      check (pooltype in ('Backup','Copy','Cloned','Archive','Migration','Scratch')),
-    labeltype	      integer	  not null default 0,
-    labelformat       text	  not null,
-    enabled	      smallint	  not null default 1,
-    scratchpoolid     integer default 0,
-    recyclepoolid     integer default 0,
-    NextPoolId	      integer default 0,
-    MigrationHighBytes BIGINT DEFAULT 0,
-    MigrationLowBytes  BIGINT DEFAULT 0,
-    MigrationTime      BIGINT DEFAULT 0,
-    primary key (poolid)
-);
-
-CREATE INDEX pool_name_idx on pool (name);
-
-CREATE TABLE client
-(
-    clientid	      serial	  not null,
-    name	      text	  not null,
-    uname	      text	  not null,
-    autoprune	      smallint	  default 0,
-    fileretention     bigint	  not null,
-    jobretention      bigint	  not null,
-    primary key (clientid)
-);
-
-create unique index client_name_idx on client (name);
-
-
 CREATE TABLE counters
 (
     counter	      text	  not null,
@@ -244,19 +242,19 @@
 CREATE TABLE basefiles
 (
     baseid	      serial		    not null,
-    jobid	      integer		    not null,
-    fileid	      integer		    not null,
+    jobid	      integer		    not null references job,
+    fileid	      integer		    not null references file,
     fileindex	      integer			    ,
-    basejobid	      integer			    ,
+    basejobid	      integer		    not null references job,
     primary key (baseid)
 );
 
 CREATE TABLE unsavedfiles
 (
     UnsavedId	      integer		    not null,
-    jobid	      integer		    not null,
-    pathid	      integer		    not null,
-    filenameid	      integer		    not null,
+    jobid	      integer		    not null references job,
+    pathid	      integer		    not null references path,
+    filenameid	      integer		    not null references filename,
     primary key (UnsavedId)
 );
 

Reply via email to