TA的每日心情 | 无聊 3 天前 |
---|
签到天数: 1050 天 连续签到: 1 天 [LV.10]测试总司令
|
数据库的多版本并发控制(MVCC)原理
Mysql 默认采用的可重复读隔离级别。每条记录在更新的时候都会同时记录一条回滚操作(回滚操作日志undo log)。同一条记录在系统中可以存在多个版本,这就是数据库的多版本并发控制(MVCC)。即通过回滚(rollback操作),可以回到前一个状态的值。
假设一个值从 1 被按顺序改成了 2、3、4,在回滚日志里面就会有类似下面的记录。
当前值是 4,但是在查询这条记录的时候,不同时刻启动的事务会有不同的 read-view。如下图所示,在视图 A、B、C 里面,这一个记录的值分别是 1、2、4,同一条记录在系统中可以存在多个版本,就是数据库的多版本并发控制(MVCC)。
对于 read-view A,要得到 1,就必须将当前值依次执行图中所有的回滚操作得到。
同时你会发现,即使现在有另外一个事务正在将 4 改成 5,这个事务跟 read-view A、B、C 对应的事务是不会冲突的。
提问:回滚操作日志(undo log)什么时候删除?
MySQL会判断当没有事务需要用到这些回滚日志的时候,回滚日志会被删除。
提问:那什么时候不需要了?
当系统里没有比这个回滚日志更早的read-view的时候。
设置隔离级别
通过set命令
SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL level;
其中,level有4种值:REPEATABLE READ | READ COMMITTED| READ UNCOMMITTED | SERIALIZABLE 。
关键词:GLOBAL,只对执行完该语句之后产生的会话起作用,当前已经存在的会话无效。
关键词:SESSION,对当前会话的所有后续的事务有效,该语句可以在已经开启的事务中间执行,但不会影响当前正在执行的事务,如果在事务之间执行,则对后续的事务有效。
无关键词:只对当前会话中下一个即将开启的事务有效,下一个事务执行完后,后续事务将恢复到之前的隔离级别,该语句不能在已经开启的事务中间执行,会报错的。
通过服务启动项命令
可以修改启动参数transaction-isolation的值。比方说,我们在启动服务器时指定了--transaction-isolation=READ UNCOMMITTED,那么事务的默认隔离级别就从原来的REPEATABLE READ变成了READ UNCOMMITTED。
查看当前会话隔离级别
方式一:
- mysql> show variables like 'transaction_isolation';
- +-----------------------+--------------+
- | Variable_name | Value |
- +-----------------------+--------------+
- | transaction_isolation | SERIALIZABLE |
- +-----------------------+--------------+
复制代码 方式二:
- +-------------------------+
- | @@transaction_isolation |
- +-------------------------+
- | SERIALIZABLE |
- +-------------------------+
复制代码 MySQL 中的事务操作
事务分为隐式事务和显式事务。
MySQL 中事务默认是隐式事务,执行insert、update、delete操作的时候,数据库自动开启事务、提交或回滚事务。是否开启隐式事务是由变量autocommit控制的。
隐式事务
事务自动开启、提交或回滚,比如insert、update、delete语句,事务的开启、提交或回滚由mysql内部自动控制的。
查看变量autocommit是否开启了自动提交,autocommit为ON表示开启了自动提交。
- mysql> show variables like 'autocommit';
- +---------------+-------+
- | Variable_name | Value |
- +---------------+-------+
- | autocommit | ON |
- +---------------+-------+
复制代码 显式事务
事务需要手动开启、提交或回滚,由开发者自己控制。有 2 种方式手动控制事务。
用 START来开始一个事务
语法:
- // 开启事务
- start transaction;
- // 执行事务操作(事务回滚/事务确认)
- commit|rollback;
复制代码 示例:提交事务操作。
- mysql> start transaction;
- Query OK, 0 rows affected (0.00 sec)
- mysql> insert into test1 values (2);
- Query OK, 1 row affected (0.00 sec)
- mysql> insert into test1 values (3);
- Query OK, 1 row affected (0.00 sec)
- mysql> commit;
- Query OK, 0 rows affected (0.00 sec)
复制代码 用 SET 来改变 MySQL 的自动提交模式
SET AUTOCOMMIT=0 禁止自动提交
SET AUTOCOMMIT=1 开启自动提交
语法:
- // 设置不自动提交事务set autocommit=0;
- // 执行事务操作commit|rollback;
复制代码 示例:回滚事务操作。
- mysql> set autocommit=0;
- Query OK, 0 rows affected (0.00 sec)
- mysql> insert into test1 values(2);
- Query OK, 1 row affected (0.00 sec)
- mysql> rollback;
- Query OK, 0 rows affected (0.00 sec)
复制代码 总结
为了达到事务的四大特性,数据库定义了4种不同的事务隔离级别,由低到高依次为读未提交、读已提交、可重复读以及可串行化,这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。
事务隔离级别为读已提交时,写数据只会锁住相应的行。
事务隔离级别为串行化时,读写数据都会锁住整张表。
InnoDB 存储引擎默认使用可重复读隔离级别。在分布式事务的情况下,InnoDB 存储引擎一般会用到可串行化隔离级别。
|
|