大纲:
- 事务特性
- 事务隔离级别
- 日志
- 锁
- 事务隔离性实现
一、事务特性
- 原子性(Atomicity):对数据的修改要么全部执行成功,要么全部失败
- 一致性(Consistent):数据一致性,其他三点就是为了保证数据最终一一致性
- 隔离性(Isalotion):事务之间相互隔离,不受影响,这个与事务设置的隔离级别有密切的关系
- 持久性(Durable):一个事务提交后,这个事务的状态会被持久化到数据库中
二、事务隔离级别
- 读未提交(READ UNCOMMITTED):脏读,不可重复读,幻读
- 读已提交(READ COMMITTED):不可重复读,幻读
- 可重复读(REPEATABLE READ):幻读
- 串行化(SERIALIZABLE):无
以上是4种隔离级别与产生的问题,1、4生产中不会使用。2、3在innodb下也不会出现幻读问题(查询结果集中insert,delete问题),区别在与是否可重复读(同一条记录update问题)
三、日志
逻辑日志简单理解是update,insert语句,物理日志是数据页的改动
binlog
逻辑日志,mysql的server层记录,作用是主从同步和数据恢复,叠加记录
sync_binlog=1,事务提交后同步刷盘
undolog:
逻辑日志,innodb存储引擎层记录,作用是事务回滚和mvcc生成版本链
undolog为每一个写入操作记录一个逆向操作,由于insert操作仅对本事务可见,提交后可直接删除,delete update操作需要帮助其他事务mvcc,需要放入undolog链表,等待purge线程清除
purge线程线程2个,清除无用undolog,清除被delete的行
redolog:
物理日志,innodb存储引擎层记录,作用是数据持久化,当脏页数据成功写入磁盘双写缓冲区redolog可以清除
redolog先写在logbuffer区,事务提交后刷入磁盘
innodb_flush_log_at_trx_commit=1,事务提交后同步刷盘
四、锁
按性质分:共享锁(读锁),SELECT ...LOCK IN SHARE MODE,排他锁(写锁)UPDATE,DELETE,INSERT。写写互斥、读写互斥、读读相容
按粒度分:记录锁(行锁)、表锁、间隙锁、临键锁(记录锁+相邻2个间隙锁)
行锁-唯一索引写操作,where条件为单行且存在,会上行锁。
表锁-写操作不走索引,或者给表加索引、alter table操作。
间隙锁-以下记录产生6个间隙:(-∞,5](5,10](10,1where5](15,20](20,25](25,+supernum],RR级别默认开启
-唯一索引等值查询:where id=5时行锁,where id = 6时间隙锁(5,10]
-普通索引等值查询:where c=5时临键锁 (-∞,5](5,10]会产生行锁及相邻两个间隙锁,where c = 6时间隙锁(5,10]
-范围查询-范围查询根据左右区间落到的范围增加间隙,再根据等值查询确定边界
id(主键) | c(普通索引) | d(无索引) |
---|---|---|
5 | 5 | 5 |
10 | 10 | 10 |
15 | 15 | 15 |
20 | 20 | 20 |
25 | 25 | 25 |
五、事务隔离性实现
LBCC(Lock-Based Concurrent Control):当前读
update,delete,insert写操作时候利用写锁解决并发控制,
MVCC(Multi-Version Concurremt Control):快照读
RC与RR两种隔离级别下,利用table view和undo log对select形成快照
InnoDB行记录中维护了三个隐藏列rowid行号,trx_id事务id,每个事务一个唯一标识,表示事务先后顺序 ,db_roll_ptr回滚指针,回滚指针会指向undolog链表,找到该行的历史版本链
table view中保存四个数据:min_trx_id当前活跃事务的最小id,max_trx_id当前最大id,trx_ids为活跃事务id列表,creator_trx_id生成当前事务的id
根据table view判断版本链中那个版本可用过程:
- 数据中trx_id==creator_trx_id,当前版本修改的数据(可见)
- 数据中trx_id<min_trx_id,已经提交过的数据(可见)
- 数据中trx_id>max_trx_id,生成table view后开启的事务(不可见)
- min_trx_id<=数据中trx_id<=max_trx_id,如果在trx_ids中则未提交(不可见),如果不在其中则已提交(可见)
- 不可见的版本通过版本链找到上一个版本重复上面的过程