MySql 数据库分表 简单思路

创建源表
CREATE TABLE `api_log` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `username` varchar(20) DEFAULT NULL COMMENT '用户名',
  `ip` varchar(45) DEFAULT NULL COMMENT '登录IP地址',
  `ip_location` varchar(255) DEFAULT NULL COMMENT 'IP所属地',
  `os` varchar(50) DEFAULT NULL COMMENT '操作系统',
  `browser` varchar(50) DEFAULT NULL COMMENT '浏览器',
  `status` smallint(6) DEFAULT '1' COMMENT '登录状态 (1成功 2失败)',
  `message` varchar(50) DEFAULT NULL COMMENT '提示消息',
  `login_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '登录时间',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  `created_by` int(11) DEFAULT NULL COMMENT '创建者',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `username` (`username`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=127 DEFAULT CHARSET=utf8 COMMENT='登录日志表';
新增日志
//按年月分表 通过redis存储 防止每次插入都需要去扫描数据库
public function apiLog():Response
{
    // 获取当前年月
    $tableName = 'api_log_' . date('Ym');
    //每月第一次创建删除一次
    if(!\support\Redis::get($tableName)){
        $prefix = 'api_log_';
        $expireDate = date('Ym', strtotime('-1 year'));
        //清理一年前的旧表
        \support\think\Db::query("DROP TABLE IF EXISTS ".$prefix . $expireDate);
        //清理一年前及更早的旧表
        // 查询所有分表
        $tables = \support\think\Db::query("SHOW TABLES LIKE '{$prefix}%'");
        foreach ($tables as $t) {
            $table = reset($t); // 获取表名
            // 提取年月后缀
            $suffix = str_replace($prefix, '', $table);
            // 如果年月 <= 过期年月,则删除
            if (ctype_digit($suffix) && $suffix <= $expireDate) {
                \support\think\Db::query("DROP TABLE IF EXISTS {$table}");
            }
        }
        //保存31天自动销毁
        \support\Redis::set($tableName,1, 60 * 60 * 24 * 31);
        // 确保表存在(没有则创建)
        \support\think\Db::query("CREATE TABLE IF NOT EXISTS {$tableName} LIKE api_log");
    }
    // 插入数据
    \support\think\Db::table($tableName)->insert([
        'username'=>'日志插入'
    ]);
    return success();
}
日志查询带分页
public function apiLogList(\support\Request $request): Response
    {
        $rows = $request->post('rows');
        $page = $request->post('page');
        $starttime = $request->post('starttime');
        $endtime = $request->post('endtime');
        $tables = $this->getTableNames($starttime, $endtime);
        $baseQuery = "SELECT id,username FROM %s WHERE status='004001'";
        $unionQueries = array_map(
            fn($table) => sprintf($baseQuery, $table),
            $tables
        );
        // 构建 UNION ALL 查询
        $unionSql = implode(' UNION ALL ', $unionQueries);
        // 总数查询
        $count = \support\think\Db::query("SELECT COUNT(*) as total_count FROM ({$unionSql}) as combined_tables");
        // 分页查询
        $offset = ($page - 1) * $rows;
        $list = \support\think\Db::query("{$unionSql} ORDER BY cts DESC LIMIT {$offset}, {$rows}");
        return success(data:$list,count: $count);
    }
    /**
     * 根据时间范围生成表名数组
     */
    private function getTableNames($starttime, $endtime){
        $startDate = new DateTime($starttime);
        $endDate = new DateTime($endtime);
        $tableList = \support\think\Db::query('SHOW TABLES');
        $tables = [];
        $current = (clone $startDate)->modify('first day of this month');
        $endMonth = (clone $endDate)->modify('first day of this month');
        while($current <= $endMonth){
            $tableName = 'api_log_' . $current->format('Ym');
            // 检查表是否存在(可选)
            if(in_array($tableName,$tableList)){
                $tables[] = $tableName;
            }
            // 下一个月
            $current->modify('+1 month');
        }
        return $tables;
    }

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值