Consider such a database implementation where fd
represents the data file and wal
represents a WAL instance.
type database struct {
fd os.File
wal *wal
}
wal.Write(record)
ensures that the record will be written to disk.A error will be return if it fails.
fd.Write(data)
will hand over the data to the operating system (OS).Whether the data is immediately written to the disk is determined by OS.As long as the data is successfully handed over to the OS, the operation is considered successful.
func (db *database) Write(data) error {
// Create a record based on the data
record:=record{Op:"Write",Data:data}
// log the opereation into disk
// if log fails,the whole db.Write is considered
if err:=db.wal.Write(record);err!=nil {
return err
}
if err:=db.fd.Write(data);err!=nil {
return err
}
return nil
}
The question is,if wal.Write
succeeds but fd.Write
fails for some reasons other than a crash,which means user knows db.Write
fails and the data should not exist,however,when the user restores the database from the WAL, he may be surprised to find that the data exists in the database because this operation was logged.
So what's wrong?Do i need to log additionly if fd.Write
fails so that user can know the operation fails when he restores the database from wal?This may not be helpful since the second log might fail.