MySQL系列文章总目录:关系型/非关系型【数据库】知识脉络
目录
为什么 MySQL要有事务?
一个数据库,一个表,十个人来查看,十个人来写数据,再来十个人删除数据。这一番操作下来,会有哪些可能性?
会有哪些可能性?
假如黄蓉郭靖分隔两地,又没有电话沟通(书信需要传一个月),恰巧又使用了没事物的银行数据库。
0. 两人都到银行先看了一眼存款:500银子!
- 黄蓉再存500银子,心想有1000银子,郭靖在天涯那边正取200银子,黄蓉存完一看,怎么才800银子? ——脏写/更新丢失
- 郭靖取完银子心想还剩300银子黄蓉不会打我吧?一看余额1000银子?——幻读
- 郭靖揉了揉眼睛,平复了一下心情再次查看余额800银子?——不可重复读!那1000哪去了
- 郭靖给自己两耳光,再次查看余额800银子。——脏读!这钱还越取越多了?
这些问题的本质都是数据库的多事务并发问题,为了解决多事务并发问题,数据库设计了事务隔离机制、锁机制、MVCC多版本并发控制隔离机制,用一整套机制来解决多事务并发问题。
MySQL事务解决哪些问题?
为避免上述情况发生,我们期待什么效果(mysql默认可重复级别读效果展示)?
0. 两人都到银行先看了一眼存款:500银子!
- 黄蓉再存500银子,心想有1000银子,郭靖在天涯那边正取200银子,取不出来,系统一直转圈圈。黄蓉存完一看余额1000银子,心满意足离开!
- —— 原子性(保证黄蓉的操作是一个不被打扰的整体)
- —— 一致性(操作前操作后数据符合更改规则)
- 郭靖一直操作不了,急的也跟着转圈圈,终于不转圈圈了,从查看余额开始了,变成了800,郭靖心想应该是黄蓉存下了。
- ——隔离性(被隔离在黄蓉事务之外)
- ——持久性,也包含了MVCC机制
数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大,因为事务隔离实质上就是使事务在一定程度上“串行化”进行,这显然与“并发”是矛盾的。
MySQL事务隔离级别
先看看你的数据库是什么事务隔离级别?
命令
show variables like 'tx_isolation';
结果
总共有多少种事务隔离级别呢?
级别 | 脏读 | 不可重复读 | 幻读 | 设置命令 |
---|---|---|---|---|
read uncommitted | 有 | 有 | 有 | set session transaction isolation level read uncommitted/set tx_isolation='read-uncommitted' |
read committed | 无 | 有 | 有 | set session transaction isolation level read committed/set tx_isolation='read-committed' |
repeatable read (mysql 默认的事务级别) | 无 | 无 | 有 | set session transaction isolation level repeatable read / set tx_isolation='repeatable-read' |
serializable | 无 | 无 | 无 | set ssion transaction isolation leval serializable /set tx_isolation='serializable' |
注:设置之后,rollback 就会滚刚才的操作,commit就可以提交刚才的操作。
设置完mysql事务隔离级别,就不会变了吗?
Mysql默认的事务隔离级别是可重复读,用Spring开发程序时,如果不设置隔离级别默认用Mysql设置的隔离级别,如果Spring设置了就用已经设置的隔离级别
事务的特性
无论是mysql事务还是spring事务都是有相同的特性,为事务特性:
- 原子性(Atomicity):事务不可分割。一系列操作为一体。
- 一致性(Consistency):每个操作的结果都是一样的,要么全成功,要么全失败。
- 隔离性(Isolation):一些列操作过程中不被其他操作干扰。
- 持久性(Durability):操作的结果是持久有效的。
Spring支持事务的种类
spring框架是个脚手架,也就是帮助我们编程的工具框架,自然也提供方便的实现事务的方法,spring的事务约等于是帮助我们实现数据库事务,它主要有两种使用方式。
编程式事务管理
顾名思义,要编程,侵入性事务管理,使用TransactionTemplate或者直接使用PlatformTransactionManager,Spring推荐使用TransactionTemplate。
每次实现个事务都要自己手动写代码实现。
声明式事务管理
顾名思义,声明一下哪里要实现事务,spring中所谓的声明,无非就是注解,事务的注解底层由AOP来实现。只需要关心业务实现逻辑,某个方法/类需要用到事务就加上@Transactional,再做些相应配置即可。
看着哪都比编程式事务好,唯独粒度上最小只能到方法级别,而编程式事务可以细化到代码块。
Spring实现的事务的重点有哪些呢?
既然spring是工具,那如何使用工具,工具都有哪些功能?如何用好工具,就是关心的问题了。
传播机制
使用场景/业务需求:A方法调用B方法调用..,AB..方法各自都有事务这种嵌套调用。
如何使用?当然是配置。
- @Transactional(PROPAGATION = REQUIRED) 默认
- 如果外层有事务,则当前事务加入到外层事务,一块提交,一块回滚。
- 如果外层没有事务,新建一个事务执行。
- @Transactional(PROPAGATION = REQUES_NEW)
- 每次都会新开启一个事务,外层事务挂起。(对mysql来讲新建一个连接并开启事务)
- 当前事务执行完毕,恢复上层事务的执行。
- @Transactional(PROPAGATION = SUPPORT)
- 如果外层有事务,则加入外层事务。
- 如果外层没有事务,则直接使用非事务方式执行。
- @Transactional(PROPAGATION = NOT_SUPPORT)
- 不支持事务。
- 如果外层存在事务则挂起,执行完当前代码,恢复外层事务。
- 无论是否异常都不会回滚当前的代码。
- @Transactional(PROPAGATION = NEVER)
- 不支持外层事务,即如果外层有事务就抛出异常。
- @Transactional(PROPAGATION = MANDATORY)
- 如果外层没有事务,则抛出异常。
- @Transactional(PROPAGATION = NESTED)
- 保存状态保存点,当前事务回滚到某一个点,避免所有的嵌套事务都回滚。
- 即各自回滚各自的,如果子事务没有把异常吃掉,引起全部回滚的。