diff --git a/internal/biz/database.go b/internal/biz/database.go
index 8bd89eae0a..14bfb41a66 100644
--- a/internal/biz/database.go
+++ b/internal/biz/database.go
@@ -20,10 +20,12 @@ type Database struct {
 	Server   string       `json:"server"`
 	ServerID uint         `json:"server_id"`
 	Encoding string       `json:"encoding"`
+	Comment  string       `json:"comment"`
 }
 
 type DatabaseRepo interface {
 	List(page, limit uint) ([]*Database, int64, error)
 	Create(req *request.DatabaseCreate) error
 	Delete(serverID uint, name string) error
+	Comment(req *request.DatabaseComment) error
 }
diff --git a/internal/data/database.go b/internal/data/database.go
index dad0c55bc0..0b0503efcf 100644
--- a/internal/data/database.go
+++ b/internal/data/database.go
@@ -1,6 +1,7 @@
 package data
 
 import (
+	"errors"
 	"fmt"
 	"slices"
 
@@ -53,6 +54,7 @@ func (r databaseRepo) List(page, limit uint) ([]*biz.Database, int64, error) {
 							Server:   server.Name,
 							ServerID: server.ID,
 							Encoding: item.Encoding,
+							Comment:  item.Comment,
 						})
 					}
 				}
@@ -134,3 +136,23 @@ func (r databaseRepo) Delete(serverID uint, name string) error {
 
 	return nil
 }
+
+func (r databaseRepo) Comment(req *request.DatabaseComment) error {
+	server, err := NewDatabaseServerRepo().Get(req.ServerID)
+	if err != nil {
+		return err
+	}
+
+	switch server.Type {
+	case biz.DatabaseTypeMysql:
+		return errors.New("mysql not support database comment")
+	case biz.DatabaseTypePostgresql:
+		postgres, err := db.NewPostgres(server.Username, server.Password, server.Host, server.Port)
+		if err != nil {
+			return err
+		}
+		return postgres.DatabaseComment(req.Name, req.Comment)
+	}
+
+	return nil
+}
diff --git a/internal/http/request/database.go b/internal/http/request/database.go
index 739b1f7251..24be05370b 100644
--- a/internal/http/request/database.go
+++ b/internal/http/request/database.go
@@ -14,3 +14,9 @@ type DatabaseDelete struct {
 	ServerID uint   `form:"server_id" json:"server_id" validate:"required,exists=database_servers id"`
 	Name     string `form:"name" json:"name" validate:"required"`
 }
+
+type DatabaseComment struct {
+	ServerID uint   `form:"server_id" json:"server_id" validate:"required,exists=database_servers id"`
+	Name     string `form:"name" json:"name" validate:"required"`
+	Comment  string `form:"comment" json:"comment"`
+}
diff --git a/internal/route/http.go b/internal/route/http.go
index 481494a99d..297c16a471 100644
--- a/internal/route/http.go
+++ b/internal/route/http.go
@@ -67,6 +67,7 @@ func Http(r chi.Router) {
 			r.Get("/", database.List)
 			r.Post("/", database.Create)
 			r.Delete("/", database.Delete)
+			r.Post("/comment", database.Comment)
 		})
 
 		r.Route("/databaseServer", func(r chi.Router) {
diff --git a/internal/service/base.go b/internal/service/base.go
index 7ab1cc6682..a9d220c3f3 100644
--- a/internal/service/base.go
+++ b/internal/service/base.go
@@ -39,6 +39,7 @@ func Success(w http.ResponseWriter, data any) {
 func Error(w http.ResponseWriter, code int, format string, args ...any) {
 	render := chix.NewRender(w)
 	defer render.Release()
+	render.Header(chix.HeaderContentType, chix.MIMEApplicationJSONCharsetUTF8) // must before Status()
 	render.Status(code)
 	render.JSON(&ErrorResponse{
 		Message: fmt.Sprintf(format, args...),
@@ -49,6 +50,7 @@ func Error(w http.ResponseWriter, code int, format string, args ...any) {
 func ErrorSystem(w http.ResponseWriter) {
 	render := chix.NewRender(w)
 	defer render.Release()
+	render.Header(chix.HeaderContentType, chix.MIMEApplicationJSONCharsetUTF8) // must before Status()
 	render.Status(http.StatusInternalServerError)
 	render.JSON(&ErrorResponse{
 		Message: "系统内部错误",
diff --git a/internal/service/database.go b/internal/service/database.go
index d12abfc22f..2c32c97805 100644
--- a/internal/service/database.go
+++ b/internal/service/database.go
@@ -68,3 +68,18 @@ func (s *Database) Delete(w http.ResponseWriter, r *http.Request) {
 
 	Success(w, nil)
 }
+
+func (s *Database) Comment(w http.ResponseWriter, r *http.Request) {
+	req, err := Bind[request.DatabaseComment](r)
+	if err != nil {
+		Error(w, http.StatusUnprocessableEntity, "%v", err)
+		return
+	}
+
+	if err = s.databaseRepo.Comment(req); err != nil {
+		Error(w, http.StatusInternalServerError, "%v", err)
+		return
+	}
+
+	Success(w, nil)
+}
diff --git a/pkg/db/postgres.go b/pkg/db/postgres.go
index 1ac1a1dcc7..e024809864 100644
--- a/pkg/db/postgres.go
+++ b/pkg/db/postgres.go
@@ -95,6 +95,11 @@ func (r *Postgres) DatabaseSize(name string) (int64, error) {
 	return size, nil
 }
 
+func (r *Postgres) DatabaseComment(name, comment string) error {
+	_, err := r.Exec(fmt.Sprintf("COMMENT ON DATABASE %s IS '%s'", name, comment))
+	return err
+}
+
 func (r *Postgres) UserCreate(user, password string) error {
 	_, err := r.Exec(fmt.Sprintf("CREATE USER %s WITH PASSWORD '%s'", user, password))
 	if err != nil {
@@ -221,7 +226,11 @@ func (r *Postgres) Users() ([]types.PostgresUser, error) {
 
 func (r *Postgres) Databases() ([]types.PostgresDatabase, error) {
 	query := `
-        SELECT d.datname, pg_catalog.pg_get_userbyid(d.datdba), pg_catalog.pg_encoding_to_char(d.encoding)
+        SELECT 
+            d.datname, 
+            pg_catalog.pg_get_userbyid(d.datdba), 
+            pg_catalog.pg_encoding_to_char(d.encoding),
+            COALESCE(pg_catalog.shobj_description(d.oid, 'pg_database'), '')
         FROM pg_catalog.pg_database d
         WHERE datistemplate = false;
     `
@@ -234,7 +243,7 @@ func (r *Postgres) Databases() ([]types.PostgresDatabase, error) {
 	var databases []types.PostgresDatabase
 	for rows.Next() {
 		var db types.PostgresDatabase
-		if err := rows.Scan(&db.Name, &db.Owner, &db.Encoding); err != nil {
+		if err := rows.Scan(&db.Name, &db.Owner, &db.Encoding, &db.Comment); err != nil {
 			return nil, err
 		}
 		if slices.Contains([]string{"template0", "template1", "postgres"}, db.Name) {
diff --git a/pkg/types/postgres.go b/pkg/types/postgres.go
index d22f5d1ca2..bbd0901f6a 100644
--- a/pkg/types/postgres.go
+++ b/pkg/types/postgres.go
@@ -9,4 +9,5 @@ type PostgresDatabase struct {
 	Name     string `json:"name"`
 	Owner    string `json:"owner"`
 	Encoding string `json:"encoding"`
+	Comment  string `json:"comment"`
 }
diff --git a/web/src/api/panel/database/index.ts b/web/src/api/panel/database/index.ts
index 67c856ee51..1c153be0c4 100644
--- a/web/src/api/panel/database/index.ts
+++ b/web/src/api/panel/database/index.ts
@@ -7,6 +7,9 @@ export default {
   create: (data: any) => http.Post(`/database`, data),
   // 删除数据库
   delete: (server_id: number, name: string) => http.Delete(`/database`, { server_id, name }),
+  // 更新评论
+  comment: (server_id: number, name: string, comment: string) =>
+    http.Post(`/database/comment`, { server_id, name, comment }),
   // 获取数据库服务器列表
   serverList: (page: number, limit: number) =>
     http.Get('/databaseServer', { params: { page, limit } }),
diff --git a/web/src/views/database/DatabaseList.vue b/web/src/views/database/DatabaseList.vue
index 0f385c9469..b683a1ef79 100644
--- a/web/src/views/database/DatabaseList.vue
+++ b/web/src/views/database/DatabaseList.vue
@@ -1,6 +1,6 @@
 <script setup lang="ts">
 import { renderIcon } from '@/utils'
-import { NButton, NPopconfirm, NTag } from 'naive-ui'
+import { NButton, NInput, NPopconfirm, NTag } from 'naive-ui'
 
 import database from '@/api/panel/database'
 
@@ -50,6 +50,23 @@ const columns: any = [
       })
     }
   },
+  {
+    title: '备注',
+    key: 'comment',
+    minWidth: 250,
+    resizable: true,
+    ellipsis: { tooltip: true },
+    render(row: any) {
+      return h(NInput, {
+        size: 'small',
+        value: row.comment,
+        onBlur: () => handleComment(row),
+        onUpdateValue(v) {
+          row.comment = v
+        }
+      })
+    }
+  },
   {
     title: '操作',
     key: 'actions',
@@ -104,6 +121,12 @@ const handleDelete = async (serverID: number, name: string) => {
   })
 }
 
+const handleComment = (row: any) => {
+  database.comment(row.server_id, row.name, row.comment).then(() => {
+    window.$message.success('修改成功')
+  })
+}
+
 onMounted(() => {
   window.$bus.on('database:refresh', () => {
     refresh()
@@ -119,7 +142,7 @@ onUnmounted(() => {
   <n-data-table
     striped
     remote
-    :scroll-x="800"
+    :scroll-x="1000"
     :loading="loading"
     :columns="columns"
     :data="data"
diff --git a/web/src/views/database/ServerList.vue b/web/src/views/database/ServerList.vue
index 123466f660..cfc1506440 100644
--- a/web/src/views/database/ServerList.vue
+++ b/web/src/views/database/ServerList.vue
@@ -215,7 +215,7 @@ onUnmounted(() => {
   <n-data-table
     striped
     remote
-    :scroll-x="1200"
+    :scroll-x="1500"
     :loading="loading"
     :columns="columns"
     :data="data"
diff --git a/web/src/views/database/UserList.vue b/web/src/views/database/UserList.vue
index 9f2e0eb7cb..f8a1dd4982 100644
--- a/web/src/views/database/UserList.vue
+++ b/web/src/views/database/UserList.vue
@@ -188,7 +188,7 @@ onUnmounted(() => {
   <n-data-table
     striped
     remote
-    :scroll-x="1400"
+    :scroll-x="1500"
     :loading="loading"
     :columns="columns"
     :data="data"