日志系统扩展一:日志落地数据库:MySQL、SQLite3

一、设计

1.怎么落地

将日志落地到数据库,首先肯定是要建表的,而日志落地其实就是向对应表当中插入数据

那么怎么落地呢?
文件落地方式:virtual void log_fs(const char *data, size_t len) = 0;
因为文件是面向字节流的,所以这么落地日志是完全OK的

而数据库落地是向表当中插入数据,因此他的落地应该是这样的:

virtual void log_db(const LogMessage &message) = 0;

将一条LogMessage插入表当中

因此我们的LogSink日志落地基类无法满足数据库的落地需求,要不然就给他增加一个log_db函数
让子类选择性的对其中一个进行重写,另一个进行空实现,这是一种方式

不过不便于扩展,为了遵循高内聚,低耦合的程序设计原则,我们将LogSink分为两个日志基类:
FSLogSink和DBLogSink

新增加的MySQLSink和SqliteSink都继承于DBLogSink

2.落地的具体设计

我们的日志落地方式是允许用户灵活的进行格式控制的,这是为了让用户能够选择性的只记录自己想要的数据

而将日志落地到数据库,是非字符串形式的,因此格式化的意义不大

所以我们的日志落地到数据库当中是无需进行格式化的,这也印证了log_db的参数为何只需要一个LogMessage即可

virtual void log_db(const LogMessage &message) = 0;

所以我们再将日志落地到数据库时,是直接将所有字段全部都进行记录的

3.表的设计

1.MySQL

在这里插入图片描述

2.SQLite3

同样的,SQLite3当中LigData的创建也是如此,只不过具体细节要求不同:
在这里插入图片描述

二、数据库访问Helper的实现

1.需要事务,但是无需回滚,如何理解?

1.需要事务

在这里插入图片描述

2.无需回滚

在这里插入图片描述
不过我们贴心的给了大家savepoint和rollback的使用,大家可以使用

2.SqliteHelper

1.SQLite3常用接口介绍

SQLite3 官方文档
在这里插入图片描述
在这里插入图片描述

2.实现

class SqliteHelper
{
   
   
public:
    using SqliteCallback = int (*)(void *, int, char **, char **);
    SqliteHelper(const std::string &dbfile)
        : _dbfile(dbfile), _handler(nullptr) {
   
   }

    ~SqliteHelper()
    {
   
   
        close();
    }

    bool open()
    {
   
   
        if (sqlite3_open_v2(_dbfile.c_str(), &_handler, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, nullptr) != SQLITE_OK)
        {
   
   
            std::cout << "打开数据库失败 " << errmsg() << " _dbfile:" << _dbfile << "\n";
            return false;
        }
        return true;
    }

    void close()
    {
   
   
        if (_handler != nullptr)
        {
   
   
            sqlite3_close_v2(_handler);
            _handler = nullptr;
        }
    }

    bool begin()
    {
   
   
        if (sqlite3_exec(_handler, "begin;", nullptr, nullptr, nullptr) != SQLITE_OK)
        {
   
   
            std::cout << "SQLite3开启事务失败," << errmsg() << "\n";
            return false;
        }
        return true;
    }

    bool exec(const std::string &sql, SqliteCallback cb, void *arg)
    {
   
   
        if (sqlite3_exec(_handler, sql.c_str(), cb, arg, nullptr) != SQLITE_OK)
        {
   
   
            std::cout << "执行sql语句:" << sql << " 失败," << errmsg() << std::endl;
            return false;
        }
        return true;
    }

    bool commit()
    {
   
   
        if (sqlite3_exec(_handler, "commit;", nullptr, nullptr, nullptr) != SQLITE_OK)
        {
   
   
            std::cout << "SQLite3提交事务失败," << errmsg() << "\n";
            return false;
        }
        return true;
    }

	bool savePoint(const std::string &point)
    {
   
   
        std::string savepoint_sql = "savepoint " + point + ";";
        if (sqlite3_exec(_handler, savepoint_sql.c_str(), nullptr, nullptr, nullptr) != SQLITE_OK)
        {
   
   
            std::cout << "SQLite3 设置事务保存点失败:" << errmsg() << "\n";
            return false;
        }
        return true;
    }

    bool rollback(const std::string &point = "")
    {
   
   
        std::string rollback_sql = "rollback";
        if (!point.empty())
        {
   
   
            rollback_sql += " to " + point + ";";
        }
        if (sqlite3_exec(_handler, rollback_sql.c_str(), nullptr, nullptr, nullptr) != SQLITE_OK)
        {
   
   
            std::cout << "SQLite3 事务回滚失败:" << errmsg() << "\n";
            return false;
        }
        return true;
    }

    std::string errmsg()
    {
   
   
        if (_handler != nullptr)
            return sqlite3_errmsg(_handler);
        else
            return "sqlite3句柄为空";
    }

private:
    std::string _dbfile;
    sqlite3 *_handler;
};

3.MySQLHelper

1.MySQL常用接口介绍

在这里插入图片描述

2.实现

我们要求用户将MySQL连接所需字段放到配置文件当中,将配置文件传递过来
我们内部进行解析

格式要求:

一个字段占一行
以key:value的形式进行传递

host:你MySQL服务器所在机器的IP地址
user:你的用户名
passwd:你的密码
db:你提前创建好并赋予权限了的数据库
port:你MySQL服务器的端口号
class MySQLHelper
{
   
   
public:
    MySQLHelper(const std::string &conf_file) : _handler(mysql_init(nullptr)), _conf_file(conf_file){
   
   }

    bool begin()
    {
   
   
        if (mysql_query(_handler, "begin;") != 0)
        {
   
   
            std::cout << "mysql开启事务失败," << errmsg() << "\n";
            return false;
        }
        return true;
    }

    bool commit()
    {
   
   
        if (mysql_query(_handler, "commit;") != 0)
        {
   
   
            std::cout << "mysql提交事务失败," << errmsg() << "\n";
            return false;
        }
        return true;
    }
	
	bool savePoint(const std::string &point)
    {
   
   
        std::string savepoint_sql = "savepoint " + point + ";";
        if (mysql_query(_handler, savepoint_sql.c_str()) != 0)
        {
   
   
            std::cout << "MySQL 设置事务保存点失败:" << errmsg() << "\n";
            return false;
        }
        return true;
    }

    bool rollback(const std::string &point = "")
    {
   
   
        std::string rollback_sql = "rollback";
        if (!point.empty())
        {
   
   
            rollback_sql += " to " + point + ";";
        }
        if (mysql_query(_handler, rollback_sql.c_str()) != 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

program-learner

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值