Spring強(qiáng)大事務(wù)兼容數(shù)據(jù)庫(kù)多種組合解決業(yè)務(wù)需求
事物的由來(lái)
在mysql中只有innodb存儲(chǔ)引擎才支持事物,所以我們后續(xù)都是基于innodb來(lái)展開(kāi)的
事物特性
事物是用來(lái)保證數(shù)據(jù)的完整性的,保證批量sql執(zhí)行的統(tǒng)一性;事物具有四個(gè)特性: A(Atomicity)、C(Consistency)、I(Isolation)、D(Durability)
原子性
一個(gè)事務(wù)(transaction)中的所有操作,要么全部完成,要么全部不完成,不會(huì)結(jié)束在中間某個(gè)環(huán)節(jié)。事務(wù)在執(zhí)行過(guò)程中發(fā)生錯(cuò)誤,會(huì)被回滾(Rollback)到事務(wù)開(kāi)始前的狀態(tài),就像這個(gè)事務(wù)從來(lái)沒(méi)有執(zhí)行過(guò)一樣。
一致性
在事務(wù)開(kāi)始之前和事務(wù)結(jié)束以后,數(shù)據(jù)庫(kù)的完整性沒(méi)有被破壞。這表示寫入的資料必須完全符合所有的預(yù)設(shè)規(guī)則,這包含資料的精確度、串聯(lián)性以及后續(xù)數(shù)據(jù)庫(kù)可以自發(fā)性地完成預(yù)定的工作。
隔離性
數(shù)據(jù)庫(kù)允許多個(gè)并發(fā)事務(wù)同時(shí)對(duì)其數(shù)據(jù)進(jìn)行讀寫和修改的能力,隔離性可以防止多個(gè)事務(wù)并發(fā)執(zhí)行時(shí)由于交叉執(zhí)行而導(dǎo)致數(shù)據(jù)的不一致。
持久性
事務(wù)處理結(jié)束后,對(duì)數(shù)據(jù)的修改就是永久的,即便系統(tǒng)故障也不會(huì)丟失。
基于四個(gè)特性,我們就需要在數(shù)據(jù)和性能進(jìn)行權(quán)衡,需要比較下場(chǎng)景。在m y s q l中就存在四種隔離級(jí)別。事務(wù)隔離分為不同級(jí)別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重復(fù)讀(repeatable read)和串行化(Serializable)。
隔離級(jí)別 | 臟讀(Dirty Read) | 不可重復(fù)讀(NonRepeatable Read) | 幻讀(Phantom Read) |
---|---|---|---|
未提交讀(Read uncommitted) | 可能 | 可能 | 可能 |
已提交讀(Read committed) | 不可能 | 可能 | 可能 |
可重復(fù)讀(Repeatable read) | 不可能 | 不可能 | 可能 |
可串行化(Serializable ) | 不可能 | 不可能 | 不可能 |
- 之前我一直錯(cuò)誤的認(rèn)為mysql中默認(rèn)的是讀已提交。后來(lái)查閱資料才知道默認(rèn)的是可重復(fù)讀隔離級(jí)別。
什么事臟讀、不可重復(fù)讀、幻讀
上面提到了三種異常數(shù)據(jù)情況,作為一名合格的程序員我們需要知道不同的隔離級(jí)別會(huì)給我們?cè)斐删唧w什么樣的傷害。
臟讀
臟讀指的是A事物在操作數(shù)據(jù),還未進(jìn)行提交此時(shí)B事物就已經(jīng)感知到數(shù)據(jù)的變化了。這是我們最不能接受的。這里以個(gè)人舉例,大學(xué)期間看中一款手機(jī)但是囊中羞澀需要爸媽支援下,打電話讓爸媽賺錢這里我們理解成A事物,我著急用錢我是B事物,此時(shí)A事物向zxh這張表新增了money=5000元的一條數(shù)據(jù)。B事物在修改zxh這張表中money這個(gè)字段。如果我們是讀未提交隔離級(jí)別。那么A事物剛新增完事物還未提交,B事物卻已經(jīng)可以修改了。那么B事物修改成功后就結(jié)束了。這個(gè)時(shí)候如果A事物因?yàn)閯e的原因出現(xiàn)異常了。那么就需要將add的5000進(jìn)行回滾,回滾后余額出現(xiàn)負(fù)數(shù)。這個(gè)負(fù)數(shù)對(duì)于銀行來(lái)說(shuō)就是壞賬。
#### 不可重復(fù)讀
- 顧名思義就是同一條數(shù)據(jù)多次讀取并不能保證數(shù)據(jù)一致性。這是因?yàn)锳事物第一次讀完數(shù)據(jù)后B事物修改了相同的數(shù)據(jù)行。那么A事物在此讀取該數(shù)據(jù)就會(huì)發(fā)生不可重復(fù)讀。
#### 幻讀
- 不可重復(fù)讀是針對(duì)同一條數(shù)據(jù)內(nèi)容的變化。而幻讀針對(duì)的是表記錄的變化。還是A事物第一次查詢數(shù)據(jù)匹配到10條,第二次相同條件匹配到的是20條。這就是幻讀。
復(fù)制代碼
查詢
s q l | 功能 |
---|---|
select @@tx_isolation; | 查詢數(shù)據(jù)庫(kù)默認(rèn)隔離級(jí)別 |
select @@global.tx_isolation; | 查看系統(tǒng)當(dāng)前隔離級(jí)別 |
set session transaction isolation level repeatable read; | 設(shè)置當(dāng)前會(huì)話隔離級(jí)別 |
set global transaction isolation level repeatable read; | 設(shè)置系統(tǒng)當(dāng)前隔離級(jí)別 |
- mysql 四種隔離級(jí)別對(duì)應(yīng)關(guān)系 ; 設(shè)置時(shí)候去掉破折號(hào)就行了
REPEATABLE-READ
READ-COMMITTED
READ-UNCOMMITTED
SERIALIZABLE
- 我們也可以通過(guò)show來(lái)查看相關(guān)配置
show variables like '%iso%';
spring事物
@Override public Map<String, Object> startTransaction(Transmodel transmodel) { int insert = transMapper.insert(transmodel); log.info("操作日志:" + insert); if ("zxhtom".equals(transmodel.getName())) { throw new RuntimeException("error"); } return new HashMap<>(); } 復(fù)制代碼
- 上面代碼邏輯非常的簡(jiǎn)單,當(dāng)我們傳送如下參數(shù)時(shí)就會(huì)報(bào)錯(cuò)
{ "name": "zxhtom", "code": "56", "age": 34 } 復(fù)制代碼
- 但是呢?我們?cè)偃?shù)據(jù)庫(kù)查看,發(fā)現(xiàn)該數(shù)據(jù)進(jìn)入數(shù)據(jù)庫(kù)了。
- 發(fā)生這種場(chǎng)景時(shí)不行的,在互聯(lián)網(wǎng)中我們要求部分接口必須具有原子性,中途報(bào)錯(cuò)之前所有的操作就必須回滾。如果我們自己使用jdbc那么直接通過(guò)連接對(duì)象rollback就行了。
- 在spring中因?yàn)檫B接session對(duì)接管了,我們就不必那么麻煩了,直接通過(guò)@Transactional標(biāo)注我們的方法就可以實(shí)現(xiàn)事物了。
@Transactional public Map<String, Object> startTransaction(Transmodel transmodel) { int insert = transMapper.insert(transmodel); log.info("操作日志:" + insert); if ("zxhtom".equals(transmodel.getName())) { throw new RuntimeException("error"); } return new HashMap<>(); } 復(fù)制代碼
- 在此執(zhí)行就會(huì)發(fā)現(xiàn),數(shù)據(jù)并沒(méi)有新增,這就是我們想要的效果
spring事物有哪些可配項(xiàng)
- 里面有幾個(gè)屬性我們需要關(guān)注下。已經(jīng)圈出來(lái)了。
字段 | 作用 |
---|---|
value | 事物管理器;用于提交和回滾的功能;默認(rèn)的DataSourceTransactionManager內(nèi)部時(shí)datasource來(lái)操作提交回滾的 |
transactionManager | 事物管理器;用于提交和回滾的功能;默認(rèn)的DataSourceTransactionManager內(nèi)部時(shí)datasource來(lái)操作提交回滾的 |
propagation | 傳播屬性;spring中方法內(nèi)方法事物傳遞屬性設(shè)置 |
isolation | 隔離級(jí)別,在數(shù)據(jù)庫(kù)基礎(chǔ)上新增一個(gè)默認(rèn)以數(shù)據(jù)庫(kù)隔離級(jí)別為準(zhǔn) |
timeout | 超時(shí)事物不提交 |
readOnly | 這個(gè)感覺(jué)沒(méi)啥意義,被標(biāo)注的方法無(wú)法執(zhí)行更新操作,只能select |
rollbackFor | 導(dǎo)致事務(wù)回滾的異常類數(shù)組 |
rollbackForClassName | 導(dǎo)致事務(wù)回滾的異常類名字?jǐn)?shù)組 |
noRollbackFor | 不會(huì)導(dǎo)致事務(wù)回滾的異常類數(shù)組 |
noRollbackForClassName | 不會(huì)導(dǎo)致事務(wù)回滾的異常類名字?jǐn)?shù)組 |
傳播屬性
- 傳播屬性spring為我們建立了枚舉
public enum Propagation { REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED), SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS), MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY), REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW), NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED), NEVER(TransactionDefinition.PROPAGATION_NEVER), NESTED(TransactionDefinition.PROPAGATION_NESTED); private final int value; Propagation(int value) { this.value = value; } public int value() { return this.value; } }
以上就是Spring強(qiáng)大事務(wù)兼容數(shù)據(jù)庫(kù)多種組合解決業(yè)務(wù)需求的詳細(xì)內(nèi)容,更多關(guān)于Spring事務(wù)解決業(yè)務(wù)需求的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Spring事務(wù)框架之TransactionStatus源碼解析
- Spring事務(wù)控制策略及@Transactional失效問(wèn)題解決避坑
- Spring?AOP實(shí)現(xiàn)聲明式事務(wù)機(jī)制源碼解析
- Spring事務(wù)@Transactional注解四種不生效案例場(chǎng)景分析
- Spring學(xué)習(xí)JdbcTemplate數(shù)據(jù)庫(kù)事務(wù)參數(shù)
- Spring框架JdbcTemplate數(shù)據(jù)庫(kù)事務(wù)管理完全注解方式
- Spring事務(wù)框架之TransactionDefinition源碼解析
相關(guān)文章
詳解springboot采用多數(shù)據(jù)源對(duì)JdbcTemplate配置的方法
在本篇文章中我們給大家詳細(xì)分享了springboot采用多數(shù)據(jù)源對(duì)JdbcTemplate配置的方法,有需要的朋友們可以學(xué)習(xí)參考下。2018-10-10解決Java中的java.io.IOException: Broken pipe問(wèn)題
這篇文章主要介紹了解決Java中 java.io.IOException: Broken pipe的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06Mybatis日志配置方式(slf4j、log4j、log4j2)
這篇文章主要介紹了Mybatis日志配置方式(slf4j、log4j、log4j2),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09JAVA maven項(xiàng)目使用釘釘SDK獲取token、用戶
這篇文章主要介紹了JAVA maven項(xiàng)目使用釘釘SDK獲取token、用戶,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06Spring?Boot?MQTT?Too?many?publishes?in?progress錯(cuò)誤的解決方
本文介紹Spring?Boot?MQTT?Too?many?publishes?in?progress錯(cuò)誤的解決方案,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下2022-07-07SpringMVC自定義攔截器實(shí)現(xiàn)過(guò)程詳解
這篇文章主要介紹了SpringMVC自定義攔截器實(shí)現(xiàn)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05