• 采用Atlas+Keepalived实现MySQL读写分离、读负载均衡


    ==========================================================================================

    一、基础介绍

    ==========================================================================================

    1、背景描述

    目前我们的高可用DB的代理层采用的是360开源的Atlas,从上线以来,已稳定运行2个多月。无论是从性能上,还是稳定性上,相比其他开源组件(amoebacobarMaxScaleMySQL-Proxy等),还是很出色的。

    当初我们之所以选择Atlas,主要看中它有以下优点:

    (1)、基于mysql-proxy-0.8.2进行修改,代码完全开源;

    (2)、比较轻量级,部署配置也比较简单;

    (3)、支持DB读写分离;

    (4)、支持从DB读负载均衡,并自动剔除故障从DB

    (5)、支持平滑上下线DB

    (6)、具备较好的安全机制(IP过滤、账号认证);

    (7)、版本更新、问题跟进、交流圈子都比较活跃。

    在测试期间以及线上问题排查过程中,得到了360 Atlas作者朱超的热心解答,在此表示感谢。有关更多Atlas的介绍,我就不一一例举,可以参考以下链接:

    https://github.com/Qihoo360/Atlas/blob/master/README_ZH.md

    2、总体架构图

    wKioL1Sw6iagbaHjAAJX6OZk-GM940.jpg

    3、系统环境

    CentOS 6.3 x86_64

    ==========================================================================================

    二、安装部署

    ==========================================================================================

    1、需注意的地方

    (1)、本次安装不使用系统默认的glib库,之前的yum安装只是为了先解决依赖库的问题;

    (2)LUA库的版本不能太高,为5.1.x即可;

    (3)glib库的版本也不能太高,为glib-2.32.x即可;

    (4)、对于编译不成功的情况,注意查看下面的说明。

    2GLIB依赖的基础库安装

    # yum -y install *glib*

    3LUA库安装

    http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz

    # tar xvzf ncurses-5.9.tar.gz

    # cd ncurses-5.9

    # ./configure --prefix=/usr/local

    # make && make install

    ftp://ftp.gnu.org/gnu/readline/readline-6.2.tar.gz

    # tar xvzf readline-6.2.tar.gz

    # cd readline-6.2

    # ./configure --prefix=/usr/local

    # make && make install

    http://www.lua.org/ftp/lua-5.1.5.tar.gz

    # tar xvzf lua-5.1.5.tar.gz

    # cd lua-5.1.5

    # make linux install

    注意:

    修改当前目录下的“Makefile”中的 INSTALL_TOP= /usr/local INSTALL_TOP= /usr/local/lua

    主要是为了避免与系统自带的lua库发生冲突的可能

    在“src/Makefile”文件中加入“-lncurses”,完整内容如下:

    linux:

            $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lncurses -lreadline"

    4GLIB库安装

    ftp://sourceware.org/pub/libffi/libffi-3.0.13.tar.gz

    # tar xvzf libffi-3.0.13.tar.gz

    # cd libffi-3.0.13

    # ./configure --prefix=/usr/local

    # make && make install

    http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz

    # tar xvzf libiconv-1.14.tar.gz

    # cd libiconv-1.14

    # ./configure --prefix=/usr/local

    # make && make install

    http://tukaani.org/xz/xz-5.0.5.tar.gz

    # tar xvzf xz-5.0.5.tar.gz

    # cd xz-5.0.5

    # ./configure --prefix=/usr/local

    # make && make install

    # /sbin/ldconfig

    http://ftp.gnome.org/pub/gnome/sources/glib/2.32/glib-2.32.4.tar.xz

    # xz -d glib-2.32.4.tar.xz

    # tar -xvf glib-2.32.4.tar

    # cd glib-2.32.4

    # ./configure --prefix=/usr/local/glib-2.32.4

    --with-libiconv=/usr/local

    LIBFFI_CFLAGS="-I/usr/local/include"

    LIBFFI_LIBS="-L/usr/local/lib -lffi"

    # make && make install

    注意:编译报错处理

    (1)configure阶段

    # vim ./glib/gconvert.c

    注释掉第2628行的内容

    注释掉从61行到67行的内容

    # vim ./configure

    7880行之上添加如下内容:

    found_iconv=yes

    (2)make阶段

    # ln -s /usr/local/lib/libffi-3.0.13/include/ffi.h /usr/local/include

    # ln -s /usr/local/lib/libffi-3.0.13/include/ffitarget.h /usr/local/include

    glib库需要安装在单独的目录“/usr/local/glib-2.32.4”,也是为了避免与系统自带的glib库发生冲突的可能

    5Atlas安装

    (1)、其他基础组件安装

    https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz

    # tar xvzf libevent-2.0.21-stable.tar.gz

    # cd libevent-2.0.21-stable

    # ./configure --prefix=/usr/local

    # make && make install

    http://www.openssl.org/source/openssl-1.0.1h.tar.gz

    # tar xvzf openssl-1.0.1h.tar.gz

    # cd openssl-1.0.1h

    # ./config shared --prefix=/usr/local

    # make && make install

    (2)MySQL安装(无需启动)

    http://wwwNaNake.org/files/v2.8/cmake-2.8.10.2.tar.gz

    # tar -xvzf cmake-2.8.10.2.tar.gz

    # cd cmake-2.8.10.2

    # ./bootstrap --prefix=/usr/local

    # gmake --jobs=`grep processor /proc/cpuinfo | wc -l`

    # gmake install

     

    http://downloads.mysql.com/archives/get/file/mysql-5.5.24.tar.gz

    # tar -xvzf mysql-5.5.24.tar.gz

    # cd mysql-5.5.24

    # rm-f CMakeCache.txt

    # cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql

    -DMYSQL_UNIX_ADDR=/var/run/mysql/mysql.sock

    -DDEFAULT_CHARSET=utf8

    -DDEFAULT_COLLATION=utf8_general_ci

    -DEXTRA_CHARSETS=all

    -DWITH_MYISAM_STORAGE_ENGINE=1

    -DWITH_INNOBASE_STORAGE_ENGINE=1

    -DWITH_READLINE=1

    -DENABLED_LOCAL_INFILE=1

    -DWITH_EMBEDDED_SERVER=1

    -DMYSQL_DATADIR=/data/dbdata/data

    -DMYSQL_TCP_PORT=3306

    # make --jobs=`grep processor /proc/cpuinfo | wc -l`

    # make install

    (3)DB中间件安装

    https://github.com/Qihoo360/Atlas/archive/2.2.1.tar.gz

    # tar xvzf Atlas-2.2.1.tar.gz

    # cd Atlas-2.2.1

    # ./configure --prefix=/usr/local/mysql-proxy

    --with-lua=/usr/local/lua

    --with-mysql=/usr/local/mysql

    GLIB_CFLAGS="-I/usr/local/glib-2.32.4/include/glib-2.0"

    GLIB_LIBS="-L/usr/local/glib-2.32.4/lib/glib-2.0 -lglib-2.0"

    GMODULE_CFLAGS="-I/usr/local/glib-2.32.4/include"

    GMODULE_LIBS="-L/usr/local/glib-2.32.4/lib -lgmodule-2.0"

    GTHREAD_CFLAGS="-I/usr/local/glib-2.32.4/include"

    GTHREAD_LIBS="-L/usr/local/glib-2.32.4/lib -lgthread-2.0"

    LUA_CFLAGS="-I/usr/local/lua/include"

    LUA_LIBS="-L/usr/local/lua/lib -llua-5.1"

    CFLAGS="-DHAVE_LUA_H -O2"

    LDFLAGS="-L/usr/local/lib -L/usr/local/lib64 -lm -ldl -lcrypto"

    # make && make install

    注意:

    编译报错处理

    # ln -s /usr/local/glib-2.32.4/lib/glib-2.0/include/glibconfig.h /usr/local/glib-2.32.4/include/glib-2.0

    # cd /usr/local

    # mv mysql-proxy atlas-2.2.1 && ln -s atlas-2.2.1 mysql-proxy

    6DB中间层配置

    (1)、主配置

    # vim /usr/local/mysql-proxy/conf/mysql-proxy.cnf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    [mysql-proxy]
    admin-username = sysadmin
    admin-password = admin2356!@()
      
    proxy-backend-addresses = 10.222.5.224:3306
    proxy-read-only-backend-addresses = 10.240.95.107:3306,10.240.95.108:3306
      
    pwds = health_check1:/iZxz+0GRoA=,health_check2:/iZxz+0GRoA=
      
    daemon = true
    keepalive = true
      
    event-threads = 16
      
    log-level = message
    log-path = /usr/local/mysql-proxy/log
    sql-log = ON
      
    proxy-address = 0.0.0.0:3306
    admin-address = 10.209.6.101:3307
      
    charset = utf8

    (2)、启动脚本

    # vim /etc/init.d/mysql-proxy

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    #!/bin/sh
    #
    # mysql-proxy This script starts and stops the mysql-proxy daemon
    #
    # chkconfig: - 78 30
    # processname: mysql-proxy
    # description: mysql-proxy is a proxy daemon to mysql
    # config: /usr/local/mysql-proxy/conf/mysql-proxy.cnf
    # pidfile: /usr/local/mysql-proxy/log/mysql-proxy.pid
    #
    PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
      
    DAEMON="/usr/local/mysql-proxy/bin/mysql-proxy"
    CONFIGFILE="/usr/local/mysql-proxy/conf/mysql-proxy.cnf"
    PIDFILE="/usr/local/mysql-proxy/log/mysql-proxy.pid"
    LOCKFILE="/var/lock/subsys/mysql-proxy"
    PROG=`basename $DAEMON`
      
    RETVAL=0
      
    start() {
        echo -n $"Starting ${PROG}......"
        [ -x $DAEMON ] || exit 5
        [ -f $CONFIGFILE ] || exit 6
        ${DAEMON} --defaults-file=${CONFIGFILE} || echo -n "${PROG} already running"
      
        RETVAL=$?
        echo
        [[ $RETVAL -eq 0 ]] && touch $LOCKFILE
      
        return $RETVAL
    }
      
    stop() {
        echo -n $"Stopping ${PROG}......"
        if [[ `ps aux | grep bin/mysql-proxy grep -v grep wc -l` -gt 0 ]]; then
            kill -TERM `ps -A -oppid,pid,cmd | grep bin/mysql-proxy grep -v grep awk '{print $2}'`
        fi
      
        RETVAL=$?
        echo
        [[ $RETVAL -eq 0 ]] && rm -f $LOCKFILE $PIDFILE
      
        return $RETVAL
    }
      
    restart() {
        stop
        sleep 1
        start
    }
      
    case "$1" in
    start)
        start
        ;;
      
    stop)
        stop
        ;;
      
    restart)
        restart
        ;;
      
    condrestart)
        [[ -e $LOCKFILE ]] && restart
        ;;
      
    *)
        echo "Usage: $0 {start|stop|restart|condrestart}"
        RETVAL=1
        ;;
    esac
      
    exit $RETVAL

    # chmod +x /etc/init.d/mysql-proxy

    # chmod 0660 /usr/local/mysql-proxy/conf/mysql-proxy.cnf

    # service mysql-proxy start

    # ps aux | grep mysql-prox[y]

    wKiom1Sw7APBGLlPAABNGlf7ct0239.jpg

    7Atlas高可用【Keepalived】环境安装

    http://rpm5.org/files/popt/popt-1.14.tar.gz

    # tar xvzf popt-1.14.tar.gz

    # cd popt-1.14

    # ./configure --prefix=/usr/local

    # make && make install

    http://www.carisma.slowglass.com/~tgr/libnl/files/libnl-3.2.24.tar.gz

    # tar xvzf libnl-3.2.24.tar.gz

    # cd libnl-3.2.24

    # ./configure --prefix=/usr/local

    # make && make install

    # ln -s /usr/local/include/libnl3/netlink /usr/local/include

    # /sbin/ldconfig

    http://www.keepalived.org/software/keepalived-1.2.10.tar.gz

    # tar xvzf keepalived-1.2.10.tar.gz

    # cd keepalived-1.2.10

    # ./configure --prefix=/usr/local/keepalived

    # make && make install

    # ln -s /usr/local/keepalived/sbin/keepalived /usr/sbin

    # ln -s /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig

    # ln -s /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d

    # chkconfig --add keepalived

    8Atlas高可用【Keepalived】配置

    # mkdir –p /etc/keepalived /data/scripts

    (1)、主节点配置

    # vim /etc/keepalived/keepalived.conf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    global_defs {
        notification_email {
            lovezym5@126.com
        }
      
        notification_email_from lovezym5@126.com
        smtp_server 127.0.0.1
        smtp_connect_timeout 30
        router_id dbproxy1
    }
      
    vrrp_script chk_mysql_proxy_health {
        script "/data/scripts/keepalived_check_mysql_proxy.sh"
        interval 1
        weight -2
    }
      
    vrrp_instance VI_1 {
        state MASTER
        interface eth1
        virtual_router_id 51
        priority 100
        advert_int 1
        smtp_alert
      
        authentication {
            auth_type PASS
            auth_pass 123456
        }
      
        virtual_ipaddress {
            10.209.6.115
        }
      
        track_script {
            chk_mysql_proxy_health
        }
      
        notify_master "/data/scripts/notify.sh master"
        notify_bakcup "/data/scripts/notify.sh backup"
        notify_fault "/data/scripts/notify.sh fault"
    }

    (2)、备用节点配置

    # vim /etc/keepalived/keepalived.conf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    global_defs {
        notification_email {
            lovezym5@126.com
        }
      
        notification_email_from lovezym5@126.com
        smtp_server 127.0.0.1
        smtp_connect_timeout 30
        router_id dbproxy2
    }
      
    vrrp_script chk_mysql_proxy_health {
        script "/data/scripts/keepalived_check_mysql_proxy.sh"
        interval 1
        weight -2
    }
      
    vrrp_instance VI_1 {
        state BACKUP
        interface eth1
        virtual_router_id 51
        priority 90
        advert_int 1
        smtp_alert
      
        authentication {
            auth_type PASS
            auth_pass 123456
        }
      
        virtual_ipaddress {
            10.209.6.115
        }
      
        track_script {
            chk_mysql_proxy_health
        }
      
        notify_master "/data/scripts/notify.sh master"
        notify_bakcup "/data/scripts/notify.sh backup"
        notify_fault "/data/scripts/notify.sh fault"
    }

    (3)VIP切换通知脚本

    # vim /data/scripts/notify.sh

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    #!/bin/sh
    PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
      
    KEEPALIVE_CONF="/etc/keepalived/keepalived.conf"
      
    VIP=`grep -A 1 virtual_ipaddress ${KEEPALIVE_CONF} | tail -1 | sed 's/ //g; s/ //g'`
    ETH1_ADDR=`/sbin/ifconfig eth1 | awk '/inet addr:/{print $2}' awk -F: '{print $2}'`
      
    MONITOR="/usr/local/oms/agent/alarm/BusMonitorAgent"
    TOKEN="ha_monitor"
      
    function notify() {
        TITLE="$ETH1_ADDR to be $1: $VIP floating"
        CONTENT="vrrp transition, $ETH1_ADDR changed to be $1"
        ${MONITOR} -c 2 -f ${TOKEN} -t "${TITLE}" -i "${CONTENT}"
    }
      
    case "$1" in
    master)
        notify master
        exit 0
        ;;
      
    backup)
        notify backup
        exit 0
        ;;
      
    fault)
        notify fault
        exit 0
        ;;
      
    *)
        echo 'Usage: `basename $0` {master|backup|fault}'
        exit 1
        ;;
    esac

    (4)DB中间层进程检查脚本

    # vim /data/scripts/keepalived_check_mysql_proxy.sh

    1
    2
    3
    4
    5
    6
    7
    #!/bin/sh
    PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
      
    if [[ `pgrep mysql-proxy | wc -l` -eq 0 ]]; then
        /sbin/service mysql-proxy start && sleep 5
        [[ -z `pgrep mysql-proxy` ]] && /sbin/service keepalived stop
    fi

    # chmod +x /data/scripts/*.sh

    # service keepalived start

    wKioL1Sw72OBWcdcAABQovflyow736.jpg

    # ip addr show eth1

    wKiom1Sw7r3S6v6_AACfXZvxonQ064.jpg

    # ps aux | grep keepalive[d]

    wKiom1Sw7tnzsSOAAABqz91YIVo562.jpg

    ==========================================================================================

    三、其他设置

    ==========================================================================================

    1Atlas服务监控

    # vim /usr/local/mysql-proxy/bin/check_service.sh

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    #!/bin/sh
    PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
      
    [[ $# -ne 3 ]] && echo "$0 端口号 协议类型 服务名" && exit 1
      
    SRV_PORT=$1  ## 端口号
    SRV_PROT=$2  ## 协议类型
    SRV_NAME=$3  ## 服务名
      
    MONITOR="/usr/local/oms/agent/alarm/BusMonitorAgent"
    TOKEN="ha_monitor"
      
    TITLE="${SRV_NAME}服务异常监控"
    CONTENT="${SRV_NAME}服务发生异常,已自动拉起!"
      
    ## 是否已正确扫描
    SCAN_FLAG=0
      
    function RESTART_SRV_AND_ALERT() 
    {
        local CUR_SRV_NAME
         
        [[ $# -ne 1 ]] && exit 1
        CUR_SRV_NAME=$1
         
        TMP_SRV_NAME=`echo ${CUR_SRV_NAME} | tr '[A-Z]' '[a-z]'`
        [[ ! -f /etc/init.d/${TMP_SRV_NAME} ]] && TMP_SRV_NAME="${TMP_SRV_NAME}d"
         
        killall -9 ${TMP_SRV_NAME}
         
        if [[ -z `ps aux | grep ${TMP_SRV_NAME} | grep -v grep` ]]; then
            /sbin/service ${TMP_SRV_NAME} start >/dev/null 2>&1
        fi
         
        ${MONITOR} -c 2 -f ${TOKEN} -t "${TITLE}" -i "${CONTENT}"
        rm -f `pwd`/connect_error.log
    }
      
    ETH1_ADDR=`/sbin/ifconfig eth1 | awk -F ':' '/inet addr/{print $2}' sed 's/[a-zA-Z ]//g'`
    TMP_SRV_PROT=`echo ${SRV_PROT} | tr '[A-Z]' '[a-z]'`
     
    if [[ "${TMP_SRV_PROT}" == "tcp" ]]; then
        PROT_OPT="S"
    elif [[ "${TMP_SRV_PROT}" == "udp" ]]; then
        PROT_OPT="U"
    else
        echo "未知的协议类型!" && exit 1
    fi
      
    ## 最多扫描3次,成功一次即可,以避免网络抖动而导致误判
    for ((i=0; i<3; i++)); do
        RETVAL=`/usr/bin/nmap -n -s${PROT_OPT} -p ${SRV_PORT} ${ETH1_ADDR} | grep open`
        [[ -n "${RETVAL}" ]] && SCAN_FLAG=1;break || sleep 10
    done
      
    ## 1、针对Atlas服务端口不通的情况,也就是服务彻底挂掉
    [[ ${SCAN_FLAG} -ne 1 ]] && RESTART_SRV_AND_ALERT ${SRV_NAME}
      
    ## 2、检查Atlas服务是否正常工作,也就是服务端口正常,但访问异常的情况【高权限DB用户】
    mysqladmin -h${ETH1_ADDR} -uhealth_check1 -p123456 --connect-timeout=15 --shutdown-timeout=15 ping
    [[ $? -ne 0 ]] && RESTART_SRV_AND_ALERT ${SRV_NAME}
      
    ## 3、检查Atlas服务是否正常工作,也就是服务端口正常,高权限DB用户访问也正常,但低权限
    ##    DB用户访问异常的情况【低权限DB用户】
    mysqladmin -h${ETH1_ADDR} -uhealth_check2 -p123456 --connect-timeout=15 --shutdown-timeout=15 ping
    [[ $? -ne 0 ]] && RESTART_SRV_AND_ALERT ${SRV_NAME}

    2Atlas访问日志切割

    # vim /data/scripts/cut_and_clear_access_log.sh

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #!/bin/sh
    # 切割Atlas的访问日志,同时清理15天之前的日志
    #
    PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
      
    ## mysql-proxy日志路径
    LOGPATH="/usr/local/mysql-proxy/log"
      
    [[ `/sbin/ip addr show eth1 | grep inet | wc -l` -eq 2 ]] || exit 
    cd ${LOGPATH}
      
    ## 日志切割
    HISTORY_LOG_PATH=`date -d '-1 hour' +"%Y-%m-%d/sql_mysql-proxy_%H.log"`
    [[ -d `dirname ${HISTORY_LOG_PATH}` ]] || mkdir -p `dirname ${HISTORY_LOG_PATH}`
    cp -a sql_mysql-proxy.log ${HISTORY_LOG_PATH}
      
    echo > sql_mysql-proxy.log
      
    ## 日志清理
    HISTORY_LOG_PATH=`date -d '15 days ago' +'%Y-%m-%d'`
    [[ -d ${HISTORY_LOG_PATH} ]] && rm -rf ${HISTORY_LOG_PATH}

    3crontab内容添加

    # touch /var/lock/check_service.lock

    # echo 'touch /var/lock/check_service.lock' >> /etc/rc.d/rc.local

    # crontab -uroot -e

    1
    2
    * * * * * (flock --timeout=0 /var/lock/check_service.lock /usr/local/mysql-proxy/bin/check_service.sh 3306 tcp mysql-proxy >/dev/null 2>&1)
    00 * * * * /data/scripts/cut_and_clear_access_log.sh >/dev/null 2>&1

     

    4、平滑设置功能

    # mysql -h10.209.6.101 -P3307 -usysadmin -p'admin2356!@()'

    wKioL1Sw8S_gXZOuAALgQK7R39c195.jpg

    来自收点资料买框架
  • 相关阅读:
    HTTP状态详解
    表锁和行锁
    memcache 加载(对象)所遇到的问题。资源
    php 数据导出csv 注意问题。
    文件不存在的话创建文件 文件上传所遇到的问题、
    获取文件的后缀名。phpinfo
    手机访问pc网站自动跳转手机端网站代码
    计算机网络学习-20180826
    计算机网络学习-20180811
    集线器和交换机的区别
  • 原文地址:https://www.cnblogs.com/xin932134334/p/5455400.html
Copyright © 2020-2023  润新知