一.Innodb存储引擎核心特性
- 事务
一组数据操作执行步骤,这些步骤被视为一个工作单元
用于对多个语句进行分组
可以在多个客户机并发访问同一个表中的数据时使用
所有步骤都成功或都失败
如果所有步骤正常,则执行
如果步骤出现错误或不完整,则取消
- 事务是保证数据的ACID特性
Atomic(原子性)
所有语句作为一个单元全部成功执行或全部取消。
Consistent(一致性)
如果数据库在事务开始时处于一致状态,则在执行该事务期间将保留一致状态。
Isolated(隔离性)
事务之间不相互影响。
Durable(持久性)
事务成功完成后,所做的所有更改都会准确地记录在数据库中。所做的更改不会丢失。
- 标准事务控制语句
begin; 开启事务
DML
DML
commit; 结束事务
begin; 开启事务
DML
DML
rollback;
autocommit=1 默认等于1,开启状态,自动提交功能
A--->B
begin
A-50
B+50
commit
关闭自动提交:
oldguo [(none)]>set autocommit=0;
oldguo [(none)]>set global autocommit=0;
永久修改:
my.cnf
AUTOCOMMIT=0
- 隐式提交
用于隐式提交的 SQL 语句:
START TRANSACTION
SET AUTOCOMMIT = 1
导致提交的非事务语句:
DDL语句: (ALTER、CREATE 和 DROP)
DCL语句: (GRANT、REVOKE 和 SET PASSWORD)
锁定语句:(LOCK TABLES 和 UNLOCK TABLES)
导致隐式提交的语句示例:
TRUNCATE TABLE
LOAD DATA INFILE
SELECT FOR UPDATE
- Innodb 存储引擎物理存储层
表空间(t1.ibd)----->
段 一个表就是一个段(除了分区表)
区 连续的多个页
页 Page(16KB)
- 存储引擎—事务日志redo
redo:重做日志
Redo是什么?
redo,顾名思义“重做日志”,是事务日志的一种。
作用是什么?
在事务ACID过程中,实现的是“D”持久化的作用,AC的特性也和redo有关
存储位置:数据路径下存放,默认两个日志,默认大小是48M,轮询覆盖形式使用日志文件
show variables like '%log%';
innodb_log_file_size=50331648
innodb_log_files_in_group=2
ib_logfile0
ib_logfile1
redo记录的是什么?
内存数据页的变化
LSN:日志序列号(数据变化的版本号)
data page
logfile
data buffer
redo log buffer
数据库要求:启动时,必须保证data page和lgfile 中LSN一致才能,正常打开数据,否则就需要自动恢复
可以在CSR过程中,实现前滚的功能
- 存储引擎—事务日志undo
undo:
undo是什么?
undo,顾名思义“回滚日志”,是事务日志的一种。
作用是什么?
在事务ACID过程中,实现的是“ACI”原子性,一致性的作用。
隔离级别实现
undo记录了什么?
数据页修改之前的状态,TXID为事务ID
作用:(未提交分为以下两种情况)
1.rollback :直接通过TXID将undo里面的数据覆盖data buffer里面的数据。
2.断电恢复(CSR),过程中,实现回滚:分两种情况讨论:
- commit未提交:通过undo回滚
- 有一种可能是前一个事务将未提交的事务一起提交了,因为commit是提交的整块日志区域:如果是已提交的数据,那么在redo 日志里面会多一个标记commited,代表这个事务已经被提交了,现在我们的事务是被前一个事务提交过来的,所以没有commit标记,按照Mysql的执行顺序,它会将数据页和redo 日志文件进行对比,发现两个数据不一致,会重新放到内存进行重演,这个过程称为前滚,然后通过TxID去undo里面找到对应的快照将data 数据覆盖,这个过程称为回滚
- 事务中的锁
什么是“锁”?
“锁”顾名思义就是锁定的意思。
“锁”的作用是什么?
在事务ACID过程中,“锁”和“隔离级别”一起来实现“I”隔离性的作用。
- Innodb存储引擎——事务的隔离级别
READ UNCOMMITTED: 最低的事务隔离级别,一个事务还没被提交时,它做的变更就能被别的事务看到,可能产生不可重复度,脏读,幻读
READ COMMITTED:保证一个事务提交后才能被另外一个事务读取,也就是另外一个事务不能读取该事务未提交的数据,这样避免了脏读的发生,但可能造成不可重复度,也可能产生幻读,幻读:与不可重复读有点类似,都是两次读取,不同的是 A 事务第一次操作的比如说是全表的数据,此时 B 事务并不是只修改某一具体数据而是插入了一条新数据,而后 A 事务第二次读取这全表的时候就发现比上一次多了一条数据,发生幻觉了。
REPEATABLE READ:Inodb的默认隔离级别,多次读取同一范围的数据会返回第一次查询的快照,即使其他事务对该数据做了更新修改。事务在执行期间看到的数据前后必须是一致的。可重复读中,该sql第一次读取到数据后,就将这些数据加锁(悲观锁),其它事务无法修改这些数据,就可以实现可重复读了。但这种方法却无法锁住insert的数据,所以当事务A先前读取了数据,或者修改了全部数据,事务B还是可以insert数据提交,这时事务A就会发现莫名其妙多了一条之前没有的数据,这就是幻读,不能通过行锁来避免。需要Serializable隔离级别 ,读用读锁,写用写锁,读锁和写锁互斥,这么做可以有效的避免幻读、不可重复读、脏读等问题,但会极大的降低数据库的并发能力。
SERIALIZABLE:Mysql最高的隔离级别,写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。事务 100% 隔离,可避免脏读、不可重复读、幻读的发生。
不可重复度和幻读的区别:
很多人容易搞混不可重复读和幻读,确实这两者有些相似。但不可重复读重点在于update和delete,而幻读的重点在于insert。所以说不可重复读和幻读最大的区别,就在于如何通过锁机制来解决他们产生的问题。