將一系列的數據操做捆綁在一塊兒,成爲一個總體進行統一管理!mysql
一條或者多條sql語句的集合!spring
原子性(Atomicity):在事務中的操做,要麼都執行,要麼都不執行!sql
一致性(Consistency):事務必須保證數據從一個一致性的狀態到達另外一個一致性的狀態!數據庫
持久性(Durability):事務一旦提交,對數據庫的數據影響是永久性的!express
隔離性(Isolation):每一個事務以前互不干擾!apache
1.事務儘量簡短併發
由於啓動事務以後,數據庫管理系統須要保留大量資源來保證事務的ACID!oracle
若是是多用戶的系統,那麼會嚴重影響咱們的系統性能!性能
2.事務中訪問的數據量要小測試
在併發的狀況下,執行事務,事務的訪問量越小,各個線程以前對數據的
爭奪就越小!
3.查詢時儘可能不使用事務
由於查詢不會修改數據!
4.在事務處理過程當中,儘可能不要出現用戶等待的狀況
若是登臺事件過程,佔用資源過久,有可能形成系統阻塞!
1.Isolation:五種事務隔離級別
01.default:採用數據庫默認的事務隔離級別
mysql:repeatable-read(可重複讀取)
oracle:read-committed(讀提交)
02.repeatable-read(可重複讀取):解決了髒讀和不可重複讀,可是有可能發生幻讀(經過其餘的鎖機制解決)!
03.read-committed(讀提交):解決了髒讀,可是沒解決不可重複讀
04.read-uncommitted(讀未提交):什麼都沒有解決!
05.serializable(串行化):解決併發的問題!
2.Propagation:七種事務傳播行爲
01.required:是spring默認的事務傳播行爲!
指定的方法必須在事務內執行,
若是沒有事務,自動建立事務並執行!
02.supports:有沒有事務都執行!
有事務就在事務中執行,不然直接執行!
03.mandatory:若是當前存在事務,就執行該事務,
若是當前不存在事務,就拋出異常。
04.requires_new:老是建立新事務,
若是當前方法存在事務,則當前事務掛起,
直到新建立的事務執行完畢!
05.not_supported:不能在事務中執行,
若是當前方法存在事務,則當前事務掛起!
06.never: 不能在事務中執行,
若是當前方法存在事務,則拋出異常。
07.nested:若是當前存在事務,則在嵌套事務內執行。
若是當前沒有事務,則執行與requires_new相似的操做。
requires_new 啓動一個新的, 不依賴於環境的 "內部" 事務.
這個事務將被徹底 commited 或 rolled back 而不依賴於外部事務,
它擁有本身的隔離範圍, 本身的鎖, 等等. 當內部事務開始執行時,
外部事務將被掛起,內務事務結束時, 外部事務將繼續執行.
另外一方面, nested 開始一個 "嵌套的" 事務,
它是已經存在事務的一個真正的子事務. 潛套事務開始執行時,
它將取得一個 savepoint. 若是這個嵌套事務失敗,
咱們將回滾到此 savepoint. 潛套事務是外部事務的一部分,
只有外部事務結束後它纔會被提交.
因而可知, requires_new 和 nested 的最大區別在於,
requires_new 徹底是一個新的事務,
而 nested 則是外部事務的子事務,
若是外部事務 commit, 潛套事務也會被 commit,
這個規則一樣適用於 roll back.
DROP TABLE IF EXISTS `account`;
CREATE TABLE `account` (
`aid` int(10) NOT NULL AUTO_INCREMENT,
`balance` double DEFAULT NULL,
`aname` varchar(20) DEFAULT NULL,
PRIMARY KEY (`aid`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
insert into `account`(`aid`,`balance`,`aname`) values (1,10000,'張三');
DROP TABLE IF EXISTS `stock`;
CREATE TABLE `stock` (
`sid` int(10) NOT NULL AUTO_INCREMENT,
`sname` varchar(20) DEFAULT NULL,
`amount` int(10) DEFAULT NULL,
PRIMARY KEY (`sid`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
insert into `stock`(`sid`,`sname`,`amount`) values (1,'張三',0);
<!-- 01.引入 jdbc文件--> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 02.配置數據源--> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${jdbc.driverClass}"/> <property name="url" value="${jdbc.jdbcUrl}"/> <property name="username" value="${jdbc.userName}"/> <property name="password" value="${jdbc.password}"/> </bean> <!--03.配置dao層--> <bean id="accountDao" class="com.xdf.dao.impl.AccountDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="stockDao" class="com.xdf.dao.impl.StockDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> <!--04.配置service層--> <bean id="buyStockService" class="com.xdf.service.BuyStockServiceImpl"> <property name="accountDao" ref="accountDao"/> <property name="stockDao" ref="stockDao"/> </bean> <!--05.不管使用什麼方式 都必須建立事務管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--06. 使用AspectJ 實現spring對事務的管理--> <tx:advice id="myAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="buyStock" isolation="DEFAULT" propagation="REQUIRED" rollback-for="com.xdf.service.BuyStockException"/> </tx:attributes> </tx:advice> <!-- 07.配置切入點--> <aop:config> <aop:pointcut id="myPoint" expression="execution(* *..service.*.*(..))"/> <aop:advisor advice-ref="myAdvice" pointcut-ref="myPoint"/> </aop:config>
測試方法代碼
<!--06.使用事務工廠--> <bean id="proxyFactoryBean" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <!--配置事務管理器--> <property name="transactionManager" ref="transactionManager"/> <!--配置目標對象--> <property name="target" ref="buyStockService"/> <!--配置切點--> <property name="transactionAttributes"> <props> <!--指定切入點 01.事務隔離級別 02.事務傳播行爲 03.發生什麼異常時?是回滾仍是提交 - 回滾 +提交 --> <prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-BuyStockException</prop> </props> </property>
測試方法代碼
測試代碼和AspectJ同樣