Mysql事务基础
事务是一个不可分割的数据库操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态变到另一种一致性状态。事务是逻辑上的一组操作,要么都执行,要么都不执行
事务的特点
A(Atomicity)原子性:整个事务的操作保证原子性,要不都成功,要不都失败。
C(consistency)一致性:事务执行前后,数据库都要处于一致性状态。如果事务某个动作失败了,系统会自动撤销任务,以保证数据库的完整性约束。
I(isolation)隔离性:不同事务之间的操作不可见,但是不同的引擎在这个地方的实现是不一样的。
D(durability)持久性:提交之后将持久到磁盘。
持久性保证的是事务系统的可靠性(High Reliablity)。
锁
-
共享锁(读锁):其他事务可以读,但不能写。
SELECT * FROM table_name WHERE … LOCK IN SHARE MODE。
其他 session 仍然可以查询记录,并也可以对该记录加 share mode 的共享锁。 -
排他锁(写锁):其他事务不能读取,也不能写。
对于 UPDATE、 DELETE 和 INSERT 语句,InnoDB会自动加排他锁(X);
SELECT * FROM table_name WHERE … FOR UPDATE。
其他 session 可以查询该记录,但是不能对该记录加共享锁或排他锁,而是等待获得锁
不同粒度的锁
-
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
表级锁更适合于以查询为主,并发用户少,只有少量按索引条件更新数据的应用 -
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
最大程度的支持并发,同时也带来了最大的锁开销。基于索引来完成行锁 -
页级锁:页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。
表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级锁,一次锁定相邻的一组记录。 -
间隙锁(Next-Key锁):当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;
对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁。
间隙锁的目的:防止幻读,以满足相关隔离级别的要求。
事务日志文件
-
Redo log :重做日志记录的是事务提交数据页的物理修改,用来实现事务的持久性,分为重做日志缓冲和重做日志文件,前者在内存中,后者在磁盘中。当事务提交后把所有修改信息都存到改日志文件中,用于在刷新脏页到磁盘发生错误时,进行数据恢复使用。
在InnoDB存储引擎中,事务日志通过重做日志文件和InnoDB存储引擎的日志缓冲(redo log_buffer) 来实现。
在系统宕机重启之后,对checkpoint之后的数据修改执行一遍redo,将事务的操作结果恢复过来,以此来保证之前事务的写操作的持久性 -
Undo log: 记录事务修改之前版本的数据信息
undo与redo正好相反,对于数据库进行修改时,数据库不但会产生 redo,而且还会产生一定量的 undo。
即使你执行的事务或语句由于某种原因失败了,或者如果你用一条 ROLLBACK语句请求回滚,就可以利用这些undo信息将数据回滚到修改之前的样子。
undo log用来实现事务的原子性。
用于记录数据被修改前的信息,作用:①提供回滚②MVCC(多版本并发控制)
undo Log是记录逻辑日志(redo log记录物理日志)
当delete一条记录时,undo log会记录一条对应的insert记录,
当update一条记录时,记录一条对应相反的update记录,
当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。
Undo Log销毁:undo log在事务执行时产生,事物提交时,并不会立即删除undo log,因为这些日志可能会用于MVCC