zoukankan      html  css  js  c++  java
  • openresty开发系列28--openresty中操作mysql

    openresty开发系列28--openresty中操作mysql

    Mysql客户端
       应用中最常使用的就是数据库了,尤其mysql数据库,那openresty lua如何操作mysql呢?
       默认安装OpenResty时已经自带了该模块。


    案例,mysql数据库的常用操作,编辑testmysql.lua

    # centos7中安装mariadb
    # yum install -y mariadb-server mariadb
    # systemctl start mariadb-server
    # 设置root密码为'root'
    # update mysql.user set password=PASSWORD('root') where user='root' and host='localhost';

    # 创建测试的数据库openresty
    create database openresty charset='utf8mb4';

    # 测试nginx配置
    # nginx.conf
    location /testmysql {
            content_by_lua_file /usr/local/lua/testmysql.lua;
        }

    # vim /usr/local/lua/testmysql.lua

    local function close_db(db)
        if not db then
            return
        end
        db:close()
    end

    -- 引入mysql实例
    local mysql = require("resty.mysql")
    --创建实例
    local db, err = mysql:new()
    if not db then
        ngx.say("new mysql error : ", err)
        return
    end

    --设置超时时间(毫秒)
    db:set_timeout(10000)

    --定义连接属性
    local props = {
        host = "127.0.0.1",
        port = 3306,
        database = 'openresty',
        user = 'root',
        password = 'root',
        charset = 'utf8'
    }


    local res,err,errno,sqlstate = db:connect(props)
    if not res then
        ngx.say("connect to mysql error:", err,", errno:", errno,", sqlstate:", sqlstate)
        return close_db(db)
    end

    --我们对数据库进行crud,统一的操作方法 query
    --不同于其他语言 insert update delete select

    ngx.say("----------删除表user----------------","<br/>")

    --删除表
    local drop_table_sql = "drop table if exists user"
    res, err, errno, sqlstate = db:query(drop_table_sql)
    if not res then
        ngx.say("drop table error :", err,", errno", errno, ", sqlstate : ",sqlstate)
        return close_db(db)
    end

    ngx.say("----------创建表user----------------","<br/>")

    local create_table_sql = "create table user(id int primary key auto_increment,username varchar(100))"
    res, err, errno, sqlstate = db:query(create_table_sql)
    if not res then
        ngx.say("create table error :", err,", errno", errno, ", sqlstate : ",sqlstate)
        return close_db(db)
    end

    ngx.say("----------插入数据user----------------","<br/>")
    local insert_table_sql = "insert into user(username) values('jack'),('lucy'),('tom'),('lily')"
    res, err, errno, sqlstate = db:query(insert_table_sql)
    if not res then
        ngx.say("insert table error :", err,", errno", errno, ", sqlstate : ",sqlstate)
        return close_db(db)
    end

    res, err, errno, sqlstate = db:query(insert_table_sql)

    ngx.say("insert rows :", res.affected_rows,", id", res.insert_id, "<br/>")


    ngx.say("----------更新表user----------------","<br/>")

    local update_sql = "update user set username = 'lucy' where id = " .. res.insert_id
    res, err, errno, sqlstate = db:query(update_sql)
    if not res then
        ngx.say("update table error :", err,", errno", errno, ", sqlstate : ",sqlstate)
        return close_db(db)
    end

    ngx.say("update rows :",res.affected_rows, "<br/>")

    ngx.say("----------查询表user----------------","<br/>")

    --查询
    local select_sql = "select id,username from user"
    res, err, errno, sqlstate = db:query(select_sql)
    if not res then
        ngx.say("select table error :", err,", errno", errno, ", sqlstate : ",sqlstate)
        return close_db(db)
    end

    for i, row in ipairs(res) do
        for username,value in pairs(row) do
            ngx.say("select row", i," : ", username, " = ", value, "<br/>")
        end
    end

    ngx.say("----------删除user----------------","<br/>")

    local ch_param = ngx.req.get_uri_args()["ch"] or ''
    --local query_sql = "select id,username from user where username = " .. ngx.quote_sql_str(ch_param)
    local query_sql = "select id,username from user where username = " .. ch_param
    ngx.say(query_sql,"<br/>")
    res, err, errno, sqlstate = db:query(query_sql)
    if not res then
       ngx.say("select error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)
       return close_db(db)
    end

    for i,row in ipairs(res) do
        for username,value in pairs(row) do
            ngx.say("select row ",i," : ",username, " = ",value,"<br/>")
        end
    end



    ngx.say("=========关闭db===========", "<br/>")

    close_db(db)

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

    对于新增/修改/删除会返回如下格式的响应:
    {
        insert_id = 0,     ----insert_id是在使用自增序列时产生的id。
        server_status = 2,
        warning_count = 1,
        affected_rows = 32,   ----affected_rows表示操作影响的行数
        message = nil
    }

    对于查询会返回如下格式的响应:
    {
        { id= 1, ch= "hello"},
        { id= 2, ch= "hello2"}
    }
    null将返回ngx.null。

    访问请求http://10.11.0.215/testmysql
    输出结果
    start connect
    end connect mysql
    ----------删除表user----------------
    ----------创建表user----------------
    ----------插入数据user----------------
    insert rows :4, id5
    ----------更新表user----------------
    update rows :1
    ----------查询表user----------------
    select row1 : username = jack
    select row1 : id = 1
    select row2 : username = lucy
    select row2 : id = 2
    select row3 : username = tom
    select row3 : id = 3
    select row4 : username = lily
    select row4 : id = 4
    select row5 : username = lucy
    select row5 : id = 5
    select row6 : username = lucy
    select row6 : id = 6
    select row7 : username = tom
    select row7 : id = 7
    select row8 : username = lily
    select row8 : id = 8
    ----------删除user----------------
    =========关闭db===========



    ===========查询user=根据ch参数=======
    select row 1 : ch = hello
    select row 1 : id = 1
    ===========删除user========
    delete rows : 2
    ===========关闭db========

    注意:

    客户端目前还没有提供预编译SQL支持(即占位符替换位置变量),
    这样在入参时记得使用ngx.quote_sql_str进行字符串转义,防止sql注入;


    --防止sql注入

    local ch_param = ngx.req.get_uri_args()["ch"] or ''
    --local query_sql = "select id,username from user where username = " .. ngx.quote_sql_str(ch_param)
    -- 不使用quote_sql_str防注入
    local query_sql = "select id,username from user where username = " .. ch_param
    ngx.say(query_sql,"<br/>")
    res, err, errno, sqlstate = db:query(query_sql)
    if not res then
       ngx.say("select error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)
       return close_db(db)
    end

    for i,row in ipairs(res) do
        for username,value in pairs(row) do
            ngx.say("select row ",i," : ",username, " = ",value,"<br/>")
        end
    end

    当我们没有使用quote_sql_str时,使用如下查询语句,会把数据表中的所有数据查询出来

    http://10.11.0.215/testmysql?ch='jack' or 1=1

    select id,username from user where username = 'jack' or 1=1
    select row 1 : username = jack
    select row 1 : id = 1
    select row 2 : username = lucy
    select row 2 : id = 2
    select row 3 : username = tom
    select row 3 : id = 3
    select row 4 : username = lily
    select row 4 : id = 4
    select row 5 : username = lucy
    select row 5 : id = 5
    select row 6 : username = lucy
    select row 6 : id = 6
    select row 7 : username = tom
    select row 7 : id = 7
    select row 8 : username = lily
    select row 8 : id = 8
    =========关闭db===========

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

    连接池和之前Redis客户端完全一样。
    local function close_db(db)  
        if not db then  
            return  
        end  
        --释放连接(连接池实现)  
        local pool_max_idle_time = 10000 --毫秒  
        local pool_size = 100 --连接池大小  
        local ok, err = db:set_keepalive(pool_max_idle_time, pool_size)  
        if not ok then  
            ngx.say("set keepalive error : ", err)  
        end  
    end  


    更多资料 https://github.com/openresty/lua-resty-mysql
    sqlstate https://blog.csdn.net/tercel99/article/details/1520094

    testmysql.lua

    [root@node5 conf]# cat /usr/local/lua/testredis.lua 
    -- --定义redis关闭连接的方法
    local function close_redis(red)
        if not red then
            return
        end
        --释放连接(连接池实现)
        local pool_max_idle_time = 1000 --毫秒
        local pool_size = 100 --连接池大小
        local ok,err = red:set_keepalive(pool_max_idle_time, pool_size)
        if not ok then
            ngx.say("set keepalive error: ",err)
        end
    end
    -- 引入redis模块
    local redis = require "resty.redis" 
    -- 创建一个对象,注意是用冒号调用的
    local red = redis:new()
    -- 设置超时(毫秒)
    red:set_timeout(1000)
    --建立连接
    local ip = "10.11.0.215"
    local port = 6379
    local ok, err = red:connect(ip, port)
    if not ok then
        ngx.say("connect to redis error : ", err)
        return close_redis(red)
    end
    
    -- 如果使用连接池,不需要每次都使用密码
    local count, err = red:get_reused_times()
    if 0 == count then
        ok, err = red:auth("redis123")
        if not ok then
            ngx.say("faied to auth:", err)
            return
        end
    elseif err then
        ngx.say("failed to get reused times:",err)
        return
    end
    
    
    --调用API设置key
    ok, err = red:set("msg", "hello world")
    
    if not ok then
        ngx.say("set msg error :", err)
        return close_redis(red)
    end
    
    -- 调用API获取key值
    local resp, err = red:get("msg1")
    if not resp then
        ngx.say("get msg error:",err)
        return close_redis(red)
    end
    
    if resp == ngx.null then
        resp = 'hello lua'
    end
    
    ngx.say("msg:",resp)
    close_redis(red)
    [root@node5 conf]# cat /usr/local/lua/testmy
    cat: /usr/local/lua/testmy: No such file or directory
    [root@node5 conf]# cat /usr/local/lua/testmy
    testmyredis.lua  testmysql.lua    
    [root@node5 conf]# cat /usr/local/lua/testmysql.lua 
    local function close_db(db)  
        if not db then  
            return  
        end  
        --释放连接(连接池实现)  
        local pool_max_idle_time = 10000 --毫秒  
        local pool_size = 100 --连接池大小  
        local ok, err = db:set_keepalive(pool_max_idle_time, pool_size)  
        if not ok then  
            ngx.say("set keepalive error : ", err)  
        end  
    end
    
    -- 引入mysql实例
    local mysql = require("resty.mysql")
    --创建实例
    local db, err = mysql:new()
    if not db then
        ngx.say("new mysql error : ", err)
        return
    end
    
    --设置超时时间
    db:set_timeout(10000)
    
    --定义连接属性
    local props = {
        host = "127.0.0.1",
        port = 3306,
        database = 'openresty',
        user = 'root',
        password = 'root',
        charset = 'utf8'
    }
    
    ngx.say("start connect","<br/>")
    local res,err,errno,sqlstate = db:connect(props)
    if not res then
        ngx.say("connect to mysql error:", err,", errno:", errno,", sqlstate:", sqlstate)
        return close_db(db)
    end
    
    ngx.say("end connect mysql","<br/>")
    
    ngx.say("----------删除表user----------------","<br/>")
    
    --删除表
    local drop_table_sql = "drop table if exists user"
    res, err, errno, sqlstate = db:query(drop_table_sql)
    if not res then
        ngx.say("drop table error :", err,", errno", errno, ", sqlstate : ",sqlstate)
        return close_db(db)
    end
    
    ngx.say("----------创建表user----------------","<br/>")
    local create_table_sql = "create table user(id int primary key auto_increment,username varchar(100))"
    res, err, errno, sqlstate = db:query(create_table_sql)
    if not res then
        ngx.say("create table error :", err,", errno", errno, ", sqlstate : ",sqlstate)
        return close_db(db)
    end
    
    ngx.say("----------插入数据user----------------","<br/>")
    local insert_table_sql = "insert into user(username) values('jack'),('lucy'),('tom'),('lily')"
    res, err, errno, sqlstate = db:query(insert_table_sql)
    if not res then
        ngx.say("insert table error :", err,", errno", errno, ", sqlstate : ",sqlstate)
        return close_db(db)
    end
    
    res, err, errno, sqlstate = db:query(insert_table_sql)
    
    ngx.say("insert rows :", res.affected_rows,", id", res.insert_id, "<br/>")
    
    
    ngx.say("----------更新表user----------------","<br/>")
    
    local update_sql = "update user set username = 'lucy' where id = " .. res.insert_id
    res, err, errno, sqlstate = db:query(update_sql)
    if not res then
        ngx.say("update table error :", err,", errno", errno, ", sqlstate : ",sqlstate)
        return close_db(db)
    end
    
    ngx.say("update rows :",res.affected_rows, "<br/>")
    
    ngx.say("----------查询表user----------------","<br/>")
    
    --查询
    local select_sql = "select id,username from user"
    res, err, errno, sqlstate = db:query(select_sql)
    if not res then
        ngx.say("select table error :", err,", errno", errno, ", sqlstate : ",sqlstate)
        return close_db(db)
    end
    
    for i, row in ipairs(res) do
        for username,value in pairs(row) do
            ngx.say("select row", i," : ", username, " = ", value, "<br/>")
        end
    end
    
    ngx.say("----------删除user----------------","<br/>")
    
    local ch_param = ngx.req.get_uri_args()["ch"] or ''
    --local query_sql = "select id,username from user where username = " .. ngx.quote_sql_str(ch_param)
    local query_sql = "select id,username from user where username = " .. ch_param
    ngx.say(query_sql,"<br/>")
    res, err, errno, sqlstate = db:query(query_sql)
    if not res then
       ngx.say("select error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)
       return close_db(db)
    end
    
    for i,row in ipairs(res) do
        for username,value in pairs(row) do
            ngx.say("select row ",i," : ",username, " = ",value,"<br/>")
        end
    end
    
    
    
    ngx.say("=========关闭db===========", "<br/>")
    
    close_db(db)
  • 相关阅读:
    extjs4 数据实体模型
    WPF实现MDI窗体的方法
    WPF中图形表示语法详解(Path之Data属性语法
    Wpf DataGrid 数据绑定 排序 删除
    WPF: 使用TestApi模拟用户输入
    extjs4 事件处理
    WPF触发器
    XPath语法 在C#中使用XPath示例
    WPF 4 中DataGrid的模板列做双向数据绑定
    extjs4 标准面板
  • 原文地址:https://www.cnblogs.com/reblue520/p/11434666.html
Copyright © 2011-2022 走看看