Redis之坑:Redis與MySQL中事務的區別

Note:java

  1. 該篇討論的只是Redis與MySQL中事務的區別,並不能統一表明NO-SQL與關係型SQL;
  2. 在 MySQL 中只有使用了 Innodb 數據庫引擎的數據庫或表才支持事務;

事務命令

MySQL:redis

  • BEGIN:顯式地開啓一個事務;
  • COMMIT:提交事務,將對數據庫進行的全部修改變成爲永久性的;
  • ROLLBACK:結束用戶的事務,並撤銷正在進行的全部未提交的修改;

Redis:spring

  • MULTI:標記事務的開始;
  • EXEC:執行事務的commands隊列;
  • DISCARD:結束事務,並清除commands隊列;

Redis之坑:理解Redis事務 中咱們經過類比MySQL的BEGAIN,COMMIT,ROLLBACK來理解Redis的事務命令。可是顯然,它們有着本質區別。數據庫


默認狀態

MySQL:bash

  • MySQL會默認開啓一個事務,且缺省設置是自動提交,即,每成功執行一個SQL,一個事務就會立刻 COMMIT。因此不能Rollback。

Redis:app


使用方式

MySQL: 包含兩種spa

  1. 用 BEGIN, ROLLBACK, COMMIT,顯式開啓並控制一個 新的 Transaction。
  2. 執行命令SET AUTOCOMMIT=0,用來禁止當前會話自動commit,控制默認開啓的事務

Redis:.net

  1. 用 MULTI, EXEC, DISCARD,顯式開啓並控制一個Transaction(注意:這裏沒有強調 「新的」 ,由於默認是不會開啓事務的)。

實現原理

很容易理解,Redis與MySQL中事務的區別其根本緣由就是實現不一樣方式形成的。日誌

MySQL:code

  • MySQL實現事務,是基於UNDO/REDO日誌
  • UNDO日誌記錄修改前狀態,ROLLBACK基於UNDO日誌實現;
  • REDO日誌記錄修改後的狀態 ,COMMIT基於REDO日誌實現;
  • 在MySQL中不管是否開啓事務,SQL都會被當即執行並返回執行結果。只是**事務開啓**後執行後的狀態只是記錄在REDO日誌,執行COMMIT以後,數據纔會被寫入磁盤
int insertSelective = serviceOrderMapper.insertSelective(s);
複製代碼

因此,上述代碼,insertSelective 將會被當即賦值(不管是否開啓事務,只是結果或未被寫入磁盤):

insertSelective = 受影響的行數;
複製代碼

Redis:

  • Redis實現事務,是基於COMMANDS隊列
  • 若是沒有開啓事務,command將會被當即執行並返回執行結果,而且直接寫入磁盤;
  • 若是事務開啓,command不會被當即執行,而是排入隊列並返回排隊狀態(具體依賴於客戶端(例如:spring-data-redis)自身實現)。調用EXCE纔會執行COMMANDS隊列
boolean a = redisTemplate.opsForZSet().add("generalService",orderId,System.currentTimeMillis());
複製代碼

上述代碼,

  • 若是沒有開啓事務,操做被當即執行,a 將會被當即賦值(true|false);
  • 若是開啓事務,操做未被當即之行,將會返回NULL值,而a的類型是boolean,因此將會拋出異常: java.lang.NullPointerException
相關文章
相關標籤/搜索