MySQL
事务学习
四大特性
-
原子性
原子性是指事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败
-
一致性
事务按照预期生效,数据的状态是预期的状态。
-
隔离性
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务, 不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
-
持久性
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的, 接下来即使数据库发生故障也不应该对其有任何影响。
俩个操作
-
提交
将事务执行结果写入数据库
-
回滚
回滚所有已执行的语句,返回修改之前的数据
锁机制
按照颗粒度划分
- 行锁
- 页锁
- 表锁
按照使用方式划分
- 共享锁
- 排它锁
按照思想划分
- 悲观锁
- 乐观锁
减少死锁的方式
- 自动死锁检测,优先回滚小事务
- 超时参数设置(
innodb*lock*wait_timeout
) - 尽量提交事务,小事务不容易产生死锁
- 加 for update、lock in share mode 读锁时,最好降低事务隔离级别,比如 rc 级别,降低死锁发生概率
- 事务中涉及多个表,或者涉及多行记录时,每个事务的操作顺序都要保持一致,降低死锁概率,最好用存储过程
- 通过索引等方式优化 sql 效率,降低死锁概率(目的是减少扫描 / 锁范围,降低概率)
并发读写带来的问题
-
脏读(Drity Read)
某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
-
不可重复读(Non-repeatable read)
在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。
-
幻读(Phantom Read)
在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就有几列数据是未查询出来的,如果此时插入和另外一个事务插入的数据,就会报错。
四种隔离级别
-
读未提交
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。读取未提交的数据,也被称之为脏读(Dirty Read)。可能会导致脏读、不可重复读以及幻读。
-
读已提交
事务A在读取数据时,事务B只能读取数据,不能修改,当事务A读取到数据后,事务B才能修改,这种 隔离级别可以避免脏读,但依然存在不可重复度以及幻读的问题。
-
可重复度
这是MySQL的默认事务隔离级别。事务A在没有结束事务时,事务B只能读取数据,不能修改,当事务A结束,事务B才能修改。它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
-
可串行化
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
评论区