事务:一个或一组SQL语句组成的一个执行单元,这个单元要么全执行,要么全不执行。是相互依赖的,其中某行语句发生失败或者错误,整个单元将会回滚。
事务ACID
原子性 Atomicity:不可分割,要么全部成功,全部失败
快照
mvcc 多版本并发过程
一致性 Consistency:事务的执行结果必须使数据库从一个一致性状态到另一个一致性状态。前后状态一致。
比如:转账前后 两个账户的总金额保持不变
数据库本身的约束 一致性读 一致性写
一致性是事务最终的根本追求,通过原子性,隔离性,持久性 保证一致性的实现
隔离性 Isolation:并发执行的事务不会相互影响 ,其对数据库的影响和它们串行执行时一样。
即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
共享锁 拍他所 独占锁 临键锁 间隙锁 自增锁 意向锁
读未提交 读已提交 可重复度 串行化
持久性Durability: 事务一旦提交,其对数据库的更新是持久的。任何事务或系统故障都不会导致数据丢失。数据持久化
wal日志 write ahead log 预写日志
事务的隔离性由锁机制实现,事务的原子性,持久性,一致性由事务的redo日志和undo日志来实现
原子性实现原理
日志 undo、redo 归属于innodb引擎 bin log 归属mysql sever
myisam 不支持事务,没有undo、 redo日志
undo log 事务回滚
逻辑日志 当delete一条记录时,undolog会记录一条insert 记录,当insert delete 当update 记录相反的update sql语句
逻辑日志 对当前sql记录,不改当前物理页的内容
物理日志
mvcc multipart version conccurry controll undolog 记录了当前数据之前的历史版本
MVCC
只在Read Committed
和Repeatable Read
下会开启。但是在这两种隔离级别下对于快照指定的数据定义不同。
在Read Committed
下,MVCC
读取的是被锁定数据的最新的一份数据。
在Repeatable Read
下,MVCC
读取的是事务刚开始时候的数据。
持久性实现原理
redo log 记录的是新数据的备份
在事务提交前,只要将redo log 持久化即可,不需要将数据持久化
user space 当前进程内存空间 innodeb engine> log buffer >redo log buffer undo log buffeg
kernel space 系统内存空间 os buffer
fsync -> 磁盘 redo log file ib_logfilen \undo log file 零拷贝
所以mysql是否持久化的关键要看redo log的持久化策略,mysql提供了三种redo log持久化策略
- 0:只写redo log,每秒落地一次,性能最高,数据一致性最差,如果mysql奔溃可能丢失一秒的数据
- 1:写redolog buffer同时落地,性能最差,一致性最高
- 2:写redo log buffer同时写入到os buffer,性能好,安全性也高,只要os不宕机就能保证数据一致性
数据更新流程:
先查询数据 再更新
获取数据
数据页是否在内存中 否从磁盘加载数据 是 返回数据
更改数据
写入新的数据
新数据更新到内存
写入redo,始于prepare 阶段
写binlog
提交事务,处于commit阶段
mysql 隔离级别 隔离级别越高,越安全,性能越低
读未提交 脏读 不可重复读 幻读
读已提交 orecal 默认隔离级别 不可重复读 幻读
rc读的最新的快照
可重复读 mysql默认隔离级别 幻读
RR 读的是历史
串行化
脏读:A,B两事务,A事务会读取到B事务未提交的数据,然后B因为某些原因回滚数据,所以A就读取了B没有提交的数据,也称脏数据。
不可重复读:同一个事务,相同的sql语句,不同的结果
幻读:类似于不可重复读,都是在一个事务周期内读的数据不一致,
幻读和不可重复读 区别在于幻读是侧重于插入操作带来的影响,而不可重复读是编辑或者删除带来的影响
为什么阻止幻读的隔离级别比不可重复读的高?
- 因为innodb是行级锁,不可重复读是针对正在修改或删除的数据行加锁,但是并不是表锁,我还可以对这个表进行插入操作,所以会出现幻读
行锁
记录锁,间隙锁,临键锁都属于行锁
记录锁
间隙锁:
临键锁
共享锁
共享锁又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到最新数据。
- 多个事务的查询语句可以共用一把共享锁;
- 如果只有一个事务拿到了共享锁,则该事务可以对数据进行 UPDATE DETELE 等操作;
- 如果有多个事务拿到了共享锁,则所有事务都不能对数据进行 UPDATE DETELE 等操作。
lock in share mode
排他锁
排他锁又称为写锁,简称X锁,顾名思义,排它锁不能与其它锁并存,而且只有一个事务能拿到某一数据行的排它锁,其余事务不能再获取该数据行的所有锁。
- 只有一个事务能获取该数据的排它锁;
- 一旦有一个事务获取了该数据的排它锁之后,其余事务对于该数据的操作将会被阻塞,直至锁释放。
for update
独占锁
自增锁
意向锁
InnoDB允许表锁和行锁同时存在。
但是,假如表锁覆盖了行锁的数据,所以表锁和行锁也会产生冲突。为了解决这种表锁和行锁共存的问题
innodb 只有通过索引条件检索数据,innodb才使用行级锁,否则,innodb将使用表锁