diff --git a/core/rawdb/database.go b/core/rawdb/database.go
index 0f994c3fd372c1845bc304866afd2271120cbb95..cd1048cbc541baf26df3e713e92074b1acc7682c 100644
--- a/core/rawdb/database.go
+++ b/core/rawdb/database.go
@@ -17,6 +17,8 @@
 package rawdb
 
 import (
+	"fmt"
+
 	"github.com/ethereum/go-ethereum/ethdb"
 	"github.com/ethereum/go-ethereum/ethdb/leveldb"
 	"github.com/ethereum/go-ethereum/ethdb/memorydb"
@@ -25,7 +27,23 @@ import (
 // freezerdb is a databse wrapper that enabled freezer data retrievals.
 type freezerdb struct {
 	ethdb.KeyValueStore
-	ethdb.Ancienter
+	ethdb.AncientStore
+}
+
+// Close implements io.Closer, closing both the fast key-value store as well as
+// the slow ancient tables.
+func (frdb *freezerdb) Close() error {
+	var errs []error
+	if err := frdb.KeyValueStore.Close(); err != nil {
+		errs = append(errs, err)
+	}
+	if err := frdb.AncientStore.Close(); err != nil {
+		errs = append(errs, err)
+	}
+	if len(errs) != 0 {
+		return fmt.Errorf("%v", errs)
+	}
+	return nil
 }
 
 // nofreezedb is a database wrapper that disables freezer data retrievals.
@@ -58,7 +76,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace st
 
 	return &freezerdb{
 		KeyValueStore: db,
-		Ancienter:     frdb,
+		AncientStore:  frdb,
 	}, nil
 }
 
diff --git a/core/rawdb/freezer.go b/core/rawdb/freezer.go
index 4f227e3b78cea917aa58996f9f5a54eba9db1a21..07df4c75997807d49b595b8e6191f9e8c6a571e5 100644
--- a/core/rawdb/freezer.go
+++ b/core/rawdb/freezer.go
@@ -20,6 +20,7 @@ import (
 	"errors"
 	"fmt"
 	"math"
+	"path/filepath"
 	"sync/atomic"
 	"time"
 
@@ -27,6 +28,7 @@ import (
 	"github.com/ethereum/go-ethereum/ethdb"
 	"github.com/ethereum/go-ethereum/log"
 	"github.com/ethereum/go-ethereum/metrics"
+	"github.com/prometheus/tsdb/fileutil"
 )
 
 // errUnknownTable is returned if the user attempts to read from a table that is
@@ -57,8 +59,9 @@ const (
 //   reserving it for go-ethereum. This would also reduce the memory requirements
 //   of Geth, and thus also GC overhead.
 type freezer struct {
-	tables map[string]*freezerTable // Data tables for storing everything
-	frozen uint64                   // Number of blocks already frozen
+	tables       map[string]*freezerTable // Data tables for storing everything
+	frozen       uint64                   // Number of blocks already frozen
+	instanceLock fileutil.Releaser        // File-system lock to prevent double opens
 }
 
 // newFreezer creates a chain freezer that moves ancient chain data into
@@ -69,9 +72,14 @@ func newFreezer(datadir string, namespace string) (*freezer, error) {
 		readMeter  = metrics.NewRegisteredMeter(namespace+"ancient/read", nil)
 		writeMeter = metrics.NewRegisteredMeter(namespace+"ancient/write", nil)
 	)
+	lock, _, err := fileutil.Flock(filepath.Join(datadir, "LOCK"))
+	if err != nil {
+		return nil, err
+	}
 	// Open all the supported data tables
 	freezer := &freezer{
-		tables: make(map[string]*freezerTable),
+		tables:       make(map[string]*freezerTable),
+		instanceLock: lock,
 	}
 	for _, name := range []string{"hashes", "headers", "bodies", "receipts", "diffs"} {
 		table, err := newTable(datadir, name, readMeter, writeMeter)
@@ -79,6 +87,7 @@ func newFreezer(datadir string, namespace string) (*freezer, error) {
 			for _, table := range freezer.tables {
 				table.Close()
 			}
+			lock.Release()
 			return nil, err
 		}
 		freezer.tables[name] = table
@@ -95,6 +104,7 @@ func newFreezer(datadir string, namespace string) (*freezer, error) {
 			for _, table := range freezer.tables {
 				table.Close()
 			}
+			lock.Release()
 			return nil, err
 		}
 	}
@@ -109,6 +119,9 @@ func (f *freezer) Close() error {
 			errs = append(errs, err)
 		}
 	}
+	if err := f.instanceLock.Release(); err != nil {
+		errs = append(errs, err)
+	}
 	if errs != nil {
 		return fmt.Errorf("%v", errs)
 	}
diff --git a/ethdb/database.go b/ethdb/database.go
index 764e304e3ca33586c4ecff23d8dcbdfbc29cb162..01483f3d4dda74250990df0013fd297546125a10 100644
--- a/ethdb/database.go
+++ b/ethdb/database.go
@@ -80,6 +80,13 @@ type AncientReader interface {
 	Ancienter
 }
 
+// AncientStore contains all the methods required to allow handling different
+// ancient data stores backing immutable chain data store.
+type AncientStore interface {
+	Ancienter
+	io.Closer
+}
+
 // Database contains all the methods required by the high level database to not
 // only access the key-value data store but also the chain freezer.
 type Database interface {