3.5 如何设置事务的隔离级别
通过下面的语句修改事务的隔离级别:
SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL 隔离级别; #其中,隔离级别格式: > READ UNCOMMITTED > READ COMMITTED > REPEATABLE READ > SERIALIZABLE
或者:
SET [GLOBAL|SESSION] TRANSACTION_ISOLATION = '隔离级别' #其中,隔离级别格式: > READ-UNCOMMITTED > READ-COMMITTED > REPEATABLE-READ > SERIALIZABLE
关于设置时使用GLOBAL或SESSION的影响:
- 使用
GLOBAL
关键字(在全局范围影响):
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE; #或 SET GLOBAL TRANSACTION_ISOLATION = 'SERIALIZABLE';
- 则:
- 当前已经存在的会话无效
- 只对执行完该语句之后产生的会话起作用
- 使用 SESSION 关键字(在会话范围影响):
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; #或 SET SESSION TRANSACTION_ISOLATION = 'SERIALIZABLE';
- 则:
- 对当前会话的所有后续的事务有效
- 如果在事务之间执行,则对后续的事务有效
- 该语句可以在已经开启的事务中间执行,但不会影响当前正在执行的事务
如果在服务器启动时想改变事务的默认隔离级别,可以修改启动参数transaction_isolation的值。比如,在启动服务器时指定了transaction_isolation=SERIALIZABLE,那么事务的默认隔离级别就从原来的REPEATABLE-READ变成了 SERIALIZABLE。
小结:
数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。
演示global
开启会话A
再开启另一个会话B
会话A中退出mysql,再登录
msql服务器重启后,会回到默认
[root@centos7-mysql-1 ~]# systemctl restart mysqld
会话A或B
演示session
会话A中
会话B中
3.6 不同隔离级别举例
会话A
初始化数据:
use atguigudb3; create table account( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(15), balance DECIMAL(15) ); INSERT INTO account VALUES(1 ,'张三', '100'),(2,'李四', '0');
表中数据如下:
SELECT * FROM account; /* +------+--------+---------+ | id | name | balance | +------+--------+---------+ | 1 | 张三 | 180 | | 2 | 李四 | 0 | +------+--------+---------+ */
演示1. 读未提交之脏读
设置隔离级别为读未提交:
演示一
会话A
mysql> select @@transaction_isolation; +-------------------------+ | @@transaction_isolation | +-------------------------+ | REPEATABLE-READ | +-------------------------+ 1 row in set (0.00 sec)
会话B
mysql> select @@transaction_isolation; +-------------------------+ | @@transaction_isolation | +-------------------------+ | REPEATABLE-READ | +-------------------------+ 1 row in set (0.00 sec)
mysql> set session transaction_isolation = 'read-uncommitted'; Query OK, 0 rows affected (0.00 sec) mysql> select @@transaction_isolation; +-------------------------+ | @@transaction_isolation | +-------------------------+ | READ-UNCOMMITTED | +-------------------------+ 1 row in set (0.00 sec)
会话A
mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> update account set balance = balance + 100 where id = 1; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql>
会话B
mysql> select * from account; +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 张三 | 200 | | 2 | 李四 | 0 | +----+--------+---------+ 2 rows in set (0.01 sec) mysql>
事务B读到了事务A未提交的数据200
会话A
mysql> rollback; Query OK, 0 rows affected (0.00 sec) mysql> select * from account; +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 张三 | 100 | | 2 | 李四 | 0 | +----+--------+---------+ 2 rows in set (0.00 sec) mysql>