mysql第三天 事务

时间:2021-03-05 20:55:15

ACID

  • A : 原子性 要么全提交成功,要么全失败回滚
  • C:一致性 是从一个一致性状态到另外一个一致性状态。 意思就是说能量守恒。
    还有的人理解其是外键的定义,即对于有班级的学生,不能创建一个不指定班级的学生
    还有人认为一致性和原子性共同满足了全好全坏的限定。
    我认为在分布式数据库中这个概念才更有意义,如何做到多几点的一致性
  • I:隔离性 跟隔离级别相关,通常来说,事物看不到其他未提交的事务的状态
  • D:持久性 事务一旦提交,所做的修改就是永久保存的

隔离级别

先看一下事务并发操作可能遇到的问题:

  • 脏读
    A 修改数据,未提交。 B读取到了A修改后的数据, 如果A提交失败那么该修改就不会生效因此就造成了B读取到了脏数据。
  • 不可重复读
    A事务两次读取同一行数据,B事务在两次之间修改了数据并提交,导致了A前后两次读取数据的不一致。
    可以使用行锁来解决,但是会减少性能,还可以使用MVCC策略解决
  • 幻读
    A事务读取范围数据, B事务在范围之间删除或者新增了数据,A事务再次读取该范围时数据发生了变化。
    可以使用间隙锁解决,还可以使用MVCC策略,这样可以减少阻塞。

mysql 中设置隔离级别

my.ini

#可选参数有:READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE.
[mysqld]
transaction-isolation = REPEATABLE-READ

当前session

SELECT @@tx_isolation;
set transaction isolation level read uncommitted;
set transaction isolation level read committed;
set transaction isolation level repeatable read;
set transaction isolation level serializable;

再看看隔离级别对应解决了的问题

READ UNCOMMITED

//session1
set autocommit = 0;
set transaction isolation level read uncommitted;
begin;
update biz_pay_task set pin = 'test1' where id=1;

// session 2
set autocommit = 0;
set transaction isolation level read uncommitted;
select * from biz_pay_task where id=1;

// session1,2
rollback;
  • 可以看到session2能够读取到未交的session1中的数据
  • 因此上面三个问题都有可能发生

READ COMMITED

// session 1,2
set transaction isolation level read committed;
// session 1
update biz_pay_task set pin = 'test1' where id=1;
// session 2
select * from biz_pay_task where id=1;
// session 1
commit;
// session 2
select * from biz_pay_task where id=1;
rollback;
  • 可以看到session2只能够查看到sesssion1中已经提交了的变更。
  • 避免了脏读
  • 很多数据库默认都是这个级别

REPEATABLE READ

// session 1,2
set transaction isolation level repeatable read;
begin;
// session 1
update biz_pay_task set pin = 'test2' where id=1;
commit;
// session 2
select * from biz_pay_task where id=1;
rollback;
begin;
select * from biz_pay_task where id between 1 and 3;
// session 1
begin;
delete from biz_pay_task where id=2;
// session 2
select * from biz_pay_task where id between 1 and 3;
// session 1
commit;
// session 2
select * from biz_pay_task where id between 1 and 3;
rollback;
  • session2事务开始后,session1所有的提交都对其没有影响
  • 可重复读这个隔离级别避免了 不可重复读以及幻读的问题。
  • 幻读问题本来并不是这个隔离级别能完成的,mysql通过mvcc的机制在这个隔离级别完成了
  • 是mysql的默认隔离级别

SERIALIZABLE

强制事务顺序执行

事务日志

mysql使用事务日志来提高写的性能,不是每次都用随机IO来写硬盘,
而是先写内存,记录硬盘一小块区域顺序io的写日志
另外有线程把事务日志回写回数据区域硬盘