您好,登錄后才能下訂單哦!
本篇文章給大家主要講的是關于MySQL和Redis事務的區別和用法的內容,感興趣的話就一起來看看這篇文章吧,相信看完MySQL和Redis事務的區別和用法對大家多少有點參考價值吧。
[1] Redis 事務可以一次執行多個命令, 并且帶有以下兩個重要的保證:
一個事務從開始到執行會經歷以下三個階段:
單個 Redis 命令的執行是原子性的,但 Redis 沒有在事務上增加任何維持原子性的機制,所以 Redis 事務的執行并不是原子性的。
事務可以理解為一個打包的批量執行腳本,但批量指令并非原子化的操作,中間某條指令的失敗不會導致前面已做指令的回滾,也不會造成后續的指令不做。
看著有點兒繞口,那就實際執行一下 看一下結果。
127.0.0.1:6379> multi OK 127.0.0.1:6379> set tr_1 233 QUEUED 127.0.0.1:6379> lpush tr_1 666 QUEUED 127.0.0.1:6379> set tr_2 888 QUEUED 127.0.0.1:6379> exec 1) OK 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value 3) OK
在上面的事務中,設置了一個 key 為 tr_1 的字符串數據,然后又通過 lpush 來添加元素,這很明顯是錯誤的操作方式,當我們提交事務候出現了一個操作錯誤,這時候我們來看看 tr_1 的值是什么。
127.0.0.1:6379> get tr_1 "233"
通過 get 命令來的tr_1 內容還是 233 ,并沒有變,那再看一下其他的。
127.0.0.1:6379> keys * 1) "tr_2" 2) "tr_1" 127.0.0.1:6379> get tr_2 "888" 127.0.0.1:6379>
這里可以看到 tr_2 存在,并打印了值,這時候我們發現,即使出現了操作錯誤 ,但是錯誤并沒有致使執行停止,錯誤之后的語句也執行了并成功執行,似乎符合上面提到的 中間某條指令的失敗不會導致前面已做指令的回滾,也不會造成后續的指令不做。
NO~,這時候還有另外一種情況 語法錯誤
127.0.0.1:6379> multi OK 127.0.0.1:6379> set tr_1 233 QUEUED 127.0.0.1:6379> lpush tr_1 666 QUEUED 127.0.0.1:6379> set (error) ERR wrong number of arguments for 'set' command 127.0.0.1:6379> set 233 (error) ERR wrong number of arguments for 'set' command 127.0.0.1:6379> set tr_2 888 QUEUED 127.0.0.1:6379> exec (error) EXECABORT Transaction discarded because of previous errors. 127.0.0.1:6379> keys * (empty list or set)
當我們執行到 set時沒有給任何參數,第二次執行時故意少給了一個參數。可以看到報了 語法錯誤,最后提交事務,也告訴了我們事務因為錯誤被丟失了,接著用 keys *檢索發現確實如此。
這里可以官方文檔中提到的
Errors inside a transaction
// 在執行過程中 可能會遇到兩種錯誤命令錯誤。
During a transaction it is possible to encounter two kind of command errors:
// 1.命令無法進入隊列 ,比如 :參數數量錯誤,命令名錯誤...,或者某些關鍵錯誤 如內存不足
- A command may fail to be queued, so there may be an error before EXEC is called. For instance the command may be syntactically wrong (wrong number of arguments, wrong command name, ...), or there may be some critical condition like an out of memory condition (if the server is configured to have a memory limit using the maxmemorydirective).
// 2. 對鍵進行錯誤的操作 如上面的 對字符串使用 lpush
- A command may fail after EXEC is called, for instance since we performed an operation against a key with the wrong value (like calling a list operation against a string value).
// 客戶端檢查鍵入的命令,大多數時候會在調用 exec 前發現第一類錯誤,如果命令執行返回來 QUEUED 則表示命令正常進入隊列,否則錯誤,大多數情況下客戶端會終止放棄這個事務。
Clients used to sense the first kind of errors, happening before the EXEC call, by checking the return value of the queued command: if the command replies with QUEUED it was queued correctly, otherwise Redis returns an error. If there is an error while queueing a command, most clients will abort the transaction discarding it.
關于 Redis 暫時看到這里 接下來看到 MySQL
眾所周知,MySQL 只有 InnoDB 引擎支持 事務,在啟用 MySQL 事務之前需要先停掉自動提交
列 | 類型 | 注釋 |
---|---|---|
id | int(11) 自動增量 | 主鍵ID |
money | int(11) [0] | 金錢 |
title | varchar(500) NULL | 稱呼 |
在這里來模擬一個轉賬的操作:A給B轉100元。
步驟解析 A+100 元,B -100元,即兩步雖然很簡單,簡單走一下流程。
可以看到,沒有問題,那么我們從中人為的制造一些問題呢?
列 | 類型 | 注釋 |
id | int(11) 自動增量 | |
money | int(11) unsigned [0] | |
title | varchar(500) NULL |
這里我們把 money 字段變成了無符號,即不能小于 0,并且,調整數據庫中的數據如下。
`SELECT * FROM `user` LIMIT 50` (0.000 秒)
修改 | id | money | title |
---|---|---|---|
編輯 | 1 | 10000 | A |
編輯 | 2 | 0 | B |
接著執行下面的 SQL
select version(); SET AUTOCOMMIT=0; begin; select * from user where title in ('A','B') for update; update user set money = money + 1000 where title = 'A'; update user set money = money - 1000 where title = 'B'; select * from user where title in ('A','B'); commit;
問題出現了,這里報出了錯誤,但是可以看到 前面的 SQL 已經是已執行的了,結果已經發生了變化,從這里看,似乎和 Redis 的處理差不多,除了錯誤之后語句繼續執行。但是 值的注意的是, 在我們實際開發中,這種情況程序會直接拋出異常,以供我們在 catch 塊中執行 rollback ,以回滾操作確保數據完整,即使是單獨使用 MySQL 命令行 我們也可以用存儲過程來對異常進行回滾。
剛剛看到 Redis 當遇到 語法錯誤 時會自動丟棄事務,阻止提交,那 MySQL 呢?
答案:不會,MySQL 在順序執行時,如果未對異常進行處理,總會將成功執行的的提交,而不會觸發自動終止,但是我們可以在程序執行時進行放棄提交。
Redis 的官方文檔給出了這樣的解釋
// 只有在使用錯誤的語法調用時才會失敗Redis命令(并且在命令排隊期間無法檢測到問題),或者對于持有錯誤數據類型的鍵,Redis命令可能會失敗:這意味著實際上失敗的命令是編程錯誤的結果,以及在開發過程中很可能檢測到的一種錯誤,而不是在生產中。
- Redis commands can fail only if called with a wrong syntax (and the problem is not detectable during the command queueing), or against keys holding the wrong data type: this means that in practical terms a failing command is the result of a programming errors, and a kind of error that is very likely to be detected during development, and not in production.
// Redis內部簡化且速度更快,因為它不需要回滾的能力。
- Redis is internally simplified and faster because it does not need the ability to roll back.
以上關于MySQL和Redis事務的區別和用法詳細內容,對大家有幫助嗎?如果想要了解更多相關,可以繼續關注我們的行業資訊板塊。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。