事务与锁
事务:一个或一组SQL语句组成的一个执行单元,这个单元要么全执行,要么全不执行。是相互依赖的,其中某行语句发生失败或者错误,整个单元将会回滚(
事务ACID
原子性 :不可分割,要么全部成功,全部失败
快照
mvcc 多版本并发过程
一致性:事务的执行结果必须使数据库从一个一致性状态到另一个一致性状态。
比如:转账前后 两个账户的总金额保持不变
数据库本身的约束 一致性读 一致性写
一致性是事务最终的根本追求,通过原子性,隔离性,持久性 保证一致性的实现
隔离性:并发执行的事务不会相互影响 ,其对数据库的影响和它们串行执行时一样
共享锁 拍他所 独占锁 临键锁 间隙锁 自增锁 意向锁
读未提交 读已提交 可重复度 串行化
持久性 事务一旦提交,其对数据库的更新是持久的。任何事务或系统故障都不会导致数据丢失。数据持久化
wal日志 write ahead log 预写日志
原子性实现原理
日志 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 记录了当前数据之前的历史版本
持久性实现原理
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 读的是历史
串行化
脏读:
不可重复读:同一个事务,相同的sql语句,不同的结果
幻读:
间隙锁:
行锁
临键锁
innodb 只有通过索引条件检索数据,innodb才使用行级锁,否则,innodb将使用表锁
共享锁
lock in share mode
排他锁
for update
独占锁
自增锁
意向锁