1. 在 Nginx 配置文件里使用 Lua 操作 MySQL 需要使用 lua-resty-mysql 模块 : https://github.com/openresty/lua-resty-mysql

  2. 在 Nginx 配置文件中引入 lua-resty-mysql

    # nginx.conf
    http {
        lua_package_path "/path/to/lua-resty-mysql/lib/?.lua;;";
        ...
    }
    
  3. lua-resty-mysq API : https://github.com/openresty/lua-resty-mysql#methods

  4. 操作数据库 Demo

    # 查询
    location /mysql-query {
        default_type "text/plain";
        content_by_lua \'
            local resty_mysql = require("resty.mysql")
            local mysql, str_err = resty_mysql:new()
    
            if not mysql then
                ngx.say("new -- failed to new a mysql. -- str_err: ", str_err)
                return
            end
    
            mysql:set_timeout(1000) -- 1 sec
    
            local conn, str_err = mysql:connect({
                host = "10.253.1.251",
                port = "3306",
                database = "peanutcar",
                user = "caikr",
                password = "caikr"
                -- ,
                -- compact_arrays = true
                -- when this option is set to true,
                -- then the query and read_result methods will return the array-of-arrays structure for the resultset,
                -- rather than the default array-of-hashes structure.
            })
    
            if not conn then
                ngx.say("connect -- failed to connect to remote mysql server. -- str_err: ", str_err)
                return
            end
    
            ngx.say("connect success! connect: ", conn)
    
            -- set utf-8
            mysql:query("SET NAMES utf8")
    
            local str_sql_for_query = "select * from car_store limit 20"
    
            local byte_data, str_err = mysql:send_query(str_sql_for_query)
            if not byte_data then
                ngx.say("send_query -- failed to send query. -- str_err: ", str_err)
                return
            end
    
            ngx.say("send_query success! byte_data: ", byte_data)
    
            local obj_res, str_err, n_errcode, n_sqlstate = mysql:read_result()
    
            -- local obj_res, str_err, n_errcode, n_sqlstate = mysql:read_result(6)
            -- The optional argument nrows can be used to specify an approximate number of rows for the result set.
            -- This value can be used to pre-allocate space in the resulting Lua table for the result set.
            -- By default, it takes the value 4.
    
            if not obj_res then
                ngx.say("read_result -- failed to read result. -- str_err: ", str_err, " -- n_errcode", n_errcode, " -- n_sqlstate", n_sqlstate)
                return
            end
    
            ngx.say("read_result success. type(obj_res): ", type(obj_res))
    
            -- ngx.say("read result success. obj_res: ", obj_res)
            -- for i = 1, #obj_res do
            --     ngx.say("i = ", i, " -- obj_res[", i , "] = ", obj_res[i])
            -- end
    
            -- for k, v in pairs(obj_res) do
            --     ngx.say("key = ", k)
            --     for x, y in pairs(v) do
            --         ngx.say("x : ", x, " -- y : ", y)
            --     end
            -- end
    
            -- 用 lua-cjson 处理结果集
            local cjson = require("cjson")
            local cj_res = cjson.encode(obj_res)
    
            ngx.say("结果集 cj_res: ", cj_res)
            -- put it into the connection pool of size 100, with 10 seconds max idle timeout
            local ok, err = mysql:set_keepalive(10000, 100)
    
            if not ok then
                ngx.say("set_keepalive -- failed to set keepalive: ", err)
                return
            end
    
            -- or just close the connection right away:
            -- local ok, err = db:close()
            -- if not ok then
            --     ngx.say("failed to close", err)
            --     return
            -- end
        ';
    }
    
    # 插入数据
    location /mysql-insert {
        default_type "text/plain";
    
        content_by_lua '
            local resty_mysql = require("resty.mysql")
            local db = resty_mysql:new()
    
            -- hello
            local conn = db:connect({
                host = "10.253.1.251",
                port = 3306,
                database = "peanutcar",
                user = "caikr",
                password = "caikr"
            })
    
            ngx.say("connect success! conn : ", conn)
    
            local str_sql_for_insert = "insert into cats (name) values (\'再\')"
    
            -- 设置字符集为 UTF-8
            -- db:query("SET NAMES utf8")
    
            local obj_res, str_err, n_errcode, n_sqlstate = db:query(str_sql_for_insert)
    
            if not obj_res then
                ngx.say("insert ---- failed to insert. str_err: ", str_err, " -- n_errcode: ", n_errcode, " -- n_sqlstate: ", n_sqlstate)
                return
            end
    
            local cjson = require("cjson")
            local cj_res = cjson.encode(obj_res)
    
            ngx.say("插入操作结果为: cj_res: ", cj_res)
    
            -- put it into the connection pool of size 100, with 10 seconds max idle timeout
            local ok, err = db:set_keepalive(10000, 100)
    
            if not ok then
                ngx.say("set_keepalive -- failed to set keepalive: ", err)
                return
            end
    
            -- or just close the connection right away:
            -- local ok, err = db:close()
            -- if not ok then
            --     ngx.say("failed to close", err)
            --     return
            -- end
        ';
    }
    
    # 事务处理
    location /mysql-transcation {
        default_type "text/plain";
    
        content_by_lua '
    
            local cjson = require("cjson")
    
            local mysql = require("resty.mysql")
            local db, err = mysql:new()
    
            db:set_timeout(1000) -- 1 sec
    
            local conn, err, errcode, sqlstate = db:connect({
                host = "10.253.1.251",
                port = 3306,
                database = "peanutcar",
                user = "root",
                password = "caikr"
            })
    
            ngx.say("success! connected to mysql.")
    
            -- set character utf8
            local res, err, errcode, sqlstate = db:query("SET NAMES utf8")
    
            -- start transcation
            res, err, errcode, sqlstate = db:query("begin")
    
            ngx.say("transcation begin! Result #1 -- res:", cjson.encode(res), ", err:", err, ", errcode:", errcode, ", sqlstate:", sqlstate)
            ngx.say("------------------------------------------\\n")
    
            local str_sql_insert = "insert into cats (name) values (\'测试事务\'), (\'test transcation ~\'), (\'hello transcation~~~\')"
    
            -- insert
            res, err, errcode, sqlstate = db:query(str_sql_insert)
            ngx.say("insert -- res: ", cjson.encode(res), ", err:", err, ", errcode:", errcode, ", sqlstate:", sqlstate)
            ngx.say("------------------------------------------\\n")
    
            -- select
            local str_sql_select = "select * from cats order by id desc limit 10"
            res, err, errcode, sqlstate = db:query(str_sql_select)
            ngx.say("select -- res: ", cjson.encode(res), ", err:", err, ", errcode:", errcode, ", sqlstate:", sqlstate)
            ngx.say("------------------------------------------\\n")
    
            -- rollback
            res, err, errcode, sqlstate = db:query("rollback")
            ngx.say("rollback -- res: ", cjson.encode(res), ", err:", err, ", errcode:", errcode, ", sqlstate:", sqlstate)
            ngx.say("------------------------------------------\\n")
    
            -- select after rollback
            local str_sql_select = "select * from cats order by id desc limit 10"
            res, err, errcode, sqlstate = db:query(str_sql_select)
            ngx.say("select [after rollback] -- res: ", cjson.encode(res), ", err:", err, ", errcode:", errcode, ", sqlstate:", sqlstate)
            ngx.say("------------------------------------------\\n")
    
            -- update after rollback
            local str_sql_update = "update cats set name = \'test update Bob > Tom\' where id = 100"
            res, err, errcode, sqlstate = db:query(str_sql_update)
            ngx.say("update -- res: ", cjson.encode(res), ", err:", err, ", errcode:", errcode, ", sqlstate:", sqlstate)
            ngx.say("------------------------------------------\\n")
    
            -- select after update
            str_sql_select = "select * from cats order by id desc limit 10"
            res, err, errcode, sqlstate = db:query(str_sql_select)
            ngx.say("select [after update] -- res: ", cjson.encode(res), ", err:", err, ", errcode:", errcode, ", sqlstate:", sqlstate)
            ngx.say("------------------------------------------\\n")
    
            -- commit
            res, err, errcode, sqlstate = db:query("commit")
            ngx.say("commit -- res: ", cjson.encode(res), ", err:", err, ", errcode:", errcode, ", sqlstate:", sqlstate)
    
            -- select after commit
            str_sql_select = "select * from cats order by id desc limit 10"
            res, err, errcode, sqlstate = db:query(str_sql_select)
            ngx.say("select [after commit] -- res: ", cjson.encode(res), ", err:", err, ", errcode:", errcode, ", sqlstate:", sqlstate)
            ngx.say("------------------------------------------")
    
            -- put it into the connection pool of size 100, with 10 seconds max idle timeout
            local ok, err = db:set_keepalive(10000, 100)
    
            if not ok then
                ngx.say("set_keepalive -- failed to set keepalive: ", err)
                return
            end
    
            -- or just close the connection right away:
            -- local ok, err = db:close()
            -- if not ok then
            --     ngx.say("failed to close", err)
            --     return
            -- end
        ';
    }
    
  5. 注意事项

    需要手动设置编码格式, 手动控制事务。

results matching ""

    No results matching ""