mysql事务没用 mysql 事务语句_mysql事务没用


本篇文章来讲讲事务是什么。

事务就是将一系列放在一起的操作,要么全部成功,要么全部失败。我们在实际的业务中,需要把有些 sql 语句放到一起,要求他们全部执行成功,如果有一个失败了,这个业务逻辑就失败了,其他的 sql 语句要回滚。

MySQL 中,事务功能是在引擎层实现的,但并不是所有引擎都支持事务。早期流行的 MyISAM 引擎就不支持事务,而后他就被支持事务的 InnoDB 取代了。

隔离性与隔离级别

事务有四个特性:原子性、一致性、隔离性、持久性。本文详细讲讲隔离性

如果数据库同时有多个事务在执行,就可能导致数据错误,这就涉及到隔离级别的概念了。

MySQL 的事务隔离级别包括:读未提交(read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(serializable )。

  1. 未提交读:一个事务还没提交的时候,它里面做的数据更改就可以被其他的事务看到。
  2. 读提交:一个事务提交之后,它做的更改才能被其他事务看到。
  3. 可重复读:一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据一致。提交后,它做的变更才能被其他事务看到。
  4. 串行化:对于同一行数据,读写都会加锁。当出现锁冲突时,后者必须等前者执行完成释放锁。

事务隔离如何实现?

我们以可重复读为例子,讲解事务隔离是如何实现的。

MySQL 每次更新记录的时候,都会同时记录一条回滚操作,这样记录上的最新值,可以通过回滚操作,一步一步回去这个数据之前的数值。

举个例子

如果一个值是 1,之后更新操作按照顺序改成了 2、3、4,每一步操作都会记录一个回滚操作,回滚的日志并不会一直保留,在不需要的时候会删除。系统会判断,当没有事务再需要使用这些回滚日志,回滚日志会被删除。

如何判断出不需要了呢?当系统里没有比这个回滚日志更早的 read_view 的时候。

由此可见,长事务是不推荐使用的。长事务意味着系统中会存很长很老的事务视图,事务没提交前,所做的一切操作都要做到可回滚,就需要很多条回滚记录保留下。这就会占用非常大的存储空间。

在 MySQL 早期版本中,回滚日志是跟数据字典放在一起,放在 ibdata 文件中。长事务最终被提交了,回滚日志被清理,这个文件也不会变小。最终会导致资源占用过大,重建数据库才能恢复。

事务的启动方式

从上文我们知道了长事务是有风险的,那么如何避免错误代码的使用导致开启长事务呢?

MySQL 事务的启动方式有以下两种:

  1. 显式启动事务语句,使用 begin 或者 start transaction。提交语句使用 commit,回滚语句使用 rollback
  2. 启动事务前,设置 set autocommit = 0,这个语句的意思是关闭线程的自动提交,需要手动执行 commit 或者 rollback 才会结束。

有的代码框架默认使用第二种,而我们却不知道,也不手动提交,就会造成超级长的事务产生。

建议使用第一种方式,同时设置 set autocommit = 0,并显式启动事务,这样就不会有问题了。

好的本文就到这里。回顾下,本文讲解了事务的概念,隔离性和隔离级别,隔离的实现原理以及如何正确开启一个事务。在实战代码中,事务操作不当是非常容易造成严重的数据库错误的,如果不好好学习这块,就可能会闯祸了。