knex事务

1.数据库事务

在执行SQL语句时,某些业务要求,一系列操作必须全部执行,而不能仅执行一部分。例如,一个转账操作:

从id=1的账户给id=2的账户转账100元

-- 第一步:将id=1的A账户余额减去100
UPDATE accounts SET balance = balance - 100 WHERE id = 1;-- 第二步:将id=2的B账户余额加上100
UPDATE accounts SET balance = balance + 100 WHERE id = 2;

这两条SQL语句必须全部执行,或者,由于某些原因,如果第一条语句成功,第二条语句失败,就必须全部撤销。

这种把多条语句作为一个整体进行操作的功能,被称为数据库事务。数据库事务可以确保该事务范围内的所有操作都可以全部成功或者全部失败。如果事务失败,那么效果就和没有执行这些SQL一样,不会对数据库数据有任何改动。

可见,数据库事务具有ACID这4个特性(参考地址):

  • A:Atomic,原子性,将所有SQL作为原子工作单元执行,要么全部执行,要么全部不执行;
  • C:Consistent,一致性,事务完成后,所有数据的状态都是一致的,即A账户只要减去了100,B账户则必定加上了100;
  • I:Isolation,隔离性,如果有多个事务并发执行,每个事务作出的修改必须与其他事务隔离;
  • D:Duration,持久性,即事务完成后,对数据库数据的修改被持久化存储。

对于MySQL数据库,要手动把多条SQL语句作为一个事务执行,可以使用BEGIN开启一个事务,使用COMMIT提交一个事务,这种事务被称为显式事务,例如,把上述的转账操作作为一个显式事务:

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

而对于nodejs使用knex框架,在不直接编写SQL语句的情况下,可以使用knex的数据库事务方法knex.transaction

2.knex事务

事务是关系数据库的一个重要功能,因为它们允许从故障中正确恢复并即使在系统发生故障时也能保持数据库的一致性。事务中的所有查询都在同一数据库连接上执行,并将整组查询作为单个工作单元运行。任何失败都意味着数据库会将在该连接上执行的任何查询回滚到事务前状态。

knex中通过将处理函数传递到 knex.transaction 中进行处理,该处理函数接受一个参数——该参数是一个对象,并可以通过两种方式使用:

  1. 作为promise aware的kenx连接
  2. 作为一个对象传递到查询进行事务处理,并最终调用提交或回滚。

两种方法的使用示例分别为:

// Using trx as a query builder:
knex.transaction(function(trx) {const books = [{title: 'Canterbury Tales'},{title: 'Moby Dick'},{title: 'Hamlet'}];return trx.insert({name: 'Old Books'}, 'id').into('catalogues').then(function(ids) {books.forEach((book) => book.catalogue_id = ids[0]);return trx('books').insert(books);});
})
.then(function(inserts) {console.log(inserts.length + ' new books saved.');
})
.catch(function(error) {// If we get here, that means that // neither the 'Old Books' catalogues insert,// nor any of the books inserts will have taken place.console.error(error);
});

或通过如下方式使用:

// Using trx as a transaction object:
knex.transaction(function(trx) {const books = [{title: 'Canterbury Tales'},{title: 'Moby Dick'},{title: 'Hamlet'}];knex.insert({name: 'Old Books'}, 'id').into('catalogues').transacting(trx).then(function(ids) {books.forEach((book) => book.catalogue_id = ids[0]);return knex('books').insert(books).transacting(trx);}).then(trx.commit).catch(trx.rollback);
})
.then(function(inserts) {console.log(inserts.length + ' new books saved.');
})
.catch(function(error) {// If we get here, that means that // neither the 'Old Books' catalogues insert,// nor any of the books inserts will have taken place.console.error(error);
});

上述示例都可以通下列async/await方法来使用:

try {await knex.transaction(async trx => {const books = [{title: 'Canterbury Tales'},{title: 'Moby Dick'},{title: 'Hamlet'}];const ids = await trx('catalogues').insert({name: 'Old Books'}, 'id')books.forEach((book) => book.catalogue_id = ids[0])const inserts = await trx('books').insert(books)console.log(inserts.length + ' new books saved.')})
} catch (error) {// If we get here, that means that neither the 'Old Books' catalogues insert,// nor any of the books inserts will have taken place.console.error(error);
}

或者通过下列方式使用:

// Using trx as a transaction object:
const trx = await knex.transaction();const books = [{title: 'Canterbury Tales'},{title: 'Moby Dick'},{title: 'Hamlet'}
];trx('catalogues').insert({name: 'Old Books'}, 'id').then(function(ids) {books.forEach((book) => book.catalogue_id = ids[0]);return trx('books').insert(books);}).then(trx.commit).catch(trx.rollback);

3.knex事务模型

如果您需要为事务指定隔离级别,可以使用配置参数isolationLevel(oracle 和 sqlite 不支持),选项包括:read uncommitted, read committed, repeatable read, snapshot (mssql only), serializable

使用方法如下:

// Simple read skew example
const isolationLevel = 'read committed';
const trx = await knex.transaction({isolationLevel});
const result1 = await trx(tableName).select();
await knex(tableName).insert({ id: 1, value: 1 });
const result2 = await trx(tableName).select();
await trx.commit();
// result1 may or may not deep equal result2 depending on isolation level

你也可以通过readOnly参数,将事务模型设置为只读(当前仅支持mysql, postgres, and redshift),使用方法如下:

const trx = await knex.transaction({ readOnly: true });
// 💥 Cannot `INSERT` while inside a `READ ONLY` transaction
const result = await trx(tableName).insert({ id: 1, foo: 'bar' });

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/146707.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp中的H5页面微信浏览器中禁止下拉出现网页由xxx.xxxxx.com提供,QQ浏览器X5内核提供技术支持这个

在App.vue文件中的onLaunch函数新增如下 onLaunch: function () {console.log(App Launch);document.body.addEventListener(touchmove,function (e) {e.preventDefault();},{ passive: false });},

数据的存储--MongoDB文档存储

MongoDB文档存储 NoSQL,全称为Not Only SQL,意为不仅仅是SQL,泛指非关系型数据库。NoSQL是基于键值对的,而且不需要经过SQL层的解析,数据之间没有耦合性,性能非常高。 非关系行数据库又可细分如下。 键值存…

【入门篇】1.2 Redis 客户端之 Jedis 详解和示例

文章目录 1. 简介2. Jedis的依赖下载Jedis导入Jedis jar包配置Redis服务器的地址和端口 3. Jedis 的基本操作连接 Redis 服务器设置和获取字符串类型的键值对判断键是否存在删除键设置键的过期时间 4. Jedis 的数据类型操作字符串类型列表类型集合类型哈希类型有序集合类型 5. …

YOLOv5独家原创改进:最新原创WIoU_NMS改进点,改进有效可以直接当做自己的原创改进点来写,提升网络模型性能精度

💡该教程为属于《芒果书》📚系列,包含大量的原创首发改进方式, 所有文章都是全网首发原创改进内容🚀 💡本篇文章为YOLOv5独家原创改进:独家首发最新原创WIoU_NMS改进点,改进有效可以直接当做自己的原创改进点来写,提升网络模型性能精度。 💡对自己数据集改进有效…

数据结构-插入排序实现

文章目录 1、描述2、代码实现3、结果4、复杂度 1、描述 待排序的数组分为已排序、未排序两部分; 初始状态时,仅有第一个元素为已排序序列,第一个以外的元素为未排序序列; 此后遍历未排序序列, 将元素逐一插入到已排序的序列中&am…

12.Oracle的索引

Oracle11g的索引 一、什么是索引二、索引的分类三、索引的语法四、分析索引四、索引的作用及使用场景 一、什么是索引 在Oracle数据库中,索引是一种特殊的数据结构,用于提高查询性能和加速数据检索。索引存储了表中某列的值和对应的行指针,这…

py 异步

Python中的异步编程通常使用多线程或异步IO库来实现。 多线程是一种并行处理方式,可以同时执行多个任务,但需要手动管理线程之间的同步和通信。Python提供了threading模块来实现多线程,但多线程在处理IO密集型任务时可能会受到阻塞&#xff…

批量替换WordPress文章内图片链接

在WordPress使用过程中,如果中途更换了域名,原先文章内的图片使用的是原来的域名,就会造成文章页里面的图片链接无法显示。如果从后台文章挨个修改就比较麻烦。可以通过数据库进行批量替换即可。 使用 PHPMyadmin 打开 数据库,登…

WPF xaml Command用法介绍

WPF (Windows Presentation Foundation) 中的命令设计模式是一种用于分离用户界面逻辑和业务逻辑的方法。在WPF中,这种模式通过命令接口(如 ICommand)实现,使得用户界面组件(如按钮、菜单项等)可以触发不直…

力扣labuladong——一刷day35

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、力扣912. 排序数组二、力扣 315. 计算右侧小于当前元素的个数三、力扣493. 翻转对四、力扣327. 区间和的个数 前言 就这么说吧,所有递归的算法&…

JDK1.8 新特性(二)【Stream 流】

前言 上节我们学了 lambda 表达式,很快我就在 Flink 的学习中用到了,我学的是 Java 版本的 Flink,一开始会以为代码会很复杂,但事实上 Flink 中很多地方都用到了 函数接口,这也让我们在编写 Flink 程序的时候可以使用 …

MIB 6.1810实验Xv6 and Unix utilities(2)sleep

难度:easy Implement a user-level sleep program for xv6, along the lines of the UNIX sleep command. Your sleep should pause for a user-specified number of ticks. A tick is a notion of time defined by the xv6 kernel, namely the time between two interrupts f…

【nlp】2.5(gpu version)人名分类器实战项目(对比RNN、LSTM、GRU模型)工程管理方式

人名分类器实战项目 0 说明1 工程项目设计2 数据预处理data_processing3 创建模型model4 模型测试test5 训练配置config6 模型训练train7 模型对比绘图plotfigure8 模型预测predict9 代码测试demo0 说明 本项目对前一个博客内容2.5(cpu version) 人名分类器实战项目(对比RNN、…

vertx学习

写在前面 新公司用到了vertx,所以这里学习下。 源码 。 1:vertx是啥? 是个框架吗?不是。只是一个工具类,只不过提供的功能比较全面,如http,websocket,tcp,json处理,定…

2D 3D 工业组态技术 meta2d JavaScript

本心、输入输出、结果 文章目录 2D 3D 工业组态技术 meta2d JavaScript前言2D 3D 工业组态技术 meta2d JavaScript 简介2D 3D 工业组态技术 meta2d JavaScript 特性丰富的组态能力0代码数据通信组态的应用多端适配能力强大的扩展能力追求卓越性能丰富的组件库资源广泛的应用场景…

C语言变量与常量

跟着肯哥(不是我)学C语言的变量和常量、跨文件访问、栈空间 栈空间还不清楚,期待明天的课程内容 C变量 变量(Variable)是用于存储和表示数据值的名称。 主要包括四个环节:定义、初始化、声明、使用 在我刚…

什么是BT种子!磁力链接又是如何工作的?

目录 一.什么是BT?1.BT简介:1.1.BT是目前最热门的下载方式之一1.2.BT服务器是通过一种传销的方式来实现文件共享的 2.小知识:2.1.你知道吗BT下载和常规下载到底有哪些不同2.2.BT下载的灵魂:种子2.3.当下载结束后,如果未…

122. 买卖股票的最佳时机 II

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。 在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。 返回 你能获得的 最大 利润 。 示例 1&…

Java实现的插件化策略模式

Java实现的插件化策略模式 目录结构实现BaseDealAnno.java(注解)BasePluginEnum.java(枚举)BaseDealFactory.javaContextBaseDealListener.java(核心类)BaseDealHandler.java(接口)BaseAudioService.java(可扩展多个)验证目录结构 com.demo.mytest ├── strategy │ ├──…

mysql客户端navicat的一些错误合集

关于mysql的客户端的使用的一些问题 问题描述: 在使用navicat prenium客户端的时候,连接数据库出现 Table ‘performance_schema.session_variables’ doesn’t exist 错误 解决方案: 首先找到mysql的bin目录 然后winR 进入到cmd界面 输入…