When checking out those new features of Sybase 15.7 (yes, from time to time I got to see what commercial databases are up to),  I stumbled over an interesting and yet amusing line: “Fully Recoverable DDL”. The details seem to indicate that not just Sybase is still having a hard time to handle transactional and crash safe DDLs in a proper way.

After 15 years of professional PostgreSQL I actually don’t remember a time, when PostgreSQL did not have transactional DDLs. The beauty of PostgreSQL is that all major DDLs are fully transactional:

test=# BEGIN;

test=# CREATE TABLE t_test (id int, name text);
test=# \d
        List of relations
 Schema |  Name  | Type  | Owner
 public | t_test | table | hs
(1 row)

test=# ROLLBACK;

test=# \d
No relations found.

Basically everything people need for their daily work is fully transactional. CREATE TABLE, ALTER TABLE, CREATE INDEX – everything works just like a charm.

The exceptions to the rule …

However, there are some minor exceptions to the rule. The most prominent thing is most likely CREATE INDEX CONCURRENTLY. The thing is: CREATE INDEX is a single transaction – CREATE INDEX CONCURRENTLY is not – and therefore it cannot be run inside a normal transaction block. The index needs to be visible to other transactions before the build can even begin:

test=# BEGIN;

test=# CREATE INDEX CONCURRENTLY idx_id ON t_test (id);
ERROR:  CREATE INDEX CONCURRENTLY cannot run inside a transaction block

But, there are some more corner cases. CREATE DATABASE is one of them:

ERROR:  CREATE DATABASE cannot run inside a transaction block

Performing a ROLLBACK in case of CREATE DATABASE should really not be a real problem anyway and nobody has ever complained about it.

The same applies to CREATE TABLESPACE:

test=# CREATE TABLESPACE some_name LOCATION '/storage';
ERROR:  CREATE TABLESPACE cannot run inside a transaction block

Of course there are some more commands along this line – this list is not meant to be complete. However, it has to be pointed out that in PostgreSQL at least 90% of all DDLs fully support transaction blocks as expected.

VACUUM: The great princess

What is interesting is that some people asked for a ROLLBACK on VACUUM. To make it clear: This is not possible and clearly makes no sense.

test=# VACUUM;
ERROR:  VACUUM cannot run inside a transaction block

VACUUM is here to physically clean up rows – it is really pointless to consider a ROLLBACK here (for countless reasons).