mysql事务的四个特性
-
原子性(Atomicity) 原子性是指整个数据库事务是不可分割的工作单位。只有使事务中的所有数据库操作都成功,整个事务才算成功。如果事务中任何一个SQL执行失败,已执行的SQL的操作必须被撤销, 数据库状态应该回退到执行事务前的状态。
-
一致性(Consistency) 一致性是指事务将数据库从一个状态转换为下一个一致性的状态。在事务开始前和开始后, 数据的完整性约束没有被破坏。
-
隔离性(Isolation) 一个事务的影响在提交前对其他事务都是不可见的。 – 这种通过锁的机制来实现。
-
持久性(durability) 事务一旦提交,其结果就是永久性的。即使发生宕机的行为, 数据库也能够恢复数据。
事务的实现
在Mysql中, 事务的原子性,一致性,持久性都是通过redo
和undo
来实现的
redo
在InnoDB存储引擎中,事务日志通过重做(redo)日志文件和InnoDB存储引擎的日志缓冲(InnoDB Log Buffer)来实现的. 当开始一个事务时,会记录该事物的一个LSN(Log Sequence Number, 日志序列号); 当执行事务时,会往InnoDB存储日志的缓冲里插入事务日志; 当事务提交时, 必须将InnoDB的日志缓冲写入磁盘(默认的实现: innodb_flush_log_at_trx_commit=1
). 也就是写数据之前,先写日志。这种方式叫做预写日志方式(Write-Ahead Logging) WAL
undo
重做日志记录了事务的行为,可以很好的通过其进行”重做”。但是事务有时候还需要撤销,这时就需要undo. 对于undo的实现, Mysql主要通过相反的方式记录, 例如INSERT操作, 实际上会记录一个DELETE操作。 对于DELETE操作,会记录一个INSERT语句。对于UPDATE会有一个相反的UPDATE操作。
NOTE: 在进行
INSERT
或者DELETE
操作的时候, 会产生多个undo
页。 在每次进行事务提交之后,undo也信息并不是每次都进行回收,回收的操作是在master thread
中进行的,master thread
中也不是每次都是对undo
页信息进行回收。
事务控制语句
-
START TRANSACTION | BEGIN : 显式的开启一个事务
-
COMMIT: 提交事务, 事务对数据的更改将会保存到数据库, 并且是永久性保存。
-
ROLLBACK: 结束一个事务,并回滚所有的没有提交的修改。
-
SAVEPOINT identifier: 在当前事务中创建一个保存点, 一个事务中允许创建多个保存点
-
RELEASE SAVEPOINT identifier: 删除一个事务的保存点, 如果删除的保存点不存在, 则会抛出异常
-
ROLLBACK TO [SAVEPOINT] indentifier: 这个语句与SAVEPOINT一起起作用。可以把事务回滚到标记点,而不用回滚在标记点前的任何工作。
-
SET TRANSACTION: 这个语句用来设置事务的隔离级别。InnoDB引擎提供的事务隔离级别有:
READ UNCOMMITTED
,READ COMMITTED
,REPEATABLE READ
,SERIALIZABLE
四种隔离级别。
事务的隔离级别
-
READ UNCOMMITTED
-
READ COMMITTED
-
REPEATABLE READ
-
SERIALIZABLE
隔离级别越低,事务请求的锁越少,或者保持锁的时间就越短。这也就是为什么大多数的数据采用的都是READ COMMITTED
的模型。
可以通过以下的命令, 来设置会话或者全局的事务级别:
set [global | session ] transaction isolation level [READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE]
如果想在mysql启动的时候就是用默认的隔离级别,需要在mysql配置文件中配置一下信息:
transaction-isolation=READ-COMMITTED
查看当前级别的事务隔离级别:
select @@tx_isolation
查看全局的隔离级别
select @@global.tx_isolation
NOTE: 在SERIALIZABLE的隔离级别下,InnoDB会为所有的SELECT操作加一个
LOCK IN SHARE MODE
加一个共享锁。
分布式事务
分布式事务指的是, 允许多个独立的事务资源参与一个全局事务之中。
分布式事务由一个或者多个资源管理器(Reources Manager)、一个事务管理器(Transaction Manager)以及一个应用程序组成。
-
资源管理器 : 提供访问事务资源的方法。通常一个事务就一个资源管理器
-
-
应用程序 : 定义事务的边界, 指定全局事务中的操作。
查看Mysql是否开启分布式事务
show variables like 'innodb_support_xa'
不好的事务习惯
-
在循环中重复提交事务 在循环中重复提交事务,会导致每一次提交都会讲提交的数据记录到
redo
的日志文件中. 例如: 循环10000次,实际上会有10000条undo
日志. 同时也伴随着, 如果中途因为某条语句插入失败,已经插入的数据实际上时不能回滚的。因此因当前在循环中,将操作的数据放到同一个事务当中, 这是性能会提升更多。 -
使用自动回滚