1.事务的定义
事务是一个同时操作多个数据库或多个表的最小逻辑单位
2.业务场景
同表操作:支付转账中,A转账给B账户100块,那么A账户-100 B账户 +100才算转账成功,这两个操作都要成功,那么就需要事务来保证他们同时成功或者同时失败。
多表操作:在电商项目中的下订单场景中,扣款,减库存,生成订单这3个操作通常会涉及到多个数据库的操作,同样需要保证这3个操作都成功下订单才算成功,否则应该回滚。
3.引擎
在5.5版本之前MySQL采用的是MyISAM,5.5之后采用的是InnoDB。MyISAM最大的区别就是表锁/行锁,事务。
4.事务的四大特性
ACID:A-atomic、C-consistent、I-isolation、D-durable
原子性,事务是最小逻辑单位,只有成功和失败两种状态
一致性,事务执行前后数据应该是合法的,符合约束条件的
隔离性,事务与事务之间是独立的,互不影响的
持久性,执行事务后的数据会落地到磁盘
5.隔离级别
说到事务的隔离性,那么就得说到事务的隔离级别,read-uncommited、read-commited、repeatable-read、serializable。这几种隔离级别主要是为了解决脏读、不可重读、幻读问题的。
脏读:在一个事务两次读取数据之间,有另一个事务修改数据但是没有提交,导致前一个事务两次读取的数据不一致。
不可重读:在一个事务两次读取数据之间,有另一个事务修改数据且提交了,导致前一个事务两次读取的数据不一致。
幻读:在一个事务两次读取数据之间,有另一个事务新增n行数据,导致前一个事务第二次读取数据时出现了第一次读取不存在的数据。
6.隔离方案
说到事务的隔离级别,那么就得说到实现这几种隔离级别的方案。主要有两种,
MVCC-multiple version concurrent control
InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的,这两个列,分别保存了这个行的创建时间和删除时间。这里的时间指系统版本号(可以理解为事务的ID),每开始一个新的事务,系统版本号就会自动递增,事务开始时刻的系统版本号会作为事务的ID。
加锁
这里的锁主要分为行锁和表锁,顾名思义,行锁是锁住某一行,表锁是锁住整个表。它们之间的差异如下:
粒度:表锁>行锁
效率:表锁>行锁
冲突:表锁>行锁
并发:表锁<行锁
7.锁模式
既然提到了加锁,那么这个锁加的是什么锁?
shared-lock
共享锁,也可称为读锁,多个事务可以共享同一把锁,但仅限于读数据。
加锁方式:在sql语句末尾加上 lock in share mode。
释放锁:commit/rollback。
exclusive-lock
排它锁,也可称为写锁,是某个事务所独占的锁。
加锁方式:delete/insert/update操作InnoDB默认自动加锁,在语句末尾加上 for update进行手动加锁。
释放锁:同上。
intention-shared-lock/intention-exclusive-lock
意向共享锁/意向排它锁,这个是由数据库引擎维护的锁,用户无法操作。这个锁可以理解为一个mark,如果一个事务想要锁表或者锁某个范围,那么它需要确认表中或者这个范围中每一行都没有其他锁,这个mark可以直接标记整个表的状态或者这个范围的状态,从而避免全表扫描。
锁住的是什么?
直接说结论,锁住的是索引,行锁锁住的是某一行的主键索引。如果一张表不加索引,会出现锁表的情况,因为在索引组织表中存在一个隐藏列rowid,在没有索引的情况下,该列会作为聚集索引,从而导致锁表。
8.锁算法
record
点锁
唯一索引,精准匹配
Gap
间隙锁,锁范围,不拆分无穷大区间
Next-Key
综合前两种,锁范围,包含右节点