MySQL 事务具有四个特性:原子性、一致性、隔离性、持久性,这四个特性简称 ACID 特性。
一个事务是一个不可再分割的整体,要么全部成功,要么全部失败。
一个事务可以让数据从一种一致状态切换到另一种一致性状态。
一个事务不受其他事务的影响,并且多个事务彼此隔离。
一个事务一旦被提交,在数据库中的改变就是永久的,提交后就不能再回滚。
事务并发问题指的是多个事务同时操作同一数据库的同一个表时,出现的问题。
要产生问题,事务里语句执行的顺序是关键,两个事务在时间上的先后顺序。
①事务A开启事务,事务B开启事务(开启事务先后顺序无影响)
②事务A更改person表,字段A内容
③事务B更改Person表,字段A内容
④事务B提交内容
⑤事务A回滚
①事务A开启事务,事务B开启事务(开启事务先后顺序无影响)
②事务A更改person表,字段A内容
③事务B读取Person表,字段A内容
④事务A回滚
①事务A开启事务,事务B开启事务(开启事务先后顺序无影响)
②事务A更改person表,字段A内容 ,并提交事务
③事务B读取Person表,字段A内容
④事务A开启事务,在此更改person表,字段A内容 ,并提交事务
⑤事务B读取Person表,字段A内容
①事务A开启事务,事务B开启事务(开启事务先后顺序无影响)
②事务A插入到person表一条数据 ,并提交事务
③事务B读取Person表所有数据
④事务A开启事务,在此插入person表一条数据 ,并提交事务
⑤事务B读取Person表所有数据
事务隔离级别是针对事务特性的隔离性来说的,隔离级别高可以解决事务的一些并发问题,但是会造成性能下降。
# 查看全局事务隔离级别
select @@global.tx_isolation;
# 查看会话事务隔离级别(也就是当前窗口)
select @@tx_isolation;
select @@transaction_isolation;
#将session改成global就变成全局的事务隔离级别,也就是MySQL服务不重启,会一直保持该设置的隔离级别不变。
#session是当前会话的隔离级别,也就是当前窗口
# 读未提交
set session transaction isolation level read uncommitted;
# 读已提交
set session transaction isolation level read committed;
# 可重复读(默认隔离级别)
set session transaction isolation level repeatable read;
# 可串行化
set session transaction isolation level serializable;
要想验证事务的隔离级别,就需要知道设置成该隔离级别解决了什么问题,不同隔离级别解决的问题如下图所示:
读已提交的隔离级别解决了脏读的问题,第一步就要复现脏读,将隔离级别设置为读未提交,因为读未提交未解决脏读问题,第二步,将隔离级别设置为读已提交,看看脏读问题是否得到解决。
(1)开启两个查询窗户,分别将起隔离级别设置为读未提交。
(2)事务A开启事务,并更新person表中name字段内容
person表初始数据如下图:
(3)事务B开启事务,并查询person表id为2的数据
查询结果
(4)再将事务A回滚
(5)事务B再次查询person表
查询结果如下:
可以看到一个现象,对于事务A更改表后回滚的操作,事务B读取到了不同的值,这就是脏读。
(6)更改这两个窗口的事务隔离级别为读已提交,在进行 (2) - (5) 的观察
这时会发现对于未提交的事务A,无论怎么更改表中数据,事务B都不会查询出不一样的结果,这就是读已提交解决的脏读问题。
按照①的思路,去验证其他隔离级别即可。