mysql · 11 4 月, 2021 0

mysql事务

mysql 事务

mysql事务的四个特性

  1. 原子性(Atomicity) 原子性是指整个数据库事务是不可分割的工作单位。只有使事务中的所有数据库操作都成功,整个事务才算成功。如果事务中任何一个SQL执行失败,已执行的SQL的操作必须被撤销, 数据库状态应该回退到执行事务前的状态。

  2. 一致性(Consistency) 一致性是指事务将数据库从一个状态转换为下一个一致性的状态。在事务开始前和开始后, 数据的完整性约束没有被破坏。

  3. 隔离性(Isolation) 一个事务的影响在提交前对其他事务都是不可见的。 – 这种通过锁的机制来实现。

  4. 持久性(durability) 事务一旦提交,其结果就是永久性的。即使发生宕机的行为, 数据库也能够恢复数据。

事务的实现

在Mysql中, 事务的原子性,一致性,持久性都是通过redoundo来实现的

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'

不好的事务习惯

  1. 在循环中重复提交事务 在循环中重复提交事务,会导致每一次提交都会讲提交的数据记录到redo的日志文件中. 例如: 循环10000次,实际上会有10000条undo日志. 同时也伴随着, 如果中途因为某条语句插入失败,已经插入的数据实际上时不能回滚的。因此因当前在循环中,将操作的数据放到同一个事务当中, 这是性能会提升更多。

  2. 使用自动回滚 如果在存储过程中, 使用了自动回滚,或者进行了异常的捕获, 实际上在程序调用的时候,很难捕获到异常信息, 我们可以将存储过程中的事务放到程序之中, 然后调用存储过程, 并在程序之中进行提交或者回滚。