第一讲 整体流程
学习极客时间 《MySQL实战45讲》
# 查看连接状态
show processlist;
长连接内存占用大如何解决?
- 定期断开长连接。使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连。
- 如果你用的是 MySQL 5.7 或更新版本,可以在每次执行一个比较大的操作后,通过执行 mysql_reset_connection 来重新初始化连接资源。这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态。
第二讲 redo log 与binlog
更新操作的流程
redo log
物理日志 redo log 用于保证 crash-safe 能力
binlog
归档日志
区别:
- redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。
- redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
- redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。
参数设置:
# 表示每次事务的 redo log 都直接持久化到磁盘。
innodb_flush_log_at_trx_commit=1
# 表示每次事务的 binlog 都持久化到磁盘。
sync_binlog=1
第三讲 事务隔离
- 事务的特性:原子性、一致性、隔离性、持久性
- 多事务同时执行的时候,可能会出现的问题:脏读、不可重复读、幻读
事务隔离级别:读未提交、读提交、可重复读、串行化
READ-UNCOMMITTED READ-COMMITTED REPEATABLE-READ SERIALIZABLE
- 配置方法:启动参数
transaction_isolation
- 事务隔离的实现:每条记录在更新的时候都会同时记录一条回滚操作。同一条记录在系统中可以存在多个版本,这就是数据库的多版本并发控制(MVCC)。
- 回滚日志什么时候删除?系统会判断当没有事务需要用到这些回滚日志的时候,回滚日志会被删除。
- 什么时候不需要了?当系统里么有比这个回滚日志更早的read-view的时候。
- 为什么尽量不要使用长事务。长事务意味着系统里面会存在很老的事务视图,在这个事务提交之前,回滚记录都要保留,这会导致大量占用存储空间。除此之外,长事务还占用锁资源,可能会拖垮库。
事务启动方式:
- 显式启动事务语句,
begin
或者start transaction
,提交commit
,回滚rollback
; set autocommit=0
,该命令会把这个线程的自动提交关掉。这样只要执行一个select语句,事务就启动,并不会自动提交,直到主动执行commit或rollback或断开连接。
- 显式启动事务语句,
- 建议使用方法一,如果考虑多一次交互问题,可以使用
commit work and chain
语法。在autocommit=1
的情况下用begin显式启动事务,如果执行commit则提交事务。如果执行commit work and chain
则提交事务并自动启动下一个事务。
读取异常
脏读,一个事务中读取到另一个事务未提交的数据。例如,事务 T1 读取到另一个事务 T2 未提交的数据,如果 T2 回滚,则 T1 相当于读取到了一个被认为不可能出现的值。
不可重复读,在一个事务中,当重复读取同一条记录时,发现该记录的结果不同或者已经被删除了;如在事务 T1 中读取了一行,接着 T2 修改或者删除了该行 并提交,那么当 T1 尝试读取新的值时,就会发现改行的值已经修改或者被删除。
幻读,通常是指在一个事务中,当重复查询一个结果集时,返回的两个不同的结果集,可能是由于另一个事务插入或者删除了一些记录。例如,事务 T1 读取一个结果集,T2 修改了该结果集中的部分记录 (例如插入一条记录),T1 再次读取时发现与之前的结果不同 (多出来一条记录),就像产生幻觉一样。
在可重复读隔离级别下,普通查询是快照读,只有当前读情况下,才可能出现幻读这种情况!!
幻读仅专指“新插入的行”,读取到行的更新不算幻读!!
隔离级别与读现象
隔离级别与读现象,性能依次下降。
隔离级别 | 脏读 | 不可重复读取 | 幻影数据行 | 隔离表现 |
---|---|---|---|---|
READ UNCOMMITTED | YES | YES | YES | 别人改数据的事务尚未提交,我在我的事务中也能读到。 |
READ COMMITTED | NO | YES | YES | 别人改数据的事务已经提交,我在我的事务中才能读到。 |
REPEATABLE READ | NO | NO | YES | 别人改数据的事务已经提交,我在我的事务中也不去读。 |
SERIALIZABLE | NO | NO | NO | 我的事务尚未提交,别人就别想改数据。 |
事务的启动时机
start transaction; # 1 并不是事务的起点
update xx set xx=xx; # 2
rollback; #3
在上面的语句中,实际上在语句2开始执行的时候,事务才正式启动。事务开始就立刻启动,用下面的语句
start transaction with consistent snapshot; # 直接开启事务
事务隔离级别总结
- 对于可重复读,查询只承认在事务启动前就已经提交完成的数据;
- 对于读提交,查询只承认在语句启动前就已经提交完成的数据(读提交每次在语句启动前都会生成新的readview);
- 更新数据都是先读后写的,而这个读,只能读当前的值,称为“当前读”(current read);
- 更新时,如果当前的记录的行锁被其他事务占用的话,就需要进入锁等待;
- 事务启动以前所有还没提交的事务,它都不可见。