diff --git a/backend/app/repo/app_install.go b/backend/app/repo/app_install.go
index 5c6d44d28..e863eebd7 100644
--- a/backend/app/repo/app_install.go
+++ b/backend/app/repo/app_install.go
@@ -3,6 +3,7 @@ package repo
 import (
 	"context"
 	"encoding/json"
+	"gorm.io/gorm/clause"
 
 	"github.com/1Panel-dev/1Panel/backend/app/model"
 	"github.com/1Panel-dev/1Panel/backend/global"
@@ -107,11 +108,11 @@ func (a *AppInstallRepo) GetFirstByCtx(ctx context.Context, opts ...DBOption) (m
 
 func (a *AppInstallRepo) Create(ctx context.Context, install *model.AppInstall) error {
 	db := getTx(ctx).Model(&model.AppInstall{})
-	return db.Create(&install).Error
+	return db.Omit(clause.Associations).Create(&install).Error
 }
 
 func (a *AppInstallRepo) Save(ctx context.Context, install *model.AppInstall) error {
-	return getTx(ctx).Save(&install).Error
+	return getTx(ctx).Omit(clause.Associations).Save(&install).Error
 }
 
 func (a *AppInstallRepo) DeleteBy(opts ...DBOption) error {
diff --git a/backend/app/service/app.go b/backend/app/service/app.go
index 2b2facbdc..eb617b2f2 100644
--- a/backend/app/service/app.go
+++ b/backend/app/service/app.go
@@ -224,34 +224,42 @@ func (a AppService) GetAppDetailByID(id uint) (*response.AppDetailDTO, error) {
 	return res, nil
 }
 
-func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error) {
-	if err := docker.CreateDefaultDockerNetwork(); err != nil {
-		return nil, buserr.WithDetail(constant.Err1PanelNetworkFailed, err.Error(), nil)
+func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (appInstall *model.AppInstall, err error) {
+	if err = docker.CreateDefaultDockerNetwork(); err != nil {
+		err = buserr.WithDetail(constant.Err1PanelNetworkFailed, err.Error(), nil)
+		return
 	}
 	if list, _ := appInstallRepo.ListBy(commonRepo.WithByName(req.Name)); len(list) > 0 {
-		return nil, buserr.New(constant.ErrNameIsExist)
+		err = buserr.New(constant.ErrNameIsExist)
+		return
 	}
-	httpPort, err := checkPort("PANEL_APP_PORT_HTTP", req.Params)
+	var (
+		httpPort  int
+		httpsPort int
+		appDetail model.AppDetail
+		app       model.App
+	)
+	httpPort, err = checkPort("PANEL_APP_PORT_HTTP", req.Params)
+	if err != nil {
+		return
+	}
+	httpsPort, err = checkPort("PANEL_APP_PORT_HTTPS", req.Params)
+	if err != nil {
+		return
+	}
+	appDetail, err = appDetailRepo.GetFirst(commonRepo.WithByID(req.AppDetailId))
+	if err != nil {
+		return
+	}
+	app, err = appRepo.GetFirst(commonRepo.WithByID(appDetail.AppId))
 	if err != nil {
 		return nil, err
 	}
-	httpsPort, err := checkPort("PANEL_APP_PORT_HTTPS", req.Params)
-	if err != nil {
-		return nil, err
-	}
-	appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(req.AppDetailId))
-	if err != nil {
-		return nil, err
-	}
-	app, err := appRepo.GetFirst(commonRepo.WithByID(appDetail.AppId))
-	if err != nil {
-		return nil, err
-	}
-	if err := checkRequiredAndLimit(app); err != nil {
-		return nil, err
+	if err = checkRequiredAndLimit(app); err != nil {
+		return
 	}
 
-	appInstall := model.AppInstall{
+	appInstall = &model.AppInstall{
 		Name:        req.Name,
 		AppId:       appDetail.AppId,
 		AppDetailId: appDetail.ID,
@@ -262,13 +270,14 @@ func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (
 		App:         app,
 	}
 	composeMap := make(map[string]interface{})
-	if err := yaml.Unmarshal([]byte(appDetail.DockerCompose), &composeMap); err != nil {
-		return nil, err
+	if err = yaml.Unmarshal([]byte(appDetail.DockerCompose), &composeMap); err != nil {
+		return
 	}
 
 	value, ok := composeMap["services"]
 	if !ok {
-		return nil, buserr.New("")
+		err = buserr.New("")
+		return
 	}
 	servicesMap := value.(map[string]interface{})
 	changeKeys := make(map[string]string, len(servicesMap))
@@ -289,35 +298,50 @@ func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (
 		servicesMap[v] = servicesMap[k]
 		delete(servicesMap, k)
 	}
-	composeByte, err := yaml.Marshal(composeMap)
+
+	var (
+		composeByte []byte
+		paramByte   []byte
+	)
+
+	composeByte, err = yaml.Marshal(composeMap)
 	if err != nil {
-		return nil, err
+		return
 	}
 	appInstall.DockerCompose = string(composeByte)
 
-	if err := copyAppData(app.Key, appDetail.Version, req.Name, req.Params, app.Resource == constant.AppResourceLocal); err != nil {
-		return nil, err
+	defer func() {
+		if err != nil {
+			hErr := handleAppInstallErr(ctx, appInstall)
+			if hErr != nil {
+				global.LOG.Errorf("delete app dir error %s", hErr.Error())
+			}
+		}
+	}()
+
+	if err = copyAppData(app.Key, appDetail.Version, req.Name, req.Params, app.Resource == constant.AppResourceLocal); err != nil {
+		return
 	}
 	fileOp := files.NewFileOp()
-	if err := fileOp.WriteFile(appInstall.GetComposePath(), strings.NewReader(string(composeByte)), 0775); err != nil {
-		return nil, err
+	if err = fileOp.WriteFile(appInstall.GetComposePath(), strings.NewReader(string(composeByte)), 0775); err != nil {
+		return
 	}
-	paramByte, err := json.Marshal(req.Params)
+	paramByte, err = json.Marshal(req.Params)
 	if err != nil {
-		return nil, err
+		return
 	}
 	appInstall.Env = string(paramByte)
 
-	if err := appInstallRepo.Create(ctx, &appInstall); err != nil {
-		return nil, err
+	if err = appInstallRepo.Create(ctx, appInstall); err != nil {
+		return
 	}
-	if err := createLink(ctx, app, &appInstall, req.Params); err != nil {
-		return nil, err
+	if err = createLink(ctx, app, appInstall, req.Params); err != nil {
+		return
 	}
-	if err := upAppPre(app, appInstall); err != nil {
-		return nil, err
+	if err = upAppPre(app, appInstall); err != nil {
+		return
 	}
-	go upApp(ctx, appInstall)
+	go upApp(appInstall)
 	go updateToolApp(appInstall)
 	ports := []int{appInstall.HttpPort}
 	if appInstall.HttpsPort > 0 {
@@ -326,7 +350,7 @@ func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (
 	go func() {
 		_ = OperateFirewallPort(nil, ports)
 	}()
-	return &appInstall, nil
+	return
 }
 
 func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) {
diff --git a/backend/app/service/app_utils.go b/backend/app/service/app_utils.go
index 007f9421f..287613666 100644
--- a/backend/app/service/app_utils.go
+++ b/backend/app/service/app_utils.go
@@ -129,6 +129,22 @@ func createLink(ctx context.Context, app model.App, appInstall *model.AppInstall
 	return nil
 }
 
+func handleAppInstallErr(ctx context.Context, install *model.AppInstall) error {
+	op := files.NewFileOp()
+	appDir := install.GetPath()
+	dir, _ := os.Stat(appDir)
+	if dir != nil {
+		_, _ = compose.Down(install.GetComposePath())
+		if err := op.DeleteDir(appDir); err != nil {
+			return err
+		}
+	}
+	if err := deleteLink(ctx, install, true, true); err != nil {
+		return err
+	}
+	return nil
+}
+
 func deleteAppInstall(ctx context.Context, install model.AppInstall, deleteBackup bool, forceDelete bool, deleteDB bool) error {
 	op := files.NewFileOp()
 	appDir := install.GetPath()
@@ -381,7 +397,7 @@ func copyAppData(key, version, installName string, params map[string]interface{}
 }
 
 // 处理文件夹权限等问题
-func upAppPre(app model.App, appInstall model.AppInstall) error {
+func upAppPre(app model.App, appInstall *model.AppInstall) error {
 	if app.Key == "nexus" {
 		dataPath := path.Join(appInstall.GetPath(), "data")
 		if err := files.NewFileOp().Chown(dataPath, 200, 0); err != nil {
@@ -391,7 +407,7 @@ func upAppPre(app model.App, appInstall model.AppInstall) error {
 	return nil
 }
 
-func getServiceFromInstall(appInstall model.AppInstall) (service *composeV2.ComposeService, err error) {
+func getServiceFromInstall(appInstall *model.AppInstall) (service *composeV2.ComposeService, err error) {
 	var (
 		project *types.Project
 		envStr  string
@@ -412,8 +428,8 @@ func getServiceFromInstall(appInstall model.AppInstall) (service *composeV2.Comp
 	return
 }
 
-func upApp(ctx context.Context, appInstall model.AppInstall) {
-	upProject := func(appInstall model.AppInstall) (err error) {
+func upApp(appInstall *model.AppInstall) {
+	upProject := func(appInstall *model.AppInstall) (err error) {
 		if err == nil {
 			var composeService *composeV2.ComposeService
 			composeService, err = getServiceFromInstall(appInstall)
@@ -437,9 +453,7 @@ func upApp(ctx context.Context, appInstall model.AppInstall) {
 	}
 	exist, _ := appInstallRepo.GetFirst(commonRepo.WithByID(appInstall.ID))
 	if exist.ID > 0 {
-		_ = appInstallRepo.Save(context.Background(), &appInstall)
-	} else {
-		_ = appInstallRepo.Save(ctx, &appInstall)
+		_ = appInstallRepo.Save(context.Background(), appInstall)
 	}
 }
 
@@ -598,7 +612,7 @@ func getAppInstallByKey(key string) (model.AppInstall, error) {
 	return appInstall, nil
 }
 
-func updateToolApp(installed model.AppInstall) {
+func updateToolApp(installed *model.AppInstall) {
 	tooKey, ok := dto.AppToolMap[installed.App.Key]
 	if !ok {
 		return
diff --git a/backend/app/service/database_mysql.go b/backend/app/service/database_mysql.go
index bf3c500bc..5984628b3 100644
--- a/backend/app/service/database_mysql.go
+++ b/backend/app/service/database_mysql.go
@@ -93,15 +93,15 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode
 	}
 
 	createSql := fmt.Sprintf("create database `%s` default character set %s collate %s", req.Name, req.Format, formatMap[req.Format])
-	if err := excuteSql(app.ContainerName, app.Password, createSql); err != nil {
+	if err := excSQL(app.ContainerName, app.Password, createSql); err != nil {
 		if strings.Contains(err.Error(), "ERROR 1007") {
 			return nil, buserr.New(constant.ErrDatabaseIsExist)
 		}
 		return nil, err
 	}
 	tmpPermission := req.Permission
-	if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("create user '%s'@'%s' identified by '%s';", req.Username, tmpPermission, req.Password)); err != nil {
-		_ = excuteSql(app.ContainerName, app.Password, fmt.Sprintf("drop database `%s`", req.Name))
+	if err := excSQL(app.ContainerName, app.Password, fmt.Sprintf("create user '%s'@'%s' identified by '%s';", req.Username, tmpPermission, req.Password)); err != nil {
+		_ = excSQL(app.ContainerName, app.Password, fmt.Sprintf("drop database `%s`", req.Name))
 		if strings.Contains(err.Error(), "ERROR 1396") {
 			return nil, buserr.New(constant.ErrUserIsExist)
 		}
@@ -114,7 +114,7 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode
 	if app.Version == "5.7.39" {
 		grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, req.Password)
 	}
-	if err := excuteSql(app.ContainerName, app.Password, grantStr); err != nil {
+	if err := excSQL(app.ContainerName, app.Password, grantStr); err != nil {
 		return nil, err
 	}
 
@@ -163,10 +163,10 @@ func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error
 		return err
 	}
 
-	if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("drop user if exists '%s'@'%s'", db.Username, db.Permission)); err != nil && !req.ForceDelete {
+	if err := excSQL(app.ContainerName, app.Password, fmt.Sprintf("drop user if exists '%s'@'%s'", db.Username, db.Permission)); err != nil && !req.ForceDelete {
 		return err
 	}
-	if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("drop database if exists `%s`", db.Name)); err != nil && !req.ForceDelete {
+	if err := excSQL(app.ContainerName, app.Password, fmt.Sprintf("drop database if exists `%s`", db.Name)); err != nil && !req.ForceDelete {
 		return err
 	}
 	global.LOG.Info("execute delete database sql successful, now start to drop uploads and records")
@@ -514,6 +514,21 @@ func excuteSql(containerName, password, command string) error {
 	return nil
 }
 
+func excSQL(containerName, password, command string) error {
+	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
+	defer cancel()
+	cmd := exec.CommandContext(ctx, "docker", "exec", containerName, "mysql", "-uroot", "-p"+password, "-e", command)
+	err := cmd.Run()
+	if ctx.Err() == context.DeadlineExceeded {
+		return buserr.WithDetail(constant.ErrExecTimeOut, containerName, nil)
+	}
+	if err != nil {
+		stdStr := strings.ReplaceAll(err.Error(), "mysql: [Warning] Using a password on the command line interface can be insecure.\n", "")
+		return errors.New(stdStr)
+	}
+	return nil
+}
+
 func updateMyCnf(oldFiles []string, group string, param string, value interface{}) []string {
 	isOn := false
 	hasGroup := false
diff --git a/backend/app/service/website.go b/backend/app/service/website.go
index c63452677..da93acf1a 100644
--- a/backend/app/service/website.go
+++ b/backend/app/service/website.go
@@ -168,18 +168,25 @@ func (w WebsiteService) CreateWebsite(ctx context.Context, create request.Websit
 	switch create.Type {
 	case constant.Deployment:
 		if create.AppType == constant.NewApp {
-			var req request.AppInstallCreate
+			var (
+				req     request.AppInstallCreate
+				install *model.AppInstall
+			)
 			req.Name = create.AppInstall.Name
 			req.AppDetailId = create.AppInstall.AppDetailId
 			req.Params = create.AppInstall.Params
-			install, err := NewIAppService().Install(ctx, req)
+			tx, installCtx := getTxAndContext()
+			install, err = NewIAppService().Install(installCtx, req)
 			if err != nil {
+				tx.Rollback()
 				return err
 			}
+			tx.Commit()
 			website.AppInstallID = install.ID
 			appInstall = install
 		} else {
-			install, err := appInstallRepo.GetFirst(commonRepo.WithByID(create.AppInstallID))
+			var install model.AppInstall
+			install, err = appInstallRepo.GetFirst(commonRepo.WithByID(create.AppInstallID))
 			if err != nil {
 				return err
 			}
@@ -187,28 +194,34 @@ func (w WebsiteService) CreateWebsite(ctx context.Context, create request.Websit
 			website.AppInstallID = appInstall.ID
 		}
 	case constant.Runtime:
-		var err error
 		runtime, err = runtimeRepo.GetFirst(commonRepo.WithByID(create.RuntimeID))
 		if err != nil {
 			return err
 		}
 		website.RuntimeID = runtime.ID
 		if runtime.Resource == constant.ResourceAppstore {
-			var req request.AppInstallCreate
+			var (
+				req          request.AppInstallCreate
+				nginxInstall model.AppInstall
+				install      *model.AppInstall
+			)
 			reg, _ := regexp.Compile(`[^a-z0-9_-]+`)
 			req.Name = reg.ReplaceAllString(strings.ToLower(create.PrimaryDomain), "")
 			req.AppDetailId = create.AppInstall.AppDetailId
 			req.Params = create.AppInstall.Params
 			req.Params["IMAGE_NAME"] = runtime.Image
-			nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
+			nginxInstall, err = getAppInstallByKey(constant.AppOpenresty)
 			if err != nil {
 				return err
 			}
 			req.Params["PANEL_WEBSITE_DIR"] = path.Join(nginxInstall.GetPath(), "/www")
-			install, err := NewIAppService().Install(ctx, req)
+			tx, installCtx := getTxAndContext()
+			install, err = NewIAppService().Install(installCtx, req)
 			if err != nil {
+				tx.Rollback()
 				return err
 			}
+			tx.Commit()
 			website.AppInstallID = install.ID
 			appInstall = install
 		}
diff --git a/backend/app/service/website_utils.go b/backend/app/service/website_utils.go
index e37cebcdd..3fdb4e00b 100644
--- a/backend/app/service/website_utils.go
+++ b/backend/app/service/website_utils.go
@@ -105,7 +105,7 @@ func createWebsiteFolder(nginxInstall model.AppInstall, website *model.Website,
 		if err := fileOp.CreateDir(path.Join(siteFolder, "ssl"), 0755); err != nil {
 			return err
 		}
-		if runtime.Type == constant.RuntimePHP && runtime.Resource == constant.ResourceLocal {
+		if website.Type == constant.Runtime && runtime.Type == constant.RuntimePHP && runtime.Resource == constant.ResourceLocal {
 			phpPoolDir := path.Join(siteFolder, "php-pool")
 			if err := fileOp.CreateDir(phpPoolDir, 0755); err != nil {
 				return err
diff --git a/backend/constant/errs.go b/backend/constant/errs.go
index dc8670b30..8ec738afc 100644
--- a/backend/constant/errs.go
+++ b/backend/constant/errs.go
@@ -91,6 +91,7 @@ var (
 var (
 	ErrUserIsExist     = "ErrUserIsExist"
 	ErrDatabaseIsExist = "ErrDatabaseIsExist"
+	ErrExecTimeOut     = "ErrExecTimeOut"
 )
 
 // redis
diff --git a/backend/i18n/lang/en.yaml b/backend/i18n/lang/en.yaml
index 0c93a9b12..6db5d9728 100644
--- a/backend/i18n/lang/en.yaml
+++ b/backend/i18n/lang/en.yaml
@@ -52,6 +52,7 @@ ErrEmailIsExist: 'Email is already exist'
 #mysql
 ErrUserIsExist: "The current user already exists. Please enter a new user"
 ErrDatabaseIsExist: "The current database already exists. Please enter a new database"
+ErrExecTimeOut: "SQL execution timed out, please check the {{ .detail }} container"
 
 #redis
 ErrTypeOfRedis: "The recovery file type does not match the current persistence mode. Modify the file type and try again"
diff --git a/backend/i18n/lang/zh.yaml b/backend/i18n/lang/zh.yaml
index 85f49cb76..108b46871 100644
--- a/backend/i18n/lang/zh.yaml
+++ b/backend/i18n/lang/zh.yaml
@@ -52,6 +52,7 @@ ErrEmailIsExist: '邮箱已存在'
 #mysql
 ErrUserIsExist: "当前用户已存在,请重新输入"
 ErrDatabaseIsExist: "当前数据库已存在,请重新输入"
+ErrExecTimeOut: "SQL 执行超时,请检查{{ .detail }}容器"
 
 #redis
 ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后重试"
diff --git a/frontend/src/views/website/website/delete/index.vue b/frontend/src/views/website/website/delete/index.vue
index 79c86cda7..a4fda5d2c 100644
--- a/frontend/src/views/website/website/delete/index.vue
+++ b/frontend/src/views/website/website/delete/index.vue
@@ -23,7 +23,7 @@
                     <span class="input-help">
                         {{ $t('website.deleteAppHelper') }}
                     </span>
-                    <span class="input-help" style="color: red">
+                    <span class="input-help" style="color: red" v-if="runtimeApp">
                         {{ $t('website.deleteRuntimeHelper') }}
                     </span>
                 </el-form-item>