mysql事务
1.事务的ACID属性
事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作。事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。
原子性(atomic),事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行
一致性(consistent),事务在完成时,必须使所有的数据都保持一致状态。
隔离性(insulation),由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。
持久性(Duration),事务完成之后,它对于系统的影响是永久性的。
2.mysql更新丢失
- 第一类丢失更新(lost update): 两个事务同时读取相同的数据,并且基于读取的值进行更新操作。其中一个事务首先完成更新并提交,而另一个事务在之后更新并提交,覆盖了第一个事务的更新结果,导致第一个事务的更新丢失。
- 第二类丢失更新(second lost updates):两个事务同时读取相同的数据,并且基于读取的值进行更新操作。其中一个事务首先完成更新并提交,而另一个事务在之后更新并提交,覆盖了第一个事务的更新结果。然而,第一个事务后来又基于自己最初读取的值进行了更新,并提交了这个更新,覆盖了第二个事务的更新结果,导致第二个事务的更新丢失。
- 脏读(dirty read):如果第二个事务查询到第一个事务还未提交的更新数据,形成脏读。
- 幻读(phantom read):一个事务执行两次查询,第二次结果集包含第一次中没有或者某些行已被删除,造成两次结果不一致,只是另一个事务在这两次查询中间插入或者删除了数据造成的。
- 不可重复读(unrepeated read):一个事务两次读取同一行数据,结果得到不同状态结果,如中间正好另一个事务更新了该数据,两次结果相异,不可信任。
3.事务的四种隔离等级,按照安全性由高到低分别为
a. Serializable 串行化
b. Repeatable Read 可重复读
c. Read Commited 可读已提交
d. Read Uncommited 可读未提交
隔离级别 | 脏读 | 不可重复读 | 幻读 | 第一类丢失更新 | 第二类丢失更新 |
---|---|---|---|---|---|
READ UNCOMMITED | 允许 | 允许 | 允许 | 不允许 | 允许 |
READ COMMITTED | 不允许 | 允许 | 允许 | 不允许 | 允许 |
REPEATABLE READ | 不允许 | 不允许 | 允许 | 不允许 | 不允许 |
SERIALIZABLE | 不允许 | 不允许 | 不允许 | 不允许 | 不允许 |
4.悲观锁和乐观锁
a.悲观锁:大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。
b.乐观锁:为了避免悲观锁的性能问题,大多是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个"version"字段来实现。
5.innodb事务特性
a.innodb能检测到死锁,可能返回错误,也可能将持有最少行级排他锁的事务进行回滚
b.innodb存储引擎在修改表数据时,使用事务日志,用追加的方式保存修改记录,将随机IO方式改为了顺序IO方式,提高处理速度、
c.事务默认采用自动提交,如果不是显示开始一个事务,则每个查询都被当做一个事务执行提交操作
6.InnoDB的事务隔离等级以及如何解决幻读:
innodb引擎默认使用REPEATABLE READ(可重复读)隔离级别。该隔离级别还是会产生幻读问题。还
需要使用next-key locking(也就是row locking+gap locking)技术启动事务来避免幻读。
具体实现是:事务A针对非唯一索引查询时,会使用排它锁 锁住索引前后两个范围,其他事务无法在此范围内写入数据,这样事务A多次查询的记录数都是一样的