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的写日志
另外有线程把事务日志回写回数据区域硬盘