Spring事务和MySQL事务详解⾯试
⽂章⽬录
数据库事务
事务是什么
是数据库操作的最⼩⼯作单元,是作为单个逻辑⼯作单元执⾏的⼀系列操作;这些操作作为⼀个整体⼀起向系统提交,要么都执⾏、要么都不执⾏;事务是⼀组不可再分割的操作集合。
事务的四⼤特性
1. 原⼦性
事务是数据库的逻辑⼯作单位,事务中包含的各操作要么都做,要么都不做
2. ⼀致性
事务执⾏的结果必须是使数据库从⼀个⼀致性状态变到另⼀个⼀致性状态。
3. 隔离性
⼀个事务的执⾏不能被其它事务⼲扰。即⼀个事务内部的操作及使⽤的数据对其它并发事务是隔离的,并发执⾏的各个事务之间不能互相⼲扰。
4. 持续性
也称永久性,指⼀个事务⼀旦提交,它对数据库中的数据的改变就是永久性的。接下来的其它操作或故障不应该对其执⾏结果有任何影响。
MySQL事务隔离级别
隔离级别隔离级别的值导致的问题
Read-Uncommitted0导致脏读
Read-Committed1避免脏读,允许不可重复读和幻读
Repeatable-Read2MySQL默认的隔离级别。避免脏读,不可重复读,允许幻读Serializable3串⾏化读,事务只能⼀个⼀个执⾏,避免了 脏读、不可重复读、幻读。执⾏效率慢,使⽤时慎重
1. 脏读
⼀个事务对数据进⾏了增删改查,但是未提交事务。另⼀个事物可以读取到未提交的数据,如果第⼀个事务进⾏了回滚,那么第⼆个事务就读到了脏数据。
例⼦:
领导给张三发⼯资,10000元已打到张三账户,但该事务还未提交,正好这时候张三去查询⼯资,发现10000元已到账。这时领导发现张三⼯资算多了5000元,于是回滚了事务,修改了⾦额后将事务提交。最后张三实际到账的只有5000元。
2. 不可重复度
⼀次事务发⽣了两次读操作,两个读操作之间发⽣了另⼀个事务对数据修改操作,这时候第⼀次和第⼆次读到的数据不⼀致。
不可重复度关注点在数据更新和删除,通过⾏级锁可以实现可重复读的隔离级别。
例⼦:
张三需要转正1000元,系统读到卡余额有2000元,此时张三⽼婆正好需要转正2000元,并且在张三提交事务前把2000元转⾛了,当张三提交转账是系统提⽰余额不⾜。
3. 幻读
幻读,指的是当某个事务在读取某个范围内的记录时,另外⼀个事务⼜在该范围内插⼊了新的记录,当之前的事务再次读取该范围的记录时,会产⽣幻⾏。
相对于不可重复读,幻读更关注其它事务的新增数据。通过⾏级锁可以避免不可重复读,但⽆法解决幻读的问题,想要解决幻读,只能通过Serializable隔离级别来实现。
例⼦:
张三⽼婆准备打印张三这个⽉的信⽤卡消费记录,经查询发现消费了两次共1000元,⽽这时张三刚按摩完准备结账,消费了1000元,这时银⾏记录新增了⼀条1000元的消费记录。当张三⽼婆将消费记录打印出来时,发现总额变为了2000元,这让张三⽼婆很诧异。
4. 串⾏化读
Serializable是最⾼的隔离级别,性能很低,⼀般很少⽤。在这级别下,事务是串⾏顺序执⾏的,不仅避免了脏读、不可重复读,还避免了幻读。
查看MySQL当前事务隔离级别
MySQL InnoDB默认的事务隔离级别为REPEATABLE-READ
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
MySQL默认操作模式为⾃动提交模式
除⾮显⽰的开启⼀个事务,否则每个查询都被当成⼀个单独的事务⾃动执⾏。可以通脱设置autocommit的值改变默认的提交模式。
1. 查看当前提交模式
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
2. 关闭⾃动提交。0代表关闭,1代表开启。
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | OFF  |
+---------------+-------+
JDBC处理事务
Connection connection = null;
PreparedStatement pstmt = null;
ResultSet resultSet = null;
try{
Class.forName("sql.jdbc.Driver");
connection = Connection("jdbc:mysql://localhost:3306/dbname?characterEncoding=utf-8","username","password");
connection.setAutoCommit(false);
// others ......
connectionmit();
}catch(Exception e){
}finally{
connection.setAutoCommit(true);
// close connection
}
Spring事务
Spring事务本质是对数据库事务的⽀持,如果数据库不⽀持事务(例如MySQL的MyISAM引擎不⽀持事务),则Spring事务也不会⽣效。Spring的事务传播
事务传播⾏为是指⼀个事务⽅法A被另⼀个事务⽅法B调⽤时,这个事务A应该如何处理。事务A应该在事务B中运⾏还是另起⼀个事务,这个有事务A的传播⾏为决定。
事务传播属性定义TransactionDefinition
int PROPAGATION_REQUIRED =0;
int PROPAGATION_SUPPORTS =1;
int PROPAGATION_MANDATORY =2;
int PROPAGATION_REQUIRES_NEW =3;
int PROPAGATION_NOT_SUPPORTED =4;
int PROPAGATION_NEVER =5;
int PROPAGATION_NESTED =6;
常量名称常量解释
PROPAGATION_REQUIRED⽀持当前事务,如果当前没有事务,就新建⼀个事务。这是Spring 默认的事务的传播。
PROPAGATION_SUPPORTS⽀持当前事务,如果当前没有事务,就以⾮事务⽅式执⾏。
PROPAGATION_MANDATORY⽀持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW
新建事务,如果当前存在事务,把当前事务挂起。新建的事务将和被挂起的事务没有任何关系,是两个独⽴的事务,外层事务失败回滚之后, 不能回滚内层事务执⾏的结果,内层事务失败抛出异常,外层事务捕获, 也可以不处理回滚操作。 使⽤JtaTransactionManager作为事务管理器
PROPAGATION_NOT_SUPPORTED以⾮事务⽅式执⾏操作,如果当前存在事务,就把当前事务挂起。使⽤JtaTransactionManager作为事务管理器PROPAGATION_NEVER以⾮事务⽅式执⾏,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED 如果⼀个活动的事务存在,则运⾏在⼀个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执⾏。它使⽤了⼀个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对
DataSourceTransactionManager事务管理器起效。
PROPAGATION_REQUIRED
如下例⼦,单独调⽤methodB时,当前上下⽂没有事务,所以会开启⼀个新的事务。
调⽤methodA⽅法时,因为当前上下⽂不存在事务,所以会开启⼀个新的事务。当执⾏到methodB时,methodB发现当前上下⽂有事务,因此就加⼊到当前事务A中来。
@Transactional(propagation = Propagation.REQUIRED)
public void methodA(){
methodB();
// do something
mysql下载失败怎么办}
@Transactional(propagation = Propagation.REQUIRED)
public void methodB(){
// do something
}
PROPAGATION_SUPPORTS
单独的调⽤methodB时,methodB⽅法是⾮事务的执⾏的。当调⽤methdA时,methodB则加⼊了methodA的事务中,事务地执⾏。@Transactional(propagation = Propagation.REQUIRED)
public void methodA(){
methodB();
// do something
}
// 事务属性为SUPPORTS
@Transactional(propagation = Propagation.SUPPORTS)
public void methodB(){
// do something
}
PROPAGATION_MANDATORY

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。