社区/学习指南/小程序·云开发高级教程

连接MySQL数据库

MySQL 可以说是互联网企业最为流行的数据库,也是最流行的关系型数据库(云开发数据库是文档型数据库)。如果你的项目已经使用了 MySQL,数据库不方便迁移到云开发数据库或者你的业务更偏向于使用 MySQL,在这种情况下,也是可以使用连接自建的 MySQL 数据库并把数据传到小程序端进行渲染的。

11.7.1 私有网络 VPC

1、公网与私有网络访问数据库的对比

在服务器自建的 MySQL 或者在腾讯云等云服务公司购买的关系型数据库服务在开放了外部网络连接和 IP 白名单的情况下,都是可以使用云函数连接的,也就是说云函数是部署在公共网络之中的,只能访问公网的数据库资源(内网或本地的数据库是不行的),而你的数据库要能被公网访问就需要开放外部网络连接和 IP 白名单。不过云函数目前没有固定的 IP,因此数据库需要添加的 IP 白名单列表会比较长。

如果你不想让数据库暴露在公网环境之下,但是又能被云函数访问,这里推荐使用腾讯云的私有网络。处于私有网络的腾讯云产品(比如云开发的云函数腾讯云的 MySQL 数据库),可以通过腾讯云提供的对等连接进行互联。对等连接服务相比公网传输有极大的优势

  • 更高质量,与其他腾讯云产品共享同一自建的内部网络,由于是内部传输,不受公网质量影响,可用性、时延、丢包率保障大大提高;

  • 更强安全,内网连接处于腾讯集团级别的防 DDos 安全防护下,由于不经过广域 Internet 和运营商链路,避免报文在公网传输可能被窃取的风险;

  • 内网传输更快,成本更低,云函数外网流量是要计费的,而同一地域的内网流量则是免费的;

如果你希望云开发的云函数使用图形图像、音视频处理等比较消耗资源的服务,以及对安全有比较高要求的MySQLRedis、TencentDB、Kafka 等服务,我们都建议使用私有网络。

2、私有网络服务的创建

1、创建上海可用区的私有网络

腾讯云控制台需要登录时,选择微信公众号(小程序账号属于公众号体系)的登录方式,扫码选择相应的小程序账号进行登录。

打开腾讯云控制台的私有网络免费创建私有网络,由于私有网络具有地域(Region)属性,我们需要在函数所在的地域来新建私有网络。云开发的云函数的服务器部署在上海,因此你的私有网络里的资源也要选择上海。私有网络有三个核心组成成分:私有网络网段 IPv4 CIDR、子网和路由表。一个私有网络下的子网可以属于该地域下不同可用区,同一私有网络下各个子网内资源无论是否在同一可用区内,均默认内网互通。而初始子网的可用区,你可以根据你的 MySQL 等数据库所在的可用区来选,如果你之前在腾讯云没有数据库等,选择上海的任意可用区即可。

2、在腾讯云购买 MySQL 并加入同一私有网络

打开腾讯云控制台的MySQL中购买一个实例,创建实例时最主要的是在网络这里找到你之前创建的私有网络以及对应的子网(下拉即可)。

3、将需要连接 MySQL 的云函数加入私有网络

打开腾讯云控制台的云开发 CloudBase中选择指定的环境,然后点击云函数菜单,然后新建一个云函数或者选择指定的云函数比如 mysql,进入配置页面后,点击右上角的“编辑”,在网络配置选择和 MySQL 服务一样的私有网络。这样云函数就可以通过私有网络的方式连接 MySQL 了。

然后我们可以根据需要或者结合自身的业务需求,往 mysql 数据库里导入数据或数据文件,比如可以使用腾讯与自带的 DMS 往里面导入 sql 文件。

11.7.2 使用 mysql2 操作 MySQL

1、使用 mysql2 连接 MySQL

支持 Nodejs 连接 MySQL 数据库的库有很多,比如 mysql、mysql2,这里推荐使用 mysql2。mysql2 是支持 async/await 的 Promise 写法的。

使用开发者工具打开之前有的 mysql 云函数(只要绑定了私有网络即可,没有的话可以参照上一步的说明),在 package.json 里添加 latest 最新版的 mysql2,并右键云函数目录选择在终端中打开输入命令 npm install 安装依赖:


  "dependencies": {

    "wx-server-sdk": "latest",

    "mysql2": "latest"

  }

然后在 index.js 里输入以下代码,这里需要注意的是我们引入的是 mysql2/promise,.query的第一个参数是 sqlString,也就是 SQL 命令行语句的字符串格式;当所有数据库请求结束之后,注意要使用.end断开连接,不然云函数会报超时错误。

const cloud = require("wx-server-sdk");

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV,
});

const mysql = require("mysql2/promise");

exports.main = async (event, context) => {
  try {
    const connection = await mysql.createConnection({
      host: "10.168.0.7", //内网ip地址

      user: "root", //数据库的用户名

      password: "tcb123", //数据库密码

      database: "tcb", //数据库名称
    });

    const [rows, fields] = await connection.query(
      'SELECT * FROM `country` WHERE `country` = "china"'
    );

    connection.end(function (err) {
      //注意要断开连接,不然尽管获取到了数据,云函数还是会报超时错误

      console.log("断开连接");
    });

    console.log(rows);

    console.log(fields);

    return rows;
  } catch (err) {
    console.log("连接错误", err);

    return err;
  }
};

mysql2 模块的很多参数的使用与 mysql 模块的比较一致,更多配置相关的信息可以查看mysql 模块技术文档.

2、mysql2 的增删改查

mysql2 支持数据库的增删改查,下面只大致列举一些简单的案例,更多的资料可以去查看 mysql 相关的技术文档:


#创建一个名称为tcb的数据库

CREATE DATABASE `tcb`


#创建一个包含name、address字段的users表格与删除表格

CREATE TABLE `users` (`name` VARCHAR(255), `address` VARCHAR(255))

DROP TABLE `users`


#向users表格里插入记录

INSERT INTO `users`(`name`, `address`) VALUES ('李东bbsky', '深圳')


#查询users表格

SELECT * FROM `users`


#限制查询到的记录数为20,建议记录比较多的数据表查询都需指定limit

SELECT * FROM `users` LIMIT 20


#查询users表格里字段等于某个值的记录

SELECT * FROM `users` WHERE `name` = '李东bbsky'


#将查询结果按名称来排序

SELECT * FROM `users` ORDER BY `name`


#删除满足条件的记录

DELETE FROM `users` WHERE `address` = '深圳'


#更新满足条件的记录的字段值

UPDATE `users` SET `address` = "广州" WHERE `address` = '深圳'


#使用Join进行联表查询

SELECT `users.name` AS `user`, `products.name` AS `favorite` FROM `users` JOIN `products` ON `users.favorite_product` = products.id

11.7.3 使用 serverless-mysql 操作 MySQL

下面还推荐一个比较好用的包 serverless-mysql,具体使用文档可以参考serverless-mysql 技术文档

使用开发者工具打开之前有的 mysql 云函数,在 package.json 里添加 latest 最新版的 mysql2,并右键云函数目录选择在终端中打开输入命令 npm install 安装依赖:


  "dependencies": {

    "wx-server-sdk": "latest",

    "serverless-mysql": "latest"

  }

然后在 index.js 里输入以下代码,这里需要注意的是我们引入的是 mysql2/promise,.query的第一个参数是 sqlString,也就是 SQL 命令行语句的字符串格式;当所有数据库请求结束之后,注意要使用.end断开连接,不然云函数会报超时错误。

const cloud = require("wx-server-sdk");

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV,
});

const mysql = require("serverless-mysql");

exports.main = async (event, context) => {
  const connection = await mysql({
    config: {
      host: "10.168.0.7", //你

      database: "country",

      user: "root",

      password: "lidongyx327",
    },
  });

  let results = await connection.query(
    'INSERT INTO country(Country, Region) VALUES ("中国","亚洲")'
  );

  await connection.end();

  return results;
};

当然,你还可以使用 Sequelize,Sequelize 是针对 node.js 和 io.js 提供的 ORM 框架。具体就是突出一个支持广泛,配置和查询方法统一。它支持的数据库包括:PostgreSQL、 MySQL、MariaDB、 SQLite 和 MSSQL。技术文档:Sequelize,这里就不多举例了。

在云函数中使用 MySQL,每个云函数在执行时就都会与 MySQL 的 server 有连接),但数据库的最大连接数是非常少的(几百几千),我们可以在数据库管理里看到并设置这个值 max_connections。由于数据库的连接数比较少,因此建议将数据库的增删改查都写在一个云函数里。这样会减少云函数冷启动的概率以及减少对数据库连接数的占用,而将增删改查的处理集中到一个云函数,我们可以使用到云函数路由 tcb-router,后面会有介绍。

本文出自 李东bbsky