node里的MySQL

这里记录node连sql数据库的代码块,方便以后复用。

执行原生mysql,只考虑 mysql2 就可以。如果是通过orm的话,使用 sequelize 也没有什么争议。


先说 mysql2 它的promise async支持的比较好,目标是取代 mysql

快速入门 #

安装 #

yarn add mysql2

快速链接 #

引入包,引入环境变量,引入sql语句

callback 写法

async 写法

创建连接池得到实例,实例去query代码

const mysql = require("mysql2/promise");
const mysqlConf = {
  host: "localhost",
  user: "root",
  password: "12345678",
  database: "wp-back"
};

// 这个sql语句忽略,稍微有点复杂
const SQL = `select ID,post_title from  wp_posts, wp_term_relationships,wp_terms 
where (
	wp_posts.post_status='publish' and 
	ID = wp_term_relationships.object_id and
	wp_term_relationships.term_taxonomy_id = wp_terms.term_id  and
	wp_terms.name='企业简介'
) `;

(async () => {
  const pool = mysql.createPool(mysqlConf);
  const [row, fields] = await pool.query(SQL);
  console.log(row);
   pool.end() // 记得关闭
})();

实际中,会把 pool 独立出去,引入。

其他配置参数 #

mysql2 的目标是取代 mysql ,所以都没有文档,直接去 node-mysql 上看 options

连接参数 #

  • host port user password database 这几项就不说了
  • localAddress 来源ip地址,用于tcp连接
  • charset 默认 UTF8_GENERAL_CI 可以指定 utf8mb4
  • timezone 时区。默认值 local+08:00
  • connectTimeout 初始化连接超时毫秒 默认10000
  • typeCast 把列和值编程js对象。默认true
  • dateString 强制把 timestamp date datetime 等编程字符串,而不是js的date 默认值 false

`passwordSha1: Buffer.from('8bb6118f8fd6935ad0876a3be34a717d32708ffd', 'hex')``

其他的忽略。

##连接池 poll 连接参数 连接池把握的核心点,连接有可能超过限制,会进行排队,轮到了才执行

  • acquireTimeout 获取连接超时毫秒,如果连接已经在排队了,时间不算,默认10000
  • waitForConnections 默认true 多的请求排队。如果false超出就报错
  • connectionLimit 最大连接数,默认10
  • queueLimit 排队最大连接数,超出的返回错误,默认0不限制

连接池事件 #

pool.on('xxx',()=>{})

  • acquire when a connection is acquired from the pool
  • connection 建立新连接,参数 connection
  • enqueue 进入排队等待
  • release 释放

query(sql, [params], callback)

事务 #

伪代码

con.beginTransaction((err)=>{
 con.query(xxx,function(){
    con.commit()
})
})

ORM Sequelize 部分 ORM Object-relational-mapping 建立映射关系,操作对象。

快速入门 #

yarn add mysql2 sequelize
const Sequelize = require('sequelize')
const sequelize = new Sequelize("wp-back", "root", "", {
  host: "localhost",
  dialect: "mysql",
  operatorsAliases: false
});
// 然后定义模型

  • aync.force=true
  • timestamps:false define 也可以有 getterMethods, setterMethods 场景 deleteFlag 有get set方法

数据模型 #

这里放一个列表


范式 #

  1. 表的列具有原子性,不可再分解
  2. 一行数据只做一件事,只要重复就该岔开
  3. 只有直接关系,没有间接关系

反范式。

数据库设计原则 #

三个境界 #

手中有剑 心中无剑 #

刚入门数据库设计,范式的重要性还未深刻理解。这时候出现的反范式设计,一般会出问题。

手中有剑 心中有剑 #

随着遇到问题解决问题,渐渐了解到范式的真正好处,从而能快速设计出低冗余、高效率的数据库。

手中无剑 心中有剑 #

再经过N年的锻炼,是一定会发觉范式的局限性的。此时再去打破范式,设计更合理的反范式部分。

范式 #

范式

第一范式 #

即表的列的具有原子性,不可再分解,即列的信息,不能分解 关系型数据库 自动满足

第二范式 #

每一行的数据只能与其中一列相关,即一行数据只做一件事。只要数据列中出现数据重复,就要把表拆分开来。 例: 一个人同时订几个房间,就会出来一个订单号多条数据,这样子联系人都是重复的,就会造成数据冗余。我们应该把他拆开来。

第三范式 #

数据不能存在传递关系,即没个属性都跟主键有直接关系而不是间接关系。

反范式 #

  • 降低范式适当增加字段
  • 没有冗余的数据库未必是最好的数据库
  • 减少查询时关联
  • 提高查询效率
  • 适度范式 在满足三范式基础上做调整
  • 适用场景
    • 核心业务适用范式
    • 弱一致性需求
    • 空间换时间

经典的还是范式,快速迭代可以反范式