DB服设计

本文介绍了游戏数据库服务器(DB服)的主要作用,包括数据存储、账户管理、物品和交易管理,以及数据备份和恢复。详细阐述了DB服的框架层、服务层和业务层的文件结构与核心方法,强调了并发、异步执行、顺序性、错误隔离和连接池等设计优势。此外,还提及了配置文件和拓扑图,并讨论了常见的数据库管理问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



DB服的主要作用

数据库服务器负责存储玩家的账户信息、游戏进度、物品数据、等各种游戏相关的信息

1. 数据存储与读取: 游戏需要持续保存玩家的进度、成就、物品等数据。数据库服务器能够高效地存储这些信息,并在需要时快速地读取出来。
2. 账户管理: 数据库服务器保存玩家的账户信息,包括用户名、密码、角色信息等。这些数据在登录、注册以及账户安全方面起着关键作用。
3. 物品和交易管理: 游戏中的物品数据,包括玩家拥有的各种道具等,也需要被数据库服务器管理。数据库可以确保物品的准确性和一致性,并支持交易操作。
4. 数据备份和恢复: 数据库服务器通常会定期备份数据,以防止数据丢失。在需要时,可以使用备份数据进行恢复

相关文件介绍

框架层

skynet层

mysql.lua

skynet层提供的一个用于连接和操作SQL数据库的模块, 模块允许在 skynet 中与 SQL 数据库进行交互

核心方法说明

1. mysql.connect(config): 该函数用于连接到 MySQL 数据库,需要传入一个配置表 config,包括数据库的主机名、端口、用户名、密码等信息。

function _M.connect(opts)
    local self = setmetatable({
   }, mt)

    local max_packet_size = opts.max_packet_size
    if not max_packet_size then
        max_packet_size = 1024 * 1024 -- default 1 MB
    end
    self._max_packet_size = max_packet_size
    self.compact = opts.compact_arrays

    local database = opts.database or ""
    local user = opts.user or ""
    local password = opts.password or ""
    local charset = CHARSET_MAP[opts.charset or "_default"]
    local channel = 
        socketchannel.channel {
   
        host = opts.host,
        port = opts.port or 3306,
        auth = _mysql_login(self, user, password, charset, database, opts.on_connect),
        overload = opts.overload
    }
    self.sockchannel = channel
    -- try connect first only once
    channel:connect(true)

    return self
end

2. mysql.query(db, sql): 用于执行 SQL 查询语句,并返回结果。db 是一个数据库连接对象,可以通过 mysql.connect 获得,sql 是要执行的 SQL 查询语句。

function _M.query(self, query)
    local querypacket = _compose_query(self, query)
    local sockchannel = self.sockchannel
    if not self.query_resp then
        self.query_resp = _query_resp(self)
    end
    return sockchannel:request(querypacket, self.query_resp)
end

3. mysql.execute(db, sql): 用于执行非查询型的 SQL 语句,比如插入、更新和删除操作。

function _M.execute(self, stmt, ...)
    local querypacket, er = _compose_stmt_execute(self, stmt, CURSOR_TYPE_NO_CURSOR, {
   ...})
    if not querypacket then
        return {
   
            badresult = true,
            errno = 30902,
            err = er
        }
    end
    local sockchannel = self.sockchannel
    if not self.execute_resp then
        self.execute_resp = _execute_resp(self)
    end
    return sockchannel:request(querypacket, self.execute_resp)
end

4. mysql.quote_sql_str(str): 用于将字符串进行 SQL 安全转义,防止 SQL 注入攻击。

function _M.quote_sql_str( str)
    return strformat("'%s'", strgsub(str, "[\0\b\n\r\t\26\\\'\"]", escape_map))
end

5. mysql.disconnect(db): 关闭数据库连接。

function _M.disconnect(self)
    self.sockchannel:close()
    setmetatable(self, nil)
end

服务层

db.lua

对接skynet框架中的MYSQL模块 实现数据库查询的调度、管理和统计

核心方法说明

1. init_db(conf): 初始化数据库连接池,将包含数据库配置信息的conf存储到全局的db_conf中,然后根据配置的连接池大小循环创建数据库连接对象,并为每个连接对象分配一个sql队列。

function init_db(conf)
    db_conf = conf
    --sync_db_conn = assert(mysql.connect(conf))
    local size = conf.conn_pool_size or 10
    for i = 1, size do
        -- 异步conn需要sql队列, 保证执行顺序
        local db_con  = assert(mysql.connect( conf ))
        db_con.sql_queue = instance("queue", 100000)

        db_conn_pool[#db_conn_pool + 1] = db_con
    end

    for i = 1, size / 2 do
        table.insert(sync_conn_pool, assert(mysql.connect(conf)))
    end

    P("init_conn_pool success!", conf.database, size)
    return true
end

2. uninit_db(conf): 用于反初始化数据库连接,关闭所有连接并清空连接池。

function uninit_db()
    --[[if sync_db_conn then
        sync_db_conn:disconnect()
        sync_db_conn = nil
    end--]]
    for _, db_conn in pairs(db_conn_pool) do
        db_conn:disconnect()
    end
    for _, conn in pairs(sync_conn_pool) do
        conn:disconnect()
    end
    db_conn_pool = {
   }
end

3. check_wait(conn): 避免在多协程中, 某个协程对conn做了修改(disconnect)而导致正在使用conn的其他协程内报错检查。

local function check_wait(conn)
    if not conn.busy then
        return true
    end

    while 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值