Wetts's blog

Stay Hungry, Stay Foolish.

0%

高性能MySQL-1.3.4-MySQL中的事务

自动提交

MySQL默认采用自动提交(AUTOCOMMIT)模式。

MySQL可以通过执行SET TRANSACTION ISOLATION LEVEL命令来设置隔离级别。新的隔离级别会在下一个事务开始的时候生效。可以在配置文件中设置整个数据库的隔离级别,也可以只改变当前绘画的隔离级别:

1
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

在事务中混合使用存储引擎

MySQL服务器层不管理事务,事务是由下层的存储引擎实现的。所以在同一个事务中,使用多种存储引擎是不可靠的。

如果在事务中混合使用了事务型和非事务型的表(例如InnoDB和MyISAM表),在正常提交的情况下不会有什么问题。

但如果该事务需要回滚,非事务型的表上的变更就无法撤销,这会导致数据库出于不一致的状态,这种状况很难修复,事务的最终结果将无法确定。所以,为每张表选择合适的存储引擎非常重要。

在非事务型的表上执行事务相关操作的时候,MySQL通常不会发出提醒,也不会报错。有时候只有回滚的时候才会发出一个警告:“某些非事务型的表傻姑娘变更不能被回滚”。但大多数情况下,对非事务型表的操作都不会有提示。

隐式和显式锁定

InnoDB采用的是两阶段锁定协议(two-phase locking protocol)。在事务执行过程中,随时都可以执行锁定,锁只有在执行COMMIT或者ROLLBACK的时候才会释放,并且所有的锁是在同一时刻被释放。前面描述的锁定都是隐式锁定,InnoDB会根据隔离级别在需要的时候自动加锁。

另外,InnoDB也支持通过特定的语句进行显式锁定,这些语句不属于SQL规范:

1
2
SELECT ... LOCK IN SHARE MODE
SELECT ... FOR UPDATE

MySQL也支持LOCK TABLES和UNLOCK TABLES语句,这是在服务器层实现的,和存储引擎无关。他们有自己的用途,但并不能替代事务处理。如果应用需要用到事务,还是应该选择事务型存储引擎。

tips:LOCK TABLES和事务之间相互影响的话,情况会变得非常复杂,在某些MySQL版本中甚至会产生无法预料的结果。因此,本书建议,除了事务中禁用了AUTOCOMMIT,可以使用LOCK TABLES之外,其他任何时候都不要显式地执行LOCK TABLES,不管使用的是什么存储引擎。