目录
数据库事务
关系数据库中一系列操作的集合 该集合中的操作要么全部执行 要么全部不执行
事务的四大特性
- 原子性:指事务是一个不可分割的单元,事务中的操作要么全部执行要么全部不执行
- 一致性:事务执行前后数据的完整性必须保持一致,这里的完整性包括实体完整性,参照完整性,用户定义的完整性
- 隔离性:多个用户并发访问数据库时,数据库为每一个用户开启了一个事务,对各事务并发执行时,相互之间是隔离开的,互不影响
- 持久性:事务一旦被提交,对数据库中的数据的改变是永久性的
事务的隔离级别
- 读未提交:事务A更新了数据但是还没有提交,事务B就读取到了事务A更新的数据,事务A回滚后,事务B就看不到更新的数据了。这种现象就是读未提交,即"脏读"
- 读已提交:事务A更新了数据并且已经提交,事务B内部就可以读取到A更新的数据。例如:开始时,事务A、B读取的库存量都是100。事务A更新库存为80,并进行了提交。由于事务B处理比较耗时,还没有执行结束,B再次读取库存时,已经变成了80。最后B在更新库存时就要在80的基础上进行更新
- 重复读:事务A更新数据并完成提交;在事务B提交之前,其内部无法读取到A更新的数据,只能读取到之前的旧数据。(普通查询,即快照读) 容易出现”幻读“: 对于innodb存储引擎,可重复读的隔离级别,使用当前读(加共享锁)时容易出现幻读,即一个事务进行两次相同条件的查询时,后一次查询看到了上一次没有看到的行。
- 串行化:所有事务串行执行,一个执行完成,在执行另一个
锁概念
悲观锁:在查询语句加锁,保证多事务==写入时==串行执行。 例如:在多个用户同时间进行订单提交时,哪个事务先执行到该语句则获取锁,等事务结束后才会释放,其他事务阻塞等待获取锁,保证了同一时刻只有一个事务再写入
乐观锁:查询时不加锁,再变更对比原数据与当前重新查询的数据是否一致,如果不一致则本次变更失败(乐观的认为当前没有其他事务在同时进行此过程), 一般采用三次循环重复此过程,由于mysql数据库事物的隔离级别默认为重复度,在事务结束之前,查询到的原数据不会更新,因此需要修改数据库事务的隔离级别为read committed(在Django2.0中已经自动将所有数据库的事务隔离级别修改为read committed),此时乐观锁可执行。
使用场景
在冲突较少时,如订单并发量较少,使用乐观锁(省去加锁、释放锁的开销,提高性能),在冲突较多时,如订单并发量大,使用悲观锁。一般将整个事务的过程都放置于try中。