Bootstrap

sysbench压测DM的高可用切换测试

一、配置集群

1. 配置svc.conf

[root@localhost dm]# cat /etc/dm_svc.conf 
TIME_ZONE=(480)
LANGUAGE=(CN)

DM=(192.168.112.139:5236,192.168.112.140:5236)
[DM]
LOGIN_MODE=(1)
SWITCH_TIME=(300)
SWITCH_INTERVAL=(200)

二、编译sysbench

2.1 配置环境变量


[dmdba@~]# vi ~/.bash_profile												--修改

[dmdba@~]# export DM_HOME="/opt/dmdbms"
[dmdba@~]# export PATH=$PATH:/opt/dmdbms/bin

[dmdba@~]# source ~/.bash_profile	

2.2 编译sysbench

2.2.1 配置

## 赋予权限
[root@localhost sysbench-master-dpi]# chmod 755 * -R
## 生成confifure
[root@localhost sysbench-master-dpi]# ./autogen.sh 
## 执行配置文件
## x86平台编译方式
[root@localhost sysbench-master-dpi]# ./configure --without-mysql --with-dm

## arm平台编译方式
## [root@localhost sysbench-master-dpi]# ./configure --without-mysql --with-dm --build=aarch64-unkown-linux-gnu


2.2.2.2 修改dpi源码

将dm_drv_connect函数的自动提交由默认的非自动提交改为自动提交,如不改 跑insert update相关的语句 事务会回滚

# 修改
sysbench-master-dpi/src/drivers/dm/drv_dpi_dm.c

将dm_drv_connect函数的自动提交由默认的非自动提交改为自动提交
  //rc = dpi_set_con_attr(dm_con->hdbc, DSQL_ATTR_AUTOCOMMIT, DSQL_AUTOCOMMIT_OFF, 0);
  rc = dpi_set_con_attr(dm_con->hdbc, DSQL_ATTR_AUTOCOMMIT, DSQL_AUTOCOMMIT_ON, 0);

2.2.3 编译

## 编译
[root@localhost sysbench-master-dpi]# make

## 拷贝sysbench到src/lua下进行测试
[root@localhost src]# cd /opt/sysbench-master-dpi/src
[root@localhost src]# cp sysbench lua/

三、压测sysbench

3.1 准备数据

## 准备数据
./sysbench oltp_read_write.lua --tables=5 --table-size=200000 --db_driver=dm --dm-db=DM --dm-user=SYSDBA --dm-password=SYSDBA --auto-inc=0 --threads=4 --time=180 --report-interval=1 prepare

3.2 开始压测

导入oltp_insert_reconnect.lua脚本到lua目录下

sysbench.cmdline.options = {
    table_size = {"Number of rows per table", 5000},
    tables = {"Number of tables", 1},
    auto_inc = {"Use auto-incremenit IDs", false},
}

local drv = sysbench.sql.driver()
local con

-- 最大重连次数
local MAX_RETRIES = 30

function connect_db()
    local retry_count = 0
    local max_retries = MAX_RETRIES or 5 

    while retry_count < max_retries do
        local status, err = pcall(function()
            con = drv:connect()
        end)

        -- 如果连接成功,跳出循环
        if status then
            print("Database connection established.")
            return
        else
            retry_count = retry_count + 1
            print(string.format("Connection failed: %s. Retrying %d/%d...", err, retry_count, max_retries))

	        os.execute("sleep 1")
        end
    end

    -- 如果达到最大重试次数,抛出错误
    error("Failed to connect to the database after multiple retries.")
end



-- 断开连接函数
function disconnect_db()
    if con then
        con:disconnect()
        con = nil
        print("Database connection closed.")
    end
end

function sysbench.hooks.before_connect()
    connect_db()
end

function sysbench.hooks.after_disconnect()
    disconnect_db()
end

-- 执行事务的函数,包含重连检测
function execute_query(query)
    local status, result = pcall(function()
        return con:query(query)
    end)

    -- 如果查询失败,尝试重连
    if not status then
        -- 具体细化的话 可以根据错误码做重连逻辑
        -- 这里统一做重连逻辑
        disconnect_db()    
        os.execute("sleep 1")
        connect_db()
        execute_query(query)
    end

    return result
end

-- 10 groups, 119 characters
local c_value_template = "###########-###########-###########-" ..
   "###########-###########-###########-" ..
   "###########-###########-###########-" ..
   "###########"

-- 5 groups, 59 characters
local pad_value_template = "###########-###########-###########-" ..
   "###########-###########"

function get_c_value()
   return sysbench.rand.string(c_value_template)
end

function get_pad_value()
   return sysbench.rand.string(pad_value_template)
end



-- 执行 write only 测试
function event()

local table_name = "sbtest" .. sysbench.rand.uniform(1, sysbench.opt.tables)
execute_query("SELECT c FROM sbtest1 WHERE id = 1")
local k_val = sysbench.rand.default(1, sysbench.opt.table_size)
local c_val = get_c_value()
local pad_val = get_pad_value()


if (sysbench.opt.auto_inc) then
     i = 0
else
    -- Convert a uint32_t value to SQL INT
    i = sysbench.rand.unique() - 2147483648
end

execute_query(string.format("INSERT INTO %s (id, k, c, pad) VALUES " ..
                            "(%d, %d, '%s', '%s')",
                        table_name, i, k_val, c_val, pad_val))


end



3.2.1 运行文件


./sysbench oltp_insert_reconnect.lua --auto-inc=0   --tables=5 --table-size=5000 --db_driver=dm --dm-db=DM --dm-user=SYSDBA --dm-password=SYSDBA --threads=4 --time=180 --report-interval=1 --db-debug=on --debug=on   run


#./sysbench oltp_insert_reconnect.lua  --db_driver=dm --dm-db=DM --dm-user=SYSDBA --dm-password=SYSDBA --threads=4 --time=180 --report-interval=1 --db-debug=on --debug=on   run

3.2.2 进行集群切换测试

[root@localhost bin]# ./dmmonitor ./dmmonitor_noc.ini

SWITCHOVER

3.3 清理数据

## 清理数据
./sysbench oltp_insert_reconnect.lua --db_driver=dm --dm-db=DM --dm-user=SYSDBA --dm-password=SYSDBA --threads=4 --time=180 --report-interval=1 --auto-inc=0   --tables=5 --table-size=5000 --db-debug=on --debug=on  cleanup

4. 附录

4.1 dpi中的reconnect代码

/* Reset connection to the server */
static int dm_drv_reconnect(db_conn_t  *sb_conn)
{
    dm_conn_t *dm_con = sb_conn->ptr;
    DPIRETURN     rc;
    sdbyte err_msg[512];
    sdint2 msg_len;
    sdint4 err_code;

    // log_text(LOG_DEBUG, "Reconnecting");

    if (dm_con == NULL){
        return 1;
    }

    if (dm_con->hdbc != NULL){
        dpi_logout(dm_con->hdbc);
    }
    /* 
  rc = dpi_login(dm_con->hdbc, (sdbyte *)args.db, (sdbyte *)args.user, (sdbyte *)args.password);
  if (rc != DSQL_SUCCESS){
        dpi_get_diag_rec(DSQL_HANDLE_DBC, dm_con->hdbc, 1, &err_code, err_msg, sizeof(err_msg), &msg_len);
    log_text(LOG_ALERT, "Error - DM_%d_%s", err_code, err_msg);  
        return 1;
  }
  */

    while (1) {
        rc = dpi_login(dm_con->hdbc, (sdbyte *) args.db, (sdbyte *) args.user, (sdbyte *) args.password);
        log_text(LOG_DEBUG, "rc= %d",rc);
        usleep(1000);
        if (rc != DSQL_SUCCESS) {
            dpi_get_diag_rec(DSQL_HANDLE_DBC, dm_con->hdbc, 1, &err_code, err_msg, sizeof(err_msg), &msg_len);
            // log_text(LOG_DEBUG, "ERR dm_drv_reconnect fail - DM_%d_%s", err_code, err_msg);
        }else{
            // log_text(LOG_DEBUG, "SUC dm_drv_reconnect");
            break;
        }
    }


    return 0;
}

4.2 TPS计算逻辑

  • 每次会调用lua脚本的 event函数 函数执行玩了以后 会调用左边这个sb_event_stop函数
  • 这个函数里面 会根据线程号 总值+1

4.2 QPS计算逻辑

  1. dm提供的驱动中在dm_drv_prepare方法中使用get_stmt_type函数方法给stmt->counter属性赋值
  2. sysbench在执行execute方法时在进行取stmt->counter属性自增

4.3 mysql的重连逻辑

每次check_error的时候根据错误码判断类型 如果是CR_SERVER_LOST_EXTENDED 则 进行 reconnect的计数器+1 同时 执行重连函数

4.4 dpi的读写分离如何配置

dpi_set_con_attr(dm_con->hdbc, DSQL_ATTR_RWSEPARATE, DSQL_RWSEPARATE_ON, 0);
dpi_set_con_attr(dm_con->hdbc, DSQL_ATTR_RWSEPARATE_PERCENT, 25);
;