mirror of
https://github.com/prometheus/prometheus.git
synced 2024-12-26 22:19:40 -08:00
Add workaround for deadlocks
This adds a workaround to avoid deadlocks for inconsistent write lock order across headBlocks. Things keep working if transactions only append data for the same timestamp, which is generally the case for Prometheus. Full behavior should be restored in a subsequent change.
This commit is contained in:
parent
3be4ef94ce
commit
a52980e0a8
43
db.go
43
db.go
|
@ -462,18 +462,22 @@ func (db *DB) Appender() Appender {
|
||||||
db.mtx.RLock()
|
db.mtx.RLock()
|
||||||
a := &dbAppender{db: db}
|
a := &dbAppender{db: db}
|
||||||
|
|
||||||
// Only instantiate appender after returning the headmtx to avoid
|
// XXX(fabxc): turn off creating initial appender as it will happen on-demand
|
||||||
// questionable locking order.
|
// anyway. For now this, with combination of only having a single timestamp per batch,
|
||||||
db.headmtx.RLock()
|
// prevents opening more than one appender and hitting an unresolved deadlock (#11).
|
||||||
app := db.appendable()
|
//
|
||||||
db.headmtx.RUnlock()
|
// // Only instantiate appender after returning the headmtx to avoid
|
||||||
|
// // questionable locking order.
|
||||||
|
// db.headmtx.RLock()
|
||||||
|
// app := db.appendable()
|
||||||
|
// db.headmtx.RUnlock()
|
||||||
|
|
||||||
for _, b := range app {
|
// for _, b := range app {
|
||||||
a.heads = append(a.heads, &metaAppender{
|
// a.heads = append(a.heads, &metaAppender{
|
||||||
meta: b.Meta(),
|
// meta: b.Meta(),
|
||||||
app: b.Appender().(*headAppender),
|
// app: b.Appender().(*headAppender),
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
|
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
@ -551,14 +555,27 @@ func (a *dbAppender) appenderFor(t int64) (*metaAppender, error) {
|
||||||
|
|
||||||
a.db.headmtx.Unlock()
|
a.db.headmtx.Unlock()
|
||||||
|
|
||||||
// Instantiate appenders after returning headmtx to avoid questionable
|
// XXX(fabxc): temporary workaround. See comment on instantiating DB.Appender.
|
||||||
// locking order.
|
|
||||||
for _, b := range newHeads {
|
for _, b := range newHeads {
|
||||||
|
// Only get appender for the block with the specific timestamp.
|
||||||
|
if t >= b.Meta().MaxTime {
|
||||||
|
continue
|
||||||
|
}
|
||||||
a.heads = append(a.heads, &metaAppender{
|
a.heads = append(a.heads, &metaAppender{
|
||||||
app: b.Appender(),
|
app: b.Appender(),
|
||||||
meta: b.Meta(),
|
meta: b.Meta(),
|
||||||
})
|
})
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // Instantiate appenders after returning headmtx to avoid questionable
|
||||||
|
// // locking order.
|
||||||
|
// for _, b := range newHeads {
|
||||||
|
// a.heads = append(a.heads, &metaAppender{
|
||||||
|
// app: b.Appender(),
|
||||||
|
// meta: b.Meta(),
|
||||||
|
// })
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
for i := len(a.heads) - 1; i >= 0; i-- {
|
for i := len(a.heads) - 1; i >= 0; i-- {
|
||||||
if h := a.heads[i]; t >= h.meta.MinTime {
|
if h := a.heads[i]; t >= h.meta.MinTime {
|
||||||
|
|
4
head.go
4
head.go
|
@ -34,6 +34,10 @@ var (
|
||||||
ErrOutOfBounds = errors.New("out of bounds")
|
ErrOutOfBounds = errors.New("out of bounds")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// func init() {
|
||||||
|
// deadlock.Opts.OnPotentialDeadlock = func() { fmt.Println("found deadlock") }
|
||||||
|
// }
|
||||||
|
|
||||||
// headBlock handles reads and writes of time series data within a time window.
|
// headBlock handles reads and writes of time series data within a time window.
|
||||||
type headBlock struct {
|
type headBlock struct {
|
||||||
mtx sync.RWMutex
|
mtx sync.RWMutex
|
||||||
|
|
Loading…
Reference in a new issue