事务的认识
什么是mysql事务,一个很简单的案例:
A用户给B用户转账100元操作。
如果没有事务支持,可能出现错:A账户减少了100,此时系统挂了,导致B账户没有加上100,而A账户凭空少了100。
因此,同时执行多条sql语句时才可能用到事务,而事务支持这些sql语句要么全部执行成功,要么全部失败,不会存在部分成功的情况。
事务的特性
1.原子性(A):要求其中的操作要么都成功,要么都失败,事务内部操作不可再分
2.持久性(I): 指事务一旦提交,它对数据库的改变就应该是永久性的。接下来的其他操作或故障都不能影响已经提交的事务。
3.隔离性(D):多个事务同时执行,并发执行的各个事务之间不能互相干扰。
4.一致性(C):事务执行的结果必须是使数据库从一个一致状态变到另一个一致状态。
和事务相关的术语
- 开启事务:Start Transaction
- 事务结束:End Transaction
- 事务提交: Commit Transaction ---- 事务回滚: Rollback Transaction
#张三给李四转账 100 元
#非事务提交---执行成功
update act set money = 400 where id = 2;update act set money = 200 where id = 1;
#非事务提交---执行失败
update act set money = 400 where id = 2;
update act set money = 200 where id = 1w; #模拟第二条语句出现了问题#事务提交---执行成功
start transaction;
update act set money = 400 where id = 2;
update act set money = 200 where id = 1;
commit;#事务提交---执行失败
start transaction;
update act set money = 400 where id = 2;
update act set money = 200 where id = 1w;
rollback;#一旦开启事务,我们就需要一个判断:
#如果执行成功则commit提交事务,将事务持久化保持,一旦执行失败,就rollback回滚,数据库数据返回原来的状态
事务的并发问题
脏读:事务A读取到了事务B修改但未提交的数据。

不可重复读:是指在一个事务内,多次读取同一数据,但是数据的值发生了改变。

幻读: 指的是在一个事务中,多次查询同一个范围的数据,却发现有新增或者减少的行。这是因为在这个事务进行的过程中,另一个事务插入或者删除了符合查询条件的数据,导致前后两次查询结果不一致。

事务的隔离等级
为了解决并发所产生的问题,我们提出了事务的隔离级别,隔离级别越高,解决并发产生的问题越多。
背景知识:读锁和写锁,在读数据时上读锁,在写数据时上写锁。
数据上读锁后不能被其他事务修改,直到读锁释放。
数据上写锁其他事务不能读也不能修改。
隔离性的隔离级别
- 读未提交 read uncommitted
- 读已提交 read committed
- 可重复读 repeatable read
- 串行化 serializable
读未提交 read uncommitted
事物A和事物B,事物A未提交的数据,事物B可以读取到。 这种隔离级别最低,这种级别一般是在理论上存在,数据库隔离级别一般都高于该级别。 三种并发问题都没解决。
演示:
1.创建表: create table t_user(id int primary key auto_increment,username varchar(255));
设置读未提交的隔离级别
set global transaction isolation level read uncommitted; #查看当前隔离级别 select @@global.tx_isolation,@@tx_isolation;
MySQL8中隔离级别的变量跟之前的版本不一样,之前是tx_isolation,MySQL8改成了transaction_isolation。

读已提交 read committed
事物A和事物B,事物A提交的数据,事物B才能读取到 这种隔离级别高于读未提交 换句话说,对方事物提交之后的数据,我当前事物才能读取到 这种级别可以避免“脏数据” 这种隔离级别会导致“不可重复读取” Oracle默认隔离级别
设置读已提交的隔离级别
set global transaction isolation level read committed; 查看当前隔离级别 select @@global.tx_isolation,@@tx_isolation;

可以看出,插入但没有提交,是读不出来的,提交之后才能读出来。
不可重复读和脏读的区别是,脏读读取到的是一个未提交的数据,而不可重复读读取到的是前一个事务已提交的数据。 而不可重复读在一些情况也并不影响数据的正确性,比如需要多次查询的数据也是要以最后一次查询到的数据为主。
可重复读 repeatable read
- 事务A和事务B,事务A提交之后的数据,事务B读取不到 - 事务B是可重复读取数据 - 这种隔离级别高于读已提交 - 换句话说,对方提交之后的数据,我还是读取不到 - 这种隔离级别可以避免“不可重复读取”,达到可重复读取 - 比如1点和2点读到数据是同一个 - MySQL默认级别 - 解决了 “不可重复读” 和 “幻读”
设置可重复读的隔离级别
set global transaction isolation level repeatable read; #查看当前隔离级别 select @@global.tx_isolation,@@tx_isolation;

可见,无论是删除还是添加,commit后都是成功的,但是另一边却还是读出原来的数据,这就是可重复读,读取的是备份数据不是真正的数据。
串行化 serializable
事务A和事务B,事务A在操作数据库时,事务B只能排队等待 这种隔离级别很少使用,吞吐量太低,用户体验差 这种级别可以避免“幻像读”,每一次读取的都是数据库中真实存在数据,事务A与事务B串行, 而不并发
设置串行化的隔离级别
set global transaction isolation level serializable; #查看当前隔离级别 select @@global.tx_isolation,@@tx_isolation;

七:隔离级别与一致性的关系

1174

被折叠的 条评论
为什么被折叠?



