Ⅰ、事务概述
- 事务是一个程序的执行单元
- 事务由一组sql组成(可以是1条或者多条)
tips:
一个事务可以有多条sql组成,tps是每秒的事务量,仅仅通过tps判断业务量高和低是不太准确的,如果事务里面sql比较多,即使tps比较低,那实际qps又是比较高的
Ⅱ、事务的特性
大家都知道事务的特性叫ACID,我们这把用很通俗的语言来描述这四个特性,具体实现后面再分析
- A——atomicity(原子性)
一个事务内所有sql操作是原子的,要么都做要么都不做
原子性由redo保证
- C——consistency(一致性)
事务前后状态保持一致,不破坏数据结构和约束
一致性由undo保证
- I——isolation(隔离性)
一个事务所做的修改对其他事务不可见,好似串行执行(和事务隔离级别是两个概念)
隔离性由lock保证
- D——durable(持久性)
一旦写了,数据不会丢失
持久性由redo和undo保证
Ⅲ、事务的类型
事务类型 | 说明 |
---|---|
flat transactions | 扁平事务,最常见的事务 |
flat transactions with savepoints | 带保存点的事务 |
chained transactions | 链事务,一个事务commit之后自动begin,没意义 |
nested transactions | 嵌套事务,目前无数据库支持 |
distributed transactions | 分布式环境下的扁平事务,每个节点支持acid,这是事务acid更高的标准 |
long transactions | 运行时间非常长的事务,比如银行利息业务,这种事务会主从延迟,尽量拆成小事务(和online ddl用pt一样,不是为了加速,而是变慢达到降低主从延迟的目的) |
tips:
-
分布式事务案例:工行转账1w元到农行
其实这个并不是用分布式事务做的,骗骗人的,所有银行网络打通?不存在的,后面详细讲这个问题
-
主从延迟是mysql这几年面临的比较头疼的问题,主从复制的机制是用binlog来搞而不是像oracle那样用物理日志做
-
innodb除了嵌套事务其他都支持,myisam不支持事务
Ⅳ、事务操作
4.1 开启/关闭事务
法1:
begin;
xxx...;
commit/rollback;
法2:
start transaction;
xxx...;
commit/rollback;
为什么有第二种方法?
因为begin在存储过程中是一个关键字,嘿嘿...
-
一个好习惯
1、不管做什么,先打个begin,安全,不打begin就会auto commit自动提交,oracle不会自动提交
2、show variables like 'autocommit'; 默认值是1 这个设成0,这样再直接delete就可以rollback
4.2 另一个玩法
begin;
aaa
savepoint s1; 设置一个保存点
bbb
rollback to s1; 回滚到aaa,aaa还没提交
这时候新开一个session,进去是看不到aaa的
最后还要commit或者rollback,当然也可以继续执行其他操作再去commit或者rollback
4.3 线上常见问题一例
线上业务经常会碰到代码里没有commit,导致事务对应的所有的锁占用的资源都没有释放,导致其他线程使用到对应资源都没办法提交
如何发现?
show processlist;满足如下4个条件:
1、用户是开发的账号
2、Command为sleep
3、Time非常大
4、Info为NULL
tips:
-
线上sleep的线程很多没问题,但是这个time并不会很高
-
通常我们用的都是线程池自动维护线程的活跃,每隔一段时间会维护一次(发个select 1来保持连通性,所以这个time应该和维护周期是一致的),发现不对劲我们可以手动kill掉这些进程
-
select * from information_schema.innodb_trxG也可以看,不过上面那种更方便