MySQL | Oracle | |
默认事务级别 | 可重复读(Repeatable read) | 已提交度(Read committed) |
读数据一致性 | 事务级 | 语句级 |
事务级别问题 | 幻读,由于GAP锁的存在,可以解决幻读的情况。 | 不可重复读,幻读 |
事务加解锁情况 | 事务处理阶段只加锁,commit时才进行解锁 | |
MVCC (读可不加锁,读写不冲突,乐观锁) | repeatable read级别下,总是读取当前 事务开始时的 快照数据。 | read committed级别下,对快照数据总是读取 最新一份的 快照数据; |
加锁情况 | 快照读:简单的select操作,属于快照读,不加锁。(当然,也有例外,下面会分析) select * from table where ?; ==================================================== 当前读:特殊的读操作,插入/更新/删除操作,属于当前读,需要加锁。 select * from table where ? lock in share mode; select * from table where ? for update; insert into table values (…); update table set ? where ?; delete from table where ?; 所有以上的语句,都属于当前读,读取记录的最新版本。并且,读取之后,还需要保证其他并发事务不能修改当前记录,对读取记录加锁。其中,除了第一条语句,对读取记录加S锁 (共享锁)外,其他的操作,都加的是X锁 (排它锁)。 | |
锁升级 | 在InnoDB中有两种情况下会发生这种升级的情况: 单独的SQL语句在一个对象上持有的锁数量超过阈值,默认为5000条。 【需要是统一个对象的,不同对象不叠加】 锁资源占用的内存超过了激活内存的40%的情况。 | |
阻塞情况 | 在事务中的锁冲突,需要等待其他线程释放资源的情况。默认情况下等待时间50秒,并且超时不会滚的。 所以大事务情况,很危险。 | |
各种情况 | 情况1:update和delete语句的条件where必须使用索引,并且尽可能使用主键索引。 否则,全表扫描会出现大量锁数据的情况。 (即使高版本对此做了优化,在条件过滤之后,会解锁,但加解锁的开销依旧很大) | |
情况2:尽量不使用select...for update 语句。 会导致,数据被加上X锁,使的事务提交前,所有当前读操作等待。 通常也就是,其他事务的更新。 | ||
情况3:不创建相同字段的索引。(通常不创建唯一索引,可在业务层处理) X锁定数据的同时,也会在对应索引上加X锁。 RR事务级别,在索引上还会加上GAP锁。 (例如:创建user_id的普通和唯一索引。 小杭个人分析认为,此情况下,通过普通索引update对数据加X锁时,会同时在唯一索引上也加上X锁。如此时,唯一索引被其他update使用,则会死锁,加锁是顺序的。) 具体解释看索引更新情况,更新的时候是会锁住的。 | ||
索引更新 | 对于数据的每一次更新,MySQL并不会每次都会更新索引(针对非唯一性索引而言) 在InnoDB中,增删改都会立刻修改主键or唯一索引,但是不会rebuild全局索引,对于非唯一性索引,InnoDB会进行change buffering操作。 参考:https://dev.mysql.com/doc/refman/8.0/en/innodb-change-buffer.html | |
参考文章: | https://blog.csdn.net/xiaohangblog/article/details/96349540 | |
https://www.jianshu.com/p/13f5777966dd |
关于MySQL的事务和使用注意等
最新推荐文章于 2021-12-22 09:57:13 发布