InnoDB事务
事务的ACID特性
- Atomic(原子性):所有语句作为一个单元全部成功执行或全部取消.不能出现中间状态
- Consistent(一致性):如果数据库在事务开始时处于一致状态,则在执行该事务期间将保留一致状态
- Isolated(隔离性):事务之间不相互影响
- Durable(持久性):事务成功完成后,所做的所有更改都会准确地记录在数据库中.所做的更改不会丢失
事务的生命周期(标准的事务控制语句)
如何开启事务和结束事务
#开启事务
begin;
#提交事务
commit;
#回滚
rollback;
标准的事务语句
#DML
use world;
#包括insert delete update语句
update city set countrycode='CHN' where id=1;
自动提交机制(autocommit)
#查看自动提交参数0为关闭 1为开启
select @@autocommit;
#在命令行设置当前会话自动提交
set autocommit=0;
#在命令行设置全局自动提交
#断开窗口重连后生效,影响到所有新开的会话
set global autocommit=0;
修改配置参数
vim /etc/my.cnf
#关闭自动提交,重启MySQL生效
autocommit=0
隐式提交的情况
触发隐式提交的语句
begin;
create database ... ;
导致提交的非事务语句
DDL语句
ALTER
CREATE
DROP
DCL语句
GRANT
REVOKE
SET PASSWORD
锁定语句
LOCK TABLES
UNLOCK TABLES
导致隐式提交的语句
TRUNCATE TABLE
LOAD DATA INFILE
SELECT FOR UPDATE
事务的ACID如何保证
- data buffer pool : 缓冲区池,数据和索引的缓冲
- redo buffer : redo内存区域
- ibd : 存储数据行和索引
- redo log : 重做日志
- LSN : 日志序列号
- ib_logfile0~1 : 默认50M,轮询使用
MySQL每次数据库启动,都会比较磁盘数据页和
redo log
的LSN
,必须要求两者LSN一致数据库才能正常启动
- 脏页 : 内存脏页,内存中发生了修改,没写入到磁盘之前,我们把内存页称之为脏页
- CKPT : Checkpoint,检查点,就是将脏页刷写到磁盘的动作
- TXID : 事务号,InnoDB会为每一个事务生成一个事务号,伴随着整个事务
- WAL(持久化) : write ahead log 日志优先写的方式实现持久化,日志是优先于数据写入磁盘的
redo重做日志的作用
主要功能保证持久性(D),原子性(A)和一致性(C)也有一定得作用
- 记录 了内存数据页的变化
- 提供 快速的事务的提交(commit)
- CSR 过程中实现前滚的操作(磁盘数据页和redo日志LSN一致)
redo日志位置
- redo的日志文件 : iblogfile0 iblogfile1
- redo buffer : 数据页的变化信息+数据页当时的LSN号
redo的刷写策略
commit;
命令会刷新当前事务的redo buffer
到磁盘,还会顺便将一部分redo buffer
中没有提交的事务日志也刷新到磁盘.MySQL在启动时,必须保证redo日志文件和数据文件LSN必须一致,如果不一致就会触发CSR,最终保证一致
事务故障流程详解
- 我们做了一个事务`
begin;
,update;
,commit;
- 在
begin
,会立即分配一个TXID=tx_01的事务号 update
时,会将需要修改的数据页(dp_01,LSN=101),加载到data buffer
中- DBWR线程,会进行dp_01数据页修改更新,并更新LSN=102
- LOGBWR日志写线程,会将dp_01数据页的变化+LSN+TXID存储到
redo buffer
- 执行
commit
时,LGWR日志写线程会将redo buffer
信息写入redo log
日志文件中,基于WAL原则 - 在日志完全写入磁盘后,
commit
命令才执行成功,(会将此日志打上commit标记) - 假如此时宕机,内存脏页没有来得及写入磁盘,内存数据全部丢失
- MySQL再次重启时,必须要
redo log
和磁盘数据页的LSN是一致的.但是,此时dp_01,TXID=tx_01磁盘是LSN=101,dp_01,TXID=tx_01,redo log
中LSN=102 - MySQL此时无法正常启动,MySQL触发CSR.在内存追平LSN号,触发ckpt,将内存数据页更新到磁盘,从而保证磁盘数据页和
redo log
中的LSN
一致.这时MySQL正常启动 - 以上的工作过程,我们把它称之为基于REDO的"前滚操作"
undo回滚日志的作用
在ACID特性中,主要保证原子性(A),同时对一致性(C)和隔离性(I)也有一定功效
- 记录 了数据修改之前的状态
- 提供 事务工作过过程中回滚操作(rollback)
- CSR 过程中实现未提交数据的回滚操作
- 实现一致性快照,配合隔离级别保证MVCC,读和写的操作不会互相阻塞
锁
实现了事务之间的隔离功能,InnoDB中实现的是行级锁(row-level lock),初次之外还有GAP(间隙锁),NextLock(下键锁),但需要索引支持
隔离级别
- RU : 读未提交,会出现脏读,不可重复读,幻读
- RC : 读已提交,可能出现幻读,不可重复读,可以防止脏读
- RR : 可重复读,(MVCC,undo快照)功能是防止幻读现象,利用的是undo的快照技术+GAP(间隙锁)+NextLock(下键锁),可以用通过GAP+Next LOCK来防止幻读(索引)
- SR : 可串行化,可以防止死锁,但是并发事务性能较差
在RC级别下,可以减轻GAP+NextLock锁的问题,但是会出现幻读现象,一般在为了读一致性会在正常select后添加for update语句.请记住执行完一定要
commit
否则容易出现所等待比较严重
可以在
my.cnf
中设置隔离级别
transaction_isolation=READ-UNCOMMITED
transaction_isolation=READ-COMMITED
transaction_isolation=REPEATABLE-READ
InnoDB核心参数的介绍
- default_storage_engine=innodb : 存储引擎默认设置
- innodb_file_per_table=1 : 表空间模式 0为共享表空间 1为独立表空间
- innodb_data_file_path=ibdata1:512M:ibdata2:512M:autoextend : 共享表空间文件个数和大小
- innodb_flush_log_at_trx_commit=1 : 事务提交日志刷新,双一标准的其中一个
有关
innodb_flush_log_at_trx_commit
参数的文档
The default setting of 1 is required for full ACID compliance. Logs are written and flushed to disk at each transaction commit.
With a setting of 0, logs are written and flushed to disk once per second. Transactions for which logs have not been flushed can be lost in a crash.
With a setting of 2, logs are written after each transaction commit and flushed to disk once per second. Transactions for which logs have not been flushed can be lost in a crash.
翻译内容
要完全符合ACID,必须使用默认设置1。 日志在每次事务提交时写入并刷新到磁盘。
设置为0时,每秒写入一次日志并将其刷新到磁盘。 尚未刷新日志的事务可能会在崩溃中丢失。
设置为2时,在每次事务提交后写入日志,并每秒刷新一次到磁盘。 尚未刷新日志的事务可能会在崩溃中丢失。
- Innodb_flush_method : 控制着innodb数据文件及
redo log
的打开,刷写模式有3个值fdatasync
,O_DSYNC
,O_DIRECT
.fdatasync
是默认值
fdatasync : 调用fsync()去刷数据文件与redo log的buffer
O_DSYNC : innodb会使用O_DSYNC方式打开和刷写redo log,使用fsync()刷写数据文件
O_DIRECT : innodb使用O_DIRECT打开数据文件,使用fsync()刷写数据文件跟redo log
最高安全模式
innodb_flush_log_at_trx_commit=1
Innodb_flush_method=O_DIRECT
最高性能
innodb_flush_log_at_trx_commit=0
Innodb_flush_method=fsync
- innodb_log_buffer_size=16777216 : redo日志设置相关设置
- innodb_log_file_size=50331648 : redo日志设置相关设置
- innodb_log_files_in_group=3 : redo日志设置相关设置
- innodb_max_dirty_pages_pct=75 : 脏页刷写策略
0 条评论