From 07576841113fa5d86d0a52d0bfa25378afe6249d Mon Sep 17 00:00:00 2001 From: ssongliu Date: Tue, 25 Oct 2022 11:41:19 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=20mysql=20=E6=80=A7?= =?UTF-8?q?=E8=83=BD=E4=BC=98=E5=8C=96=E5=8A=9F=E8=83=BD=E5=8F=8A=E5=9B=BD?= =?UTF-8?q?=E9=99=85=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/v1/databse_mysql.go | 17 + backend/app/dto/database.go | 19 ++ backend/app/service/database_mysql.go | 55 ++++ backend/app/service/database_test.go | 46 ++- backend/router/ro_database.go | 1 + frontend/src/api/interface/database.ts | 1 + frontend/src/api/modules/database.ts | 3 + frontend/src/lang/modules/zh.ts | 46 +++ .../views/database/mysql/setting/helper.ts | 103 ++++++ .../views/database/mysql/setting/index.vue | 300 ++++++++++++------ 10 files changed, 489 insertions(+), 102 deletions(-) create mode 100644 frontend/src/views/database/mysql/setting/helper.ts diff --git a/backend/app/api/v1/databse_mysql.go b/backend/app/api/v1/databse_mysql.go index 088812db7..2771ed7c5 100644 --- a/backend/app/api/v1/databse_mysql.go +++ b/backend/app/api/v1/databse_mysql.go @@ -42,6 +42,23 @@ func (b *BaseApi) UpdateMysql(c *gin.Context) { helper.SuccessWithData(c, nil) } +func (b *BaseApi) UpdateMysqlVariables(c *gin.Context) { + var req dto.MysqlVariablesUpdate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := mysqlService.UpdateVariables(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} + func (b *BaseApi) SearchMysql(c *gin.Context) { var req dto.SearchWithPage if err := c.ShouldBindJSON(&req); err != nil { diff --git a/backend/app/dto/database.go b/backend/app/dto/database.go index 26abc1abf..5a84e0a7b 100644 --- a/backend/app/dto/database.go +++ b/backend/app/dto/database.go @@ -80,6 +80,25 @@ type MysqlVariables struct { Tmp_tableSize string `json:"tmp_table_size"` } +type MysqlVariablesUpdate struct { + Version string `json:"version" validate:"required"` + KeyBufferSize int64 `json:"key_buffer_size" validate:"required"` + QueryCacheSize int64 `json:"query_cache_size" validate:"required"` + TmpTableSize int64 `json:"tmp_table_size" validate:"required"` + InnodbBufferPoolSize int64 `json:"innodb_buffer_pool_size" validate:"required"` + InnodbLogBufferSize int64 `json:"innodb_log_buffer_size" validate:"required"` + SortBufferSize int64 `json:"sort_buffer_size" validate:"required"` + ReadBufferSize int64 `json:"read_buffer_size" validate:"required"` + + ReadRndBufferSize int64 `json:"read_rnd_buffer_size" validate:"required"` + JoinBufferSize int64 `json:"join_buffer_size" validate:"required"` + ThreadStack int64 `json:"thread_stack" validate:"required"` + BinlogCachSize int64 `json:"binlog_cache_size" validate:"required"` + ThreadCacheSize int64 `json:"thread_cache_size" validate:"required"` + TableOpenCache int64 `json:"table_open_cache" validate:"required"` + MaxConnections int64 `json:"max_connections" validate:"required"` +} + type ChangeDBInfo struct { ID uint `json:"id" validate:"required"` Operation string `json:"operation" validate:"required,oneof=password privilege"` diff --git a/backend/app/service/database_mysql.go b/backend/app/service/database_mysql.go index 6bb514a54..649df8742 100644 --- a/backend/app/service/database_mysql.go +++ b/backend/app/service/database_mysql.go @@ -20,6 +20,7 @@ type IMysqlService interface { SearchWithPage(search dto.SearchWithPage) (int64, interface{}, error) Create(mysqlDto dto.MysqlDBCreate) error ChangeInfo(info dto.ChangeDBInfo) error + UpdateVariables(variables dto.MysqlVariablesUpdate) error Delete(ids []uint) error LoadStatus(version string) (*dto.MysqlStatus, error) LoadVariables(version string) (*dto.MysqlVariables, error) @@ -164,6 +165,60 @@ func (u *MysqlService) ChangeInfo(info dto.ChangeDBInfo) error { return nil } +func (u *MysqlService) UpdateVariables(variables dto.MysqlVariablesUpdate) error { + db, err := newDatabaseClient() + if err != nil { + return err + } + defer db.Close() + + if _, err := db.Exec(fmt.Sprintf("SET GLOBAL key_buffer_size=%d", variables.KeyBufferSize)); err != nil { + return err + } + if _, err := db.Exec(fmt.Sprintf("SET GLOBAL query_cache_size=%d", variables.QueryCacheSize)); err != nil { + return err + } + if _, err := db.Exec(fmt.Sprintf("SET GLOBAL tmp_table_size=%d", variables.TmpTableSize)); err != nil { + return err + } + if _, err := db.Exec(fmt.Sprintf("SET GLOBAL innodb_buffer_pool_size=%d", variables.InnodbBufferPoolSize)); err != nil { + return err + } + // if _, err := db.Exec(fmt.Sprintf("SET GLOBAL innodb_log_buffer_size=%d", variables.InnodbLogBufferSize)); err != nil { + // return err + // } + if _, err := db.Exec(fmt.Sprintf("SET GLOBAL sort_buffer_size=%d", variables.SortBufferSize)); err != nil { + return err + } + if _, err := db.Exec(fmt.Sprintf("SET GLOBAL read_buffer_size=%d", variables.ReadBufferSize)); err != nil { + return err + } + + if _, err := db.Exec(fmt.Sprintf("SET GLOBAL read_rnd_buffer_size=%d", variables.ReadRndBufferSize)); err != nil { + return err + } + if _, err := db.Exec(fmt.Sprintf("SET GLOBAL join_buffer_size=%d", variables.JoinBufferSize)); err != nil { + return err + } + // if _, err := db.Exec(fmt.Sprintf("SET GLOBAL thread_stack=%d", variables.ThreadStack)); err != nil { + // return err + // } + if _, err := db.Exec(fmt.Sprintf("SET GLOBAL binlog_cache_size=%d", variables.BinlogCachSize)); err != nil { + return err + } + if _, err := db.Exec(fmt.Sprintf("SET GLOBAL thread_cache_size=%d", variables.ThreadCacheSize)); err != nil { + return err + } + if _, err := db.Exec(fmt.Sprintf("SET GLOBAL table_open_cache=%d", variables.TableOpenCache)); err != nil { + return err + } + if _, err := db.Exec(fmt.Sprintf("SET GLOBAL max_connections=%d", variables.MaxConnections)); err != nil { + return err + } + + return nil +} + func (u *MysqlService) LoadVariables(version string) (*dto.MysqlVariables, error) { db, err := newDatabaseClient() if err != nil { diff --git a/backend/app/service/database_test.go b/backend/app/service/database_test.go index 2637b2d63..223b04946 100644 --- a/backend/app/service/database_test.go +++ b/backend/app/service/database_test.go @@ -3,8 +3,10 @@ package service import ( "database/sql" "fmt" + "reflect" "testing" + "github.com/1Panel-dev/1Panel/backend/app/dto" _ "github.com/go-sql-driver/mysql" ) @@ -16,18 +18,54 @@ func TestMysql(t *testing.T) { } defer db.Close() - rows, err := db.Query("show master status") + rows, err := db.Query("show variables") if err != nil { fmt.Println(err) } + variableMap := make(map[string]int) - masterRows := make([]string, 5) for rows.Next() { - if err := rows.Scan(&masterRows[0], &masterRows[1], &masterRows[2], &masterRows[3], &masterRows[4]); err != nil { + var variableName string + var variableValue int + if err := rows.Scan(&variableName, &variableValue); err != nil { fmt.Println(err) } + variableMap[variableName] = variableValue } - for k, v := range masterRows { + for k, v := range variableMap { fmt.Println(k, v) } } + +func TestMs(t *testing.T) { + db, err := newDatabaseClient() + if err != nil { + fmt.Println(err) + } + defer db.Close() + + variables := dto.MysqlVariablesUpdate{ + Version: "5.7.39", + KeyBufferSize: 8388608, + QueryCacheSize: 1048576, + TmpTableSize: 16777216, + InnodbBufferPoolSize: 134217728, + InnodbLogBufferSize: 16777216, + SortBufferSize: 262144, + ReadBufferSize: 131072, + + ReadRndBufferSize: 262144, + JoinBufferSize: 262144, + ThreadStack: 262144, + BinlogCachSize: 32768, + ThreadCacheSize: 9, + TableOpenCache: 2000, + MaxConnections: 150, + } + + v := reflect.ValueOf(variables) + typeOfS := v.Type() + for i := 0; i < v.NumField(); i++ { + fmt.Printf("SET GLOBAL %s=%d \n", typeOfS.Field(i).Name, v.Field(i).Interface()) + } +} diff --git a/backend/router/ro_database.go b/backend/router/ro_database.go index ba728206c..60e176d1b 100644 --- a/backend/router/ro_database.go +++ b/backend/router/ro_database.go @@ -24,6 +24,7 @@ func (s *DatabaseRouter) InitDatabaseRouter(Router *gin.RouterGroup) { withRecordRouter.POST("", baseApi.CreateMysql) withRecordRouter.PUT("/:id", baseApi.UpdateMysql) withRecordRouter.POST("/del", baseApi.DeleteMysql) + withRecordRouter.POST("/variables/update", baseApi.UpdateMysqlVariables) cmdRouter.POST("/search", baseApi.SearchMysql) cmdRouter.GET("/conf", baseApi.LoadConf) cmdRouter.GET("/status", baseApi.LoadStatus) diff --git a/frontend/src/api/interface/database.ts b/frontend/src/api/interface/database.ts index 8deed946e..cbea672a1 100644 --- a/frontend/src/api/interface/database.ts +++ b/frontend/src/api/interface/database.ts @@ -19,6 +19,7 @@ export namespace Database { description: string; } export interface MysqlVariables { + version: string; binlog_cache_size: number; innodb_buffer_pool_size: number; innodb_log_buffer_size: number; diff --git a/frontend/src/api/modules/database.ts b/frontend/src/api/modules/database.ts index 499d505c3..9c0693f90 100644 --- a/frontend/src/api/modules/database.ts +++ b/frontend/src/api/modules/database.ts @@ -12,6 +12,9 @@ export const addMysqlDB = (params: Database.MysqlDBCreate) => { export const updateMysqlDBInfo = (params: Database.ChangeInfo) => { return http.put(`/databases/${params.id}`, params); }; +export const updateMysqlVariables = (params: Database.MysqlVariables) => { + return http.post(`/databases/variables/update`, params); +}; export const deleteMysqlDB = (params: { ids: number[] }) => { return http.post(`/databases/del`, params); }; diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 8cd0c3682..f9522344d 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -165,8 +165,54 @@ export default { baseSetting: '基础设置', confChange: '配置修改', + currentStatus: '当前状态', runTime: '启动时间', + connections: '总连接数', + bytesSent: '发送', + bytesReceived: '接收', + queryPerSecond: '每秒查询', + txPerSecond: '每秒事务', + connInfo: '活动/峰值连接数', + connInfoHelper: '若值过大,增加 max_connections', + threadCacheHit: '线程缓存命中率', + threadCacheHitHelper: '若过低,增加 thread_cache_size', + indexHit: '索引命中率', + indexHitHelper: '若过低,增加 key_buffer_size', + innodbIndexHit: 'Innodb 索引命中率', + innodbIndexHitHelper: '若过低,增加 innodb_buffer_pool_size', + cacheHit: '查询缓存命中率', + cacheHitHelper: '若过低,增加 query_cache_size', + tmpTableToDB: '创建临时表到磁盘', + tmpTableToDBHelper: '若过大,尝试增加 tmp_table_size', + openTables: '已打开的表', + openTablesHelper: 'table_open_cache 配置值应大于等于此值', + selectFullJoin: '没有使用索引的量', + selectFullJoinHelper: '若不为0,请检查数据表的索引是否合理', + selectRangeCheck: '没有索引的 JOIN 量', + selectRangeCheckHelper: '若不为0,请检查数据表的索引是否合理', + sortMergePasses: '排序后的合并次数', + sortMergePassesHelper: '若值过大,增加sort_buffer_size', + tableLocksWaited: '锁表次数', + tableLocksWaitedHelper: '若值过大,请考虑增加您的数据库性能', + + performanceTuning: '性能调整', + optimizationScheme: '优化方案', + keyBufferSizeHelper: '用于索引的缓冲区大小', + queryCacheSizeHelper: '查询缓存,不开启请设为0', + tmpTableSizeHelper: '临时表缓存大小', + innodbBufferPoolSizeHelper: 'Innodb 缓冲区大小', + innodbLogBufferSizeHelper: 'Innodb 日志缓冲区大小', + sortBufferSizeHelper: '* 连接数, 每个线程排序的缓冲大小', + readBufferSizeHelper: '* 连接数, 读入缓冲区大小', + readRndBufferSizeHelper: '* 连接数, 随机读取缓冲区大小', + joinBufferSizeHelper: '* 连接数, 关联表缓存大小', + threadStackelper: '* 连接数, 每个线程的堆栈大小', + binlogCacheSizeHelper: '* 连接数, 二进制日志缓存大小(4096的倍数)', + threadCacheSizeHelper: '线程池大小', + tableOpenCacheHelper: '表缓存', + maxConnectionsHelper: '最大连接数', + restart: '重启数据库', }, container: { operatorHelper: '将对选中容器进行 {0} 操作,是否继续?', diff --git a/frontend/src/views/database/mysql/setting/helper.ts b/frontend/src/views/database/mysql/setting/helper.ts new file mode 100644 index 000000000..b2bf59ed9 --- /dev/null +++ b/frontend/src/views/database/mysql/setting/helper.ts @@ -0,0 +1,103 @@ +export const planOptions = [ + { + id: 1, + title: '1-2GB', + data: { + version: '', + key_buffer_size: 128, + query_cache_size: 64, + tmp_table_size: 64, + innodb_buffer_pool_size: 256, + sort_buffer_size: 768, + read_buffer_size: 768, + read_rnd_buffer_size: 512, + join_buffer_size: 1024, + thread_stack: 256, + binlog_cache_size: 64, + thread_cache_size: 64, + table_open_cache: 128, + max_connections: 100, + }, + }, + { + id: 2, + title: '2-4GB', + data: { + version: '', + key_buffer_size: 256, + query_cache_size: 128, + tmp_table_size: 384, + innodb_buffer_pool_size: 384, + sort_buffer_size: 768, + read_buffer_size: 768, + read_rnd_buffer_size: 512, + join_buffer_size: 2048, + thread_stack: 256, + binlog_cache_size: 64, + thread_cache_size: 96, + table_open_cache: 192, + max_connections: 200, + }, + }, + { + id: 3, + title: '4-8GB', + data: { + version: '', + key_buffer_size: 384, + query_cache_size: 192, + tmp_table_size: 512, + innodb_buffer_pool_size: 512, + sort_buffer_size: 1024, + read_buffer_size: 1024, + read_rnd_buffer_size: 768, + join_buffer_size: 2048, + thread_stack: 256, + binlog_cache_size: 128, + thread_cache_size: 128, + table_open_cache: 384, + max_connections: 300, + }, + }, + { + id: 4, + title: '8-16GB', + data: { + version: '', + key_buffer_size: 512, + query_cache_size: 256, + tmp_table_size: 1024, + innodb_buffer_pool_size: 1024, + sort_buffer_size: 2048, + read_buffer_size: 2048, + read_rnd_buffer_size: 1024, + join_buffer_size: 4096, + thread_stack: 384, + binlog_cache_size: 192, + thread_cache_size: 192, + table_open_cache: 1024, + max_connections: 400, + }, + }, + { + id: 5, + title: '16-32GB', + data: { + version: '', + key_buffer_size: 1024, + query_cache_size: 384, + tmp_table_size: 2048, + innodb_buffer_pool_size: 4096, + innodb_log_buffer_size: 32, + sort_buffer_size: 4096, + read_buffer_size: 4096, + read_rnd_buffer_size: 2048, + join_buffer_size: 8192, + thread_stack: 512, + binlog_cache_size: 256, + thread_cache_size: 256, + table_open_cache: 2048, + max_connections: 500, + }, + }, +]; diff --git a/frontend/src/views/database/mysql/setting/index.vue b/frontend/src/views/database/mysql/setting/index.vue index dd293af85..d7c945bc2 100644 --- a/frontend/src/views/database/mysql/setting/index.vue +++ b/frontend/src/views/database/mysql/setting/index.vue @@ -2,7 +2,7 @@
- +
@@ -47,7 +47,7 @@
- + - +
- + - + - + - +
启动时间{{ $t('database.runTime') }} {{ mysqlStatus.run }}
总连接次数{{ $t('database.connections') }} {{ mysqlStatus.connections }}
发送{{ $t('database.bytesSent') }} {{ mysqlStatus!.bytesSent }}
接收{{ $t('database.bytesReceived') }} {{ mysqlStatus!.bytesReceived }}
@@ -96,11 +96,11 @@ - + - + @@ -119,157 +119,184 @@
每秒查询{{ $t('database.queryPerSecond') }} {{ mysqlStatus!.queryPerSecond }}
每秒事务{{ $t('database.queryPerSecond') }} {{ mysqlStatus!.txPerSecond }}
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
活动/峰值连接数{{ $t('database.queryPerSecond') }} {{ mysqlStatus!.connInfo }}若值过大,增加max_connections{{ $t('database.connInfoHelper') }}
线程缓存命中率{{ $t('database.threadCacheHit') }} {{ mysqlStatus!.threadCacheHit }}若过低,增加thread_cache_size{{ $t('database.threadCacheHitHelper') }}
索引命中率{{ $t('database.indexHit') }} {{ mysqlStatus!.indexHit }}若过低,增加key_buffer_size{{ $t('database.indexHitHelper') }}
Innodb 索引命中率{{ $t('database.innodbIndexHit') }} {{ mysqlStatus!.innodbIndexHit }}若过低,增加innodb_buffer_pool_size{{ $t('database.innodbIndexHitHelper') }}
查询缓存命中率{{ $t('database.cacheHit') }} {{ mysqlStatus!.cacheHit }}若过低,增加query_cache_size{{ $t('database.cacheHitHelper') }}
创建临时表到磁盘{{ $t('database.tmpTableToDB') }} {{ mysqlStatus!.tmpTableToDB }}若过大,尝试增加tmp_table_size{{ $t('database.tmpTableToDBHelper') }}
已打开的表{{ $t('database.openTables') }} {{ mysqlStatus!.openTables }}table_open_cache配置值应大于等于此值{{ $t('database.openTablesHelper') }}
没有使用索引的量{{ $t('database.selectFullJoin') }} {{ mysqlStatus!.selectFullJoin }}若不为0,请检查数据表的索引是否合理{{ $t('database.selectFullJoinHelper') }}
没有索引的JOIN量{{ $t('database.selectRangeCheck') }} {{ mysqlStatus!.selectRangeCheck }}若不为0,请检查数据表的索引是否合理{{ $t('database.selectRangeCheckHelper') }}
排序后的合并次数{{ $t('database.sortMergePasses') }} {{ mysqlStatus!.sortMergePasses }}若值过大,增加sort_buffer_size{{ $t('database.sortMergePassesHelper') }}
锁表次数{{ $t('database.tableLocksWaited') }} {{ mysqlStatus!.tableLocksWaited }}若值过大,请考虑增加您的数据库性能{{ $t('database.tableLocksWaitedHelper') }}
- + - +
- - - + + + + + + + +
+ +
+ + + - 用于索引的缓冲区大小 + {{ $t('database.keyBufferSizeHelper') }} - - + + - 查询缓存,不开启请设为0 + {{ $t('database.queryCacheSizeHelper') }} - - + + - 临时表缓存大小 + {{ $t('database.tmpTableSizeHelper') }} - - + + - Innodb缓冲区大小 + {{ $t('database.innodbBufferPoolSizeHelper') }} - - + + - Innodb日志缓冲区大小 + {{ $t('database.innodbLogBufferSizeHelper') }} - - + + - * 连接数, 每个线程排序的缓冲大小 + {{ $t('database.sortBufferSizeHelper') }} - - + + - * 连接数, 读入缓冲区大小 + {{ $t('database.readBufferSizeHelper') }} - + {{ $t('commons.button.save') }} - 重启数据库 + + {{ $t('database.restart') }} +
- - - + + + - * 连接数, 随机读取缓冲区大小 + {{ $t('database.readRndBufferSizeHelper') }} - - + + - * 连接数, 关联表缓存大小 + {{ $t('database.joinBufferSizeHelper') }} - - + + - * 连接数, 每个线程的堆栈大小 + {{ $t('database.threadStackelper') }} - - + + - * 连接数, 二进制日志缓存大小(4096的倍数) + {{ $t('database.binlogCacheSizeHelper') }} - - - 线程池大小 + + + {{ $t('database.threadCacheSizeHelper') }} - - - 表缓存 + + + {{ $t('database.tableOpenCacheHelper') }} - - - 最大连接数 + + + {{ $t('database.maxConnectionsHelper') }}
@@ -283,15 +310,17 @@