说起事务,得先说说mysql ACID。
ACID 是 atomicity, consistency, isolation, and durability 的英文首字母缩写,即原子性、一致性、隔离性和持久性。一个数据库系统需要这四点,mysql innodb引擎的事务特性与这四点紧密相关。
事务是可以提交或者回滚的任务单元。当一个事务内对数据库做多个改变时,要么在提交事务后保证所有改变都成功,要么在回滚后保证所有改变都取消。
每次提交或者回滚事务后,或者在处理事务中,数据库总是处在一致状态。如果多个表都数据有更新,那么查询到的数据要么都是旧值,要么都是新值,不会新旧混合出现。
在多个事务同时进行都情况下,事务之间相互隔离;它们不会读取或者改动彼此之间未提交都数据。这种隔离通过锁都机制实现。高级用户在保证事务之间不相互影响都情况下,可以通过改变隔离级别来提高数据库性能和并发数。
事务完成后那就是持久化了:一旦所提交的操作都成功了那么事务内都变动都会保证保存成功,不论断电、系统崩溃、竞争资源或者其他不可抗力因素的出现。典型的持久化是写入一定冗余量的数据盘里以免断电或者软件崩溃造成数据丢失。
开始与提交transaction
- 使用
START TRANSACTION
或者BEGIN
开始一个新事务 - 使用
COMMIT
提交当前事务,使改动生效存盘 - 使用
ROLLBACK
回滚事务,取消改动 - 使用
SET autocommit
设置当前连接会话内的autocommit模式
默认情况下,mysql的autocommit是打开的。这就意味着执行完一条dml更新操作,mysql立马提交变更,使改动存盘生效。变更不能回滚。
使用START TRANSACTION
,autocommit会自动关闭,直到执行COMMIT
:
START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=@A WHERE type=1;
COMMIT;
可以使用下面声明显式关闭autocommit:
SET autocommit=0;
注意autocommit是session级别的变量,每次建立mysql 连接后都需要设置。
事务隔离级别
事务隔离是数据库运行的基础。mysql提供4个级别的隔离:READ UNCOMMITTED
, READ COMMITTED
, REPEATABLE READ
, 和 SERIALIZABLE
。默认级别是REPEATABLE READ
。用户可以使用SET TRANSACTION
声明来设置隔离级别。
mysql的InnoDB引擎使用不同的锁策略来支持不同隔离级别。可以使用默认的REPEATABLE READ
级别来保持强一致性。也可以使用READ COMMITTED
甚至READ UNCOMMITTED
级别来放宽一致性限制,减小加锁造成的开销,以适应高查询低准确的场景。SERIALIZABLE
级别在一致性上比REPEATABLE READ
更严格。
- REPEATABLE READ
在同一个事务下多次读取数据其值保持相同(读第一次查询时刻的snapshot),即使这个过程中有数据改变。
在这种级别下,普通的select
查询不会加锁,就是所谓的一致性不加锁读
(consistent nonlocking read)。SELECT with FOR UPDATE or LOCK IN SHARE MODE
这种查询操作会加锁,根据索引使用情况和查询条件使用不同的锁机制。 - READ COMMITTED
这个级别下,与REPEATABLE READ
不同的是,每次在同一个事务下,每次读取都是最新的值,即读最新的snapshot。 - READ UNCOMMITTED
即所谓的“脏读“,这种级别下不能保证数据一致性。 - SERIALIZABLE
这种级别跟REPEATABLE READ
一样能保持一致性,而且更加严格,普通的select
也会加锁。在autocommit
关闭情况下,InnoDB 引擎会“暗地里“将select
转换为SELECT ... LOCK IN SHARE MODE
;在autocommit
打开情况下,select
本身就是事务。
to be continue…