目录
事务传播属性propagation
事务是指与database建立一次连接后, 直到提交前的这个过程, 同一个事务当中, 只要未提交到数据库, 都属于业务层面的操作, 不影响真实数据.
事物的传播行为(属性), 当一个含有事务的方法运行在另一个开启事务的方法中时, 此方法使用原来的事务还是开启新的事务
spring定义了7种事务传播属性propagation
required
默认事务
如果有事务运行, 就以自己的事务运行, 两个方法在同一个事务中, 如果第一个方法没有事务就用第二个方法的事务
方法A调用方法B 2次, 这个过程将使用方法A的事务, 直到a运行完才会提交事务, 方法b的两次执行在同一个事务当中, 当第二次调用b时出现异常, 将整个事务中的, 包含第一次b方法的操作全部回滚
@Transactional
method A(){
method B();
method B();
}
@Transactional
method B(){
dao.update(sth);
}
required _new
同样调用b两次, 但b使用了新的事务, 虽然仍在方法a当中, 方法a的事务仍然存在, 但是方法b运行时将会使用一个新的数据库连接(事务), 这样两次方法b运行会使用两个不同的连接, 每次方法b执行完都会提交自己的事务, 当第二次b执行时出错, 仅会回滚第二次b中的操作, 并不影响第一次b执行操作数据库的结果
@Transactional
method A(){
method B();
method B();
}
@Transactional(propagation="Propagation.REQUIRES_NEW")
method B(){
dao.update(sth);
}
supports
如果有事务在运行, 当前方法就在这个事务中运行, 如果没有就不用
not_support
方法运行时, 如果有事务, 就将事务挂起, 不使用事务
mandatory
方法运行前必须有事务, 如果不在事务中, 就抛异常
never
当前方法不在事务中,如果有事务, 就抛异常
nested
与required相同, 但nested方法中出现异常时, 只会回滚nested方法内的操作,不影响外部, 但外部出现异常时, 将会把nested方法的操作一并回滚
事务隔离级别isolation
数据库事务并发
age的初始值为10
- 脏读
连接conn1 将age改为了20, conn2读到了age的值为20, conn1之后回滚将age的值改为10 - 不可重复读
连接1读到age的值为10, conn2操作将age改为20, conn1再次读取age的值为20, 对conn1来说, 同一个连接中两次读取的值不一样 - 幻读
conn1对user表进行了查询, 有3条数据, 此时conn2向表中插入了2条数据, conn1再次读取时, 发现有5条数据
隔离级别
隔离级别为了解决事务并发问题, 使不同事务间具有隔离性, 这是在sql标准中定义的
- 读未提交
不同事务间可以读到其他事务的操作结果, 可以解决不了任何事务并发问题 - 读已提交(常用)
只能读到其他事务提交的值, 可以解决脏读问题 - 可重复读
同一个事务中, 读取同一个字段的值是相同的, 加了行锁, 在读取期间禁止别的事务操作 - serializable 串行化
字面意思, 操作需要串行按照顺序处理, 加了表锁, 事务操作的时候, 其他事务不能对该表进行写操作, 因为表锁, 所以性能低, 可以避免所有并发问题
oracle支持的隔离级别是读已提交和串行化, 默认的事务隔离级别是读已提交
mysql4中全部支持, 默认的是可重复读
其他
隔离级别查询方式
SELECT @@tx_isolation
当隔离级别为读已提交时, 针对幻读和不可重复读可通过悲观锁乐观锁来控制
乐观锁通过设置版本字段, 假设每次事务都操作都保证原子性, 中间不会有人打断, 操作完成后对比版本号,
悲观锁假设每次操作均在不安全的环境下, 为自己的操作上锁, 提交后释放锁, 悲观锁需要关闭自动提交
- InnoDB 支持事务,MyISAM 不支持事务。这是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一;
- InnoDB 支持外键,而 MyISAM 不支持。对一个包含外键的 InnoDB 表转为 MYISAM 会失败;
- InnoDB 是聚集索引,MyISAM 是非聚集索引。聚簇索引的文件存放在主键索引的叶子节点上,因此 InnoDB 必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而
MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。- InnoDB不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;
- InnoDB 最小的锁粒度是行锁,MyISAM最小的锁粒度是表锁。一个更新语句会锁住整张表,导致其他查询和更新都会被阻塞,因此并发访问受限。这也是 MySQL 将默认存储引擎从MyISAM 变成 InnoDB 的重要原因之一;