--[[ 使用方法: local mysql = require "mysql_pool" local ret, res, sqlstate = mysql:query(sql, true); local tmp if ret then tmp = cjson.encode(res) else ngx.say("error") end --]] --[[ 注意事项: 1. 启用连接池需要开启 lua_code_cache on 2. 测试连接池时,线程数需要小于set_keepalive中的第二个参数(即连接数) 3. 根据程序里的SQL情况,设置set_timeout为适当的值(即连接超时??) --]] module("mysql_pool", package.seeall) local mysql = require("resty.mysql") local cfg = require "youngyedu.common.resources.config" local mysql_pool = {} --[[ 先从连接池取连接,如果没有再建立连接. 返回: false,出错信息. true,数据库连接 --]] function mysql_pool:get_connect() if ngx.ctx[mysql_pool] then return true, ngx.ctx[mysql_pool] end local client, errmsg = mysql:new() if not client then return false, "mysql.socket_failed: " .. (errmsg or "nil") end client:set_timeout(10000) --30秒 local options = { host = cfg.db.prod.HOST, port = cfg.db.prod.PORT, user = cfg.db.prod.USER, password = cfg.db.prod.PASSWORD, database = cfg.db.prod.DATABASE } local result, errmsg, errno, sqlstate = client:connect(options) if not result then return false, "mysql.cant_connect: " .. (errmsg or "nil") .. ", errno:" .. (errno or "nil") .. ", sql_state:" .. (sqlstate or "nil") end local query = "SET NAMES " .. "utf8" local result, errmsg, errno, sqlstate = client:query(query) if not result then return false, "mysql.query_failed: " .. (errmsg or "nil") .. ", errno:" .. (errno or "nil") .. ", sql_state:" .. (sqlstate or "nil") end ngx.ctx[mysql_pool] = client -- 测试,验证连接池重复使用情况 --[[ comments by leon1509 local count, err = client:get_reused_times() ngx.say("xxx reused times" .. count); --]] return true, ngx.ctx[mysql_pool] end --[[ 把连接返回到连接池 用set_keepalive代替close() 将开启连接池特性,可以为每个nginx工作进程,指定连接最大空闲时间,和连接池最大连接数 --]] function mysql_pool:close() if ngx.ctx[mysql_pool] then -- 连接池机制,不调用 close 而是 keeplive 下次会直接继续使用 -- lua_code_cache 为 on 时才有效 -- 60000 : pool_max_idle_time , 100:connections ngx.ctx[mysql_pool]:set_keepalive(60000, 80) -- 调用了 set_keepalive,不能直接再次调用 query,会报错 ngx.ctx[mysql_pool] = nil end end --[[ 查询 有结果数据集时返回结果数据集 无数据数据集时返回查询影响 返回: false,出错信息,sqlstate结构. true,结果集,sqlstate结构. --]] function mysql_pool:query(sql, flag) local ret, client = self:get_connect(flag) if not ret then return false, client, nil end local result, errmsg, errno, sqlstate = client:query(sql) while errmsg == "again" do result, errmsg, errno, sqlstate = client:read_result() end self:close() if not result then errmsg = "mysql.query_failed:" .. (errno or "nil") .. (errmsg or "nil") return false, errmsg, sqlstate end return true, result, sqlstate end return mysql_pool