ACID
Atomicity: 原子性,一次事务中的操作要么全部成功,要么全部失败
Consistency: 一致性 跨表跨行跨事务,数据库始终保持一致状态
Isolation: 隔离性 可见性,保护事务不会互相干扰,包含四种隔离级别
Durability: 持久性,事务提交成功后,不会丢数据
表级锁
意向锁: 表明事务稍后要进行哪种类型的锁定
共享锁S
排他锁X
共享意向锁 IS :打算在某些行上设置共享锁
排他意向锁IX :打算在某些行设置排他锁
Insert意向锁 :Insert操作设置的间隙锁
X锁于其他锁都冲突
IS锁和X之外的锁都兼容
S和S兼容
IX和IX兼容
X | IX | S | IS | |
---|---|---|---|---|
X | 冲突 | 冲突 | 冲突 | 冲突 |
IX | 冲突 | 兼容 | 冲突 | 兼容 |
S | 冲突 | 冲突 | 兼容 | 兼容 |
IS | 冲突 | 兼容 | 兼容 | 兼容 |
行级锁
记录锁Record:始终锁定索引记录,注意隐藏的聚族索引 in share model上一个S锁,或者for update上一个X锁
间隙锁Gap:锁住一个范围
临键锁Next-key 记录锁+间隙锁的组合可以锁表中不存在的记录 5.8前开后闭合
谓词锁Predicat 空间索引
隔离级别
读未提交
并发事务还未提交但是别的事务都能看的到 脏数据
使用很少,因为会产生脏数据,不能保证一致性
可能导致脏读,幻读,不可重复度
脏读就是读到了还未提交的脏数据,随时可能被回滚
幻读就是第一次读出来3条数据,第二次读出来5条数据
不可重复读就是第一次读出来三条,第二次读出来也是三条,但是其中的一条值是不一样的
读已提交
事务提交后才会被别的事务看到
每次查询都会设置和读取自己的新快照
仅支持基于行的bin_log
update优化 半一致读 semi—consistent read
不加锁的情况下会产生不可重复读和幻读的问题
锁:
锁定索引记录,但不锁定记录之间的间隙
可重复读
每一次读的数据和上一次是一样的
使用事务第一次读取时创建的快照
MVCC
锁:
使用唯一索引的唯一查询条件时,只锁定查找到的索引记录,不锁定间隙
其他查询条件,会锁定扫描到的索引范围,通过间隙锁或临键锁来阻止其他会话在这个范围中插入值
InnoDB不能保证没有幻读需要加锁保证
可串行化
所有的事务都排队
最严格的级别,事务串行执行,资源消耗最大
MYSQL
可以设置全局的默认隔离级别
可以单独设置会话的隔离级别
InnoDB实现与标准存在小差异
常见的关系数据库PostgreSQL Oracle DB2 SQL server 默认隔离级别是读已提交RC
MYSQL默认是RR可重复读
解决脏读幻读不可重复读的问题的方法==》提高隔离级别,使用间隙锁或临键锁
日志
undo log撤销日志
保证事务的原子性
用处:事务回滚,一致性读,崩溃恢复
记录事务回滚所需要的撤销操作
例如:一条insert语句对应一条DELETE 的undo log
保存位置
5.7默认在系统的表空间
8.0默认在undo log自己的表空间
redo log重做日志
确保事务的持久性,防止事务提交后数据未刷到磁盘就掉电或崩溃
事务执行过程中写入redo log,记录事务对数据页做了哪些更改
使用了WAL WRITING AHEAD LOGGING技术,顺序追加写日志的方式优化性能,比我们随机写入磁盘要快,先写日志,再写磁盘
日志文件 ib_logfile0,ib_logfile1
日志缓冲:innodb_log_buffer_size
强刷:fsync()
MVCC多版本并发控制
隐藏列
隐藏列 | DB_TRX_ID | DB_ROLL_PTR | DB_ROW_ID |
---|---|---|---|
长度 | 6 byte | 7 byte | 6 byte |
说明 | 指示最后插入或更新该行的事务ID | 回滚指针,指向回滚段中写入的undo log记录 | 聚簇row ID/聚簇索引 |
事务链表,保存还未提交的事务,事务提交则会从链表中摘除(针对当前活动的未提交的事务做成一个链表放在内存里,一旦事务提交了刷到磁盘了就会从这个链表中摘除)
可以通过 select * from performance_schema.data_locks;看出是什么锁和锁的范围