Swoft MySQL

注意事项

要使用MySQL前提条件必须安装了MySQL,由于目前采用的是Docker的使用,所以提前需要使用Docker安装MySQL,具体操作参见《Docker MySQL》

基础概念

  • 数据库实例:数据库实例相当于分配,默认节点分为masterslave,属于默认实例default
  • masterslave是两个特殊的名称,他们会归纳到default实例中,表现为default.masterdefault.slave
  • 数据库节点:每个实例下的item都是一个节点,key是节点名称。
  • 每个节点都会创建一个连接池,连接池的名称是instance.node
  • 可以通过\Swoft::getPool("instance.node")获取连接池对象

为什么需要引入连接池呢?

对于基于PHP-FPM的传统PHP Web应用,包括且不限于MySQL、Redis、RabbitMq,每次请求到来时都需要为其新建一套独享的连接,这直接带来了一个典型的问题:

  • 连接开销
    连接随着HTTP请求的到来而新建,随着请求返回而销毁,大量连接新建销毁是对系统资源的浪费。
  • 连接数量过高
    每个请求都需要一套自己的连接,系统连接数和并发数会成一个线性的关系。如果系统并发量达到1W,那就需要建立1W个对应的连接,这对MySQL之类的后端服务来说是一个很大的负荷。
  • 空闲连接
    假如接口使用了一个MySQL连接,接口在一开始进行一次SQL查询后,后面的操作都是与SQL无关的,那么这个请求占据的空闲连接完全就是一种资源的浪费。

对于异步系统而言,这个问题变得更加严重。一个请求处理进程要对同一服务进行并发操作,这意味着请求要持有一个以上的同类连接。对系统压力而言,无疑是雪上加霜。所以连接池对基于Swoole的Web框架是必须实现的机制。

数据库配置

  • Swoft提供propertiesenv两种方式配置,env会覆盖properties配置。
  • Swoft提供数据库主从master-slave配置,默认读操作使用从配置slave,写操作使用主配置master,若只配置主则读写都会使用。

如果对数据库主从不是很清晰,可参见《MySQL读写分离主从复制》

env配置

$ vim .env
# 数据库主节点配置
# 连接池节点名称用于服务发现
DB_NAME=dbMaster
# 连接地址信息
DB_URI=127.0.0.1:3306/test?user=root&password=123456&charset=utf8,127.0.0.1:3306/test?user=root&password=123456&charset=utf8
# 最小活跃连接数
DB_MIN_ACTIVE=5
# 最大活跃连接数
DB_MAX_ACTIVE=10
# 最大等待连接
DB_MAX_WAIT=20
# 最大等待时间
DB_MAX_WAIT_TIME=3
# 连接最大空闲时间
DB_MAX_IDLE_TIME=60
# 连接超时时间
DB_TIMEOUT=2

# 数据库从节点配置
# 连接池节点名称用于服务发现
DB_SLAVE_NAME=dbSlave
# 连接地址信息
DB_SLAVE_URI=127.0.0.1:3306/test?user=root&password=123456&charset=utf8,127.0.0.1:3306/test?user=root&password=123456&charset=utf8
# 最小活跃连接数
DB_SLAVE_MIN_ACTIVE=5
# 最大活跃连接数
DB_SLAVE_MAX_ACTIVE=10
# 最大等待连接
DB_SLAVE_MAX_WAIT=20
# 最大等待时间
DB_SLAVE_MAX_WAIT_TIME=3
# 连接最大空闲时间
DB_SLAVE_MAX_IDLE_TIME=60
# 连接超时时间
DB_SLAVE_TIMEOUT=3
  • 数据库连接地址uri规则:ip:端口/数据库名?user=用户名&password=密码&charset=utf8

properties属性配置

$ vim config/properties/db.php
<?php
return [
    //数据库主节点配置
    'master' => [
        //连接池节点名称用于服务发现
        'name'        => 'master',
        //连接地址信息
        'uri'         => [
            '127.0.0.1:3306/test?user=root&password=123456&charset=utf8',
            '127.0.0.1:3306/test?user=root&password=123456&charset=utf8',
        ],
        //最小活跃连接数
        'minActive'   => 8,
        //最大活跃连接数
        'maxActive'   => 8,
        //最大等待连接
        'maxWait'     => 8,
        //超时时间
        'timeout'     => 8,
        //连接最大空闲时间
        'maxIdleTime' => 60,
        //连接最大等待时间
        'maxWaitTime' => 3,
    ],
    //数据库从节点配置
    'slave' => [
        //连接池节点名称用于服务发现
        'name'        => 'slave',
        //连接地址信息
        'uri'         => [
            '127.0.0.1:3306/test?user=root&password=123456&charset=utf8',
            '127.0.0.1:3306/test?user=root&password=123456&charset=utf8',
        ],
        //最小活跃连接数
        'minActive'   => 8,
        //最大活跃连接数
        'maxActive'   => 8,
        //最大等待连接
        'maxWait'     => 8,
        //超时时间
        'timeout'     => 8,
        //连接最大空闲时间
        'maxIdleTime' => 60,
        //连接最大等待时间
        'maxWaitTime' => 3,
    ],
];

实体定义

无论是高级查询还是基础查询都需要表实体,一个表字段和一个表属性是一一映射的关系,对类的操作相当于对表的操作,该类称为一个实体。实体不能作为属性被注入到任何类,因为每个实体对象都有不同的数据记录行。实体对象都是在那里使用就在那里创建。

  • 一个实体类对应一张数据表
  • 实体对象代表了表的一行数据记录

创建数据表

CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '名称',
  `age` tinyint(1) unsigned DEFAULT '0' COMMENT '年龄',
  `sex` tinyint(1) unsigned DEFAULT '0' COMMENT '性别',
  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '描述',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';
CREATE TABLE `count` (
  `uid` int(11) unsigned DEFAULT '0' COMMENT '用户ID',
  `fans` int(10) unsigned DEFAULT '0' COMMENT '粉丝数量',
  `follows` int(10) unsigned DEFAULT '0' COMMENT '关注数量'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='计数表';

快速生成实体类

使用Swoft提供的内置命令快速生成实体类

php bin/swoft entity:create -d test user,count

查看生成的实体类

$ vim app/Models/Entity/User.php
<?php
/**
 * This file is part of Swoft.
 *
 * @link https://swoft.org
 * @document https://doc.swoft.org
 * @contact group@swoft.org
 * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE
 */

namespace App\Models\Entity;

use Swoft\Db\Bean\Annotation\Id;
use Swoft\Db\Bean\Annotation\Required;
use Swoft\Db\Bean\Annotation\Table;
use Swoft\Db\Bean\Annotation\Column;
use Swoft\Db\Bean\Annotation\Entity;
use Swoft\Db\Model;
use Swoft\Db\Types;

/**
 * 用户实体
 *
 * @Entity()
 * @Table(name="user")
 * @uses      User
 * @version   2017年08月23日
 * @author    stelin <phpcrazy@126.com>
 * @copyright Copyright 2010-2016 Swoft software
 * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
 */
class User extends Model
{
    /**
     * 主键ID
     *
     * @Id()
     * @Column(name="id", type=Types::INT)
     * @var null|int
     */
    private $id;

    /**
     * 名称
     *
     * @Column(name="name", type=Types::STRING, length=20)
     * @Required()
     * @var null|string
     */
    private $name;

    /**
     * 年龄
     *
     * @Column(name="age", type=Types::INT)
     * @var int
     */
    private $age = 0;

    /**
     * 性别
     *
     * @Column(name="sex", type="int")
     * @var int
     */
    private $sex = 0;

    /**
     * 描述
     *
     * @Column(name="description", type="string")
     * @var string
     */
    private $desc = '';

    /**
     * 非数据库字段,未定义映射关系
     *
     * @var mixed
     */
    private $otherProperty;

    /**
     * @return int|null
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param int|null $id
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    /**
     * @return null|string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param null|string $name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * @return int
     */
    public function getAge(): int
    {
        return $this->age;
    }

    /**
     * @param int $age
     */
    public function setAge(int $age)
    {
        $this->age = $age;
    }

    /**
     * @return int
     */
    public function getSex(): int
    {
        return $this->sex;
    }

    /**
     * @param int $sex
     */
    public function setSex(int $sex)
    {
        $this->sex = $sex;
    }

    /**
     * @return string
     */
    public function getDesc(): string
    {
        return $this->desc;
    }

    /**
     * @param string $desc
     */
    public function setDesc(string $desc)
    {
        $this->desc = $desc;
    }

    /**
     * @return mixed
     */
    public function getOtherProperty()
    {
        return $this->otherProperty;
    }

    /**
     * @param mixed $otherProperty
     */
    public function setOtherProperty($otherProperty)
    {
        $this->otherProperty = $otherProperty;
    }
}
$ vim app/Models/Count.php
<?php
/**
 * This file is part of Swoft.
 *
 * @link https://swoft.org
 * @document https://doc.swoft.org
 * @contact group@swoft.org
 * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE
 */

namespace App\Models\Entity;

use Swoft\Db\Bean\Annotation\Column;
use Swoft\Db\Bean\Annotation\Entity;
use Swoft\Db\Bean\Annotation\Id;
use Swoft\Db\Bean\Annotation\Table;
use Swoft\Db\Model;
use Swoft\Db\Types;

/**
 * 计数表实体
 *
 * @Entity()
 * @Table("count")
 * @uses      Count
 * @version   2017年09月15日
 * @author    stelin <phpcrazy@126.com>
 * @copyright Copyright 2010-2016 swoft software
 * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
 */
class Count extends Model
{
    /**
     * 用户ID
     *
     * @Column(name="uid", type=Types::INT)
     * @Id()
     * @var null|int
     */
    private $uid;

    /**
     * 粉丝数
     *
     * @Column(name="fans", type=Types::NUMBER)
     * @var int
     */
    private $fans = 0;

    /**
     * 关注数
     *
     * @Column("follows", type=Types::NUMBER)
     * @var int
     */
    private $follows = 0;

    /**
     * @return int|null
     */
    public function getUid()
    {
        return $this->uid;
    }

    /**
     * @param int|null $uid
     */
    public function setUid($uid)
    {
        $this->uid = $uid;
    }

    /**
     * @return int
     */
    public function getFans(): int
    {
        return $this->fans;
    }

    /**
     * @param int $fans
     */
    public function setFans(int $fans)
    {
        $this->fans = $fans;
    }

    /**
     * @return mixed
     */
    public function getFollows()
    {
        return $this->follows;
    }

    /**
     * @param mixed $follows
     */
    public function setFollows($follows)
    {
        $this->follows = $follows;
    }
}

注解标签

  • @Entity 标记一个类是一个实体,无需多余参数。
  • @Table 定义实体映射的数据库表名
  • @Column(name, type) 类属性默认值为表字段默认值
    name 定义类属性映射的表字段,若无则不映射。type 定义字段数据更新时验证类型。所有字段属性必须存在gettersetter方法。
  • @Id 表明当前类属性对应了数据库表中的主键,必须存在。

错误处理

{
  "msg":"Database connection error,error=Connection refused",
  "file":"\/var\/www\/swoft\/vendor\/swoft\/db\/src\/Driver\/Mysql\/MysqlConnection.php",
  "line":89,
  "code":0
}

数据库连接失败,需要检查.envdb.php配置文件中数据库配置选项。

未完待续...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值