https://itbilu.com/nodejs/npm/NJ5VAqfYZ.html

Sequelize 中事务的使用-启动、提交、回滚

  1. 数据库中的事务是指单个逻辑所包含的一系列数据操作,要么全部执行,要么全部不执行。在一个事务中,可能会包含开始(START)、提交(COMMIT)、回滚(ROLLBACK)等操作,Sequelize 通过Transaction类来实现事务相关功能。Sequelize 中的事务有两种使用:可以基于Promise结果链进行自动提交或回滚,也可以由用户控制提交或回滚。
  1. Transaction类的构造函数
  2. 实例化
  3. 事务控制
    • 3.1 受管理事务的提交与回滚
    • 3.2 不受管理事务的提交与回滚

      1. Transaction类的构造函数

      Transaction类的构造函数结构如下:
      new Transaction(sequelize, [options])
      构造函数参数:
  • sequelize - 一个已配置的 Sequlize 实例
  • options是一个包含以下可选值的对象:
    • autocommit - Boolean,是否自动提交
    • type - String,事务类型
    • isolationLevel - String,事务的隔离级别
    • autocommit - String,立即或延迟检查约束

      2. 实例化

      虽然Transaction类可以直接访问(通过require(‘sequelize’).Transaction或sequelize.Transaction),但一般不需要直接实例化。
      其创建对象(实例化)可以使用Sequlize实例的sequelize.transaction()方法,创建Transaction对象后,被创建的对象回调到then回调链中。
      如,创建一个事务并在其中执行一些操作: ```javascript var Sequelize = require(‘sequelize’);

var sequelize = new Sequelize(‘modelTest’, ‘root’, ‘111111’, {host: ‘localhost’, port:3306, logging:console.log}); var User = sequelize.import(‘./user.js’); var UserCheckin = sequelize.import(‘./userCheckin.js’);

// 创建事务 sequelize.transaction(function (t) { // 在事务中执行操作 return User.create({username: ‘itbilu.com’, password: ‘pwd’, active: true}, {transaction:t}) .then(function(user){ return UserCheckin.create({userId: user.id, loginIp:’localhost’}, {transaction:t}) }); }).then(function (results){ / 操作成功,事务会自动提交 / }).catch(function(err){ / 操作失败,事件会自动回滚 / });

  1. 以上示例执行结果类似如下:
  2. ```javascript
  3. Executing (3e756dc6-4f73-40f6-aa1c-d21ae832a302): START TRANSACTION;
  4. Executing (3e756dc6-4f73-40f6-aa1c-d21ae832a302): SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
  5. Executing (3e756dc6-4f73-40f6-aa1c-d21ae832a302): SET autocommit = 1;
  6. Executing (3e756dc6-4f73-40f6-aa1c-d21ae832a302): INSERT INTO `user` (`id`,`username`,`password`,`active`,`created_at`,`updated_at`) VALUES (DEFAULT,'itbilu.com','pwd',true,'2016-08-09 09:34:46','2016-08-09 09:34:46');
  7. Executing (3e756dc6-4f73-40f6-aa1c-d21ae832a302): INSERT INTO `userCheckin` (`id`,`user_id`,`login_ip`,`created_at`,`updated_at`) VALUES (DEFAULT,2,'127.0.0.1','2016-08-09 09:34:46','2016-08-09 09:34:46');
  8. Executing (3e756dc6-4f73-40f6-aa1c-d21ae832a302): COMMIT;

3. 事务控制

一个事务实例(创建事务对象)就表示一个正在执行事务,即:启动一个事务。Sequelize 中的事务可以基于Promise结果链进行自动提交或回滚。也可以由用户控制,通过调用事务实例的commit()或rollback()来手工提交或回滚。
在一个关系型数据库的事务中,可能会包含开始(START)、提交(COMMIT)、回滚(ROLLBACK)等操作三个操作。Sequelize中同样会有这三种操作,创建一个Transaction类实例就是“开始”一个事务。事务启动后,对于受管理的事务(auto-callback)可以基于Promise回调链由Sequelize自动“提交”或“回滚”事务;而对于不受管理的事务(then-callback),我们可以手工调用commit()方法来“提交”事务,或调用rollback()来“回滚”事务。

3.1 受管理事务的提交与回滚

在使用sequelize.transaction()创建类实列时(启动事务),可以向其传递一个回调函数。通过这种方式创建的事务,是受管理的事务:

  1. // 启动一个受管理的事务
  2. return sequelize.transaction(function (t) {
  3. // 一些在事务中进行的操作
  4. }).then(function (result) {
  5. // Transaction 会自动提交
  6. // result 是事务回调中使用promise链中执行结果
  7. }).catch(function (err) {
  8. // Transaction 会自动回滚
  9. // err 是事务回调中使用promise链中的异常结果
  10. });

创建受管理事务后,传递给回调函数的transaction会返回一个promise链,在promise返回的then或catch方法中,并不能调用t.commit()或t.rollback()来控制事务。在这种方式下,如果使用事务的所有promise链都执行成功,则自动提交;如果其中之一执行失败(即:catch()方法被调用),则自动回滚。
注意:也不建议回调函数内部调t.commit()或t.rollback()提交或回滚事务,这样会造成阻塞。
强制回调
虽然不能在promise返回的then或catch方法中手工提交或回滚方法,但可以基于promise通过抛出异常来强制回滚事务:

  1. return sequelize.transaction(function (t) {
  2. return User.create({
  3. firstName: 'Abraham',
  4. lastName: 'Lincoln'
  5. }, {transaction: t}).then(function (user) {
  6. // 注意,虽然所有操作成功但仍会回滚
  7. throw new Error();
  8. });
  9. });

3.2 不受管理事务的提交与回滚

如果调用sequelize.transaction()创建事务实例时不传入回调函数,会启动一个不受管理事务。不受管理的事务需要你强制(手工)提交或回滚,如果不进行这些操作,事务会一直保持挂起状态直到超时。
不受管理的事务对象会被传递至then方法的回调函数中,在这里我们可以通过调用t.commit()或t.rollback()提交或回滚事务:

  1. // 启动一个不受管理的事务
  2. return sequelize.transaction().then(function (t) {
  3. // 一些在事务中进行的操作
  4. return User.create({
  5. firstName: 'Homer',
  6. lastName: 'Simpson'
  7. }, {transaction: t}).then(function (user) {
  8. return user.addSibling({
  9. firstName: 'Lisa',
  10. lastName: 'Simpson'
  11. }, {transaction: t});
  12. }).then(function () {
  13. // 手工提交事务
  14. return t.commit();
  15. }).catch(function (err) {
  16. // 手工回滚事务
  17. return t.rollback();
  18. });
  19. });