diff --git a/internal/sqladapter/exql/template.go b/internal/sqladapter/exql/template.go
index 7b873b0f1b8eeb6a85652faaec699b16977b3d19..5b8637f971092e48be3c4a05873f3297fb95085c 100644
--- a/internal/sqladapter/exql/template.go
+++ b/internal/sqladapter/exql/template.go
@@ -2,6 +2,7 @@ package exql
 
 import (
 	"bytes"
+	"sync"
 	"text/template"
 
 	"upper.io/db.v2/internal/cache"
@@ -32,7 +33,7 @@ type (
 )
 
 var (
-	parsedTemplates = make(map[string]*template.Template)
+	templateCache = templateMap{M: make(map[string]*template.Template)}
 )
 
 // Template is an SQL template.
@@ -76,13 +77,33 @@ func mustParse(text string, data interface{}) string {
 	var b bytes.Buffer
 	var ok bool
 
-	if _, ok = parsedTemplates[text]; !ok {
-		parsedTemplates[text] = template.Must(template.New("").Parse(text))
+	v, ok := templateCache.Get(text)
+	if !ok {
+		v = template.Must(template.New("").Parse(text))
+		templateCache.Set(text, v)
 	}
 
-	if err := parsedTemplates[text].Execute(&b, data); err != nil {
+	if err := v.Execute(&b, data); err != nil {
 		panic("There was an error compiling the following template:\n" + text + "\nError was: " + err.Error())
 	}
 
 	return b.String()
 }
+
+type templateMap struct {
+	sync.RWMutex
+	M map[string]*template.Template
+}
+
+func (m *templateMap) Get(k string) (*template.Template, bool) {
+	m.RLock()
+	defer m.RUnlock()
+	v, ok := m.M[k]
+	return v, ok
+}
+
+func (m *templateMap) Set(k string, v *template.Template) {
+	m.Lock()
+	defer m.Unlock()
+	m.M[k] = v
+}