一、什么是事务?
是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合(工作逻辑单元);
二、事务的几种特性?
事务具有4个属性,通常称为ACID特性:
原子性(atomicity):事务是一个完整的操作。事务的各步操作是不可分的;要么都执行、要么都不执行。
一致性(consistency):当事务完成时,数据必须处于一致状态。
隔离性(isolation):对数据进行修改的所有并发事务是彼此隔离的,这表明事务必须是独立的,它不应以任何方式依赖于或影响其他事务。
持久性(durability):事务完成后,它对数据库的修改被永久保存,事务日志能保持事务的永久性。
三、事务并发会出现哪些问题?
更新丢失:两个事务同时更新一条数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失败。
脏读:一个事务读取了另外一个事务没有提交的数据;
例: 事务a读取了事务b已经修改但未提交的数据,但由于某种原因事务b回滚了,这时事务a读取到的就是脏读。
不可重复读:一个事务分别两次读取同一条数据,可两次读取到的数据不一样;
例: 事务a读取一条数据,事务b修改了这条数据,等事务a再次读取这条数据
四、事务的隔离级别?
1.read uncommitted(读未提交): 保证了读取过程中不会读取到非法数据
此隔离级别可以防止更新丢失,可以通过“排他写锁”实现。
2. read committed(读提交): 保证了一个事务不会读到另一个并行事务已修改但未提交的数据;
此隔离级别可以防止更新丢失、脏读,
可以通过“瞬间共享读锁”和“排他写锁”实现。
3.repeatable read(可重复读):保证了一个事务不会修改已经由另一个事务读取但为提交的数据;
此隔离级别可以防止更新丢失、脏读、不可重复读,
此隔离级别可以通过“共享读锁”和“排他写锁”实现。
4. Serializable(序列化):最严格的级别,事务串行执行,资源消耗最大;
此隔离级别可以防止更新丢失、脏读、不可重复读、幻读。
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大,对于多数应用程序,可以优先考虑把数据库系统的隔离级别设置为read committed。它能避免更新丢失、脏读,而且具有较好的并发性能。尽管它会导致不可重复读、幻读这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。
mysql默认的事务隔离级别是repeatable read
mysql 操作隔离级别命令
查询全局事务隔离级别: select global @@global.tx_isolation;
查询当前会话事务隔离级别: select session @@tx_isolation;
设置事务的隔离级别:set global tx_isolation='REPEATABLE-READ'; (可以设置为global或者session),如果没有显式指定,则事务隔离级别将按会话进行设置
五、锁机制
(1)读锁(Read Lock)
读锁(Read Lock)也称为共享锁(Shared Lock)。它是共享的,或者说是相互不阻塞的。多个客户端在同一时间可以同时读取同一资源,互不干扰。
sql语句后面加 lock in share mode
(2)写锁(Write Lock)
写锁(Write Lock)也称为排他锁(Exclusive Lock)。它是排他的,也就是说一个写锁会阻塞其他的写锁和读锁,这是为了确保在给定的时间里,只有一个用户能执行写入,并防止其他用户读取正在写入的同一资源,保证安全。
Sql语句后面加for update
行锁: 对某行记录加上锁
表锁: 对整个表加上锁
这样组合起来就有,行级共享锁,表级共享锁,行级排他锁,表级排他锁
六、spring中的事务传播机制
PROPAGATION_REQUIRED (propagation_required)
如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS(propagation_supports)
支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY(propagation_mandatory)
使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW(propagation_requires_new)
新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED(propagation_not_supported)
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER (propagation_never)
以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED(propagation_nested)
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。