当前位置: 首页 > 工具软件 > Swoft > 使用案例 >

SW mysql_Swoft MySQL

黄弘新
2023-12-01

注意事项

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

基础概念

数据库实例:数据库实例相当于分配,默认节点分为master和slave,属于默认实例default。

master和slave是两个特殊的名称,他们会归纳到default实例中,表现为default.master和default.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提供properties和env两种方式配置,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

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

/**

* 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

* @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

/**

* 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

* @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 定义字段数据更新时验证类型。所有字段属性必须存在getter和setter方法。

@Id 表明当前类属性对应了数据库表中的主键,必须存在。

错误处理

{

"msg":"Database connection error,error=Connection refused",

"file":"\/var\/www\/swoft\/vendor\/swoft\/db\/src\/Driver\/Mysql\/MysqlConnection.php",

"line":89,

"code":0

}

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

未完待续...

 类似资料:

相关阅读

相关文章

相关问答