此係列文章的應用示例已發佈於 GitHub: sequelize-docs-Zh-CN. 能夠 Fork 幫助改進或 Star 關注更新. 歡迎 Star.node
Sequelize 支持兩種使用事務的方法:git
主要區別在於託管事務使用一個回調,對非託管事務而言指望 promise 返回一個 promise 的結果。github
託管事務自動處理提交或回滾事務。你能夠經過將回調傳遞給 sequelize.transaction
來啓動託管事務。數據庫
注意回傳傳遞給 transaction
的回調是不是一個 promise 鏈,而且沒有明確地調用t.commit()
或 t.rollback()
。 若是返回鏈中的全部 promise 都已成功解決,則事務被提交。 若是一個或幾個 promise 被拒絕,事務將回滾。npm
return sequelize.transaction(function (t) { // 在這裏連接您的全部查詢。 確保你返回他們。 return User.create({ firstName: 'Abraham', lastName: 'Lincoln' }, {transaction: t}).then(function (user) { return user.setShooter({ firstName: 'John', lastName: 'Boothe' }, {transaction: t}); }); }).then(function (result) { // 事務已被提交 // result 是 promise 鏈返回到事務回調的結果 }).catch(function (err) { // 事務已被回滾 // err 是拒絕 promise 鏈返回到事務回調的錯誤 });
使用託管事務時,你應該 永不 手動提交或回滾事務。 若是全部查詢都成功,但您仍然但願回滾事務(例如由於驗證失敗),則應該拋出一個錯誤來斷開和拒絕連接:promise
return sequelize.transaction(function (t) { return User.create({ firstName: 'Abraham', lastName: 'Lincoln' }, {transaction: t}).then(function (user) { // 查詢成功,但咱們仍然想回滾! throw new Error(); }); });
在上面的例子中,事務仍然是手動傳遞的,經過傳遞 {transaction:t}
做爲第二個參數。 要自動將事務傳遞給全部查詢,您必須安裝 continuation local storage (CLS) 模塊,並在您本身的代碼中實例化一個命名空間:併發
const cls = require('continuation-local-storage'), namespace = cls.createNamespace('my-very-own-namespace');
要啓用CLS,您必須經過使用sequelize構造函數的靜態方法來告訴Sequelize要使用的命名空間:函數
const Sequelize = require('sequelize'); Sequelize.useCLS(namespace); new Sequelize(....);
請注意, useCLS()
方法在 構造函數 上,而不是在 sequelize 的實例上。 這意味着全部實例將共享相同的命名空間,而且 CLS 是所有或全無方式 - 你不能僅在某些實例中啓用它。post
CLS 的工做方式就像一個用於回調的本地線程存儲。 這在實踐中意味着不一樣的回調鏈能夠經過使用 CLS 命名空間來訪問局部變量。 當啓用 CLS 時,建立新事務時,Sequelize 將在命名空間上設置 transaction
屬性。 因爲回調鏈中設置的變量對該鏈是私有的,所以能夠同時存在多個併發事務:ui
sequelize.transaction(function (t1) { namespace.get('transaction') === t1; // true }); sequelize.transaction(function (t2) { namespace.get('transaction') === t2; // true });
在大多數狀況下,你不須要直接訪問 namespace.get('transaction')
,由於全部查詢都將自動在命名空間中查找事務:
sequelize.transaction(function (t1) { // 啓用 CLS 後,將在事務中建立用戶 return User.create({ name: 'Alice' }); });
在使用 Sequelize.useCLS()
後,從 sequelize 返回的全部 promise 將被修補以維護 CLS 上下文。 CLS 是一個複雜的課題 - cls-bluebird的文檔中有更多細節,用於使 bluebird promise 的補丁與CLS一塊兒工做。
你能夠在一系列查詢中執行併發事務,或者將某些事務從任何事務中排除。 使用 {transaction: }
選項來控制查詢所屬的事務:
sequelize.transaction(function (t1) { return sequelize.transaction(function (t2) { // 啓用CLS,這裏的查詢將默認使用 t2 // 經過 `transaction` 選項來定義/更改它們所屬的事務。 return Promise.all([ User.create({ name: 'Bob' }, { transaction: null }), User.create({ name: 'Mallory' }, { transaction: t1 }), User.create({ name: 'John' }) // 這將默認爲 t2 ]); }); });
啓動事務時可能使用的隔離等級:
Sequelize.Transaction.ISOLATION_LEVELS.READ_UNCOMMITTED // "READ UNCOMMITTED" Sequelize.Transaction.ISOLATION_LEVELS.READ_COMMITTED // "READ COMMITTED" Sequelize.Transaction.ISOLATION_LEVELS.REPEATABLE_READ // "REPEATABLE READ" Sequelize.Transaction.ISOLATION_LEVELS.SERIALIZABLE // "SERIALIZABLE"
默認狀況下,sequelize 使用數據庫的隔離級別。 若是要使用不一樣的隔離級別,請傳入所需級別做爲第一個參數:
return sequelize.transaction({ isolationLevel: Sequelize.Transaction.ISOLATION_LEVELS.SERIALIZABLE }, function (t) { // 你的事務 });
注意: 在MSSQL的狀況下,SET ISOLATION LEVEL 查詢不被記錄, 指定的 isolationLevel 直接傳遞到tedious
非託管事務強制您手動回滾或提交交易。 若是不這樣作,事務將掛起,直到超時。 要啓動非託管事務,請調用 sequelize.transaction()
而不用 callback(你仍然能夠傳遞一個選項對象),並在返回的 promise 上調用 then
。 請注意,commit()
和 rollback()
返回一個 promise。
return sequelize.transaction().then(function (t) { return User.create({ firstName: 'Homer', lastName: 'Simpson' }, {transaction: t}).then(function (user) { return user.addSibling({ firstName: 'Lisa', lastName: 'Simpson' }, {transaction: t}); }).then(function () { return t.commit(); }).catch(function (err) { return t.rollback(); }); });
可使用options對象做爲第一個參數來調用transaction
方法,這容許配置事務。
return sequelize.transaction({ /* options */ });
如下選項(使用默認值)可用:
{ autocommit: true, isolationLevel: 'REPEATABLE_READ', deferrable: 'NOT DEFERRABLE' // postgres 的默認設置 }
在爲 Sequelize 實例或每一個局部事務初始化時,isolationLevel
能夠全局設置:
// 全局 new Sequelize('db', 'user', 'pw', { isolationLevel: Sequelize.Transaction.ISOLATION_LEVELS.SERIALIZABLE }); // 局部 sequelize.transaction({ isolationLevel: Sequelize.Transaction.ISOLATION_LEVELS.SERIALIZABLE });
deferrable
選項在事務開始後觸發一個額外的查詢,可選地將約束檢查設置爲延遲或當即。 請注意,這僅在PostgreSQL中受支持。
sequelize.transaction({ // 推遲全部約束: deferrable: Sequelize.Deferrable.SET_DEFERRED, // 推遲具體約束: deferrable: Sequelize.Deferrable.SET_DEFERRED(['some_constraint']), // 不推遲約束: deferrable: Sequelize.Deferrable.SET_IMMEDIATE })
transaction
選項與其餘大多數選項一塊兒使用,一般是方法的第一個參數。
對於取值的方法,如 .create
, .update()
, .updateAttributes()
等。應該傳遞給第二個參數的選項。
若是不肯定,請參閱API文檔中的用於肯定簽名的方法。
若是這篇文章對您有幫助, 感謝 下方點贊 或 Star GitHub: sequelize-docs-Zh-CN 支持, 謝謝.