diff --git a/.gitignore b/.gitignore index 8c1067a..95c3b77 100644 --- a/.gitignore +++ b/.gitignore @@ -355,7 +355,6 @@ flycheck_*.el .idea/**/usage.statistics.xml .idea/**/dictionaries .idea/**/shelf -.idea # Generated files .idea/**/contentModel.xml diff --git a/CHANGELOG/README.md b/CHANGELOG/README.md index 381407e..cb5d388 100644 --- a/CHANGELOG/README.md +++ b/CHANGELOG/README.md @@ -1,5 +1,30 @@ # Changelog +## 2022-11-17 + +Release v1.3.0 + ++ Enhancement & New Features + + Support backup and restore. + + Support multiple architecture: linux/amd64, linux/arm64. + + Support log(audit, error) collection. + + Support read only cluster. + + Support parameter template and configuration. + + Support XStore node rebuild. + + Support splitting dn data and log into different directories. + + Support archiving cold data into OSS and NFS. ++ Bug Fix + + Fix `mycnfOverwrite` not working issue. + + Fix issue of cn topology rules not working in host network mode. + + Fix XStore node not ready when ip changed in container network mode. + + Fix logstash oom + + Fix rebuild job does continue, when the instance is upgrading + + Fix failing to create readonly pxc when dnReplicas is less than 2 + + Fix xstore topology of restored instance not in sync with original instance + + Fix binlog purge lock not working during backup + + Fix change leader command issue for xsl. + + Fix backup progress hang in binlogbackuping phase. + ## 2022-10-26 Release v1.3.0-alpha.1 diff --git a/api/v1/polardbx/restore.go b/api/v1/polardbx/restore.go index 7d51fe1..85640f4 100644 --- a/api/v1/polardbx/restore.go +++ b/api/v1/polardbx/restore.go @@ -17,8 +17,9 @@ limitations under the License. package polardbx type RestoreSpec struct { - //BackupSet defines the source of backup set + // BackupSet defines the source of backup set BackupSet string `json:"backupset,omitempty"` + // From defines the source information, either backup sets, snapshot or an running cluster. From PolarDBXRestoreFrom `json:"from,omitempty"` @@ -28,6 +29,14 @@ type RestoreSpec struct { // TimeZone defines the specified time zone of the restore time. Default is the location of current cluster. // +optional TimeZone string `json:"timezone,omitempty"` + + // +kubebuilder:default=false + + // SyncSpecWithOriginalCluster identifies whether restored cluster should use the same spec as the original cluster. + // If the field is set to true, spec of original cluster is used; otherwise users have to declare spec manually or + // use default spec, but replicas of dn will be forced to sync with original cluster now. Default is false + // +optional + SyncSpecWithOriginalCluster bool `json:"syncSpecWithOriginalCluster,omitempty"` } // PolarDBXRestoreFrom defines the source information of the restored cluster. diff --git a/api/v1/polardbx/status.go b/api/v1/polardbx/status.go index 21d7d8d..e28c3a1 100644 --- a/api/v1/polardbx/status.go +++ b/api/v1/polardbx/status.go @@ -168,6 +168,6 @@ type ParameterPhase string const ( ParameterStatusNew ParameterPhase = "" ParameterStatusCreating ParameterPhase = "Creating" - ParameterStatusRunning ParameterPhase = "Running" + ParameterStatusFinished ParameterPhase = "Finished" ParameterStatusModifying ParameterPhase = "Modifying" ) diff --git a/api/v1/polardbx/topology.go b/api/v1/polardbx/topology.go index 4291d35..41b97f8 100644 --- a/api/v1/polardbx/topology.go +++ b/api/v1/polardbx/topology.go @@ -207,7 +207,6 @@ type TopologyNodes struct { CN TopologyNodeCN `json:"cn,omitempty"` // +kubebuilder:default={replicas:2,template:{hostNetwork:true,resources:{limits:{cpu:4,memory:"8Gi"}}}} - DN TopologyNodeDN `json:"dn,omitempty"` CDC *TopologyNodeCDC `json:"cdc,omitempty"` diff --git a/api/v1/polardbxbackup_types.go b/api/v1/polardbxbackup_types.go index c68aacb..7e29a47 100644 --- a/api/v1/polardbxbackup_types.go +++ b/api/v1/polardbxbackup_types.go @@ -98,6 +98,7 @@ type PolarDBXBackupStatus struct { // XStores represents the backup xstore name. // +optional XStores []string `json:"xstores,omitempty"` + // ClusterSpecSnapshot records the snapshot of polardbx cluster spec // +optional ClusterSpecSnapshot *PolarDBXClusterSpec `json:"clusterSpecSnapshot,omitempty"` diff --git a/api/v1/polardbxparameter_types.go b/api/v1/polardbxparameter_types.go index 02a37a3..2d5ec1a 100644 --- a/api/v1/polardbxparameter_types.go +++ b/api/v1/polardbxparameter_types.go @@ -59,6 +59,9 @@ type PolarDBXParameterStatus struct { // Phase is the current phase of the cluster. Phase polardbxv1polardbx.ParameterPhase `json:"phase,omitempty"` + // ModifiedTimestamp is timestamp of the last modified + ModifiedTimestamp string `json:"modifiedTimestamp,omitempty"` + // PrevParameterSpecSnapshot represents the previous version snapshot of the parameter. PrevParameterSpecSnapshot *PolarDBXParameterSpec `json:"prevParameterSpecSnapshot,omitempty"` @@ -69,7 +72,10 @@ type PolarDBXParameterStatus struct { // +kubebuilder:object:root=true // +kubebuilder:resource:shortName=pxp;polardbxp;polardbxparameter // +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="CLUSTER NAME",type=string,JSONPath=`.spec.clusterName` +// +kubebuilder:printcolumn:name="LAST MODIFIED",type=string,JSONPath=`.status.modifiedTimestamp` // +kubebuilder:printcolumn:name="PHASE",type=string,JSONPath=`.status.phase` +// +kubebuilder:printcolumn:name="AGE",type=date,JSONPath=`.metadata.creationTimestamp` type PolarDBXParameter struct { metav1.TypeMeta `json:",inline"` diff --git a/api/v1/xstorebackup_types.go b/api/v1/xstorebackup_types.go index ba4b268..c8e5bad 100644 --- a/api/v1/xstorebackup_types.go +++ b/api/v1/xstorebackup_types.go @@ -33,12 +33,12 @@ type XStoreBackupSpec struct { // Engine is the engine used by xstore. Default is "galaxy". // +optional - Engine string `json:"engine,omitempty"` - - XStore XStoreReference `json:"xstore,omitempty"` - Timezone string `json:"timezone,omitempty"` + Engine string `json:"engine,omitempty"` + XStore XStoreReference `json:"xstore,omitempty"` + Timezone string `json:"timezone,omitempty"` + // RetentionTime defines how long will this backup set be kept RetentionTime metav1.Duration `json:"retentionTime,omitempty"` - // file storage + // StorageProvider defines backup storage configuration StorageProvider BackupStorageProvider `json:"storageProvider,omitempty"` } diff --git a/build/root/Makefile b/build/root/Makefile index ae7d2d2..232cf84 100644 --- a/build/root/Makefile +++ b/build/root/Makefile @@ -62,6 +62,8 @@ ifneq (, $(TARGET)) BUILD_IMAGE_ARGS:=${BUILD_IMAGE_ARGS} $(TARGET) endif +E2E_PARALLELISM=3 + define BUILD_IMAGES_HELP_INFO # Build images. # @@ -165,7 +167,7 @@ e2e-test: else # @go test ./test/e2e -v -args timeout 6000 -ginkgo.progress -ginkgo.v e2e-test: - @ginkgo -v -progress -p ./test/e2e + @ginkgo -nodes=${E2E_PARALLELISM} -v -progress -p ./test/e2e endif .PHONY: manifests diff --git a/charts/polardbx-logcollector/Chart.yaml b/charts/polardbx-logcollector/Chart.yaml index c6fb8c0..50b116b 100644 --- a/charts/polardbx-logcollector/Chart.yaml +++ b/charts/polardbx-logcollector/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: polardbx-logcollector description: Helm chart of polardbx-operator logcollector plugin type: application -version: 1.3.0-alpha.1 -appVersion: v1.3.0-alpha.1 +version: 1.3.0 +appVersion: v1.3.0 keywords: - polardb-x - operator diff --git a/charts/polardbx-logcollector/templates/configmap/filebeat-configmap.yaml b/charts/polardbx-logcollector/templates/configmap/filebeat-configmap.yaml index cd95fa3..6de1d1e 100644 --- a/charts/polardbx-logcollector/templates/configmap/filebeat-configmap.yaml +++ b/charts/polardbx-logcollector/templates/configmap/filebeat-configmap.yaml @@ -1,6 +1,11 @@ apiVersion: v1 data: filebeat.yml: |- + queue: + mem: + events: 4096 + flush.min_events: 2048 + flush.timeout: 5s filebeat.autodiscover: providers: - type: kubernetes @@ -15,6 +20,8 @@ data: config: - type: log + scan_frequency: 0.3s + harvester_buffer_size: 10485760 fields: log_type: cn_sql_log instance_id: ${data.kubernetes.labels.polardbx/name} diff --git a/charts/polardbx-logcollector/templates/configmap/logstash-config-configmap.yaml b/charts/polardbx-logcollector/templates/configmap/logstash-config-configmap.yaml index 35d0faf..706a778 100644 --- a/charts/polardbx-logcollector/templates/configmap/logstash-config-configmap.yaml +++ b/charts/polardbx-logcollector/templates/configmap/logstash-config-configmap.yaml @@ -6,8 +6,8 @@ data: # Xms represents the initial size of total heap space # Xmx represents the maximum size of total heap space - -Xms1g - -Xmx1g + -Xms800m + -Xmx800m ################################################################ ## Expert settings diff --git a/charts/polardbx-logcollector/values.yaml b/charts/polardbx-logcollector/values.yaml index 222d417..9414b29 100644 --- a/charts/polardbx-logcollector/values.yaml +++ b/charts/polardbx-logcollector/values.yaml @@ -4,9 +4,9 @@ logstash: #image repo of logstash repo: polardbx #image name of logstash - name: logstash + name: polardbx-logstash #image tag of logstash - version: 8.1.2-polardbx-20220624153221 + version: v1.3.0 #the name of the logstash deployment name: logstash #the exported port the logstash. filebeat will access this port. @@ -18,10 +18,10 @@ logstash: #the resource configuration of one logstash replica resources: limits: - cpu: "2" + cpu: "1" memory: "1200Mi" requests: - cpu: "2" + cpu: "1" memory: "1200Mi" elastic: #the name of elastic cert secret, which will be need when logtash upload data to an elastic search cluster. diff --git a/charts/polardbx-monitor/Chart.yaml b/charts/polardbx-monitor/Chart.yaml index cf1776a..2125834 100644 --- a/charts/polardbx-monitor/Chart.yaml +++ b/charts/polardbx-monitor/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: polardbx-monitor description: Helm chart of polardbx-operator monitor plugin type: application -version: 1.3.0-alpha.1 -appVersion: v1.3.0-alpha.1 +version: 1.3.0 +appVersion: v1.3.0 keywords: - polardb-x - operator diff --git a/charts/polardbx-monitor/values.yaml b/charts/polardbx-monitor/values.yaml index b432cda..47dd8c7 100644 --- a/charts/polardbx-monitor/values.yaml +++ b/charts/polardbx-monitor/values.yaml @@ -58,9 +58,9 @@ monitors: # kube-state-metrics (KSM) is a simple service that listens to the Kubernetes API server and generates metrics # about the state of the objects. kubeStateMetrics: - repo: quay.io/coreos + repo: kubesphere image: kube-state-metrics - version: v1.9.7 + version: v2.3.0 replicas: 1 # The node selector labels, KubeStateMetrics pod will deploy only on the nodes with such labels diff --git a/charts/polardbx-operator/Chart.yaml b/charts/polardbx-operator/Chart.yaml index decf40f..1b637f5 100644 --- a/charts/polardbx-operator/Chart.yaml +++ b/charts/polardbx-operator/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: polardbx-operator description: Helm chart of polardbx-operator type: application -version: 1.3.0-alpha.1 -appVersion: v1.3.0-alpha.1 +version: 1.3.0 +appVersion: v1.3.0 keywords: - polardb-x - operator diff --git a/charts/polardbx-operator/crds/polardbx.aliyun.com_polardbxbackups.yaml b/charts/polardbx-operator/crds/polardbx.aliyun.com_polardbxbackups.yaml index eb5b467..fb29b63 100644 --- a/charts/polardbx-operator/crds/polardbx.aliyun.com_polardbxbackups.yaml +++ b/charts/polardbx-operator/crds/polardbx.aliyun.com_polardbxbackups.yaml @@ -301,6 +301,15 @@ spec: that this polardbx is restored from. Optional. type: string type: object + syncSpecWithOriginalCluster: + default: false + description: SyncSpecWithOriginalCluster identifies whether + restored cluster should use the same spec as the original + cluster. If the field is set to true, spec of original cluster + is used; otherwise users have to declare spec manually or + use default spec, but replicas of dn will be forced to sync + with original cluster now. Default is false + type: boolean time: description: Time defines the specified time of the restored data, in the format of 'yyyy-MM-dd HH:mm:ss'. Required. diff --git a/charts/polardbx-operator/crds/polardbx.aliyun.com_polardbxclusters.yaml b/charts/polardbx-operator/crds/polardbx.aliyun.com_polardbxclusters.yaml index 19039e3..d144ebd 100644 --- a/charts/polardbx-operator/crds/polardbx.aliyun.com_polardbxclusters.yaml +++ b/charts/polardbx-operator/crds/polardbx.aliyun.com_polardbxclusters.yaml @@ -267,6 +267,15 @@ spec: this polardbx is restored from. Optional. type: string type: object + syncSpecWithOriginalCluster: + default: false + description: SyncSpecWithOriginalCluster identifies whether restored + cluster should use the same spec as the original cluster. If + the field is set to true, spec of original cluster is used; + otherwise users have to declare spec manually or use default + spec, but replicas of dn will be forced to sync with original + cluster now. Default is false + type: boolean time: description: Time defines the specified time of the restored data, in the format of 'yyyy-MM-dd HH:mm:ss'. Required. diff --git a/charts/polardbx-operator/crds/polardbx.aliyun.com_polardbxparameters.yaml b/charts/polardbx-operator/crds/polardbx.aliyun.com_polardbxparameters.yaml index 46e607d..cdb734c 100644 --- a/charts/polardbx-operator/crds/polardbx.aliyun.com_polardbxparameters.yaml +++ b/charts/polardbx-operator/crds/polardbx.aliyun.com_polardbxparameters.yaml @@ -20,9 +20,18 @@ spec: scope: Namespaced versions: - additionalPrinterColumns: + - jsonPath: .spec.clusterName + name: CLUSTER NAME + type: string + - jsonPath: .status.modifiedTimestamp + name: LAST MODIFIED + type: string - jsonPath: .status.phase name: PHASE type: string + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date name: v1 schema: openAPIV3Schema: @@ -108,6 +117,9 @@ spec: type: object status: properties: + modifiedTimestamp: + description: ModifiedTimestamp is timestamp of the last modified + type: string parameterSpecSnapshot: description: ParameterSpecSnapshot represents the snapshot of the parameter. diff --git a/charts/polardbx-operator/crds/polardbx.aliyun.com_xstorebackups.yaml b/charts/polardbx-operator/crds/polardbx.aliyun.com_xstorebackups.yaml index 61dc64a..eac5bcd 100644 --- a/charts/polardbx-operator/crds/polardbx.aliyun.com_xstorebackups.yaml +++ b/charts/polardbx-operator/crds/polardbx.aliyun.com_xstorebackups.yaml @@ -64,9 +64,11 @@ spec: description: Engine is the engine used by xstore. Default is "galaxy". type: string retentionTime: + description: RetentionTime defines how long will this backup set be + kept type: string storageProvider: - description: file storage + description: StorageProvider defines backup storage configuration properties: sink: description: Sink defines the storage configuration choose to diff --git a/charts/polardbx-operator/templates/controller-config-configmap.yaml b/charts/polardbx-operator/templates/controller-config-configmap.yaml index 89bdc60..513f107 100644 --- a/charts/polardbx-operator/templates/controller-config-configmap.yaml +++ b/charts/polardbx-operator/templates/controller-config-configmap.yaml @@ -48,6 +48,7 @@ data: enable_aliyun_ack_resource_controller: {{ .Values.controllerManager.config.scheduler.enableAliyunAckResourceController }} enable_debug_mode_for_compute_nodes: false enable_privileged_container: {{ .Values.controllerManager.config.container.privileged }} + force_cgroup: {{ .Values.controllerManager.config.container.forceCGroup }} store: enable_privileged_container: {{ .Values.controllerManager.config.container.privileged }} host_paths: diff --git a/charts/polardbx-operator/templates/host-path-file-service-daemonset.yaml b/charts/polardbx-operator/templates/host-path-file-service-daemonset.yaml index 1be462b..a0d3302 100644 --- a/charts/polardbx-operator/templates/host-path-file-service-daemonset.yaml +++ b/charts/polardbx-operator/templates/host-path-file-service-daemonset.yaml @@ -45,7 +45,6 @@ spec: - name: cgroups-blkio hostPath: path: /sys/fs/cgroup/blkio - type: Directory - name: tmpfs emptyDir: {} - name: config diff --git a/charts/polardbx-operator/templates/parameter-template-product.yaml b/charts/polardbx-operator/templates/parameter-template-product.yaml new file mode 100644 index 0000000..688215d --- /dev/null +++ b/charts/polardbx-operator/templates/parameter-template-product.yaml @@ -0,0 +1,2653 @@ +apiVersion: polardbx.aliyun.com/v1 +kind: PolarDBXParameterTemplate +metadata: + name: product +spec: + nodeType: + cn: + name: cnTemplate + paramList: + - defaultValue: 05:00 + divisibilityFactor: 0 + mode: readwrite + name: BACKGROUND_STATISTIC_COLLECTION_END_TIME + optional: '[00:00|01:00|02:00|03:00|04:00|05:00|06:00|07:00|08:00|09:00|10:00|11:00|12:00|13:00|14:00|15:00|16:00|17:00|18:00|19:00|20:00|21:00|22:00|23:00]' + restart: false + unit: STRING + - defaultValue: 02:00 + divisibilityFactor: 0 + mode: readwrite + name: BACKGROUND_STATISTIC_COLLECTION_START_TIME + optional: '[00:00|01:00|02:00|03:00|04:00|05:00|06:00|07:00|08:00|09:00|10:00|11:00|12:00|13:00|14:00|15:00|16:00|17:00|18:00|19:00|20:00|21:00|22:00|23:00]' + restart: false + unit: STRING + - defaultValue: '5000' + divisibilityFactor: 1 + mode: readwrite + name: CONN_POOL_BLOCK_TIMEOUT + optional: '[1000-60000]' + restart: false + unit: INT + - defaultValue: '30' + divisibilityFactor: 1 + mode: readwrite + name: CONN_POOL_IDLE_TIMEOUT + optional: '[1-60]' + restart: false + unit: INT + - defaultValue: '60' + divisibilityFactor: 1 + mode: readwrite + name: CONN_POOL_MAX_POOL_SIZE + optional: '[1-1600]' + restart: false + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: CONN_POOL_MAX_WAIT_THREAD_COUNT + optional: '[-1-8192]' + restart: false + unit: INT + - defaultValue: '20' + divisibilityFactor: 1 + mode: readwrite + name: CONN_POOL_MIN_POOL_SIZE + optional: '[0-60]' + restart: false + unit: INT + - defaultValue: '512' + divisibilityFactor: 1 + mode: readwrite + name: CONN_POOL_XPROTO_MAX_POOLED_SESSION_PER_INST + optional: '[1-8192]' + restart: false + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: CONN_POOL_XPROTO_STORAGE_DB_PORT + optional: '[-1-0]' + restart: false + unit: INT + - defaultValue: 'true' + divisibilityFactor: 0 + mode: readwrite + name: ENABLE_BACKGROUND_STATISTIC_COLLECTION + optional: '[true|false]' + restart: false + unit: STRING + - defaultValue: 'true' + divisibilityFactor: 1 + mode: readwrite + name: ENABLE_COMPLEX_DML_CROSS_DB + optional: '[true|false]' + restart: false + unit: STRING + - defaultValue: 'true' + divisibilityFactor: 0 + mode: readwrite + name: ENABLE_HLL + optional: '[true|false]' + restart: false + unit: STRING + - defaultValue: 'true' + divisibilityFactor: 0 + mode: readwrite + name: ENABLE_LOCAL_MODE + optional: '[true|false]' + restart: false + unit: STRING + - defaultValue: 'true' + divisibilityFactor: 0 + mode: readwrite + name: ENABLE_LOGICALVIEW_COST + optional: '[true|false]' + restart: false + unit: STRING + - defaultValue: 'false' + divisibilityFactor: 1 + mode: readwrite + name: ENABLE_RECYCLEBIN + optional: '[true|false]' + restart: false + unit: STRING + - defaultValue: 'true' + divisibilityFactor: 0 + mode: readwrite + name: ENABLE_SPM + optional: '[true|false]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 1 + mode: readwrite + name: ENABLE_SQL_FLASHBACK_EXACT_MATCH + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: 'true' + divisibilityFactor: 0 + mode: readwrite + name: ENABLE_STATEMENTS_SUMMARY + optional: '[true|false]' + restart: false + unit: STRING + - defaultValue: 'true' + divisibilityFactor: 0 + mode: readwrite + name: ENABLE_STATISTIC_FEEDBACK + optional: '[true|false]' + restart: false + unit: STRING + - defaultValue: 'true' + divisibilityFactor: 1 + mode: readwrite + name: FORBID_EXECUTE_DML_ALL + optional: '[true|false]' + restart: false + unit: STRING + - defaultValue: '-1' + divisibilityFactor: 1 + mode: readwrite + name: GENERAL_DYNAMIC_SPEED_LIMITATION + optional: '[-1-10000000]' + restart: false + unit: INT + - defaultValue: 'false' + divisibilityFactor: 1 + mode: readwrite + name: INFO_SCHEMA_QUERY_WITH_STAT + optional: '[true|false]' + restart: false + unit: STRING + - defaultValue: '2' + divisibilityFactor: 0 + mode: readwrite + name: IN_SUB_QUERY_THRESHOLD + optional: '[1-65535]' + restart: false + unit: INT + - defaultValue: SYSTEM + divisibilityFactor: 1 + mode: readwrite + name: LOGICAL_DB_TIME_ZONE + optional: '[SYSTEM|±HH:mm]' + restart: false + unit: TZ + - defaultValue: '28800000' + divisibilityFactor: 1 + mode: readwrite + name: LOGIC_IDLE_TIMEOUT + optional: '[3600000-86400000]' + restart: false + unit: INT + - defaultValue: '16777216' + divisibilityFactor: 1 + mode: readwrite + name: MAX_ALLOWED_PACKET + optional: '[4194304-33554432]' + restart: false + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: PARALLELISM + optional: '[-1-8]' + restart: false + unit: INT + - defaultValue: '-1' + divisibilityFactor: 1 + mode: readwrite + name: PER_QUERY_MEMORY_LIMIT + optional: '[-1-9223372036854775807]' + restart: false + unit: INT + - defaultValue: 00:00-01:00 + divisibilityFactor: 1 + mode: readwrite + name: PURGE_TRANS_START_TIME + optional: 00:00~23:59 + restart: false + unit: HOUR_RANGE + - defaultValue: '1000' + divisibilityFactor: 1 + mode: readwrite + name: SLOW_SQL_TIME + optional: '[1000-900000]' + restart: false + unit: INT + - defaultValue: '900000' + divisibilityFactor: 1 + mode: readwrite + name: SOCKET_TIMEOUT + optional: '[0-3600000]' + restart: false + unit: INT + - defaultValue: '1' + divisibilityFactor: 1 + mode: readwrite + name: STATEMENTS_SUMMARY_PERCENT + optional: '[0-100]' + restart: false + unit: INT + - defaultValue: REPEATABLE-READ + divisibilityFactor: 0 + mode: readwrite + name: TRANSACTION_ISOLATION + optional: '[REPEATABLE-READ|READ-COMMITTED|READ-UNCOMMITTED|SERIALIZABLE]' + restart: false + unit: STRING + - defaultValue: '500' + divisibilityFactor: 1 + mode: readwrite + name: XPROTO_MAX_DN_CONCURRENT + optional: '[1-8192]' + restart: false + unit: INT + - defaultValue: '32' + divisibilityFactor: 1 + mode: readwrite + name: XPROTO_MAX_DN_WAIT_CONNECTION + optional: '[1-8192]' + restart: false + unit: INT + - defaultValue: 'false' + divisibilityFactor: 1 + mode: readwrite + name: ENABLE_COROUTINE + optional: '[true|false]' + restart: true + unit: STRING + dn: + name: dnTemplate + paramList: + - defaultValue: '1' + divisibilityFactor: 1 + mode: readwrite + name: auto_increment_increment + optional: '[1-65535]' + restart: false + unit: INT + - defaultValue: '1' + divisibilityFactor: 1 + mode: readwrite + name: auto_increment_offset + optional: '[1-65535]' + restart: false + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: autocommit + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: automatic_sp_privileges + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: avoid_temporal_upgrade + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '3000' + divisibilityFactor: 1 + mode: readwrite + name: back_log + optional: '[0-65535]' + restart: true + unit: INT + - defaultValue: '1048576' + divisibilityFactor: 4096 + mode: readwrite + name: binlog_cache_size + optional: '[4096-16777216]' + restart: false + unit: INT + - defaultValue: CRC32 + divisibilityFactor: 0 + mode: readwrite + name: binlog_checksum + optional: '[CRC32|NONE]' + restart: true + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 1 + mode: readwrite + name: binlog_order_commits + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: full + divisibilityFactor: 0 + mode: readwrite + name: binlog_row_image + optional: '[full|minimal]' + restart: false + unit: STRING + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: binlog_rows_query_log_events + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '32768' + divisibilityFactor: 4096 + mode: readwrite + name: binlog_stmt_cache_size + optional: '[4096-16777216]' + restart: false + unit: INT + - defaultValue: WRITESET + divisibilityFactor: 1 + mode: readwrite + name: binlog_transaction_dependency_tracking + optional: '[WRITESET|WRITESET_SESSION|COMMIT_ORDER]' + restart: false + unit: STRING + - defaultValue: '"aes-128-ecb"' + divisibilityFactor: 1 + mode: readwrite + name: block_encryption_mode + optional: '["aes-128-ecb"|"aes-192-ecb"|"aes-256-ecb"|"aes-128-cbc"|"aes-192-cbc"|"aes-256-cbc"]' + restart: false + unit: STRING + - defaultValue: '4194304' + divisibilityFactor: 1 + mode: readwrite + name: bulk_insert_buffer_size + optional: '[0-4294967295]' + restart: false + unit: INT + - defaultValue: utf8 + divisibilityFactor: 0 + mode: readwrite + name: character_set_server + optional: '[utf8|latin1|gbk|gb18030|utf8mb4]' + restart: true + unit: STRING + - defaultValue: '2' + divisibilityFactor: 0 + mode: readwrite + name: concurrent_insert + optional: '[0|1|2]' + restart: false + unit: STRING + - defaultValue: '10' + divisibilityFactor: 1 + mode: readwrite + name: connect_timeout + optional: '[1-3600]' + restart: false + unit: INT + - defaultValue: mysql_native_password + divisibilityFactor: 0 + mode: readwrite + name: default_authentication_plugin + optional: '[mysql_native_password|sha256_password|caching_sha2_password]' + restart: true + unit: STRING + - defaultValue: InnoDB + divisibilityFactor: 0 + mode: readwrite + name: default_storage_engine + optional: '[InnoDB|innodb]' + restart: true + unit: STRING + - defaultValue: '+8:00' + divisibilityFactor: 0 + mode: readwrite + name: default_time_zone + optional: '[SYSTEM|-12:00|-11:00|-10:00|-9:00|-8:00|-7:00|-6:00|-5:00|-4:00|-3:00|-2:00|-1:00|\+0:00|\+1:00|\+2:00|\+3:00|\+4:00|\+5:00|\+5:30|\+5:45|\+6:00|\+6:30|\+7:00|\+8:00|\+9:00|\+10:00|\+11:00|\+12:00|\+13:00]' + restart: true + unit: STRING + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: default_week_format + optional: '[0-7]' + restart: false + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: delay_key_write + optional: '[ON|OFF|ALL]' + restart: false + unit: STRING + - defaultValue: '100' + divisibilityFactor: 1 + mode: readwrite + name: delayed_insert_limit + optional: '[1-4294967295]' + restart: false + unit: INT + - defaultValue: '300' + divisibilityFactor: 1 + mode: readwrite + name: delayed_insert_timeout + optional: '[1-3600]' + restart: false + unit: INT + - defaultValue: '1000' + divisibilityFactor: 1 + mode: readwrite + name: delayed_queue_size + optional: '[1-4294967295]' + restart: false + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: disconnect_on_expired_password + optional: '[ON|OFF]' + restart: true + unit: STRING + - defaultValue: '4' + divisibilityFactor: 1 + mode: readwrite + name: div_precision_increment + optional: '[0-30]' + restart: false + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: end_markers_in_json + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: enforce_gtid_consistency + optional: .* + restart: true + unit: STRING + - defaultValue: '200' + divisibilityFactor: 1 + mode: readwrite + name: eq_range_index_dive_limit + optional: '[0-4294967295]' + restart: false + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: event_scheduler + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: expire_logs_days + optional: .* + restart: true + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: explicit_defaults_for_timestamp + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: flush_time + optional: '[0-31536000]' + restart: false + unit: INT + - defaultValue: '84' + divisibilityFactor: 1 + mode: readwrite + name: ft_max_word_len + optional: '[10-4294967295]' + restart: true + unit: INT + - defaultValue: '4' + divisibilityFactor: 1 + mode: readwrite + name: ft_min_word_len + optional: '[1-3600]' + restart: true + unit: INT + - defaultValue: '20' + divisibilityFactor: 1 + mode: readwrite + name: ft_query_expansion_limit + optional: '[0-1000]' + restart: true + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: general_log + optional: 'OFF' + restart: true + unit: STRING + - defaultValue: '1024' + divisibilityFactor: 1 + mode: readwrite + name: group_concat_max_len + optional: '[4-1844674407370954752]' + restart: false + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: gtid_mode + optional: .* + restart: true + unit: STRING + - defaultValue: '644' + divisibilityFactor: 1 + mode: readwrite + name: host_cache_size + optional: '[0-65535]' + restart: false + unit: INT + - defaultValue: '''''' + divisibilityFactor: 0 + mode: readwrite + name: init_connect + optional: '[''''|''set names utf8mb4''|''set names utf8''|''set default_collation_for_utf8mb4=utf8mb4_general_ci''|''set + default_collation_for_utf8mb4=utf8mb4_general_ci;set names utf8mb4''|''set + names utf8mb4 collate utf8mb4_general_ci'']' + restart: false + unit: STRING + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: innodb_adaptive_flushing + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '10' + divisibilityFactor: 1 + mode: readwrite + name: innodb_adaptive_flushing_lwm + optional: '[0-70]' + restart: false + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: innodb_adaptive_hash_index + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '150000' + divisibilityFactor: 1 + mode: readwrite + name: innodb_adaptive_max_sleep_delay + optional: '[1-1000000]' + restart: false + unit: INT + - defaultValue: '64' + divisibilityFactor: 1 + mode: readwrite + name: innodb_autoextend_increment + optional: '[1-1000]' + restart: false + unit: INT + - defaultValue: '2' + divisibilityFactor: 0 + mode: readwrite + name: innodb_autoinc_lock_mode + optional: '[0|1|2]' + restart: true + unit: STRING + - defaultValue: '33554432' + divisibilityFactor: 1048576 + mode: readwrite + name: innodb_buffer_pool_chunk_size + optional: '[1048576-9223372036854775807]' + restart: true + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: innodb_buffer_pool_dump_at_shutdown + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '25' + divisibilityFactor: 1 + mode: readwrite + name: innodb_buffer_pool_dump_pct + optional: '[1-100]' + restart: false + unit: INT + - defaultValue: '8' + divisibilityFactor: 1 + mode: readwrite + name: innodb_buffer_pool_instances + optional: '[1-64]' + restart: true + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: innodb_buffer_pool_load_at_startup + optional: '[ON|OFF]' + restart: true + unit: STRING + - defaultValue: '{DBInstanceClassMemory*3/4}' + divisibilityFactor: 1 + mode: readwrite + name: innodb_buffer_pool_size + optional: '[134217728-18446744073709551615]' + restart: true + unit: INT + - defaultValue: '25' + divisibilityFactor: 1 + mode: readwrite + name: innodb_change_buffer_max_size + optional: '[0-50]' + restart: false + unit: INT + - defaultValue: none + divisibilityFactor: 0 + mode: readwrite + name: innodb_change_buffering + optional: '[none|inserts|deletes|changes|purges|all]' + restart: false + unit: STRING + - defaultValue: crc32 + divisibilityFactor: 0 + mode: readwrite + name: innodb_checksum_algorithm + optional: '[innodb|crc32|none|strict_innodb|strict_crc32|strict_none]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: innodb_cmp_per_index_enabled + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '9999999999' + divisibilityFactor: 1 + mode: readwrite + name: loose_innodb_commit_cleanout_max_rows + optional: '[0-9223372036854775807]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: innodb_commit_concurrency + optional: '[0-1000]' + restart: true + unit: INT + - defaultValue: '5' + divisibilityFactor: 1 + mode: readwrite + name: innodb_compression_failure_threshold_pct + optional: '[0-100]' + restart: false + unit: INT + - defaultValue: '6' + divisibilityFactor: 1 + mode: readwrite + name: innodb_compression_level + optional: '[0-9]' + restart: false + unit: INT + - defaultValue: '50' + divisibilityFactor: 1 + mode: readwrite + name: innodb_compression_pad_pct_max + optional: '[0-70]' + restart: false + unit: INT + - defaultValue: '5000' + divisibilityFactor: 1 + mode: readwrite + name: innodb_concurrency_tickets + optional: '[1-4294967295]' + restart: false + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: innodb_data_file_purge + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '100' + divisibilityFactor: 1 + mode: readwrite + name: innodb_data_file_purge_interval + optional: '[0-10000]' + restart: false + unit: INT + - defaultValue: '128' + divisibilityFactor: 1 + mode: readwrite + name: innodb_data_file_purge_max_size + optional: '[16-1073741824]' + restart: false + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: innodb_deadlock_detect + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: innodb_disable_sort_file_cache + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: innodb_equal_gcn_visible + optional: .* + restart: true + unit: INT + - defaultValue: '1' + divisibilityFactor: 0 + mode: readwrite + name: innodb_flush_log_at_trx_commit + optional: '[0|1|2]' + restart: false + unit: STRING + - defaultValue: O_DIRECT + divisibilityFactor: 0 + mode: readwrite + name: innodb_flush_method + optional: '[fsync|O_DSYNC|littlesync|nosync|O_DIRECT|O_DIRECT_NO_FSYNC]' + restart: true + unit: STRING + - defaultValue: '0' + divisibilityFactor: 0 + mode: readwrite + name: innodb_flush_neighbors + optional: '[0|1|2]' + restart: false + unit: STRING + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: innodb_flush_sync + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '8000000' + divisibilityFactor: 1 + mode: readwrite + name: innodb_ft_cache_size + optional: '[1600000-80000000]' + restart: true + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: innodb_ft_enable_diag_print + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: innodb_ft_enable_stopword + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '84' + divisibilityFactor: 1 + mode: readwrite + name: innodb_ft_max_token_size + optional: '[10-84]' + restart: true + unit: INT + - defaultValue: '3' + divisibilityFactor: 1 + mode: readwrite + name: innodb_ft_min_token_size + optional: '[0-16]' + restart: true + unit: INT + - defaultValue: '2000' + divisibilityFactor: 1 + mode: readwrite + name: innodb_ft_num_word_optimize + optional: '[0-10000]' + restart: false + unit: INT + - defaultValue: '2000000000' + divisibilityFactor: 1 + mode: readwrite + name: innodb_ft_result_cache_limit + optional: '[1000000-4294967295]' + restart: false + unit: INT + - defaultValue: '2' + divisibilityFactor: 1 + mode: readwrite + name: innodb_ft_sort_pll_degree + optional: '[1-16]' + restart: true + unit: INT + - defaultValue: '640000000' + divisibilityFactor: 1 + mode: readwrite + name: innodb_ft_total_cache_size + optional: '[32000000-1600000000]' + restart: true + unit: INT + - defaultValue: '20000' + divisibilityFactor: 1 + mode: readwrite + name: innodb_io_capacity + optional: '[0-18446744073709551615]' + restart: false + unit: INT + - defaultValue: '40000' + divisibilityFactor: 1 + mode: readwrite + name: innodb_io_capacity_max + optional: '[0-18446744073709551615]' + restart: false + unit: INT + - defaultValue: '50' + divisibilityFactor: 1 + mode: readwrite + name: innodb_lock_wait_timeout + optional: '[1-1073741824]' + restart: false + unit: INT + - defaultValue: '209715200' + divisibilityFactor: 1 + mode: readwrite + name: innodb_log_buffer_size + optional: .* + restart: true + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: innodb_log_checksums + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: innodb_log_compressed_pages + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '2147483648' + divisibilityFactor: 1024 + mode: readwrite + name: innodb_log_file_size + optional: '[4194304-107374182400]' + restart: true + unit: INT + - defaultValue: '8192' + divisibilityFactor: 1 + mode: readwrite + name: innodb_lru_scan_depth + optional: '[100-18446744073709551615]' + restart: false + unit: INT + - defaultValue: '75' + divisibilityFactor: 1 + mode: readwrite + name: innodb_max_dirty_pages_pct + optional: '[0-99]' + restart: false + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: innodb_max_dirty_pages_pct_lwm + optional: '[0-99]' + restart: false + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: innodb_max_purge_lag + optional: '[0-4294967295]' + restart: false + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: innodb_max_purge_lag_delay + optional: '[0-10000000]' + restart: false + unit: INT + - defaultValue: '1073741824' + divisibilityFactor: 1 + mode: readwrite + name: innodb_max_undo_log_size + optional: '[10485760-18446744073709551615]' + restart: false + unit: INT + - defaultValue: '' + divisibilityFactor: 0 + mode: readwrite + name: innodb_monitor_disable + optional: all + restart: false + unit: STRING + - defaultValue: '' + divisibilityFactor: 0 + mode: readwrite + name: innodb_monitor_enable + optional: all + restart: false + unit: STRING + - defaultValue: '37' + divisibilityFactor: 1 + mode: readwrite + name: innodb_old_blocks_pct + optional: '[5-95]' + restart: false + unit: INT + - defaultValue: '1000' + divisibilityFactor: 1 + mode: readwrite + name: innodb_old_blocks_time + optional: '[0-1024]' + restart: false + unit: INT + - defaultValue: '134217728' + divisibilityFactor: 1 + mode: readwrite + name: innodb_online_alter_log_max_size + optional: '[134217728-2147483647]' + restart: false + unit: INT + - defaultValue: '20000' + divisibilityFactor: 1 + mode: readwrite + name: innodb_open_files + optional: '[10-2147483647]' + restart: true + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: innodb_optimize_fulltext_only + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '4' + divisibilityFactor: 1 + mode: readwrite + name: innodb_page_cleaners + optional: '[1-64]' + restart: true + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: innodb_print_all_deadlocks + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: '300' + divisibilityFactor: 1 + mode: readwrite + name: innodb_purge_batch_size + optional: '[1-5000]' + restart: true + unit: INT + - defaultValue: '128' + divisibilityFactor: 1 + mode: readwrite + name: innodb_purge_rseg_truncate_frequency + optional: '[1-128]' + restart: false + unit: INT + - defaultValue: '2' + divisibilityFactor: 1 + mode: readwrite + name: innodb_purge_threads + optional: '[1-32]' + restart: true + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: innodb_random_read_ahead + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: innodb_read_ahead_threshold + optional: '[0-1024]' + restart: false + unit: INT + - defaultValue: '4' + divisibilityFactor: 1 + mode: readwrite + name: innodb_read_io_threads + optional: '[1-64]' + restart: true + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: innodb_rollback_on_timeout + optional: '[OFF|ON]' + restart: true + unit: STRING + - defaultValue: '128' + divisibilityFactor: 1 + mode: readwrite + name: innodb_rollback_segments + optional: '[1-128]' + restart: false + unit: INT + - defaultValue: '1' + divisibilityFactor: 1 + mode: readwrite + name: innodb_snapshot_update_gcn + optional: .* + restart: true + unit: INT + - defaultValue: '1048576' + divisibilityFactor: 512 + mode: readwrite + name: innodb_sort_buffer_size + optional: '[65536-67108864]' + restart: true + unit: INT + - defaultValue: '6' + divisibilityFactor: 1 + mode: readwrite + name: innodb_spin_wait_delay + optional: '[0-4294967295]' + restart: false + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: innodb_stats_auto_recalc + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: nulls_equal + divisibilityFactor: 0 + mode: readwrite + name: innodb_stats_method + optional: '[nulls_equal|nulls_unequal|nulls_ignored]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: innodb_stats_on_metadata + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: innodb_stats_persistent + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '20' + divisibilityFactor: 1 + mode: readwrite + name: innodb_stats_persistent_sample_pages + optional: '[0-4294967295]' + restart: false + unit: INT + - defaultValue: '8' + divisibilityFactor: 1 + mode: readwrite + name: innodb_stats_transient_sample_pages + optional: '[1-4294967295]' + restart: false + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: innodb_status_output + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: innodb_status_output_locks + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: innodb_strict_mode + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '16' + divisibilityFactor: 1 + mode: readwrite + name: innodb_sync_array_size + optional: '[1-64]' + restart: true + unit: INT + - defaultValue: '30' + divisibilityFactor: 1 + mode: readwrite + name: innodb_sync_spin_loops + optional: '[0-4294967295]' + restart: false + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: innodb_table_locks + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: block + divisibilityFactor: 0 + mode: readwrite + name: innodb_tcn_cache_level + optional: .* + restart: true + unit: STRING + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: innodb_thread_concurrency + optional: '[0-1000]' + restart: false + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: innodb_thread_sleep_delay + optional: '[0-1000000]' + restart: false + unit: INT + - defaultValue: '4' + divisibilityFactor: 1 + mode: readwrite + name: innodb_write_io_threads + optional: '[1-64]' + restart: true + unit: INT + - defaultValue: '7200' + divisibilityFactor: 1 + mode: readwrite + name: interactive_timeout + optional: '[10-86400]' + restart: false + unit: INT + - defaultValue: '{LEAST(DBInstanceClassMemory/1048576*128, 262144)}' + divisibilityFactor: 1 + mode: readwrite + name: join_buffer_size + optional: '[128-4294967295]' + restart: false + unit: INT + - defaultValue: '16777216' + divisibilityFactor: 1 + mode: readwrite + name: key_buffer_size + optional: .* + restart: true + unit: INT + - defaultValue: '300' + divisibilityFactor: 100 + mode: readwrite + name: key_cache_age_threshold + optional: '[100-4294967295]' + restart: false + unit: INT + - defaultValue: '1024' + divisibilityFactor: 512 + mode: readwrite + name: key_cache_block_size + optional: '[512-16384]' + restart: false + unit: B + - defaultValue: '100' + divisibilityFactor: 1 + mode: readwrite + name: key_cache_division_limit + optional: '[1-100]' + restart: false + unit: INT + - defaultValue: en_US + divisibilityFactor: 0 + mode: readwrite + name: lc_time_names + optional: '[ja_JP|pt_BR|en_US]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: local_infile + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '31536000' + divisibilityFactor: 1 + mode: readwrite + name: lock_wait_timeout + optional: '[1-1073741824]' + restart: false + unit: INT + - defaultValue: '1' + divisibilityFactor: 0 + mode: readwrite + name: log_bin_use_v1_row_events + optional: '[0|1]' + restart: false + unit: STRING + - defaultValue: '2' + divisibilityFactor: 1 + mode: readwrite + name: log_error_verbosity + optional: '[1-3]' + restart: false + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: log_queries_not_using_indexes + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '0' + divisibilityFactor: 0 + mode: readwrite + name: log_slave_updates + optional: .* + restart: true + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: log_slow_admin_statements + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: log_throttle_queries_not_using_indexes + optional: '[0-4294967295]' + restart: false + unit: INT + - defaultValue: '1' + divisibilityFactor: 6 + mode: readwrite + name: long_query_time + optional: '[0.1-31536000]' + restart: false + unit: DOUBLE + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_ccl_max_waiting_count + optional: '[0-9223372036854775807]' + restart: false + unit: INT + - defaultValue: '4' + divisibilityFactor: 1 + mode: readwrite + name: loose_ccl_queue_bucket_count + optional: '[1-64]' + restart: false + unit: INT + - defaultValue: '64' + divisibilityFactor: 1 + mode: readwrite + name: loose_ccl_queue_bucket_size + optional: '[1-4096]' + restart: false + unit: INT + - defaultValue: '86400' + divisibilityFactor: 1 + mode: readwrite + name: loose_ccl_wait_timeout + optional: '[1-31536000]' + restart: false + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: loose_consensus_auto_leader_transfer + optional: .* + restart: true + unit: STRING + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: loose_consensus_auto_reset_match_index + optional: .* + restart: true + unit: STRING + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_consensus_election_timeout + optional: .* + restart: true + unit: INT + - defaultValue: '8' + divisibilityFactor: 1 + mode: readwrite + name: loose_consensus_io_thread_cnt + optional: .* + restart: true + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: loose_consensus_large_trx + optional: .* + restart: true + unit: STRING + - defaultValue: '536870912' + divisibilityFactor: 1 + mode: readwrite + name: loose_consensus_log_cache_size + optional: .* + restart: true + unit: INT + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_consensus_max_delay_index + optional: .* + restart: true + unit: INT + - defaultValue: '20971520' + divisibilityFactor: 1 + mode: readwrite + name: loose_consensus_max_log_size + optional: .* + restart: true + unit: INT + - defaultValue: '131072' + divisibilityFactor: 1 + mode: readwrite + name: loose_consensus_max_packet_size + optional: .* + restart: true + unit: INT + - defaultValue: '268435456' + divisibilityFactor: 1 + mode: readwrite + name: loose_consensus_prefetch_cache_size + optional: .* + restart: true + unit: INT + - defaultValue: '8' + divisibilityFactor: 1 + mode: readwrite + name: loose_consensus_worker_thread_cnt + optional: .* + restart: true + unit: INT + - defaultValue: '1' + divisibilityFactor: 1 + mode: readwrite + name: loose_implicit_primary_key + optional: '[0-1]' + restart: false + unit: INT + - defaultValue: '86400' + divisibilityFactor: 1 + mode: readwrite + name: loose_information_schema_stats_expiry + optional: '[0-31536000]' + restart: false + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_innodb_buffer_pool_in_core_file + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: '64' + divisibilityFactor: 1 + mode: readwrite + name: loose_innodb_doublewrite_pages + optional: '[0-512]' + restart: true + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_innodb_lizard_stat_enabled + optional: '[ON|OFF]' + restart: true + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_innodb_log_compressed_pages + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_innodb_log_optimize_ddl + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '4096' + divisibilityFactor: 1 + mode: readwrite + name: loose_innodb_log_write_ahead_size + optional: '[512-16384]' + restart: false + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: loose_innodb_multi_blocks_enabled + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_innodb_numa_interleave + optional: '[ON|OFF]' + restart: true + unit: STRING + - defaultValue: '1' + divisibilityFactor: 1 + mode: readwrite + name: loose_innodb_parallel_read_threads + optional: '[0-256]' + restart: false + unit: INT + - defaultValue: '1800' + divisibilityFactor: 1 + mode: readwrite + name: loose_innodb_undo_retention + optional: '[0-172800]' + restart: false + unit: INT + - defaultValue: '1024' + divisibilityFactor: 1 + mode: readwrite + name: loose_innodb_undo_space_reserved_size + optional: '[0-20480]' + restart: false + unit: INT + - defaultValue: '102400' + divisibilityFactor: 1 + mode: readwrite + name: loose_innodb_undo_space_supremum_size + optional: '[0-524288]' + restart: false + unit: INT + - defaultValue: TempTable + divisibilityFactor: 0 + mode: readwrite + name: loose_internal_tmp_mem_storage_engine + optional: '[TempTable|MEMORY]' + restart: false + unit: STRING + - defaultValue: index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on,loosescan=on,firstmatch=on,subquery_materialization_cost_based=on,use_index_extensions=on + divisibilityFactor: 0 + mode: readwrite + name: loose_optimizer_switch + optional: .* + restart: false + unit: STRING + - defaultValue: enabled=off,one_line=off + divisibilityFactor: 0 + mode: readwrite + name: loose_optimizer_trace + optional: .* + restart: false + unit: STRING + - defaultValue: greedy_search=on,range_optimizer=on,dynamic_range=on,repeated_subselect=on + divisibilityFactor: 0 + mode: readwrite + name: loose_optimizer_trace_features + optional: .* + restart: false + unit: STRING + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_point_lock_rwlock_enabled + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_accounts_size + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_schema_consumer_events_stages_current + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_schema_consumer_events_stages_history + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_schema_consumer_events_stages_history_long + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_schema_consumer_events_statements_current + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_schema_consumer_events_statements_history + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_schema_consumer_events_statements_history_long + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_schema_consumer_events_transactions_current + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_schema_consumer_events_transactions_history + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_schema_consumer_events_transactions_history_long + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_schema_consumer_events_waits_current + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_schema_consumer_events_waits_history + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_schema_consumer_events_waits_history_long + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_schema_consumer_global_instrumentation + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_schema_consumer_statements_digest + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_schema_consumer_thread_instrumentation + optional: '[OFF|ON]' + restart: false + unit: STRING + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_digests_size + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_error_size + optional: '[0-1048576]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_events_stages_history_long_size + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_events_stages_history_size + optional: '[-1-1024]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_events_statements_history_long_size + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_events_statements_history_size + optional: '[-1-1024]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_events_transactions_history_long_size + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_events_transactions_history_size + optional: '[-1-1024]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_events_waits_history_long_size + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_events_waits_history_size + optional: '[-1-1024]' + restart: true + unit: INT + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_hosts_size + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: "'%%%%=OFF'" + divisibilityFactor: 0 + mode: readwrite + name: performance_schema_instrument + optional: .* + restart: true + unit: STRING + - defaultValue: '''wait/lock/metadata/sql/mdl=ON''' + divisibilityFactor: 0 + mode: readwrite + name: loose_performance_schema_instrument + optional: .* + restart: true + unit: STRING + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_cond_classes + optional: '[0-256]' + restart: true + unit: INT + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_cond_instances + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_digest_length + optional: '[0-1048576]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_digest_sample_age + optional: '[0-1048576]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_file_classes + optional: '[0-256]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_file_handles + optional: '[-1-32768]' + restart: true + unit: INT + - defaultValue: '1000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_file_instances + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_index_stat + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_memory_classes + optional: '[0-1024]' + restart: true + unit: INT + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_metadata_locks + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_mutex_classes + optional: '[0-256]' + restart: true + unit: INT + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_mutex_instances + optional: '[-1-104857600]' + restart: true + unit: INT + - defaultValue: '1000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_prepared_statements_instances + optional: '[-1-4194304]' + restart: true + unit: INT + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_program_instances + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_rwlock_classes + optional: '[0-256]' + restart: true + unit: INT + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_rwlock_instances + optional: '[-1-104857600]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_socket_classes + optional: '[0-256]' + restart: true + unit: INT + - defaultValue: '1000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_socket_instances + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_sql_text_length + optional: '[0-1048576]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_stage_classes + optional: '[0-256]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_statement_classes + optional: '[0-256]' + restart: true + unit: INT + - defaultValue: '1' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_statement_stack + optional: '[0-256]' + restart: true + unit: INT + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_table_handles + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '1000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_table_instances + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_table_lock_stat + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_thread_classes + optional: '[0-256]' + restart: true + unit: INT + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_max_thread_instances + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_session_connect_attrs_size + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_setup_actors_size + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_setup_objects_size + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: loose_performance_schema_users_size + optional: '[-1-1048576]' + restart: true + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 1 + mode: readwrite + name: loose_persist_binlog_to_redo + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '1048576' + divisibilityFactor: 1 + mode: readwrite + name: loose_persist_binlog_to_redo_size_limit + optional: '[0-10485760]' + restart: false + unit: STRING + - defaultValue: '16777216' + divisibilityFactor: 1 + mode: readwrite + name: loose_rds_audit_log_buffer_size + optional: '[16777216-104857600]' + restart: false + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_rds_audit_log_enabled + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '8192' + divisibilityFactor: 1 + mode: readwrite + name: loose_rds_audit_log_event_buffer_size + optional: '[0-32768]' + restart: false + unit: INT + - defaultValue: '100000' + divisibilityFactor: 1 + mode: readwrite + name: loose_rds_audit_log_row_limit + optional: '[0-100000000]' + restart: false + unit: INT + - defaultValue: MYSQL_V1 + divisibilityFactor: 0 + mode: readwrite + name: loose_rds_audit_log_version + optional: '[MYSQL_V1|MYSQL_V3]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_recovery_apply_binlog + optional: '[ON|OFF]' + restart: true + unit: STRING + - defaultValue: '3000' + divisibilityFactor: 1 + mode: readwrite + name: loose_replica_read_timeout + optional: '[0-2147483647]' + restart: true + unit: INT + - defaultValue: '"*"' + divisibilityFactor: 0 + mode: readwrite + name: loose_session_track_system_variables + optional: .* + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: loose_session_track_transaction_info + optional: '[STATE|CHARACTERISTICS|OFF]' + restart: false + unit: STRING + - defaultValue: '32' + divisibilityFactor: 1 + mode: readwrite + name: loose_slave_parallel_workers + optional: '[0-1024]' + restart: false + unit: INT + - defaultValue: '0' + divisibilityFactor: 0 + mode: readwrite + name: low_priority_updates + optional: '[0|1]' + restart: false + unit: STRING + - defaultValue: '1' + divisibilityFactor: 0 + mode: readwrite + name: lower_case_table_names + optional: '[0|1]' + restart: true + unit: STRING + - defaultValue: TABLE + divisibilityFactor: 0 + mode: readwrite + name: master_info_repository + optional: '[TABLE|FILE]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: master_verify_checksum + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '1073741824' + divisibilityFactor: 1 + mode: readwrite + name: max_allowed_packet + optional: '[16384-1073741824]' + restart: false + unit: INT + - defaultValue: '18446744073709551615' + divisibilityFactor: 1 + mode: readwrite + name: max_binlog_cache_size + optional: '[4096-18446744073709547520]' + restart: false + unit: INT + - defaultValue: '18446744073709551615' + divisibilityFactor: 4096 + mode: readwrite + name: max_binlog_stmt_cache_size + optional: '[4096-18446744073709547520]' + restart: false + unit: INT + - defaultValue: '65536' + divisibilityFactor: 1 + mode: readwrite + name: max_connect_errors + optional: '[0-4294967295]' + restart: false + unit: INT + - defaultValue: '5532' + divisibilityFactor: 1 + mode: readwrite + name: max_connections + optional: .* + restart: true + unit: INT + - defaultValue: '1024' + divisibilityFactor: 1 + mode: readwrite + name: max_error_count + optional: '[0-65535]' + restart: false + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: max_execution_time + optional: '[0-4294967295]' + restart: false + unit: INT + - defaultValue: '67108864' + divisibilityFactor: 1024 + mode: readwrite + name: max_heap_table_size + optional: '[16384-1844674407370954752]' + restart: false + unit: INT + - defaultValue: '18446744073709551615' + divisibilityFactor: 1 + mode: readwrite + name: max_join_size + optional: '[1-18446744073709551615]' + restart: false + unit: INT + - defaultValue: '4096' + divisibilityFactor: 1 + mode: readwrite + name: max_length_for_sort_data + optional: '[0-838860]' + restart: false + unit: INT + - defaultValue: '65536' + divisibilityFactor: 1 + mode: readwrite + name: max_points_in_geometry + optional: '[3-1048576]' + restart: false + unit: INT + - defaultValue: '16382' + divisibilityFactor: 1 + mode: readwrite + name: max_prepared_stmt_count + optional: '[0-1048576]' + restart: false + unit: INT + - defaultValue: '18446744073709551615' + divisibilityFactor: 1 + mode: readwrite + name: max_seeks_for_key + optional: '[1-18446744073709551615]' + restart: false + unit: INT + - defaultValue: '1024' + divisibilityFactor: 1 + mode: readwrite + name: max_sort_length + optional: '[4-8388608]' + restart: false + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: max_sp_recursion_depth + optional: '[0-255]' + restart: false + unit: INT + - defaultValue: '5000' + divisibilityFactor: 1 + mode: readwrite + name: max_user_connections + optional: .* + restart: true + unit: INT + - defaultValue: '102400' + divisibilityFactor: 1 + mode: readwrite + name: max_write_lock_count + optional: '[1-102400]' + restart: false + unit: INT + - defaultValue: '0' + divisibilityFactor: 1 + mode: readwrite + name: min_examined_row_limit + optional: '[0-4294967295]' + restart: false + unit: INT + - defaultValue: '262144' + divisibilityFactor: 1 + mode: readwrite + name: myisam_sort_buffer_size + optional: '[262144-16777216]' + restart: false + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: mysql_native_password_proxy_users + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '16384' + divisibilityFactor: 1024 + mode: readwrite + name: net_buffer_length + optional: '[1024-1048576]' + restart: false + unit: INT + - defaultValue: '30' + divisibilityFactor: 1 + mode: readwrite + name: net_read_timeout + optional: '[1-18446744073709551615]' + restart: false + unit: INT + - defaultValue: '10' + divisibilityFactor: 1 + mode: readwrite + name: net_retry_count + optional: '[1-4294967295]' + restart: false + unit: INT + - defaultValue: '60' + divisibilityFactor: 1 + mode: readwrite + name: net_write_timeout + optional: '[1-18446744073709551615]' + restart: false + unit: INT + - defaultValue: '2' + divisibilityFactor: 1 + mode: readwrite + name: ngram_token_size + optional: '[0-20]' + restart: true + unit: int + - defaultValue: '65535' + divisibilityFactor: 1 + mode: readwrite + name: open_files_limit + optional: '[1-2147483647]' + restart: true + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: opt_indexstat + optional: '[ON|OFF]' + restart: true + unit: STRING + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: opt_tablestat + optional: '[ON|OFF]' + restart: true + unit: STRING + - defaultValue: '1' + divisibilityFactor: 0 + mode: readwrite + name: optimizer_prune_level + optional: '[0|1]' + restart: false + unit: STRING + - defaultValue: '62' + divisibilityFactor: 1 + mode: readwrite + name: optimizer_search_depth + optional: '[0-62]' + restart: false + unit: INT + - defaultValue: '1' + divisibilityFactor: 1 + mode: readwrite + name: optimizer_trace_limit + optional: '[0-4294967295]' + restart: false + unit: INT + - defaultValue: '1048576' + divisibilityFactor: 1 + mode: readwrite + name: optimizer_trace_max_mem_size + optional: '[0-4294967295]' + restart: false + unit: INT + - defaultValue: '-1' + divisibilityFactor: 1 + mode: readwrite + name: optimizer_trace_offset + optional: '[-2147483648-2147483647]' + restart: false + unit: INT + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: performance_schema + optional: '[ON|OFF]' + restart: true + unit: STRING + - defaultValue: '32768' + divisibilityFactor: 1 + mode: readwrite + name: preload_buffer_size + optional: '[1024-1073741824]' + restart: false + unit: INT + - defaultValue: '8192' + divisibilityFactor: 1024 + mode: readwrite + name: query_alloc_block_size + optional: '[1024-16384]' + restart: false + unit: INT + - defaultValue: '8192' + divisibilityFactor: 1024 + mode: readwrite + name: query_prealloc_size + optional: '[8192-1048576]' + restart: false + unit: INT + - defaultValue: '4096' + divisibilityFactor: 1 + mode: readwrite + name: range_alloc_block_size + optional: '[4096-18446744073709551615]' + restart: false + unit: INT + - defaultValue: '8388608' + divisibilityFactor: 1 + mode: readwrite + name: range_optimizer_max_mem_size + optional: '[0-18446744073709551615]' + restart: false + unit: INT + - defaultValue: '{LEAST(DBInstanceClassMemory/1048576*128, 262144)}' + divisibilityFactor: 1 + mode: readwrite + name: read_buffer_size + optional: '[8200-2147479552]' + restart: false + unit: INT + - defaultValue: '442368' + divisibilityFactor: 1 + mode: readwrite + name: read_rnd_buffer_size + optional: .* + restart: true + unit: INT + - defaultValue: TABLE + divisibilityFactor: 0 + mode: readwrite + name: relay_log_info_repository + optional: '[TABLE|FILE]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: relay_log_purge + optional: .* + restart: true + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: relay_log_recovery + optional: '[ON|OFF]' + restart: true + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: replicate_same_server_id + optional: .* + restart: true + unit: STRING + - defaultValue: '' + divisibilityFactor: 0 + mode: readwrite + name: rotate_log_table_last_name + optional: .* + restart: true + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: session_track_gtids + optional: '[OFF|OWN_GTID|ALL_GTIDS]' + restart: false + unit: STRING + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: session_track_schema + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: session_track_state_change + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: sha256_password_proxy_users + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: show_old_temporals + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: skip_slave_start + optional: .* + restart: true + unit: STRING + - defaultValue: 'ON' + divisibilityFactor: 0 + mode: readwrite + name: skip_ssl + optional: .* + restart: true + unit: STRING + - defaultValue: strict + divisibilityFactor: 0 + mode: readwrite + name: slave_exec_mode + optional: strict + restart: false + unit: STRING + - defaultValue: '4' + divisibilityFactor: 1 + mode: readwrite + name: slave_net_timeout + optional: '[15-300]' + restart: false + unit: INT + - defaultValue: LOGICAL_CLOCK + divisibilityFactor: 0 + mode: readwrite + name: slave_parallel_type + optional: '[DATABASE|LOGICAL_CLOCK]' + restart: true + unit: STRING + - defaultValue: '1073741824' + divisibilityFactor: 1 + mode: readwrite + name: slave_pending_jobs_size_max + optional: .* + restart: true + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: slave_sql_verify_checksum + optional: .* + restart: true + unit: STRING + - defaultValue: '' + divisibilityFactor: 0 + mode: readwrite + name: slave_type_conversions + optional: '[s*|ALL_LOSSY|ALL_NON_LOSSY|ALL_SIGNED|ALL_UNSIGNED]' + restart: true + unit: STRING + - defaultValue: '2' + divisibilityFactor: 1 + mode: readwrite + name: slow_launch_time + optional: '[1-1024]' + restart: false + unit: INT + - defaultValue: 'OFF' + divisibilityFactor: 0 + mode: readwrite + name: slow_query_log + optional: '[ON|OFF]' + restart: false + unit: STRING + - defaultValue: '868352' + divisibilityFactor: 1 + mode: readwrite + name: sort_buffer_size + optional: '[32768-4294967295]' + restart: false + unit: INT + - defaultValue: NO_ENGINE_SUBSTITUTION + divisibilityFactor: 0 + mode: readwrite + name: sql_mode + optional: (s*|REAL_AS_FLOAT|PIPES_AS_CONCAT|ANSI_QUOTES|IGNORE_SPACE|ONLY_FULL_GROUP_BY|NO_UNSIGNED_SUBTRACTION|NO_DIR_IN_CREATE|ANSI|NO_AUTO_VALUE_ON_ZERO|NO_BACKSLASH_ESCAPES|STRICT_TRANS_TABLES|STRICT_ALL_TABLES|NO_ZERO_IN_DATE|NO_ZERO_DATE|ALLOW_INVALID_DATES|ERROR_FOR_DIVISION_BY_ZERO|TRADITIONAL|HIGH_NOT_PRECEDENCE|NO_ENGINE_SUBSTITUTION|PAD_CHAR_TO_FULL_LENGTH)(,REAL_AS_FLOAT|,PIPES_AS_CONCAT|,ANSI_QUOTES|,IGNORE_SPACE|,ONLY_FULL_GROUP_BY|,NO_UNSIGNED_SUBTRACTION|,NO_DIR_IN_CREATE|,ANSI|,NO_AUTO_VALUE_ON_ZERO|,NO_BACKSLASH_ESCAPES|,STRICT_TRANS_TABLES|,STRICT_ALL_TABLES|,NO_ZERO_IN_DATE|,NO_ZERO_DATE|,ALLOW_INVALID_DATES|,ERROR_FOR_DIVISION_BY_ZERO|,TRADITIONAL|,HIGH_NOT_PRECEDENCE|,NO_ENGINE_SUBSTITUTION|,PAD_CHAR_TO_FULL_LENGTH)* + restart: false + unit: STRING + - defaultValue: '256' + divisibilityFactor: 1 + mode: readwrite + name: stored_program_cache + optional: '[16-524288]' + restart: false + unit: INT + - defaultValue: '1' + divisibilityFactor: 1 + mode: readwrite + name: sync_binlog + optional: .* + restart: true + unit: INT + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: sync_master_info + optional: '[0-18446744073709551615]' + restart: false + unit: INT + - defaultValue: '1' + divisibilityFactor: 1 + mode: readwrite + name: sync_relay_log + optional: .* + restart: true + unit: INT + - defaultValue: '10000' + divisibilityFactor: 1 + mode: readwrite + name: sync_relay_log_info + optional: '[0-18446744073709551615]' + restart: false + unit: INT + - defaultValue: '{LEAST(DBInstanceClassMemory/1073741824*512, 2048)}' + divisibilityFactor: 1 + mode: readwrite + name: table_definition_cache + optional: '[400-524288]' + restart: false + unit: INT + - defaultValue: '{LEAST(DBInstanceClassMemory/1073741824*512, 8192)}' + divisibilityFactor: 1 + mode: readwrite + name: table_open_cache + optional: '[1-524288]' + restart: false + unit: INT + - defaultValue: '16' + divisibilityFactor: 1 + mode: readwrite + name: table_open_cache_instances + optional: '[1-64]' + restart: true + unit: INT + - defaultValue: '1073741824' + divisibilityFactor: 1 + mode: readwrite + name: temptable_max_ram + optional: '[2097152-107374182400]' + restart: false + unit: INT + - defaultValue: '100' + divisibilityFactor: 1 + mode: readwrite + name: thread_cache_size + optional: '[0-16384]' + restart: false + unit: INT + - defaultValue: '262144' + divisibilityFactor: 1024 + mode: readwrite + name: thread_stack + optional: '[131072-2147483647]' + restart: true + unit: INT + - defaultValue: TLSv1,TLSv1.1,TLSv1.2 + divisibilityFactor: 0 + mode: readwrite + name: tls_version + optional: '[TLSv1,TLSv1.1,TLSv1.2|TLSv1,TLSv1.1|TLSv1.2]' + restart: true + unit: STRING + - defaultValue: '2097152' + divisibilityFactor: 1 + mode: readwrite + name: tmp_table_size + optional: '[262144-134217728]' + restart: false + unit: INT + - defaultValue: '8192' + divisibilityFactor: 1024 + mode: readwrite + name: transaction_alloc_block_size + optional: '[1024-131072]' + restart: false + unit: INT + - defaultValue: REPEATABLE-READ + divisibilityFactor: 0 + mode: readwrite + name: transaction_isolation + optional: '[READ-UNCOMMITTED|READ-COMMITTED|REPEATABLE-READ|SERIALIZABLE]' + restart: false + unit: STRING + - defaultValue: '4096' + divisibilityFactor: 1024 + mode: readwrite + name: transaction_prealloc_size + optional: '[1024-131072]' + restart: false + unit: INT + - defaultValue: XXHASH64 + divisibilityFactor: 1 + mode: readwrite + name: transaction_write_set_extraction + optional: '[OFF|MURMUR32|XXHASH64]' + restart: false + unit: STRING + - defaultValue: 'YES' + divisibilityFactor: 0 + mode: readwrite + name: updatable_views_with_limit + optional: '[YES|NO]' + restart: false + unit: STRING + - defaultValue: '28800' + divisibilityFactor: 1 + mode: readwrite + name: wait_timeout + optional: '[1-31536000]' + restart: false + unit: INT diff --git a/charts/polardbx-operator/values.yaml b/charts/polardbx-operator/values.yaml index 9471c6d..2a052de 100644 --- a/charts/polardbx-operator/values.yaml +++ b/charts/polardbx-operator/values.yaml @@ -71,6 +71,7 @@ controllerManager: # Container settings of PolarDB-X pods. container: privileged: false + forceCGroup: false nodeSelector: { } affinity: { } diff --git a/pkg/binlogtool/cmd/cpshow.go b/pkg/binlogtool/cmd/cpshow.go index 9fc9b48..2261dbc 100644 --- a/pkg/binlogtool/cmd/cpshow.go +++ b/pkg/binlogtool/cmd/cpshow.go @@ -45,17 +45,14 @@ func init() { // =========Consistent point file layout=========== // TXID LENGTH -- 4 bytes // REPEAT -// -// TXID -- 8 bytes -// +// TXID -- 8 bytes // STREAM LENGTH -- 2 bytes // REPEAT -// -// STREAM NAME LEN -- 1 byte -// STREAM NAME -- len bytes -// OFFSET BINLOG FILE NAME LEN -- 1 byte -// OFFSET BINLOG FILE NAME -- len bytes -// OFFSET -- 8 bytes +// STREAM NAME LEN -- 1 byte +// STREAM NAME -- len bytes +// OFFSET BINLOG FILE NAME LEN -- 1 byte +// OFFSET BINLOG FILE NAME -- len bytes +// OFFSET -- 8 bytes func parseConsistentPoint(gr io.Reader) (map[uint64]int, map[string]binlog.EventOffset, error) { var length uint32 if err := layout.Number(&length).FromStream(gr); err != nil { diff --git a/pkg/hpfs/remote/aliyun_oss.go b/pkg/hpfs/remote/aliyun_oss.go index ca081ce..15bd136 100644 --- a/pkg/hpfs/remote/aliyun_oss.go +++ b/pkg/hpfs/remote/aliyun_oss.go @@ -207,11 +207,11 @@ func (o *aliyunOssFs) UploadFile(ctx context.Context, reader io.Reader, path str pageNumber := 1 copiedParts := make([]oss.UploadPart, 0) if totalSize%limitReaderSize != 0 { + imur, err = bucket.InitiateMultipartUpload(path, opts...) + if err != nil { + return + } for { - imur, err = bucket.InitiateMultipartUpload(path, opts...) - if err != nil { - return - } partSize := totalSize - copyPosition if partSize >= MaxPartSize { partSize = MaxPartSize diff --git a/pkg/k8s/prometheus/TBD b/pkg/k8s/prometheus/TBD new file mode 100644 index 0000000..e69de29 diff --git a/pkg/meta/core/gms/manager_impl.go b/pkg/meta/core/gms/manager_impl.go index c39993e..84bd683 100644 --- a/pkg/meta/core/gms/manager_impl.go +++ b/pkg/meta/core/gms/manager_impl.go @@ -612,7 +612,7 @@ func (meta *manager) RestoreSchemas(fromPxcCluster, fromPxcHash, PxcHash string) // Reset the single group's storage id //goland:noinspection SqlNoDataSourceInspection,SqlResolve - _, err = conn.ExecContext(ctx, "UPDATE inst_config SET param_val=REPLACE(param_val, ?, ?) where param_key='SINGLE_GROUP_STORAGE_INST_LIST'", fromPxcCluster+"-"+fromPxcHash, meta.getClusterID()+"-"+fromPxcHash) + _, err = conn.ExecContext(ctx, "UPDATE inst_config SET param_val=REPLACE(param_val, ?, ?) where param_key='SINGLE_GROUP_STORAGE_INST_LIST'", fromPxcCluster+"-"+fromPxcHash, meta.getClusterID()+"-"+PxcHash) if err != nil { return errors.New("unable to reset single group's storage id: " + err.Error()) } diff --git a/pkg/meta/core/group/group_manager.go b/pkg/meta/core/group/group_manager.go index 2a39f71..bcc23ab 100644 --- a/pkg/meta/core/group/group_manager.go +++ b/pkg/meta/core/group/group_manager.go @@ -73,6 +73,28 @@ type DDLPlanStatus struct { Progress int `json:"progress,omitempty"` // Progress } +// SlaveStatus describes slave status for xstore follower/logger +type SlaveStatus struct { + SlaveSQLRunning string `json:"slave_sql_running,omitempty"` // Slave_SQL_Running + LastError string `json:"last_error,omitempty"` // Last_Error +} + +// ClusterStatus describes status of xstore cluster +type ClusterStatus struct { + ServerId int `json:"server_id,omitempty"` // SERVER_ID + IPPort string `json:"ip_port,omitempty"` // IP_PORT + MatchIndex int64 `json:"match_index,omitempty"` // MATCH_INDEX + NextIndex int64 `json:"next_index,omitempty"` // NEXT_INDEX + Role string `json:"role,omitempty"` // ROLE + HasVoted string `json:"has_voted,omitempty"` // HAS_VOTED + ForceSync string `json:"force_sync,omitempty"` // FORCE_SYNC + ElectionWeight int64 `json:"election_weight,omitempty"` // ELECTION_WEIGHT + LearnerSource int64 `json:"learner_source,omitempty"` // LEARNER_SOURCE + AppliedIndex int64 `json:"applied_index,omitempty"` // APPLIED_INDEX + Pipelining string `json:"pipelining,omitempty"` // PIPELINING + SendApplied string `json:"send_applied,omitempty"` // SEND_APPLIED +} + func (s *DDLPlanStatus) IsSuccess() bool { return strings.ToUpper(s.State) == "SUCCESS" } @@ -101,6 +123,8 @@ type GroupManager interface { ListFileStorage() ([]polardbx.FileStorageInfo, error) CreateFileStorage(info polardbx.FileStorageInfo, config config.Config) error DropFileStorage(fileStorageName string) error + ShowSlaveStatus() (*SlaveStatus, error) + ShowClusterStatus() ([]*ClusterStatus, error) } type groupManager struct { @@ -833,6 +857,76 @@ func (m *groupManager) SetGlobalVariables(variables map[string]string) error { return nil } +// ShowSlaveStatus aims to check slave status, which should only be used for follower/logger of xstore +func (m *groupManager) ShowSlaveStatus() (*SlaveStatus, error) { + conn, err := m.getConn("") + if err != nil { + return nil, err + } + defer dbutil.DeferClose(conn) + + rs, err := conn.QueryContext(m.ctx, fmt.Sprintf("SHOW SLAVE STATUS")) + if err != nil { + return nil, err + } + defer dbutil.DeferClose(rs) + + if !rs.Next() { + return nil, nil + } + + status := &SlaveStatus{} + dest := map[string]interface{}{ + "Slave_SQL_Running": &status.SlaveSQLRunning, + "Last_Error": &status.LastError, + } + err = dbutil.Scan(rs, dest, dbutil.ScanOpt{CaseInsensitive: true}) + if err != nil { + return nil, err + } + return status, nil +} + +// ShowClusterStatus aims to check global status of xstore cluster +func (m *groupManager) ShowClusterStatus() ([]*ClusterStatus, error) { + conn, err := m.getConn("") + if err != nil { + return nil, err + } + defer dbutil.DeferClose(conn) + + rs, err := conn.QueryContext(m.ctx, fmt.Sprintf("SELECT * FROM INFORMATION_SCHEMA.ALISQL_CLUSTER_GLOBAL")) + if err != nil { + return nil, err + } + defer dbutil.DeferClose(rs) + + var statusList []*ClusterStatus + for rs.Next() { + status := &ClusterStatus{} + dest := map[string]interface{}{ + "SERVER_ID": &status.ServerId, + "IP_PORT": &status.IPPort, + "MATCH_INDEX": &status.MatchIndex, + "NEXT_INDEX": &status.NextIndex, + "ROLE": &status.Role, + "HAS_VOTED": &status.HasVoted, + "FORCE_SYNC": &status.ForceSync, + "ELECTION_WEIGHT": &status.ElectionWeight, + "LEARNER_SOURCE": &status.LearnerSource, + "APPLIED_INDEX": &status.AppliedIndex, + "PIPELINING": &status.Pipelining, + "SEND_APPLIED": &status.SendApplied, + } + err = dbutil.Scan(rs, dest, dbutil.ScanOpt{CaseInsensitive: true}) + if err != nil { + return nil, err + } + statusList = append(statusList, status) + } + return statusList, nil +} + func NewGroupManagerWithDB(ctx context.Context, db *sql.DB, caseInsensitive bool) GroupManager { if ctx == nil { ctx = context.Background() diff --git a/pkg/operator/v1/config/config.go b/pkg/operator/v1/config/config.go index 1da4c7b..997cab6 100644 --- a/pkg/operator/v1/config/config.go +++ b/pkg/operator/v1/config/config.go @@ -159,6 +159,7 @@ type clusterConfig struct { OptionEnableAliyunAckResourceController bool `json:"enable_aliyun_ack_resource_controller,omitempty"` OptionEnableDebugModeForComputeNodes bool `json:"enable_debug_mode_for_compute_nodes,omitempty"` OptionEnablePrivilegedContainer bool `json:"enable_privileged_container,omitempty"` + OptionForceCGroup bool `json:"force_cgroup,omitempty"` } func (c *clusterConfig) EnableExporters() bool { @@ -177,6 +178,10 @@ func (c *clusterConfig) ContainerPrivileged() bool { return c.OptionEnablePrivilegedContainer } +func (c *clusterConfig) ForceCGroup() bool { + return c.OptionForceCGroup +} + type storeConfig struct { EnablePrivilegedContainer bool `json:"enable_privileged_container,omitempty"` HostPaths map[string]string `json:"host_paths,omitempty"` diff --git a/pkg/operator/v1/config/interface.go b/pkg/operator/v1/config/interface.go index 988593e..df24a14 100644 --- a/pkg/operator/v1/config/interface.go +++ b/pkg/operator/v1/config/interface.go @@ -44,8 +44,8 @@ type ClusterConfig interface { EnableExporters() bool EnableAliyunAckResourceController() bool EnableDebugModeForComputeNodes() bool - ContainerPrivileged() bool + ForceCGroup() bool } type StoreConfig interface { diff --git a/pkg/operator/v1/operator.go b/pkg/operator/v1/operator.go index 9ea91d6..2182285 100644 --- a/pkg/operator/v1/operator.go +++ b/pkg/operator/v1/operator.go @@ -211,12 +211,12 @@ func setupXStoreBackupControllers(opts controllerOptions) error { // to handle signals correctly. The second parameter opts defines the configurable options of controllers. // // Currently, these controllers are included: -// 1. Controller for PolarDBXCluster (v1) -// 2. Controller for XStore (v1) -// 3. Controllers for PolarDBXBackup, PolarDBXBinlogBackup (v1) -// 4. Controllers for XStoreBackup, XStoreBinlogBackup (v1) -// 5. Controllers for PolarDBXBackupSchedule, PolarDBXBinlogBackupSchedule (v1) -// 6. Controllers for PolarDBXParameter (v1) +// 1. Controller for PolarDBXCluster (v1) +// 2. Controller for XStore (v1) +// 3. Controllers for PolarDBXBackup, PolarDBXBinlogBackup (v1) +// 4. Controllers for XStoreBackup, XStoreBinlogBackup (v1) +// 5. Controllers for PolarDBXBackupSchedule, PolarDBXBinlogBackupSchedule (v1) +// 6. Controllers for PolarDBXParameter (v1) func Start(ctx context.Context, opts Options) { // Start instruction loader. hint.StartLoader(ctx) diff --git a/pkg/operator/v1/polardbx/controllers/polardbxbackup_controller.go b/pkg/operator/v1/polardbx/controllers/polardbxbackup_controller.go index bf21c40..ab6e946 100644 --- a/pkg/operator/v1/polardbx/controllers/polardbxbackup_controller.go +++ b/pkg/operator/v1/polardbx/controllers/polardbxbackup_controller.go @@ -28,6 +28,7 @@ import ( "golang.org/x/time/rate" batchv1 "k8s.io/api/batch/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/util/workqueue" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/controller" @@ -68,6 +69,11 @@ func (r *PolarDBXBackupReconciler) Reconcile(ctx context.Context, request reconc return reconcile.Result{}, err } + rc.SetPolarDBXKey(types.NamespacedName{ + Namespace: request.Namespace, + Name: polardbxBackup.Spec.Cluster.Name, + }) + return r.reconcile(rc, polardbxBackup, log) } @@ -96,6 +102,7 @@ func (r *PolarDBXBackupReconciler) newReconcileTask(rc *polardbxreconcile.Contex commonsteps.CollectBinlogStartIndex(task) commonsteps.DrainCommittingTrans(task) commonsteps.SendHeartBeat(task) + commonsteps.WaitHeartbeatSentToFollower(task) commonsteps.CollectBinlogEndIndex(task) commonsteps.TransferPhaseTo(polardbxv1.BackupCalculating, false)(task) case polardbxv1.BackupCalculating: diff --git a/pkg/operator/v1/polardbx/controllers/polardbxcluster_controller.go b/pkg/operator/v1/polardbx/controllers/polardbxcluster_controller.go index 686a81f..d949de4 100644 --- a/pkg/operator/v1/polardbx/controllers/polardbxcluster_controller.go +++ b/pkg/operator/v1/polardbx/controllers/polardbxcluster_controller.go @@ -126,6 +126,8 @@ func (r *PolarDBXReconciler) newReconcileTask(rc *polardbxreconcile.Context, pol commonsteps.InitializePolardbxLabel(task) commonsteps.GenerateRandInStatus(task) commonsteps.InitializeServiceName(task) + control.When(polardbx.Spec.Restore != nil, + commonsteps.SyncSpecFromBackupSet)(task) commonsteps.TransferPhaseTo(polardbxv1polardbx.PhasePending, true)(task) case polardbxv1polardbx.PhasePending: diff --git a/pkg/operator/v1/polardbx/controllers/polardbxparameter_controller.go b/pkg/operator/v1/polardbx/controllers/polardbxparameter_controller.go index 74656b1..41ababe 100644 --- a/pkg/operator/v1/polardbx/controllers/polardbxparameter_controller.go +++ b/pkg/operator/v1/polardbx/controllers/polardbxparameter_controller.go @@ -108,9 +108,10 @@ func (r *PolarDBXParameterReconciler) newReconcileTask(rc *polardbxreconcile.Con if polardbx.Status.Phase == polardbxv1polardbx.PhaseRunning { switch parameter.Status.Phase { case polardbxv1polardbx.ParameterStatusNew: + parametersteps.AddLabels(task) parametersteps.SyncPolarDBXParameterStatus(task) parametersteps.TransferParameterPhaseTo(polardbxv1polardbx.ParameterStatusModifying, true)(task) - case polardbxv1polardbx.ParameterStatusRunning: + case polardbxv1polardbx.ParameterStatusFinished: // Schedule after 10 seconds. defer control.ScheduleAfter(10*time.Second)(task, true) @@ -143,7 +144,8 @@ func (r *PolarDBXParameterReconciler) newReconcileTask(rc *polardbxreconcile.Con parametersteps.GMSRestart(task) parametersteps.SyncPolarDBXParameterStatus(task) - parametersteps.TransferParameterPhaseTo(polardbxv1polardbx.ParameterStatusRunning, true)(task) + parametersteps.SyncModifiedTimestamp(task) + parametersteps.TransferParameterPhaseTo(polardbxv1polardbx.ParameterStatusFinished, true)(task) } } diff --git a/pkg/operator/v1/polardbx/factory/env_factory.go b/pkg/operator/v1/polardbx/factory/env_factory.go index bc041aa..2d5d78a 100644 --- a/pkg/operator/v1/polardbx/factory/env_factory.go +++ b/pkg/operator/v1/polardbx/factory/env_factory.go @@ -246,7 +246,7 @@ func (e *envFactory) newJvmInjectionEnvVarForCNEngine(debugPort int) corev1.EnvV staticConfig := e.polardbx.Spec.Config.CN.Static if staticConfig != nil { if staticConfig.EnableCoroutine { - tddlOpts = append(tddlOpts, "-XX:+UseWisp2", "-Dio.grpc.netty.shaded.io.netty.transport.noNative=true", "-Dio.netty.transport.noNative=true") + tddlOpts = append(tddlOpts, "-XX:+UnlockExperimentalVMOptions", "-XX:+UseWisp2", "-Dio.grpc.netty.shaded.io.netty.transport.noNative=true", "-Dio.netty.transport.noNative=true") } if staticConfig.EnableJvmRemoteDebug { tddlOpts = append(tddlOpts, fmt.Sprintf("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=%d", debugPort)) diff --git a/pkg/operator/v1/polardbx/factory/probe_configure.go b/pkg/operator/v1/polardbx/factory/probe_configure.go index 5dc15bc..26a9e63 100644 --- a/pkg/operator/v1/polardbx/factory/probe_configure.go +++ b/pkg/operator/v1/polardbx/factory/probe_configure.go @@ -58,7 +58,7 @@ func (p *probeConfigure) ConfigureForCNEngine(container *corev1.Container, ports InitialDelaySeconds: 10, TimeoutSeconds: 10, PeriodSeconds: 10, - FailureThreshold: 18, + FailureThreshold: 6, Handler: p.newProbeWithProber("/liveness", ports), } container.LivenessProbe = &corev1.Probe{ diff --git a/pkg/operator/v1/polardbx/meta/label.go b/pkg/operator/v1/polardbx/meta/label.go index f6319bd..51b0f65 100644 --- a/pkg/operator/v1/polardbx/meta/label.go +++ b/pkg/operator/v1/polardbx/meta/label.go @@ -17,23 +17,24 @@ limitations under the License. package meta const ( - LabelName = "polardbx/name" - LabelRand = "polardbx/rand" - LabelRole = "polardbx/role" - LabelCNType = "polardbx/cn-type" - LabelDNIndex = "polardbx/dn-index" - LabelTopologyRule = "polardbx/topology-rule" - LabelGeneration = "polardbx/generation" - LabelPortLock = "polardbx/port-lock" - LabelGroup = "polardbx/group" - LabelHash = "polardbx/hash" - LabelTopBackup = "polardbx/top-backup" - LabelBackupXStore = "polardbx/xstore" - LabelBackupXStoreUID = "polardbx/xstore-uid" - LabelBinlogPurgeLock = "polardbx/binlogpurge-lock" - LabelPrimaryName = "polardbx/primary-name" - LabelType = "polardbx/type" - LabelAuditLog = "polardbx/enableAuditLog" + LabelName = "polardbx/name" + LabelRand = "polardbx/rand" + LabelRole = "polardbx/role" + LabelCNType = "polardbx/cn-type" + LabelDNIndex = "polardbx/dn-index" + LabelTopologyRule = "polardbx/topology-rule" + LabelGeneration = "polardbx/generation" + LabelPortLock = "polardbx/port-lock" + LabelGroup = "polardbx/group" + LabelHash = "polardbx/hash" + LabelTopBackup = "polardbx/top-backup" + LabelBackupXStore = "polardbx/xstore" + LabelBackupXStoreUID = "polardbx/xstore-uid" + LabelPreferredBackupNode = "polardbx/preferred-backup-node" + LabelBinlogPurgeLock = "polardbx/binlogpurge-lock" + LabelPrimaryName = "polardbx/primary-name" + LabelType = "polardbx/type" + LabelAuditLog = "polardbx/enableAuditLog" ) const ( SeekCpJobLabelPXCName = "seekcp-job/pxc" diff --git a/pkg/operator/v1/polardbx/reconcile/context.go b/pkg/operator/v1/polardbx/reconcile/context.go index eff602a..530cf7d 100644 --- a/pkg/operator/v1/polardbx/reconcile/context.go +++ b/pkg/operator/v1/polardbx/reconcile/context.go @@ -762,6 +762,16 @@ func (rc *Context) GetDN(i int) (*polardbxv1.XStore, error) { return xstore, nil } +func (rc *Context) GetLeaderOfDN(xstore *polardbxv1.XStore) (*corev1.Pod, error) { + var leaderPod corev1.Pod + leadrPodName := types.NamespacedName{Namespace: rc.Namespace(), Name: xstore.Status.LeaderPod} + err := rc.Client().Get(rc.Context(), leadrPodName, &leaderPod) + if err != nil { + return nil, err + } + return &leaderPod, nil +} + func (rc *Context) getDeploymentMap(polardbx *polardbxv1.PolarDBXCluster, role string) (map[string]*appsv1.Deployment, error) { var deploymentList appsv1.DeploymentList err := rc.Client().List(rc.Context(), &deploymentList, @@ -1080,17 +1090,17 @@ func (rc *Context) GetPolarDBXCNGroupManager(backup *polardbxv1.PolarDBXBackup) return rc.groupManager, nil } -func (rc *Context) GetPolarDBXGroupManagerByXStore(backupPod corev1.Pod) (group.GroupManager, *polardbxv1.XStore, error) { +func (rc *Context) GetPolarDBXGroupManagerByXStorePod(pod corev1.Pod) (group.GroupManager, *polardbxv1.XStore, error) { var xstore polardbxv1.XStore var serviceList corev1.ServiceList err := rc.Client().List(rc.Context(), &serviceList, client.InNamespace(rc.Namespace()), client.MatchingLabels{ - xstoremeta.LabelPod: backupPod.Name, + xstoremeta.LabelPod: pod.Name, }) if err != nil || len(serviceList.Items) == 0 { return nil, nil, err } - host := serviceList.Items[0].Name + "." + backupPod.Namespace - xstoreSpec := types.NamespacedName{Namespace: backupPod.Namespace, Name: backupPod.Labels[xstoremeta.LabelName]} + host := serviceList.Items[0].Name + "." + pod.Namespace + xstoreSpec := types.NamespacedName{Namespace: pod.Namespace, Name: pod.Labels[xstoremeta.LabelName]} err = rc.Client().Get(rc.Context(), xstoreSpec, &xstore) if err != nil { return nil, nil, err @@ -1099,7 +1109,7 @@ func (rc *Context) GetPolarDBXGroupManagerByXStore(backupPod corev1.Pod) (group. if err != nil { return nil, nil, err } - port, err := strconv.Atoi(backupPod.Labels[xstoremeta.LabelPortLock]) + port, err := strconv.Atoi(pod.Labels[xstoremeta.LabelPortLock]) if err != nil { return nil, nil, err } @@ -1225,6 +1235,7 @@ func (rc *Context) UpdatePolarDBXBackupStatus() error { rc.polardbxBackupStatusSnapshot = rc.polardbxBackup.Status.DeepCopy() return nil } + func (rc *Context) IsPXCBackupStatusChanged() bool { if rc.polardbxBackupStatusSnapshot == nil { return false @@ -1375,6 +1386,7 @@ func (rc *Context) GetPXCBackupByName(name string) (*polardbxv1.PolarDBXBackup, } return polardbxBackup, nil } + func (rc *Context) SaveTaskContext(key string, t interface{}) error { b, err := json.MarshalIndent(t, "", " ") if err != nil { diff --git a/pkg/operator/v1/polardbx/steps/backup/common/object.go b/pkg/operator/v1/polardbx/steps/backup/common/object.go index 76d27c4..5b0b17a 100644 --- a/pkg/operator/v1/polardbx/steps/backup/common/object.go +++ b/pkg/operator/v1/polardbx/steps/backup/common/object.go @@ -18,6 +18,7 @@ package common import ( "bytes" + "errors" "fmt" polardbxv1 "github.com/alibaba/polardbx-operator/api/v1" xstorev1 "github.com/alibaba/polardbx-operator/api/v1" @@ -35,6 +36,8 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "math" + "modernc.org/mathutil" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" "strconv" @@ -62,6 +65,14 @@ var UpdateBackupStartInfo = polardbxv1reconcile.NewStepBinder("UpdateBackupStart } backup.Labels[polardbxmeta.LabelName] = backup.Spec.Cluster.Name backup.Status.BackupRootPath = util.BackupRootPath(backup) + + // record topology of original pxc + pxc, err := rc.GetPolarDBX() + if err != nil { + return flow.Error(err, "Unable to get original pxc") + } + backup.Status.ClusterSpecSnapshot = pxc.Spec.DeepCopy() + if err := rc.UpdatePolarDBXBackup(); err != nil { return flow.Error(err, "Unable to update PXC backup.") } @@ -247,7 +258,7 @@ var CollectBinlogStartIndex = polardbxv1reconcile.NewStepBinder("CollectBinlogSt return flow.Error(err, "Unable to get XStore list") } for _, backupPod := range backupPodList { - groupManager, xstore, err := rc.GetPolarDBXGroupManagerByXStore(backupPod) + groupManager, xstore, err := rc.GetPolarDBXGroupManagerByXStorePod(backupPod) if err != nil { return flow.Error(err, "get DataSource Failed") } @@ -289,53 +300,6 @@ var CollectBinlogStartIndex = polardbxv1reconcile.NewStepBinder("CollectBinlogSt return flow.Continue("Collect Binlog Start Offset!") }) -var CollectBinlogEndIndex = polardbxv1reconcile.NewStepBinder("CollectBinlogEndIndex", - func(rc *polardbxv1reconcile.Context, flow control.Flow) (reconcile.Result, error) { - backupPodList, err := rc.GetXStoreBackupPods() - pxcBackup, err := rc.GetPolarDBXBackup() - if err != nil { - return flow.Error(err, "Unable to get XStore list") - } - for _, backupPod := range backupPodList { - groupManager, xstore, err := rc.GetPolarDBXGroupManagerByXStore(backupPod) - if err != nil { - return flow.Error(err, "get DN DataSource Failed", "podName:", backupPod) - } - binlogOffset, err := groupManager.GetBinlogOffset() - if err != nil { - return flow.Error(err, "get binlogoffset Failed") - } - err = rc.Close() - if err != nil { - return flow.Error(err, "Close Database Failed") - } - - binlogOffset = fmt.Sprintf("%s\ntimestamp:%s", binlogOffset, time.Now().Format("2006-01-02 15:04:05")) - backupRootPath := pxcBackup.Status.BackupRootPath - remotePath := fmt.Sprintf("%s/%s/%s-end", backupRootPath, polardbxmeta.BinlogOffsetPath, xstore.Name) - command := command.NewCanonicalCommandBuilder().Collect(). - UploadOffset(binlogOffset, remotePath, string(pxcBackup.Spec.StorageProvider.StorageName), pxcBackup.Spec.StorageProvider.Sink).Build() - stdout := &bytes.Buffer{} - stderr := &bytes.Buffer{} - err = rc.ExecuteCommandOn(&backupPod, "engine", command, control.ExecOptions{ - Logger: flow.Logger(), - Stdin: nil, - Stdout: stdout, - Stderr: stderr, - Timeout: 1 * time.Minute, - }) - if err != nil { - if ee, ok := xstorectrlerrors.ExitError(err); ok { - if ee.ExitStatus() != 0 { - return flow.Retry("Failed to upload binlog end index", "pod", backupPod.Name, "exit-status", ee.ExitStatus()) - } - } - return flow.Error(err, "Failed to upload binlog end index", "pod", backupPod.Name, "stdout", stdout.String(), "stderr", stderr.String()) - } - } - return flow.Continue("Collect Binlog End Offset!") - }) - var DrainCommittingTrans = polardbxv1reconcile.NewStepBinder("DrainCommittingTrans", func(rc *polardbxv1reconcile.Context, flow control.Flow) (reconcile.Result, error) { backup := rc.MustGetPolarDBXBackup() @@ -345,6 +309,7 @@ var DrainCommittingTrans = polardbxv1reconcile.NewStepBinder("DrainCommittingTra if err != nil { return flow.Error(err, "get CN DataSource Failed") } + flow.Logger().Info("Waiting trans commited") err = cnManager.IsTransCommited("TRX_ID", "INNODB_TRX") if err != nil { return flow.Error(err, "Drain Committing Trans Failed") @@ -384,6 +349,141 @@ var SendHeartBeat = polardbxv1reconcile.NewStepBinder("SendHeartBeat", return flow.Continue("HeartBeat Send!") }) +var WaitHeartbeatSentToFollower = polardbxv1reconcile.NewStepBinder("WaitHeartbeatSentToFollower", + func(rc *polardbxv1reconcile.Context, flow control.Flow) (reconcile.Result, error) { + backupPodList, err := rc.GetXStoreBackupPods() + if err != nil { + return flow.Error(err, "Unable to get backup pods") + } + + // check whether backup happened on follower, if so, wait heartbeat sent to them + // waitingPodMap records followers with their leader + waitingPodMap := make(map[*corev1.Pod]*corev1.Pod) + for i, backupPod := range backupPodList { + if backupPod.Labels[xstoremeta.LabelRole] == xstoremeta.RoleLeader { + continue + } + + // get its leader + var xstore xstorev1.XStore + xstoreName := types.NamespacedName{ + Namespace: backupPod.Namespace, + Name: backupPod.Labels[xstoremeta.LabelName], + } + flow.Logger().Info("Try to get xstore for backup pod", "pod", backupPod.Name, "xstore", xstoreName) + err := rc.Client().Get(rc.Context(), xstoreName, &xstore) + if err != nil { + return flow.Error(err, "Unable to get xstore for backup pod", "backup pod", backupPod.Name) + } + leaderPod, err := rc.GetLeaderOfDN(&xstore) + if err != nil { + return flow.Error(err, "Unable to get leader for backup pod", "backup pod", backupPod.Name) + } + waitingPodMap[&backupPodList[i]] = leaderPod + } + if len(waitingPodMap) == 0 { + return flow.Continue("No backup happened on follower, skip waiting") + } + + // get APPLIED_INDEX of leader, and wait APPLIED_INDEX of follower sync with it + flow.Logger().Info("Waiting heartbeat sent to follower pods") + timeout := time.After(120 * time.Minute) // timeout after 120 min TODO(dengli): calculate timeout by delay + tick := time.Tick(1 * time.Minute) // check period + targetIndex := make(map[*corev1.Pod]int64) // record APPLIED_INDEX of leader per follower + for { + select { + case <-timeout: + return flow.Error(errors.New("timeout"), "waiting heartbeat sync timeout") + case <-tick: + for waitingPod, leaderPod := range waitingPodMap { + manager, _, err := rc.GetPolarDBXGroupManagerByXStorePod(*leaderPod) + if err != nil || manager == nil { + return flow.Error(err, "unable to connect to leader", "leader pod", leaderPod.Name) + } + clusterStatusList, err := manager.ShowClusterStatus() + if err != nil { + return flow.Error(err, "unable to get cluster status", "leader pod", leaderPod.Name) + } + + // leader may hava changed, just abort the backup + if len(clusterStatusList) != 3 { + return flow.Error(errors.New("global cluster status incorrect, leader may have changed"), + "leader pod", leaderPod.Name) + } + + var currentIndex int64 = math.MaxInt64 + for _, status := range clusterStatusList { + if status.Role == "Leader" { + if _, ok := targetIndex[waitingPod]; !ok { + targetIndex[waitingPod] = status.AppliedIndex + } + } else if status.Role == "Follower" { // to avoid checking per pod, just wait for all followers + currentIndex = mathutil.MinInt64(currentIndex, status.AppliedIndex) + } + } + if currentIndex >= targetIndex[waitingPod] { + delete(waitingPodMap, waitingPod) + flow.Logger().Info("Waiting finished", "waiting pod", waitingPod.Name, + "target index", targetIndex[waitingPod], "current index", currentIndex) + continue + } + flow.Logger().Info("Still waiting", "pod", waitingPod.Name, + "target index", targetIndex[waitingPod], "current index", currentIndex) + } + if len(waitingPodMap) == 0 { + return flow.Continue("Heartbeat has already been sent to all the followers") + } + } + } + }) + +var CollectBinlogEndIndex = polardbxv1reconcile.NewStepBinder("CollectBinlogEndIndex", + func(rc *polardbxv1reconcile.Context, flow control.Flow) (reconcile.Result, error) { + backupPodList, err := rc.GetXStoreBackupPods() + pxcBackup, err := rc.GetPolarDBXBackup() + if err != nil { + return flow.Error(err, "Unable to get XStore list") + } + for _, backupPod := range backupPodList { + groupManager, xstore, err := rc.GetPolarDBXGroupManagerByXStorePod(backupPod) + if err != nil { + return flow.Error(err, "get DN DataSource Failed", "podName:", backupPod) + } + binlogOffset, err := groupManager.GetBinlogOffset() + if err != nil { + return flow.Error(err, "get binlogoffset Failed") + } + err = rc.Close() + if err != nil { + return flow.Error(err, "Close Database Failed") + } + + binlogOffset = fmt.Sprintf("%s\ntimestamp:%s", binlogOffset, time.Now().Format("2006-01-02 15:04:05")) + backupRootPath := pxcBackup.Status.BackupRootPath + remotePath := fmt.Sprintf("%s/%s/%s-end", backupRootPath, polardbxmeta.BinlogOffsetPath, xstore.Name) + command := command.NewCanonicalCommandBuilder().Collect(). + UploadOffset(binlogOffset, remotePath, string(pxcBackup.Spec.StorageProvider.StorageName), pxcBackup.Spec.StorageProvider.Sink).Build() + stdout := &bytes.Buffer{} + stderr := &bytes.Buffer{} + err = rc.ExecuteCommandOn(&backupPod, "engine", command, control.ExecOptions{ + Logger: flow.Logger(), + Stdin: nil, + Stdout: stdout, + Stderr: stderr, + Timeout: 1 * time.Minute, + }) + if err != nil { + if ee, ok := xstorectrlerrors.ExitError(err); ok { + if ee.ExitStatus() != 0 { // TODO(dengli): whether need to retry here + return flow.Retry("Failed to upload binlog end index", "pod", backupPod.Name, "exit-status", ee.ExitStatus()) + } + } + return flow.Error(err, "Failed to upload binlog end index", "pod", backupPod.Name, "stdout", stdout.String(), "stderr", stderr.String()) + } + } + return flow.Continue("Collect Binlog End Offset!") + }) + var WaitAllCollectBinlogJobFinished = polardbxv1reconcile.NewStepBinder("WaitAllCollectBinlogJobFinished", func(rc *polardbxv1reconcile.Context, flow control.Flow) (reconcile.Result, error) { backup := rc.MustGetPolarDBXBackup() diff --git a/pkg/operator/v1/polardbx/steps/backup/xstorejobbuilder/xstore_backup_builder.go b/pkg/operator/v1/polardbx/steps/backup/xstorejobbuilder/xstore_backup_builder.go index 5576862..876b787 100644 --- a/pkg/operator/v1/polardbx/steps/backup/xstorejobbuilder/xstore_backup_builder.go +++ b/pkg/operator/v1/polardbx/steps/backup/xstorejobbuilder/xstore_backup_builder.go @@ -46,6 +46,11 @@ func NewXStoreBackup(scheme *runtime.Scheme, backup *polardbxv1.PolarDBXBackup, }, } + // set preferred backup node + if node, ok := backup.Labels[meta.LabelPreferredBackupNode]; ok { + xstoreBackup.Labels[meta.LabelPreferredBackupNode] = node + } + if err := ctrl.SetControllerReference(backup, xstoreBackup, scheme); err != nil { return nil, err } diff --git a/pkg/operator/v1/polardbx/steps/instance/common/object.go b/pkg/operator/v1/polardbx/steps/instance/common/object.go index 08c6602..eb2f10d 100644 --- a/pkg/operator/v1/polardbx/steps/instance/common/object.go +++ b/pkg/operator/v1/polardbx/steps/instance/common/object.go @@ -122,3 +122,27 @@ var CheckDNs = polardbxv1reconcile.NewStepBinder("CheckDNs", return flow.Pass() }, ) + +// SyncSpecFromBackupSet aims to sync spec with original pxc cluster from backup set, +// currently restore does not support change DN replicas +var SyncSpecFromBackupSet = polardbxv1reconcile.NewStepBinder("SyncSpecFromBackupSet", + func(rc *polardbxv1reconcile.Context, flow control.Flow) (reconcile.Result, error) { + polardbx := rc.MustGetPolarDBX() + pxcBackup, err := rc.GetPXCBackupByName(polardbx.Spec.Restore.BackupSet) + if err != nil { + return flow.Error(err, "Unable to get polardbx backup {}", pxcBackup.Name) + } + + // TODO(dengli): load spec from remote backup set + if polardbx.Spec.Restore.SyncSpecWithOriginalCluster { + polardbx.Spec = *pxcBackup.Status.ClusterSpecSnapshot + } else { // ensure that restored cluster have the same dn replicas with original cluster + polardbx.Spec.Topology.Nodes.DN.Replicas = pxcBackup.Status.ClusterSpecSnapshot.Topology.Nodes.DN.Replicas + } + err = rc.Client().Update(rc.Context(), polardbx) + if err != nil { + return flow.Error(err, "Failed to sync topology from backup set") + } + return flow.Pass() + }, +) diff --git a/pkg/operator/v1/polardbx/steps/instance/gms/gms.go b/pkg/operator/v1/polardbx/steps/instance/gms/gms.go index 6d79a94..1383c91 100644 --- a/pkg/operator/v1/polardbx/steps/instance/gms/gms.go +++ b/pkg/operator/v1/polardbx/steps/instance/gms/gms.go @@ -215,6 +215,18 @@ func SyncDynamicConfigs(force bool) control.BindFunc { }) } +// For trailing stores which should be deleted, +// we only care about their id, rather than other infos +func transformIntoTrailingStorageInfosWithOnlyId(xstores []*polardbxv1.XStore) []gms.StorageNodeInfo { + storageInfos := make([]gms.StorageNodeInfo, 0, len(xstores)) + for _, xstore := range xstores { + storageInfos = append(storageInfos, gms.StorageNodeInfo{ + Id: xstore.Name, + }) + } + return storageInfos +} + func transformIntoStorageInfos(rc *polardbxreconcile.Context, polardbx *polardbxv1.PolarDBXCluster, xstores []*polardbxv1.XStore) ([]gms.StorageNodeInfo, error) { topology := polardbx.Status.SpecSnapshot.Topology cpuLimit := topology.Nodes.DN.Template.Resources.Limits.Cpu().Value() @@ -366,16 +378,13 @@ var DisableTrailingDNs = polardbxreconcile.NewStepBinder("DisableTrailingDNs", return flow.Pass() } - storageInfos, err := transformIntoStorageInfos(rc, polardbx, trailingStores) - if err != nil { - return flow.Error(err, "Unable to transform xstores into storage infos.") - } + storageInfoIds := transformIntoTrailingStorageInfosWithOnlyId(trailingStores) mgr, err := rc.GetPolarDBXGMSManager() if err != nil { return flow.Error(err, "Unable to get GMS manager.") } - err = mgr.DisableStorageNodes(storageInfos...) + err = mgr.DisableStorageNodes(storageInfoIds...) if err != nil { return flow.Error(err, "Unable to enable trailing storage nodes in GMS.") } diff --git a/pkg/operator/v1/polardbx/steps/instance/restart/restart.go b/pkg/operator/v1/polardbx/steps/instance/restart/restart.go index e9e7656..20bf1c5 100644 --- a/pkg/operator/v1/polardbx/steps/instance/restart/restart.go +++ b/pkg/operator/v1/polardbx/steps/instance/restart/restart.go @@ -40,8 +40,8 @@ var RollingRestartPods = polardbxreconcile.NewStepBinder("RollingRestartPods", lastDeletedPod := polardbx.Status.RestartingPods.LastDeletedPod if lastDeletedPod != "" { - s := strings.Split(lastDeletedPod, "-") - podNum := s[len(s)-3] + delName := strings.Split(lastDeletedPod, "-") + podNum := delName[len(delName)-3] podDel := corev1.Pod{} var podList corev1.PodList err := rc.Client().List( @@ -54,15 +54,15 @@ var RollingRestartPods = polardbxreconcile.NewStepBinder("RollingRestartPods", return flow.Error(err, "Error getting pods") } for _, podTemp := range podList.Items { - ss := strings.Split(podTemp.Name, "-") - num := s[len(ss)-3] - if num == podNum { + tempName := strings.Split(podTemp.Name, "-") + num := tempName[len(tempName)-3] + if num == podNum && podTemp.Name != lastDeletedPod { podDel = podTemp break } } if !helper.IsPodReady(&podDel) || podDel.Name == "" || !podDel.DeletionTimestamp.IsZero() { - return flow.Retry("Pod hasn't been deleted") + return flow.Retry("Pod hasn't been deleted", "pod", podDel.Name) } } diff --git a/pkg/operator/v1/polardbx/steps/parameter/parameter.go b/pkg/operator/v1/polardbx/steps/parameter/parameter.go index 605bcbc..c473649 100644 --- a/pkg/operator/v1/polardbx/steps/parameter/parameter.go +++ b/pkg/operator/v1/polardbx/steps/parameter/parameter.go @@ -17,6 +17,7 @@ limitations under the License. package parameter import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "time" "github.com/alibaba/polardbx-operator/pkg/util/gms" @@ -28,6 +29,8 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" + conventionXstore "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/convention" + "github.com/alibaba/polardbx-operator/pkg/operator/v1/polardbx/steps/instance/common" polardbxmeta "github.com/alibaba/polardbx-operator/pkg/operator/v1/polardbx/meta" @@ -56,6 +59,16 @@ var SyncPolarDBXParameterStatus = polardbxv1reconcile.NewStepBinder("SyncPolarDB }, ) +var AddLabels = polardbxv1reconcile.NewStepBinder("AddLabels", + func(rc *polardbxv1reconcile.Context, flow control.Flow) (reconcile.Result, error) { + polardbxParameter := rc.MustGetPolarDBXParameter() + labels := conventionXstore.GetParameterLabel() + labels[polardbxmeta.LabelName] = polardbxParameter.Spec.ClusterName + polardbxParameter.SetLabels(labels) + return flow.Pass() + }, +) + var PersistPolarDBXParameter = polardbxv1reconcile.NewStepBinder("PersistPolarDBXParameter", func(rc *polardbxv1reconcile.Context, flow control.Flow) (reconcile.Result, error) { if rc.IsPolarDBXParameterChanged() { @@ -551,3 +564,11 @@ var GetRolesToRestart = polardbxv1reconcile.NewStepBinder("GetRolesToRestart", return flow.Pass() }, ) + +var SyncModifiedTimestamp = polardbxv1reconcile.NewStepBinder("SyncModifiedTimestamp", + func(rc *polardbxv1reconcile.Context, flow control.Flow) (reconcile.Result, error) { + polardbxParameter := rc.MustGetPolarDBXParameter() + polardbxParameter.Status.ModifiedTimestamp = metav1.Now().Format("2006-01-02 15:04:05") + return flow.Pass() + }, +) diff --git a/pkg/operator/v1/xstore/backupreconciler/reconciler.go b/pkg/operator/v1/xstore/backupreconciler/reconciler.go deleted file mode 100644 index 02a705a..0000000 --- a/pkg/operator/v1/xstore/backupreconciler/reconciler.go +++ /dev/null @@ -1,26 +0,0 @@ -/* -Copyright 2021 Alibaba Group Holding Limited. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package backupreconciler - -import ( - "github.com/go-logr/logr" - "sigs.k8s.io/controller-runtime/pkg/reconcile" -) - -type Reconciler interface { - Reconcile(rc *Context, log logr.Logger, request reconcile.Request) (reconcile.Result, error) -} diff --git a/pkg/operator/v1/xstore/change/driver/model/node.go b/pkg/operator/v1/xstore/change/driver/model/node.go index 3052321..8304c54 100644 --- a/pkg/operator/v1/xstore/change/driver/model/node.go +++ b/pkg/operator/v1/xstore/change/driver/model/node.go @@ -80,6 +80,7 @@ func (s *PaxosNodeStatus) FromPod(pod *corev1.Pod) error { if configHash, ok := pod.Labels[xstoremeta.LabelConfigHash]; ok { s.RebuildConfig[xstoremeta.LabelConfigHash] = configHash } + s.RebuildConfig["NodeName"] = pod.Spec.NodeName if xStoreRole, ok := pod.Labels[xstoremeta.LabelRole]; ok { s.XStoreRole = xStoreRole } diff --git a/pkg/operator/v1/xstore/change/driver/plan/check.go b/pkg/operator/v1/xstore/change/driver/plan/check.go index 64849c8..64d4fe1 100644 --- a/pkg/operator/v1/xstore/change/driver/plan/check.go +++ b/pkg/operator/v1/xstore/change/driver/plan/check.go @@ -87,7 +87,7 @@ func matches(a, b map[string]model.PaxosNode) bool { if !ok { return false } - if v.PaxosInnerNode != vb.PaxosInnerNode { + if !v.DeepEquals(&vb) { return false } } diff --git a/pkg/operator/v1/xstore/change/driver/planner/planner.go b/pkg/operator/v1/xstore/change/driver/planner/planner.go index e0f9c50..f9365ae 100644 --- a/pkg/operator/v1/xstore/change/driver/planner/planner.go +++ b/pkg/operator/v1/xstore/change/driver/planner/planner.go @@ -83,11 +83,12 @@ func (p *Planner) buildExpectedNodes() map[string]model.PaxosNode { if p.selfHeal { topology = p.xstore.Status.ObservedTopology } - nodeRebuildConfig := p.createNodeRebuildConfig() + nodes := make(map[string]model.PaxosNode) for _, ns := range topology.NodeSets { for i := 0; i < int(ns.Replicas); i++ { name := xstoreconvention.NewPodName(p.xstore, &ns, i) + nodeRebuildConfig := p.createNodeRebuildConfig(name) nodes[name] = model.PaxosNode{ PaxosInnerNode: model.PaxosInnerNode{ Pod: name, @@ -104,10 +105,11 @@ func (p *Planner) buildExpectedNodes() map[string]model.PaxosNode { return nodes } -func (p *Planner) createNodeRebuildConfig() map[string]interface{} { +func (p *Planner) createNodeRebuildConfig(podName string) map[string]interface{} { rebuildConfig := make(map[string]interface{}) config := xstoremeta.RebuildConfig{ LogSeparation: strconv.FormatBool(p.xstore.Spec.Config.Dynamic.LogDataSeparation), + NodeName: p.xstore.Status.BoundVolumes[podName].Host, } rebuildConfig[xstoremeta.LabelConfigHash] = config.ComputeHash() return rebuildConfig diff --git a/pkg/operator/v1/xstore/command/commands.go b/pkg/operator/v1/xstore/command/commands.go index bbfaa9d..c617191 100644 --- a/pkg/operator/v1/xstore/command/commands.go +++ b/pkg/operator/v1/xstore/command/commands.go @@ -102,6 +102,14 @@ func (b *nullCommandBuilder) Consensus() *commandConsensusBuilder { } } +func (b *commandConsensusBuilder) List(full bool) *CommandBuilder { + b.args = append(b.args, "list") + if full { + b.args = append(b.args, "--full") + } + return b.end() +} + func (b *commandConsensusBuilder) This(full bool) *CommandBuilder { b.args = append(b.args, "this") if full { diff --git a/pkg/operator/v1/xstore/controllers/xstorebackup_controller.go b/pkg/operator/v1/xstore/controllers/xstore_backup_controller.go similarity index 84% rename from pkg/operator/v1/xstore/controllers/xstorebackup_controller.go rename to pkg/operator/v1/xstore/controllers/xstore_backup_controller.go index b941178..55a2c5a 100644 --- a/pkg/operator/v1/xstore/controllers/xstorebackup_controller.go +++ b/pkg/operator/v1/xstore/controllers/xstore_backup_controller.go @@ -22,8 +22,8 @@ import ( "github.com/alibaba/polardbx-operator/pkg/k8s/control" "github.com/alibaba/polardbx-operator/pkg/operator/hint" "github.com/alibaba/polardbx-operator/pkg/operator/v1/config" - backupxstorev1reconcile "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/backupreconciler" "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/plugin" + xstorev1reconcile "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/reconcile" "github.com/go-logr/logr" "golang.org/x/time/rate" batchv1 "k8s.io/api/batch/v1" @@ -41,7 +41,6 @@ type XStoreBackupReconciler struct { BaseRc *control.BaseReconcileContext Logger logr.Logger config.LoaderFactory - MaxConcurrency int } @@ -52,10 +51,9 @@ func (r *XStoreBackupReconciler) Reconcile(ctx context.Context, request reconcil log.Info("Reconciling is paused, skip") return reconcile.Result{}, nil } - rc := backupxstorev1reconcile.NewContext( + rc := xstorev1reconcile.NewBackupContext( control.NewBaseReconcileContextFrom(r.BaseRc, ctx, request), ) - defer rc.Close() // Verify the existence of the xstore. @@ -70,6 +68,21 @@ func (r *XStoreBackupReconciler) Reconcile(ctx context.Context, request reconcil } } + // Record the context of the corresponding xstore + xstore, err := rc.GetXStore() + if err != nil { + log.Error(err, "Unable to get corresponding xstore") + return reconcile.Result{}, err + } + xstoreRequest := request + xstoreRequest.Name = xstore.Name + xstoreRc := xstorev1reconcile.NewContext( + control.NewBaseReconcileContextFrom(r.BaseRc, ctx, xstoreRequest), + r.LoaderFactory(), + ) + xstoreRc.SetXStoreKey(xstoreRequest.NamespacedName) + rc.SetXStoreContext(xstoreRc) + engine := xstoreBackup.Spec.Engine reconciler := plugin.GetXStoreBackupReconciler(engine) diff --git a/pkg/operator/v1/xstore/controllers/xstore_follower_controller.go b/pkg/operator/v1/xstore/controllers/xstore_follower_controller.go index f1239e2..8f650cf 100644 --- a/pkg/operator/v1/xstore/controllers/xstore_follower_controller.go +++ b/pkg/operator/v1/xstore/controllers/xstore_follower_controller.go @@ -160,6 +160,7 @@ func (r *XStoreFollowerReconciler) newReconcileTask(rc *xstorev1reconcile.Follow followersteps.TryCleanHostPathVolumeIfRemote(task) followersteps.RemoveFinalizer(task) case xstore.FollowerPhaseSuccess: + followersteps.TryCleanHostPathVolumeIfRemote(task) case xstore.FollowerPhaseFailed: } diff --git a/pkg/operator/v1/xstore/convention/convention.go b/pkg/operator/v1/xstore/convention/convention.go index aeb95a9..84bca90 100644 --- a/pkg/operator/v1/xstore/convention/convention.go +++ b/pkg/operator/v1/xstore/convention/convention.go @@ -223,7 +223,7 @@ const ( FileStreamRootDir = "/filestream" XClusterBackupBinFilepath = "/u01/xcluster_xtrabackup/bin/innobackupex" XClusterBackupSetPrepareArg = "--apply-log" - GalaxyEngineBackupSlaveInfoArgs = "--slave-info" + GalaxyEngineBackupSlaveInfoArgs = "--slave-info --lock-ddl " XClusterBackupSlaveInfoArgs = "" GalaxyEngineBackupStreamArgs = "--stream=xbstream" XClusterBackupStreamArgs = "--stream=tar" diff --git a/pkg/operator/v1/xstore/factory/pod_extra.go b/pkg/operator/v1/xstore/factory/pod_extra.go index 099f4a1..d59ddfc 100644 --- a/pkg/operator/v1/xstore/factory/pod_extra.go +++ b/pkg/operator/v1/xstore/factory/pod_extra.go @@ -346,6 +346,7 @@ func (f *DefaultExtraPodFactory) ExtraLabels(ctx *PodFactoryContext) map[string] } config := xstoremeta.RebuildConfig{ LogSeparation: strconv.FormatBool(ctx.xstore.Spec.Config.Dynamic.LogDataSeparation), + NodeName: ctx.volumes[0].Host, } extraLabels[xstoremeta.LabelConfigHash] = config.ComputeHash() return extraLabels diff --git a/pkg/operator/v1/xstore/meta/rebuild_config.go b/pkg/operator/v1/xstore/meta/rebuild_config.go index 077440d..cf832e4 100644 --- a/pkg/operator/v1/xstore/meta/rebuild_config.go +++ b/pkg/operator/v1/xstore/meta/rebuild_config.go @@ -4,6 +4,7 @@ import "github.com/alibaba/polardbx-operator/pkg/meta/core/gms/security" type RebuildConfig struct { LogSeparation string + NodeName string } func (r *RebuildConfig) ComputeHash() string { diff --git a/pkg/operator/v1/xstore/plugin/backupreconciler.go b/pkg/operator/v1/xstore/plugin/backup_reconciler.go similarity index 75% rename from pkg/operator/v1/xstore/plugin/backupreconciler.go rename to pkg/operator/v1/xstore/plugin/backup_reconciler.go index d698997..3bfea60 100644 --- a/pkg/operator/v1/xstore/plugin/backupreconciler.go +++ b/pkg/operator/v1/xstore/plugin/backup_reconciler.go @@ -17,16 +17,16 @@ limitations under the License. package plugin import ( - "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/backupreconciler" + "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/reconcile" "sync" ) var ( - xstoreBackupReconcilerMap = map[string]backupreconciler.Reconciler{} + xstoreBackupReconcilerMap = map[string]reconcile.BackupReconciler{} xstoreBackupReconcilerMu sync.RWMutex ) -func RegisterXStoreBackupReconciler(engine string, reconciler backupreconciler.Reconciler) { +func RegisterXStoreBackupReconciler(engine string, reconciler reconcile.BackupReconciler) { xstoreBackupReconcilerMu.Lock() defer xstoreBackupReconcilerMu.Unlock() @@ -37,7 +37,7 @@ func RegisterXStoreBackupReconciler(engine string, reconciler backupreconciler.R xstoreBackupReconcilerMap[engine] = reconciler } -func GetXStoreBackupReconciler(engine string) backupreconciler.Reconciler { +func GetXStoreBackupReconciler(engine string) reconcile.BackupReconciler { xstoreBackupReconcilerMu.RLock() defer xstoreBackupReconcilerMu.RUnlock() diff --git a/pkg/operator/v1/xstore/plugin/galaxy/reconcilers/galaxy_backup_reconciler.go b/pkg/operator/v1/xstore/plugin/galaxy/reconcilers/galaxy_backup_reconciler.go index 3b2e54b..e5e01be 100644 --- a/pkg/operator/v1/xstore/plugin/galaxy/reconcilers/galaxy_backup_reconciler.go +++ b/pkg/operator/v1/xstore/plugin/galaxy/reconcilers/galaxy_backup_reconciler.go @@ -19,7 +19,7 @@ package reconcilers import ( xstorev1 "github.com/alibaba/polardbx-operator/api/v1" "github.com/alibaba/polardbx-operator/pkg/k8s/control" - "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/backupreconciler" + xstorev1reconcile "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/reconcile" backupsteps "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/steps/backup" "github.com/go-logr/logr" "sigs.k8s.io/controller-runtime/pkg/reconcile" @@ -28,7 +28,7 @@ import ( type GalaxyBackupReconciler struct { } -func (r *GalaxyBackupReconciler) Reconcile(rc *backupreconciler.Context, log logr.Logger, request reconcile.Request) (reconcile.Result, error) { +func (r *GalaxyBackupReconciler) Reconcile(rc *xstorev1reconcile.BackupContext, log logr.Logger, request reconcile.Request) (reconcile.Result, error) { backup := rc.MustGetXStoreBackup() log = log.WithValues("phase", backup.Status.Phase) @@ -40,7 +40,7 @@ func (r *GalaxyBackupReconciler) Reconcile(rc *backupreconciler.Context, log log return control.NewExecutor(log).Execute(rc, task) } -func (r *GalaxyBackupReconciler) newReconcileTask(rc *backupreconciler.Context, xstoreBackup *xstorev1.XStoreBackup, log logr.Logger) (*control.Task, error) { +func (r *GalaxyBackupReconciler) newReconcileTask(rc *xstorev1reconcile.BackupContext, xstoreBackup *xstorev1.XStoreBackup, log logr.Logger) (*control.Task, error) { task := control.NewTask() @@ -64,6 +64,7 @@ func (r *GalaxyBackupReconciler) newReconcileTask(rc *backupreconciler.Context, backupsteps.WaitPXCSeekCpJobFinished(task) backupsteps.StartBinlogBackupJob(task) backupsteps.WaitBinlogBackupJobFinished(task) + backupsteps.ExtractLastEventTimestamp(task) backupsteps.UpdatePhaseTemplate(xstorev1.XStoreBinlogWaiting)(task) case xstorev1.XStoreBinlogWaiting: backupsteps.WaitPXCBackupFinished(task) diff --git a/pkg/operator/v1/xstore/plugin/galaxy/steps/instance/log.go b/pkg/operator/v1/xstore/plugin/galaxy/steps/instance/log.go index 36de0c5..f0f3cc1 100644 --- a/pkg/operator/v1/xstore/plugin/galaxy/steps/instance/log.go +++ b/pkg/operator/v1/xstore/plugin/galaxy/steps/instance/log.go @@ -43,7 +43,7 @@ func PurgeLogsTemplate(d time.Duration) control.BindFunc { // if Purge binlog Locked if xstore.Labels[xstoremeta.LabelBinlogPurgeLock] == xstoremeta.BinlogPurgeLock { - flow.Pass() + return flow.Pass() } // avoid duplicated purge request from learner diff --git a/pkg/operator/v1/xstore/backupreconciler/context.go b/pkg/operator/v1/xstore/reconcile/backup_context.go similarity index 67% rename from pkg/operator/v1/xstore/backupreconciler/context.go rename to pkg/operator/v1/xstore/reconcile/backup_context.go index 72c75f9..3abc104 100644 --- a/pkg/operator/v1/xstore/backupreconciler/context.go +++ b/pkg/operator/v1/xstore/reconcile/backup_context.go @@ -14,17 +14,21 @@ See the License for the specific language governing permissions and limitations under the License. */ -package backupreconciler +package reconcile import ( "encoding/json" - xstorev1 "github.com/alibaba/polardbx-operator/api/v1" + "errors" + polardbxv1 "github.com/alibaba/polardbx-operator/api/v1" "github.com/alibaba/polardbx-operator/pkg/k8s/control" k8shelper "github.com/alibaba/polardbx-operator/pkg/k8s/helper" + "github.com/alibaba/polardbx-operator/pkg/meta/core/group" "github.com/alibaba/polardbx-operator/pkg/operator/v1/polardbx/meta" "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/convention" + xstoreconvention "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/convention" xstoremeta "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/meta" "github.com/alibaba/polardbx-operator/pkg/util" + dbutil "github.com/alibaba/polardbx-operator/pkg/util/database" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" @@ -34,23 +38,25 @@ import ( "k8s.io/utils/pointer" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "strconv" ) -type Context struct { +type BackupContext struct { *control.BaseReconcileContext - xstore *xstorev1.XStore - xstoreBackup *xstorev1.XStoreBackup - xstoreBackupStatusSnapshot *xstorev1.XStoreBackupStatus + xStoreContext *Context + xstore *polardbxv1.XStore + xstoreBackup *polardbxv1.XStoreBackup + xstoreBackupStatusSnapshot *polardbxv1.XStoreBackupStatus xstorePods []corev1.Pod xstoreTargetPod *corev1.Pod xstoreBackupJob *batchv1.Job xstoreCollectJob *batchv1.Job xstoreBinlogBackupJob *batchv1.Job - polardbxBackup *xstorev1.PolarDBXBackup + polardbxBackup *polardbxv1.PolarDBXBackup taskConfigMap *corev1.ConfigMap } -func (rc *Context) SetControllerRef(obj metav1.Object) error { +func (rc *BackupContext) SetControllerRef(obj metav1.Object) error { if obj == nil { return nil } @@ -58,14 +64,22 @@ func (rc *Context) SetControllerRef(obj metav1.Object) error { return ctrl.SetControllerReference(backup, obj, rc.Scheme()) } -func (rc *Context) SetControllerRefAndCreate(obj client.Object) error { +func (rc *BackupContext) SetControllerRefAndCreate(obj client.Object) error { if err := rc.SetControllerRef(obj); err != nil { return err } return rc.Client().Create(rc.Context(), obj) } -func (rc *Context) MustGetXStoreBackup() *xstorev1.XStoreBackup { +func (rc *BackupContext) SetXStoreContext(xstoreContext *Context) { + rc.xStoreContext = xstoreContext +} + +func (rc *BackupContext) XStoreContext() *Context { + return rc.xStoreContext +} + +func (rc *BackupContext) MustGetXStoreBackup() *polardbxv1.XStoreBackup { xstoreBackup, err := rc.GetXStoreBackup() if err != nil { panic(err) @@ -73,9 +87,9 @@ func (rc *Context) MustGetXStoreBackup() *xstorev1.XStoreBackup { return xstoreBackup } -func (rc *Context) GetXStoreBackup() (*xstorev1.XStoreBackup, error) { +func (rc *BackupContext) GetXStoreBackup() (*polardbxv1.XStoreBackup, error) { if rc.xstoreBackup == nil { - var xstoreBackup xstorev1.XStoreBackup + var xstoreBackup polardbxv1.XStoreBackup err := rc.Client().Get(rc.Context(), rc.Request().NamespacedName, &xstoreBackup) if err != nil { return nil, err @@ -86,13 +100,13 @@ func (rc *Context) GetXStoreBackup() (*xstorev1.XStoreBackup, error) { return rc.xstoreBackup, nil } -func (rc *Context) GetPolarDBXBackup() (*xstorev1.PolarDBXBackup, error) { +func (rc *BackupContext) GetPolarDBXBackup() (*polardbxv1.PolarDBXBackup, error) { if rc.polardbxBackup == nil { xstoreBackup, err := rc.GetXStoreBackup() if err != nil { return nil, err } - var polardbxBackup xstorev1.PolarDBXBackup + var polardbxBackup polardbxv1.PolarDBXBackup pxcBackupKey := types.NamespacedName{ Namespace: xstoreBackup.Namespace, Name: xstoreBackup.Labels[meta.LabelTopBackup], @@ -106,7 +120,7 @@ func (rc *Context) GetPolarDBXBackup() (*xstorev1.PolarDBXBackup, error) { return rc.polardbxBackup, nil } -func (rc *Context) GetXStoreBackupJob() (*batchv1.Job, error) { +func (rc *BackupContext) GetXStoreBackupJob() (*batchv1.Job, error) { if rc.xstoreBackupJob == nil { xstoreBackup := rc.MustGetXStoreBackup() @@ -144,10 +158,10 @@ func (rc *Context) GetXStoreBackupJob() (*batchv1.Job, error) { return rc.xstoreBackupJob, nil } -func (rc *Context) GetXStore() (*xstorev1.XStore, error) { +func (rc *BackupContext) GetXStore() (*polardbxv1.XStore, error) { if rc.xstore == nil { backup := rc.MustGetXStoreBackup() - var xstore xstorev1.XStore + var xstore polardbxv1.XStore xstoreSpec := types.NamespacedName{Namespace: rc.Request().Namespace, Name: backup.Spec.XStore.Name} err := rc.Client().Get(rc.Context(), xstoreSpec, &xstore) if err != nil { @@ -158,7 +172,7 @@ func (rc *Context) GetXStore() (*xstorev1.XStore, error) { return rc.xstore, nil } -func (rc *Context) UpdateXStoreBackupStatus() error { +func (rc *BackupContext) UpdateXStoreBackupStatus() error { if rc.xstoreBackupStatusSnapshot == nil { return nil } @@ -170,14 +184,14 @@ func (rc *Context) UpdateXStoreBackupStatus() error { return nil } -func (rc *Context) IsXStoreBackupStatusChanged() bool { +func (rc *BackupContext) IsXStoreBackupStatusChanged() bool { if rc.xstoreBackupStatusSnapshot == nil { return false } return !equality.Semantic.DeepEqual(rc.xstoreBackup.Status, *rc.xstoreBackupStatusSnapshot) } -func (rc *Context) GetXStorePods() ([]corev1.Pod, error) { +func (rc *BackupContext) GetXStorePods() ([]corev1.Pod, error) { xstore, err := rc.GetXStore() if err != nil { return nil, err @@ -211,7 +225,7 @@ func (rc *Context) GetXStorePods() ([]corev1.Pod, error) { return rc.xstorePods, nil } -func (rc *Context) GetXStoreTargetPod() (*corev1.Pod, error) { +func (rc *BackupContext) GetXStoreTargetPod() (*corev1.Pod, error) { if rc.xstoreTargetPod == nil { xstoreBackup := rc.MustGetXStoreBackup() @@ -239,7 +253,8 @@ func (rc *Context) GetXStoreTargetPod() (*corev1.Pod, error) { } // TODO: Take health info and delay into consideration - // If not found, find any follower/learner/leader + // set target pod for XStoreBackup on which backup will be performed + // priority of the target pod: choice made by user > follower > leader pods, err := rc.GetXStorePods() if err != nil { return nil, err @@ -251,19 +266,41 @@ func (rc *Context) GetXStoreTargetPod() (*corev1.Pod, error) { rolePodMap[p.Labels[xstoremeta.LabelRole]] = p } - for _, r := range []string{xstoremeta.RoleLeader, xstoremeta.RoleFollower, xstoremeta.RoleLearner} { - if p, ok := rolePodMap[r]; ok { - rc.xstoreTargetPod = p - return p, nil + preferred, _ := xstoreBackup.Labels[meta.LabelPreferredBackupNode] + if preferred == xstoremeta.RoleLeader { // preferred backup node is leader, just set it + p, ok := rolePodMap[xstoremeta.RoleLeader] + if !ok { + return nil, errors.New("target pod is leader, but leader not found") } + rc.xstoreTargetPod = p + return p, nil } - return nil, nil + // if `PreferredBackupNode` has not been set or set to something other than leader, then we pick follower as backup pod + p, ok := rolePodMap[xstoremeta.RoleFollower] + if !ok { + return nil, errors.New("target pod is follower, but follower not found") + } + manager, err := rc.GetXstoreGroupManagerByPod(p) + if err != nil { + return nil, err + } + if manager == nil { + return nil, errors.New("fail to connect to follower") + } + status, err := manager.ShowSlaveStatus() + if err != nil { + return nil, err + } + if status.SlaveSQLRunning == "No" || status.LastError != "" { + return nil, errors.New("follower status abnormal") + } + rc.xstoreTargetPod = p } return rc.xstoreTargetPod, nil } -func (rc *Context) UpdateXStoreBackup() error { +func (rc *BackupContext) UpdateXStoreBackup() error { if rc.xstoreBackup == nil { return nil } @@ -277,7 +314,7 @@ func (rc *Context) UpdateXStoreBackup() error { return nil } -func (rc *Context) GetCollectBinlogJob() (*batchv1.Job, error) { +func (rc *BackupContext) GetCollectBinlogJob() (*batchv1.Job, error) { if rc.xstoreCollectJob == nil { xstoreBackup := rc.MustGetXStoreBackup() @@ -315,7 +352,7 @@ func (rc *Context) GetCollectBinlogJob() (*batchv1.Job, error) { return rc.xstoreCollectJob, nil } -func (rc *Context) GetBackupBinlogJob() (*batchv1.Job, error) { +func (rc *BackupContext) GetBackupBinlogJob() (*batchv1.Job, error) { if rc.xstoreBinlogBackupJob == nil { xstoreBackup := rc.MustGetXStoreBackup() @@ -353,13 +390,13 @@ func (rc *Context) GetBackupBinlogJob() (*batchv1.Job, error) { return rc.xstoreBinlogBackupJob, nil } -func NewContext(base *control.BaseReconcileContext) *Context { - return &Context{ +func NewBackupContext(base *control.BaseReconcileContext) *BackupContext { + return &BackupContext{ BaseReconcileContext: base, } } -func (rc *Context) GetOrCreateXStoreBackupTaskConfigMap() (*corev1.ConfigMap, error) { +func (rc *BackupContext) GetOrCreateXStoreBackupTaskConfigMap() (*corev1.ConfigMap, error) { if rc.taskConfigMap == nil { xstorebackup := rc.MustGetXStoreBackup() @@ -367,7 +404,7 @@ func (rc *Context) GetOrCreateXStoreBackupTaskConfigMap() (*corev1.ConfigMap, er err := rc.Client().Get(rc.Context(), types.NamespacedName{Namespace: rc.Namespace(), Name: util.XStoreBackupStableName(xstorebackup, "backup")}, &cm) if err != nil { if apierrors.IsNotFound(err) { - rc.taskConfigMap = NewTaskConfigMap(xstorebackup) + rc.taskConfigMap = NewBackupTaskConfigMap(xstorebackup) err = rc.SetControllerRefAndCreate(rc.taskConfigMap) if err != nil { return nil, err @@ -382,7 +419,7 @@ func (rc *Context) GetOrCreateXStoreBackupTaskConfigMap() (*corev1.ConfigMap, er return rc.taskConfigMap, nil } -func NewTaskConfigMap(xstoreBackup *xstorev1.XStoreBackup) *corev1.ConfigMap { +func NewBackupTaskConfigMap(xstoreBackup *polardbxv1.XStoreBackup) *corev1.ConfigMap { return &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: convention.NewBackupConfigMapName(xstoreBackup, "backup"), @@ -392,7 +429,7 @@ func NewTaskConfigMap(xstoreBackup *xstorev1.XStoreBackup) *corev1.ConfigMap { } } -func (rc *Context) SaveTaskContext(key string, t interface{}) error { +func (rc *BackupContext) SaveTaskContext(key string, t interface{}) error { b, err := json.MarshalIndent(t, "", " ") if err != nil { return err @@ -417,7 +454,7 @@ func (rc *Context) SaveTaskContext(key string, t interface{}) error { return rc.Client().Update(rc.Context(), cm) } -func (rc *Context) IsTaskContextExists(key string) (bool, error) { +func (rc *BackupContext) IsTaskContextExists(key string) (bool, error) { cm, err := rc.GetOrCreateXStoreBackupTaskConfigMap() if err != nil { return false, err @@ -426,7 +463,7 @@ func (rc *Context) IsTaskContextExists(key string) (bool, error) { return ok, nil } -func (rc *Context) GetTaskContext(key string, t interface{}) error { +func (rc *BackupContext) GetTaskContext(key string, t interface{}) error { cm, err := rc.GetOrCreateXStoreBackupTaskConfigMap() if err != nil { return err @@ -435,7 +472,7 @@ func (rc *Context) GetTaskContext(key string, t interface{}) error { return json.Unmarshal([]byte(cm.Data[key]), t) } -func (rc *Context) GetSecret(name string) (*corev1.Secret, error) { +func (rc *BackupContext) GetSecret(name string) (*corev1.Secret, error) { secretKey := types.NamespacedName{ Namespace: rc.Namespace(), Name: name, @@ -448,7 +485,7 @@ func (rc *Context) GetSecret(name string) (*corev1.Secret, error) { return secret, nil } -func (rc *Context) NewSecretFromXStore(secret *corev1.Secret) (*corev1.Secret, error) { +func (rc *BackupContext) NewSecretFromXStore(secret *corev1.Secret) (*corev1.Secret, error) { backup := rc.MustGetXStoreBackup() data := make(map[string][]byte) for user, passwd := range secret.Data { @@ -462,3 +499,37 @@ func (rc *Context) NewSecretFromXStore(secret *corev1.Secret) (*corev1.Secret, e Data: data, }, nil } + +func (rc *BackupContext) GetXstoreGroupManagerByPod(pod *corev1.Pod) (group.GroupManager, error) { + var serviceList corev1.ServiceList + err := rc.Client().List(rc.Context(), &serviceList, client.InNamespace(rc.Namespace()), client.MatchingLabels{ + xstoremeta.LabelPod: pod.Name, + }) + if err != nil { + return nil, err + } + if len(serviceList.Items) == 0 { + return nil, errors.New("no service found related to xstore " + rc.xstore.Name) + } + host := serviceList.Items[0].Name + "." + pod.Namespace + port, err := strconv.Atoi(pod.Labels[xstoremeta.LabelPortLock]) + secret, err := rc.GetSecret(pod.Labels[xstoremeta.LabelName]) + if err != nil { + return nil, err + } + user := xstoreconvention.SuperAccount + passwd, ok := secret.Data[user] + if !ok { + return nil, errors.New("can not get passwd for xsotre " + rc.xstore.Name) + } + return group.NewGroupManager( + rc.Context(), + dbutil.MySQLDataSource{ + Host: host, + Port: port, + Username: user, + Password: string(passwd), + }, + true, + ), nil +} diff --git a/pkg/operator/v1/xstore/reconcile/reconciler.go b/pkg/operator/v1/xstore/reconcile/reconciler.go index e3aa834..976afe6 100644 --- a/pkg/operator/v1/xstore/reconcile/reconciler.go +++ b/pkg/operator/v1/xstore/reconcile/reconciler.go @@ -25,3 +25,7 @@ import ( type Reconciler interface { Reconcile(rc *Context, log logr.Logger, request reconcile.Request) (reconcile.Result, error) } + +type BackupReconciler interface { + Reconcile(rc *BackupContext, log logr.Logger, request reconcile.Request) (reconcile.Result, error) +} diff --git a/pkg/operator/v1/xstore/steps/backup/status.go b/pkg/operator/v1/xstore/steps/backup/status.go index c677e22..c5d713c 100644 --- a/pkg/operator/v1/xstore/steps/backup/status.go +++ b/pkg/operator/v1/xstore/steps/backup/status.go @@ -25,8 +25,8 @@ import ( "github.com/alibaba/polardbx-operator/pkg/k8s/control" k8shelper "github.com/alibaba/polardbx-operator/pkg/k8s/helper" polardbxmeta "github.com/alibaba/polardbx-operator/pkg/operator/v1/polardbx/meta" - "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/backupreconciler" xstoremeta "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/meta" + xstorev1reconcile "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/reconcile" xstorectrlerrors "github.com/alibaba/polardbx-operator/pkg/util/error" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -51,8 +51,8 @@ type BackupJobContext struct { } func UpdatePhaseTemplate(phase xstorev1.XStoreBackupPhase, requeue ...bool) control.BindFunc { - return backupreconciler.NewStepBinder("UpdatePhaseTo"+string(phase), - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { + return NewStepBinder("UpdatePhaseTo"+string(phase), + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { xstoreBackup := rc.MustGetXStoreBackup() xstoreBackup.Status.Phase = phase @@ -70,8 +70,8 @@ func GenerateJobName(targetPod *corev1.Pod, JobLabel string) string { return jobName } -var PersistentStatusChanges = backupreconciler.NewStepBinder("PersistentStatusChanges", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { +var PersistentStatusChanges = NewStepBinder("PersistentStatusChanges", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { if debug.IsDebugEnabled() { xstoreBackup := rc.MustGetXStoreBackup() err := rc.Client().Status().Update(rc.Context(), xstoreBackup) @@ -89,8 +89,8 @@ var PersistentStatusChanges = backupreconciler.NewStepBinder("PersistentStatusCh return flow.Continue("Backup status not changed!") }) -var UpdateBackupStartInfo = backupreconciler.NewStepBinder("UpdateBackupStartInfo", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { +var UpdateBackupStartInfo = NewStepBinder("UpdateBackupStartInfo", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { xstoreBackup := rc.MustGetXStoreBackup() if xstoreBackup.Status.StartTime == nil { @@ -116,8 +116,8 @@ var UpdateBackupStartInfo = backupreconciler.NewStepBinder("UpdateBackupStartInf return flow.Continue("Update backup start info!") }) -var CreateBackupConfigMap = backupreconciler.NewStepBinder("CreateBackupConfigMap", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { +var CreateBackupConfigMap = NewStepBinder("CreateBackupConfigMap", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { const backupJobkey = "backup" exists, err := rc.IsTaskContextExists(backupJobkey) if err != nil { @@ -156,8 +156,8 @@ var CreateBackupConfigMap = backupreconciler.NewStepBinder("CreateBackupConfigMa return flow.Continue("Job context for backup prepared!") }) -var StartXStoreFullBackupJob = backupreconciler.NewStepBinder("StartXStoreFullBackupJob", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { +var StartXStoreFullBackupJob = NewStepBinder("StartXStoreFullBackupJob", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { const backupJobKey = "backup" backupJobContext := &BackupJobContext{} err := rc.GetTaskContext(backupJobKey, &backupJobContext) @@ -173,6 +173,9 @@ var StartXStoreFullBackupJob = backupreconciler.NewStepBinder("StartXStoreFullBa if targetPod == nil { return flow.Wait("Unable to find target pod!") } + if targetPod.Labels[xstoremeta.LabelRole] == xstoremeta.RoleLeader { // warning when backup on leader pod + flow.Logger().Info("Warning: performing backup on leader", "leader pod", targetPod.Name) + } job, err := rc.GetXStoreBackupJob() if client.IgnoreNotFound(err) != nil { @@ -197,8 +200,8 @@ var StartXStoreFullBackupJob = backupreconciler.NewStepBinder("StartXStoreFullBa return flow.Continue("Full Backup job started!", "job-name", jobName) }) -var WaitFullBackupJobFinished = backupreconciler.NewStepBinder("WaitFullBackupJobFinished", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { +var WaitFullBackupJobFinished = NewStepBinder("WaitFullBackupJobFinished", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { xstoreBackup := rc.MustGetXStoreBackup() job, err := rc.GetXStoreBackupJob() @@ -244,8 +247,8 @@ var WaitFullBackupJobFinished = backupreconciler.NewStepBinder("WaitFullBackupJo return flow.Continue("Full Backup job wait finished!", "job-name", job.Name) }) -var RemoveFullBackupJob = backupreconciler.NewStepBinder("RemoveFullBackupJob", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { +var RemoveFullBackupJob = NewStepBinder("RemoveFullBackupJob", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { job, err := rc.GetXStoreBackupJob() if client.IgnoreNotFound(err) != nil { return flow.Error(err, "Unable to get full backup job!") @@ -262,8 +265,8 @@ var RemoveFullBackupJob = backupreconciler.NewStepBinder("RemoveFullBackupJob", return flow.Continue("Full backup job removed!", "job-name", job.Name) }) -var WaitBinlogOffsetCollected = backupreconciler.NewStepBinder("WaitBinlogCollected", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { +var WaitBinlogOffsetCollected = NewStepBinder("WaitBinlogCollected", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { polardbxBackup, err := rc.GetPolarDBXBackup() if err != nil { flow.Error(err, "Unable to find polardbxBackup") @@ -274,8 +277,8 @@ var WaitBinlogOffsetCollected = backupreconciler.NewStepBinder("WaitBinlogCollec return flow.Continue("Binlog Collected!") }) -var StartCollectBinlogJob = backupreconciler.NewStepBinder("StartCollectBinlogJob", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { +var StartCollectBinlogJob = NewStepBinder("StartCollectBinlogJob", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { const backupJobKey = "backup" backupJobContext := &BackupJobContext{} err := rc.GetTaskContext(backupJobKey, &backupJobContext) @@ -323,8 +326,8 @@ var StartCollectBinlogJob = backupreconciler.NewStepBinder("StartCollectBinlogJo return flow.Continue("collect binlog job started!", "job-name", jobName) }) -var WaitCollectBinlogJobFinished = backupreconciler.NewStepBinder("WaitBackupJobFinished", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { +var WaitCollectBinlogJobFinished = NewStepBinder("WaitBackupJobFinished", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { xstore, err := rc.GetXStore() if err != nil { return flow.Error(err, "Unable to find xstore") @@ -349,8 +352,8 @@ var WaitCollectBinlogJobFinished = backupreconciler.NewStepBinder("WaitBackupJob return flow.Continue("Collect binlog wait finished!", "job-name", job.Name) }) -var RemoveCollectBinlogJob = backupreconciler.NewStepBinder("RemoveCollectBinlogJob", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { +var RemoveCollectBinlogJob = NewStepBinder("RemoveCollectBinlogJob", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { job, err := rc.GetCollectBinlogJob() if client.IgnoreNotFound(err) != nil { return flow.Error(err, "Unable to get collect binlog job!") @@ -367,8 +370,8 @@ var RemoveCollectBinlogJob = backupreconciler.NewStepBinder("RemoveCollectBinlog return flow.Continue("Collect binlog job removed!", "job-name", job.Name) }) -var WaitPXCSeekCpJobFinished = backupreconciler.NewStepBinder("WaitPXCSeekCpJobFinished", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { +var WaitPXCSeekCpJobFinished = NewStepBinder("WaitPXCSeekCpJobFinished", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { polardbxBackup, err := rc.GetPolarDBXBackup() if err != nil { flow.Error(err, "Unable to find polardbxBackup") @@ -382,8 +385,8 @@ var WaitPXCSeekCpJobFinished = backupreconciler.NewStepBinder("WaitPXCSeekCpJobF return flow.Continue("Binlog Collected!") }) -var StartBinlogBackupJob = backupreconciler.NewStepBinder("StartBinlogBackupJob", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { +var StartBinlogBackupJob = NewStepBinder("StartBinlogBackupJob", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { const backupJobKey = "backup" backupJobContext := &BackupJobContext{} err := rc.GetTaskContext(backupJobKey, &backupJobContext) @@ -426,23 +429,27 @@ var StartBinlogBackupJob = backupreconciler.NewStepBinder("StartBinlogBackupJob" return flow.Continue("collect binlog job started!", "job-name", jobName) }) -var WaitBinlogBackupJobFinished = backupreconciler.NewStepBinder("WaitBinlogBackupJobFinished", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { - backup := rc.MustGetXStoreBackup() +var WaitBinlogBackupJobFinished = NewStepBinder("WaitBinlogBackupJobFinished", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { job, err := rc.GetBackupBinlogJob() if client.IgnoreNotFound(err) != nil { return flow.Error(err, "Unable to get binlog backup job!") } if job == nil { + flow.Logger().Info("Binlog backup job nil!", "err", err) return flow.Continue("Binlog backup job removed!") } - if !k8shelper.IsJobCompleted(job) { return flow.Wait("Binlog backup job is still running!", "job-name", job.Name) } + return flow.Continue("Binlog backup job wait finished!", "job-name", job.Name) + }) + +var ExtractLastEventTimestamp = NewStepBinder("ExtractLastEventTimestamp", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { + backup := rc.MustGetXStoreBackup() nowTime := metav1.Now() backup.Status.EndTime = &nowTime - flow.Logger().Info("Binlog backup job completed!", "job-name", job.Name) targetPod, err := rc.GetXStoreTargetPod() if err != nil { @@ -472,11 +479,11 @@ var WaitBinlogBackupJobFinished = backupreconciler.NewStepBinder("WaitBinlogBack } timestamp := metav1.Unix(timestampNum, 0) backup.Status.BackupSetTimestamp = ×tamp - return flow.Continue("Binlog backup job wait finished!", "job-name", job.Name) + return flow.Continue("Extract binlog last event timestamp finished!", "pod", targetPod.Name) }) -var RemoveBinlogBackupJob = backupreconciler.NewStepBinder("RemoveBinlogBackupJob", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { +var RemoveBinlogBackupJob = NewStepBinder("RemoveBinlogBackupJob", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { job, err := rc.GetBackupBinlogJob() if client.IgnoreNotFound(err) != nil { return flow.Error(err, "Unable to get binlog backup job!") @@ -493,8 +500,8 @@ var RemoveBinlogBackupJob = backupreconciler.NewStepBinder("RemoveBinlogBackupJo return flow.Continue("Binlog backup job removed!", "job-name", job.Name) }) -var RemoveXSBackupOverRetention = backupreconciler.NewStepBinder("RemoveXSBackupOverRetention", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { +var RemoveXSBackupOverRetention = NewStepBinder("RemoveXSBackupOverRetention", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { backup := rc.MustGetXStoreBackup() if backup.Spec.RetentionTime.Duration.Seconds() > 0 { toCleanTime := backup.Status.EndTime.Add(backup.Spec.RetentionTime.Duration) @@ -525,8 +532,8 @@ var RemoveXSBackupOverRetention = backupreconciler.NewStepBinder("RemoveXSBackup return flow.Continue("PolarDBX backup deleted!", "XSBackup-name", backup.Name) }) -var WaitPXCBackupFinished = backupreconciler.NewStepBinder("WaitPXCBackupFinished", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { +var WaitPXCBackupFinished = NewStepBinder("WaitPXCBackupFinished", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { polardbxBackup, err := rc.GetPolarDBXBackup() if err != nil { flow.Error(err, "Unable to find polardbxBackup") @@ -537,8 +544,8 @@ var WaitPXCBackupFinished = backupreconciler.NewStepBinder("WaitPXCBackupFinishe return flow.Continue("Backup Finished!") }) -var SaveXStoreSecrets = backupreconciler.NewStepBinder("SaveXStoreSecrets", - func(rc *backupreconciler.Context, flow control.Flow) (reconcile.Result, error) { +var SaveXStoreSecrets = NewStepBinder("SaveXStoreSecrets", + func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) { backup := rc.MustGetXStoreBackup() backupSecret, err := rc.GetSecret(backup.Name) if backupSecret != nil { diff --git a/pkg/operator/v1/xstore/backupreconciler/adaptor.go b/pkg/operator/v1/xstore/steps/backup/step_binder.go similarity index 77% rename from pkg/operator/v1/xstore/backupreconciler/adaptor.go rename to pkg/operator/v1/xstore/steps/backup/step_binder.go index d825ccf..5ed2a54 100644 --- a/pkg/operator/v1/xstore/backupreconciler/adaptor.go +++ b/pkg/operator/v1/xstore/steps/backup/step_binder.go @@ -14,24 +14,23 @@ See the License for the specific language governing permissions and limitations under the License. */ -package backupreconciler +package backup import ( + "github.com/alibaba/polardbx-operator/pkg/k8s/control" + xstorev1reconcile "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/reconcile" "github.com/go-logr/logr" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - - "github.com/alibaba/polardbx-operator/pkg/k8s/control" ) -type ConditionFunc func(rc *Context, log logr.Logger) (bool, error) -type StepFunc func(rc *Context, flow control.Flow) (reconcile.Result, error) +type ConditionFunc func(rc *xstorev1reconcile.BackupContext, log logr.Logger) (bool, error) +type StepFunc func(rc *xstorev1reconcile.BackupContext, flow control.Flow) (reconcile.Result, error) func NewStepBinder(name string, f StepFunc) control.BindFunc { return control.NewStepBinder( control.NewStep( name, func(rc control.ReconcileContext, flow control.Flow) (reconcile.Result, error) { - return f(rc.(*Context), flow) + return f(rc.(*xstorev1reconcile.BackupContext), flow) }, ), ) @@ -40,7 +39,7 @@ func NewStepBinder(name string, f StepFunc) control.BindFunc { func NewStepIfBinder(conditionName string, condFunc ConditionFunc, binders ...control.BindFunc) control.BindFunc { condition := control.NewCachedCondition( control.NewCondition(conditionName, func(rc control.ReconcileContext, log logr.Logger) (bool, error) { - return condFunc(rc.(*Context), log) + return condFunc(rc.(*xstorev1reconcile.BackupContext), log) }), ) diff --git a/pkg/operator/v1/xstore/steps/follower/job.go b/pkg/operator/v1/xstore/steps/follower/job.go index 894bf7c..f361cb1 100644 --- a/pkg/operator/v1/xstore/steps/follower/job.go +++ b/pkg/operator/v1/xstore/steps/follower/job.go @@ -260,6 +260,7 @@ out: var jobParallelism int32 = 1 var completions int32 = 1 var backOffLimit int32 = 0 + var jobTTL int32 = 3600 * 24 * 7 job := batchv1.Job{ ObjectMeta: metav1.ObjectMeta{ Name: ctx.jobName, @@ -271,9 +272,10 @@ out: }, }, Spec: batchv1.JobSpec{ - Parallelism: &jobParallelism, - Completions: &completions, - BackoffLimit: &backOffLimit, + TTLSecondsAfterFinished: &jobTTL, + Parallelism: &jobParallelism, + Completions: &completions, + BackoffLimit: &backOffLimit, Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Namespace: ctx.jobTargetPod.Namespace, diff --git a/pkg/operator/v1/xstore/steps/instance/cgroup_blkio.go b/pkg/operator/v1/xstore/steps/instance/cgroup_blkio.go index 8a0493e..1853da8 100644 --- a/pkg/operator/v1/xstore/steps/instance/cgroup_blkio.go +++ b/pkg/operator/v1/xstore/steps/instance/cgroup_blkio.go @@ -135,6 +135,10 @@ var SyncBlkioCgroupResourceLimits = xstorev1reconcile.NewStepBinder("SyncBlkioCg // Sync via hpfs. err := SyncBlkioCgroupValuesViaHpfs(ctx, hpfsClient, &pod, volumes[pod.Name], resources) if err != nil { + if !rc.Config().Cluster().ForceCGroup() { + flow.Error(err, "Failed to SyncBlkioCgroupValues") + return flow.Continue("Skip syncing cgroup blkio values.") + } return flow.Error(err, "Failed to sync blkio cgroup values.", "host", pod.Spec.NodeName, "pod", pod.Name, "blkio", blkioVal) } diff --git a/pkg/probe/proxy.go b/pkg/probe/proxy.go index f7e15ee..9900cc1 100644 --- a/pkg/probe/proxy.go +++ b/pkg/probe/proxy.go @@ -37,7 +37,7 @@ func handleErr(w http.ResponseWriter, err error) { log.Println("Timeout!") w.WriteHeader(http.StatusRequestTimeout) } else { - log.Println("Failed!") + log.Println("Failed!" + err.Error()) w.WriteHeader(http.StatusInternalServerError) } } diff --git a/pkg/util/formula/fomula.go b/pkg/util/formula/fomula.go index a98fc41..2b15faf 100644 --- a/pkg/util/formula/fomula.go +++ b/pkg/util/formula/fomula.go @@ -10,47 +10,47 @@ import ( ) /* -* 支持变量 - -AllocatedStorage:实例购买的存储空间大小,整数型 -DBInstanceClassMemory:实例规格的内存大小,整数型 -DBInstanceClassCPU:实例规格的CPU核数,整数型 - -* 支持公式 - -数据库参数公式支持两个运算符:除法和乘法。 -除法运算符:/ -用除数除以被除数,返回整数型商。商中的小数不四舍五入,直接截断。 -语法 -dividend / divisor -被除数和除数参数必须是整数型表达式。 -乘法运算符:* -用除数除以被除数,返回整数型商。商中的小数不四舍五入,直接截断。 -语法 -expression * expression -两个表达式必须都是整数型。 - -* 支持函数 - -GREATEST() -返回整数型或者参数公式列表中最大的值。 -语法 -GREATEST(argument1, argument2,...argumentn) -返回整数。 -LEAST() -返回整数型或者参数公式列表中最小的值。 -语法 -LEAST(argument1, argument2,...argumentn) -返回整数。 -SUM() -添加指定整数型或者参数公式的值。 -语法 -SUM(argument1, argument2,...argumentn) -返回整数。 - -例如 -innodb_buffer_pool_size = {DBInstanceClassMemory*3/4} -read_buffer_size = {LEAST(DBInstanceClassMemory/1048576*128, 262144)} + * 支持变量 + + AllocatedStorage:实例购买的存储空间大小,整数型 + DBInstanceClassMemory:实例规格的内存大小,整数型 + DBInstanceClassCPU:实例规格的CPU核数,整数型 + + * 支持公式 + + 数据库参数公式支持两个运算符:除法和乘法。 + 除法运算符:/ + 用除数除以被除数,返回整数型商。商中的小数不四舍五入,直接截断。 + 语法 + dividend / divisor + 被除数和除数参数必须是整数型表达式。 + 乘法运算符:* + 用除数除以被除数,返回整数型商。商中的小数不四舍五入,直接截断。 + 语法 + expression * expression + 两个表达式必须都是整数型。 + + * 支持函数 + + GREATEST() + 返回整数型或者参数公式列表中最大的值。 + 语法 + GREATEST(argument1, argument2,...argumentn) + 返回整数。 + LEAST() + 返回整数型或者参数公式列表中最小的值。 + 语法 + LEAST(argument1, argument2,...argumentn) + 返回整数。 + SUM() + 添加指定整数型或者参数公式的值。 + 语法 + SUM(argument1, argument2,...argumentn) + 返回整数。 + + 例如 + innodb_buffer_pool_size = {DBInstanceClassMemory*3/4} + read_buffer_size = {LEAST(DBInstanceClassMemory/1048576*128, 262144)} */ func formulaComputing(valueStr string, memory, cpu, storage int) (int, error) { if valueStr[len(valueStr)-1] != '}' { diff --git a/pkg/webhook/parameter/utils.go b/pkg/webhook/parameter/utils.go index 040bf41..5c7cb98 100644 --- a/pkg/webhook/parameter/utils.go +++ b/pkg/webhook/parameter/utils.go @@ -100,47 +100,47 @@ func calculate(s string) int64 { } /* -* 支持变量 - -AllocatedStorage:实例购买的存储空间大小,整数型 -DBInstanceClassMemory:实例规格的内存大小,整数型 -DBInstanceClassCPU:实例规格的CPU核数,整数型 - -* 支持公式 - -数据库参数公式支持两个运算符:除法和乘法。 -除法运算符:/ -用除数除以被除数,返回整数型商。商中的小数不四舍五入,直接截断。 -语法 -dividend / divisor -被除数和除数参数必须是整数型表达式。 -乘法运算符:* -用除数除以被除数,返回整数型商。商中的小数不四舍五入,直接截断。 -语法 -expression * expression -两个表达式必须都是整数型。 - -* 支持函数 - -GREATEST() -返回整数型或者参数公式列表中最大的值。 -语法 -GREATEST(argument1, argument2,...argumentn) -返回整数。 -LEAST() -返回整数型或者参数公式列表中最小的值。 -语法 -LEAST(argument1, argument2,...argumentn) -返回整数。 -SUM() -添加指定整数型或者参数公式的值。 -语法 -SUM(argument1, argument2,...argumentn) -返回整数。 - -例如 -innodb_buffer_pool_size = {DBInstanceClassMemory*3/4} -read_buffer_size = {LEAST(DBInstanceClassMemory/1048576*128, 262144)} + * 支持变量 + + AllocatedStorage:实例购买的存储空间大小,整数型 + DBInstanceClassMemory:实例规格的内存大小,整数型 + DBInstanceClassCPU:实例规格的CPU核数,整数型 + + * 支持公式 + + 数据库参数公式支持两个运算符:除法和乘法。 + 除法运算符:/ + 用除数除以被除数,返回整数型商。商中的小数不四舍五入,直接截断。 + 语法 + dividend / divisor + 被除数和除数参数必须是整数型表达式。 + 乘法运算符:* + 用除数除以被除数,返回整数型商。商中的小数不四舍五入,直接截断。 + 语法 + expression * expression + 两个表达式必须都是整数型。 + + * 支持函数 + + GREATEST() + 返回整数型或者参数公式列表中最大的值。 + 语法 + GREATEST(argument1, argument2,...argumentn) + 返回整数。 + LEAST() + 返回整数型或者参数公式列表中最小的值。 + 语法 + LEAST(argument1, argument2,...argumentn) + 返回整数。 + SUM() + 添加指定整数型或者参数公式的值。 + 语法 + SUM(argument1, argument2,...argumentn) + 返回整数。 + + 例如 + innodb_buffer_pool_size = {DBInstanceClassMemory*3/4} + read_buffer_size = {LEAST(DBInstanceClassMemory/1048576*128, 262144)} */ func formulaComputing(valueStr string, polardbxcluster *polardbxv1.PolarDBXCluster) (int64, error) { if valueStr[len(valueStr)-1] != '}' { diff --git a/pkg/webhook/parameter/validator.go b/pkg/webhook/parameter/validator.go index d25cb94..8de736c 100644 --- a/pkg/webhook/parameter/validator.go +++ b/pkg/webhook/parameter/validator.go @@ -33,10 +33,6 @@ type Validator struct { func (v *Validator) validateObject(ctx context.Context, obj *polardbxv1.PolarDBXParameter, polardbxcluster *polardbxv1.PolarDBXCluster) field.ErrorList { var errList field.ErrorList - if obj.Labels[convention.ParameterName] != convention.ParameterType { - errList = append(errList, field.Required(field.NewPath("labels", "convention.ParameterType"), "parameter's label must add \"parameter: dynamic\"")) - } - polarDBXParameterList := polardbxv1.PolarDBXParameterList{} err := v.List(context.Background(), &polarDBXParameterList, client.InNamespace(obj.Namespace), diff --git a/test/e2e/polardbxparameter/common.go b/test/e2e/polardbxparameter/common.go index 36d0955..054f6bf 100644 --- a/test/e2e/polardbxparameter/common.go +++ b/test/e2e/polardbxparameter/common.go @@ -26,7 +26,7 @@ func CreatePolarDBXParameterAndWaitUntilRunningOrFail(f *framework.Framework, po pxmframework.WaitPolarDBXParameterInPhase(f.Client, polardbxparameter.Name, polardbxparameter.Namespace, []polardbxv1polardbx.ParameterPhase{ - polardbxv1polardbx.ParameterStatusRunning, + polardbxv1polardbx.ParameterStatusFinished, }, timeout) framework.ExpectNoError(err) diff --git a/tools/xstore/cli/collect.py b/tools/xstore/cli/collect.py index 20cc888..e40d7bf 100644 --- a/tools/xstore/cli/collect.py +++ b/tools/xstore/cli/collect.py @@ -47,10 +47,10 @@ def get_binlog_list(context, start_binlog_name, end_binlog_name): log_dir = context.volume_path(VOLUME_DATA, "log") binlog_list = binlog.get_local_binlog(min_binlog_name=start_binlog_name, max_binglog_name=end_binlog_name, left_contain=True, right_contain=True) - binlog_list_str = "" + binlog_path_list = [] for i, (logname, start_log_index) in enumerate(binlog_list): - binlog_list_str = binlog_list_str + os.path.join(log_dir, logname) + " " - return binlog_list, binlog_list_str.strip() + binlog_path_list.append(os.path.join(log_dir, logname)) + return binlog_list, binlog_path_list def seekhb_and_upload(filstream_client, file_path, context, binlog_list, heartbeat_name, backup_dir, logger): @@ -71,7 +71,7 @@ def seekhb_and_upload(filstream_client, file_path, context, binlog_list, heartbe break -def collect_and_upload(context, start_binlog_name, start_offset, end_binlog_name, end_offset, binlog_list_name, +def collect_and_upload(context, start_binlog_name, start_offset, end_binlog_name, end_offset, binlog_path_list, file_path, filestream_client, backup_dir, logger): collect_local_file = os.path.join(backup_dir, "collect") os.makedirs(collect_local_file, exist_ok=True) @@ -81,9 +81,8 @@ def collect_and_upload(context, start_binlog_name, start_offset, end_binlog_name collect_cmd = [context.bb_home, 'txdump', '--start-offset', start_binlog, '--end-offset', end_binlog, - '--bin', '--output', local_collect_file_path, - binlog_list_name - ] + '--bin', '--output', local_collect_file_path + ] + binlog_path_list check_run_process(collect_cmd, logger=logger) filestream_client.upload_from_file(remote=file_path, local=local_collect_file_path, logger=logger) @@ -123,12 +122,14 @@ def collect_binlog_index(backup_context, heartbeat_name): start_binlog_name, start_offset, end_binlog_name, end_offset = download_binlog_offset_to_local(offsetfile_name, filestream_client, backup_dir) - binlog_list, binlog_list_name = get_binlog_list(context, start_binlog_name, end_binlog_name) + # binlog_list only records binlog name, while binlog_path_list contains absolute path for each binlog + binlog_list, binlog_path_list = get_binlog_list(context, start_binlog_name, end_binlog_name) + logger.info("start_binlog_name:%s, start_offset:%s, end_binlog_name:%s, end_offset:%s", start_binlog_name, start_offset, end_binlog_name, end_offset) seekhb_and_upload(filestream_client, collect_file, context, binlog_list, heartbeat_name, backup_dir, logger) - collect_and_upload(context, start_binlog_name, start_offset, end_binlog_name, end_offset, binlog_list_name, + collect_and_upload(context, start_binlog_name, start_offset, end_binlog_name, end_offset, binlog_path_list, collect_file, filestream_client, backup_dir, logger) diff --git a/tools/xstore/core/consensus/manager_impl.py b/tools/xstore/core/consensus/manager_impl.py index db38a13..fa227ce 100644 --- a/tools/xstore/core/consensus/manager_impl.py +++ b/tools/xstore/core/consensus/manager_impl.py @@ -411,9 +411,8 @@ def current_node(self) -> ConsensusNode: return self._consensus_node_from_local_row(r) def change_leader(self, target: Union[str, ConsensusNode]): - target_server_id = self._get_server_id(target) with self._conn.cursor() as cur: - cur.execute('call dbms_consensus.change_leader(%d)' % target_server_id) + cur.execute('call dbms_consensus.change_leader("%s")' % target) def configure_follower(self, target: Union[str, ConsensusNode], election_weight: int, force_sync: bool): addr = self._get_address(target)