数据库事务
事务的边界
事务的开始边界(begin)
事务的结束边界(commit):提交事务,永久保存被事务更新后的数据库状态。
事务的异常结束边界(rollback):撤销事务,使数据库退回到执行事务前的初始状态。
每启动一个MySQL.exe程序,就会得到一个单独的数据库连接。每个数据库连接都有一个全局变量autocommit,表示当前的事务模式,它有两个值可选:
0:表示手工提交模式
1:表示自动提交模式,默认值
我们可以查看和修改这个值。
数据库事务的4个特性(ACID):
原子性(Atomicity):事务是一个原子操作单元,其对数据的修改,要么全部执行,要么全都不执行;
一致性(Consistent):在事务开始和完成时,数据都必须保持一致状态;
隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行;
持久性(Durable):事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。
事务隔离级别
数据库事务隔离级别,只是针对一个事务能不能读取其它事务的中间结果。
Read Uncommitted (读取未提交内容)
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读( Dirty Read )。Read Committed (读取提交内容)
这是大多数数据库系统的默认隔离级别(但不是 MySQL 默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读( Nonrepeatable Read ),因为同一事务的其他实例在该实例处理其间可能会有新的 commit ,所以同一 select 可能返回不同结果。Repeatable Read (可重读)
这是 MySQL 的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 ( Phantom Read )。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的 ” 幻影 ” 行。 InnoDB和 Falcon 存储引擎通过多版本并发控制( MVCC , Multiversion Concurrency Control )机制解决了该问题。Serializable (可串行化)
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。
对于多数应用程序,可以有效考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读,而且具有较好的并发性能。尽管它会导致不可重复读、虚度和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁和乐观锁来控制。
事务的传播性
PROPAGATION_REQUIRED
加入当前正要执行的事务,如果当前事务不存在,那么就起一个新的事务。Spring 操作数据库默认的事务传播行为就是 propagation_required 。PROPAGATION_SUPPORTS
如果当前在事务中,即以事务的形式运行,如果当前不再一个事务中,那么就以非事务的形式运行.PROPAGATION_MANDATORY
必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异常。PROPAGATION_REQUIRES_NEW
挂起当前事务,另起一个新的事务。PROPAGATION_NOT_SUPPORTED
当前不支持事务。如果在事务中,会挂起当前事务,自己以非事务的行为运行。
PROPAGATION_NEVER
不能在事务中运行,如果在事务中运行就会抛出异常。PROPAGATION_NESTED
嵌套的事务依赖父事务,父事务提交,它跟着提交,父事务回滚,它跟着回滚。
行级锁
Mysql中三种类型的锁:
行级:引擎 INNODB , 单独的一行记录加锁
页级:引擎 BDB,一次锁定相邻的一组记录。
表级:引擎 MyISAM , 理解为锁住整个表,可以同时读,写不行。
三种锁的特性可大致归纳如下:
1) 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
2) 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
3) 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
我们这里主要谈论的是行级锁,一般的在秒杀系统中我们会对商品库存使用行级锁,因为秒杀的时候库存是一个很重要的数据,我们在创建数据库的表时可能会出现下面这样的设置:
ENGINE = InnoDB AUTO_INCREMENT=10 DEFAULT CHARACTER SET = utf8 comment='用户表
将引擎设置为InnoDB,InnnoDB与其他引擎的不同:一是支持事务(TRANCSACTION),二是采用了行级锁。
InnoDB中两种