81-Trx

mysql_transactionopen in new window

0. Summary

  • Transation:一组操作的集合,把集合作为整体向系统提交。要么同时成功,要么同时失败
# 1. 查看mysql连接
show full processlist;

# 2.1. 查询mysql_trx
select * from information_schema.innodb_trx;

# 2.2. 查看mysql_trx
SELECT t.trx_mysql_thread_id,
       t.trx_state,
       t.trx_tables_in_use,
       t.trx_tables_locked,
       t.trx_query,
       t.trx_rows_locked,
       t.trx_rows_modified,
       t.trx_lock_structs,
       t.trx_started,
       t.trx_isolation_level,
       p.time,
       p.user,
       p.host,
       p.db,
       p.command
FROM information_schema.innodb_trx t
         INNER JOIN information_schema.processlist p
                    ON t.trx_mysql_thread_id = p.id;

# 3. 查看、设置事务提交方式
select @@autocommit;
set @@autocommit = 0;

# 4.1. 开启事务
begin;
start transaction;

# 4.2. 提交事务
commit;

# 4.3. 回滚事务
rollback;

1. 四大特性(ACID)

  1. 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败《undo_log》
    • 原子性关注状态,要么全部成功,要么全部失败,不存在部分成功的状态
  2. 一致性(Consistency):事务完成时,必须使用所有的数据都保持一致状态《A + I + D》
    1. 一致性关注数据的可见性,中间状态的数据对外部不可见,只有最初状态和最终状态的数据对外可见
    2. 数据库机制层面:数据会符合你设置的约束(唯一约束,外键约束,Check约束等)和触发器设置
    3. 业务层面:保持业务的一致性
  3. 隔离性(Isolation):通过隔离机制,保证事务在不受外部并发操作影响的独立环境下运行《锁》
  4. 持久性(Durability):事务一旦提交或回滚,它对DB中的数据的更改就是永久的《redo_log》

2. 并发问题

并发问题描述
脏读trx_A读到trx_B没有commit的数据
不可重复读trx_A先后读取一条记录,结果不同(在trx_A事务里,同一个sql两个结果)
幻读trx_A没有读到trx_B插入的数据,trx_A插入时却已经存在。好像出现了“幻影”

3. 隔离级别

  1. 事务隔离级别越高,数据越安全,但是性能越低
  2. Mysql默认:《repeatable read》
  3. Oracle默认:《read committed》
隔离级别脏读不可重复读幻读
read_uncommitted(读未提交)
read_committed(读已提交)
repeatable_read(可重复读)
serializable(串行化)

1. 原理

image-20220608144206857
隔离级别原理
read_uncommittedA、B直连DB
read_committedDB里数据实时更新到SDB。即:A可以看到B_commit的数据
repeatable_readDB里的数据不会更新到SDB。即:A看不到B_commit的数据。产生幻读,A插入B已经插入的数据失败
serializableA开启,B可以select操作,update,insert操作需要等待A的commit

4. 测试事务

# 1. 查询事务隔离级别
select @@transaction_isolation;

# 2. 设置会话隔离级别
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;

# 3. 设置全局隔离级别
set global transaction isolation level read uncommitted;
set global transaction isolation level read committed;
set global transaction isolation level repeatable read;
set global transaction isolation level serializable;
create table mysql_trx (
    id       varchar(36)                         not null primary key,
    name     varchar(255)                        null,
    age      int                                 null,
    upd_time datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP
);

create index idx_age
    on mysql_trx (age);

create index idx_name
    on mysql_trx (name);
# T1
# 查询事务隔离级别
select @@transaction_isolation;

# 设置会话隔离级别,仅针对本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;     -- 解决幻读

select @@autocommit;
# 仅针对本session
set autocommit = 0;

begin;

select * from mysql_trx;

# 测试幻读
insert into mysql_trx (id, name, age, upd_time)
values ('phantom_row', 'name', 1, now());

commit;
# T2
begin;

select * from mysql_trx;

insert into mysql_trx (id) values (uuid());

insert into mysql_trx (id, name, age, upd_time)
values ('phantom_row', 'name', 1, now());

commit;

5. 总结

  1. 现在学习的是DB级别的事务,需要掌握的就是事务的隔离级别和产生的数据不一致的情况
  2. 后续声明式事务、事务的传播特性、分布式事务