数据库事务
结合基本例子(银行转账)来分析:
AB账户都有500元存款,A账户向B账户转账100元钱 ,操作分为6步
- 取出A账户余额为500元
- 把500元转出100,还剩400元
- 将400元存入A的账户中
- 取出B的余额为500元
- 将B的500元加上100元,总共600元
- 将600元存入B的账户中
事务有四大特性(ACID):
- 原子性(Atomicity):所有的操作要么都成功,要么都失败回滚,恢复之前状态。如上6步操作,任何一步操作失败,AB账户不受任何影响。
- 一致性(Consistency): 事务必须使数据库从一个状态整体变到另一个状态,就是执行前后,必须保持状态一致。相当于转账前AB加起来一共1000元,不管中间进行几次转账,最终两人加起来还得是1000元。
- 隔离性(Isolation):多事务并发执行,相互之间不存在影响。事务没有提交之前,其他事务读取的数据还是修改之前的数值。相当于AC都向B转账,A和C向B转账的过程中,其他事务读取B的余额还是500元,直到AC两个事务提交成功,B的账户应该就是700元。
- 持久性(Druability):一旦事务被提交,对数据库的改变就是永久的。一旦转账事务提交成功,数据库数据将永久被改变。
数据库隔离级别
-
未提交读:
事务进行的修改,即使没有提交,对于其他事务也是可见的 -
提交读:
大部分数据库用这个(mysql不是),事务在开始到提交前,进行的修改对其他事务都是不可见的,因为会出现不可重复读,两次读到的数据不一致 -
可重复读:
mysql数据库默认使用的这种,保证了一个事务中多次读取同样的数据保持结果一致。但是不能避免幻读现象(事务读取某范围内记录,另外事务插入一行,再次读取,就会产生幻行) -
可串行化:
最高的隔离级别,强制事务串行执行,避免幻读问题,会在读取的每一行数据上加锁,可能会导致大量超时和锁争用。
InnoDB存储引擎
InnoDB的MVCC(多版本并发控制),通过在每行记录后面增加两个隐藏列,保存行创建时系统版本号和删除时的版本号。
优点:大部分读操作不用加锁,保证只能读到符合标准的行
缺点:每行记录需要增加额外的存储空间
默认使用的隔离级别是REPEATABLE READ(可重复读),并且采用间隙锁策略防止幻读。(删除一个不存在的记录,就会扫描索引,找到第一个比给定参数小的值,找到第一个比给定参数大的值,这样形成一个区间,锁住这个区间,就是间隙锁,这样容易出现死锁)
MyISAM存储引擎
对整张表加锁,读数据时加共享锁,写数据时加排他锁,但是在表有读取数据的查询时,还是可以往表中插入数据(并发插入)