刘鸿宁,你看到了吗?????????
InnoDB 与 myisam 的区别?
-
在MySQL 5.1 及之前的版本,MyISAM是默认引擎。
-
在MySQL以后,支持InnoDB,InnoDB支持事务,行锁。
-
InnoDB 和 myisam都支持索引,但是InnoDB的索引是聚集索引,效率更高,Myisam的索引是非聚集索引,需要进行回表操作,效率更低。
-
InnoDB的每一行都是一个事务。
update STUDENT set name = “刘鸿宁” where id = 888
等效于:
BEGIN
update STUDENT set name = “刘鸿宁” where id = 888
COMMIT
数据库事务
什么是事务
- 事务是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;
- 这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;
- 事务是一组不可再分割的操作集合(工作逻辑单元);
事务的特性
- 原子性_Atomicity
- 一致性_Consistency
- 隔离性_Isolation
- 持久性_Durability
-
原子性指的是一个事务中的操作要么全部成功,要么全部失败。
-
一致性指的是数据库总是从一个一致性的状态转换到另外一个一致性的状态。比如A转账给B100块钱,假设中间sql执行过程中系统崩溃A也不会损失100块,因为事务没有提交,修改也就不会保存到数据库。
-
隔离性指的是一个事务的修改在最终提交前,对其他事务是不可见的。
-
持久性指的是一旦事务提交,所做的修改就会永久保存到数据库中。
事务的隔离级别
而隔离性有4个隔离级别,分别是:
-
read uncommit 读未提交,可能会读到其他事务未提交的数据,也叫做脏读。
-
read commit 读已提交,两次读取结果不一致,叫做不可重复读。不可重复读解决了脏读的问题,他只会读取已经提交的事务。
用户开启事务读取id=1用户,查询到age=10,再次读取发现结果=20,在同一个事务里同一个查询读取到不同的结果叫做不可重复读。 -
repeatable read 可重复复读,这是mysql的默认级别,就是每次读取结果都一样,但是有可能产生幻读。
-
serializable 串行,一般是不会使用的,他会给每一行读取的数据加锁,会导致大量超时和锁竞争的问题。
隔离级别比较
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | 可能 | 可能 | 可能 |
读已经提交 | 不可能 | 可能 | 可能 |
可重复读 | 不可能 | 不可能 | 可能 |
序列化 | 不可能 | 不可能 | 不可能 |
并发性能越来越低
锁的类型有哪些呢?
行锁和表锁 、 共享锁和排他锁 、 乐观锁和悲观锁、意向共享锁 和 意向排他锁 、间隙锁和 临键锁 和行锁
-
行锁和表锁,行锁 锁的是一行,表锁 锁的是一个表。 行锁的并发效率比表锁的高,但是锁定粒度,加锁效率、冲突概率都比表锁小。
-
共享锁和排他锁(读锁和写锁),可以多个事务加共享锁,排他锁只能一个事务加。
-
mysql锁分为共享锁和排他锁,也叫做读锁和写锁。
-
读锁是共享的,可以通过lock in share mode实现,这时候只能读不能写。
-
写锁是排他的,它会阻塞其他的写锁和读锁。从颗粒度来区分,可以分为表锁和行锁两种。
-
表锁会锁定整张表并且阻塞其他用户对该表的所有读写操作,比如alter修改表结构的时候会锁表。
-
行锁又可以分为乐观锁和悲观锁,悲观锁可以通过for update实现,乐观锁则通过版本号实现。
-
意向共享锁 和 意向排他锁 来告诉用户是否有共享锁或者排他锁。
-
间隙锁、 临键锁 、行锁
https://blog.youkuaiyun.com/weixin_43732955/article/details/104697551
https://www.jianshu.com/p/bf862c37c4c9
间隙锁、 临键锁 、行锁 加锁的基本原则(RR隔离级别下)
原则1:加锁的对象是next-key lock。(是一个前开后闭的区间)
原则2:查找过程中访问到的对象才加锁
优化1:唯一索引加锁时,next-key lock退化为行锁。;
索引上的等值查询,向右遍历时最后一个不满足等值条件的时候,next-key lock 退化为间隙锁
唯一索引和普通索引在范围查询的时候 都会访问到不满足条件的第一个值为止
————————————————
版权声明:本文为优快云博主「莫失莫忘hh」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/weixin_43732955/article/details/104697551
0 —5 —10—15—20—25
间隙锁:
(-inf,0) (0,5) (5,10) (10,15) (15,20) (20,25) (25,+inf)
begin
update set d=d+1 where id=7
end
锁的是 (5,10)
begin
select * from where id>=10 and id <11
end
锁的是 (5,10] and (10,15] 因为是范围查找,所以不进行优化
mvcc实现原理
https://www.jianshu.com/p/8845ddca3b23
mvcc multi-Version Conncurrency control
实现数据库并发访问控制
当前读:读取当前记录最新版本
快照读:读取版本控制后的记录版本
隐藏字段:
DB_TRX_ID 修改的事物ID/最后修改事务的ID
DB_ROLL_PTR 回滚指针
DB_ROW_ID 自增ID
insert undo log
update undo log
有一个事务,操作Person表,插入一条数据,
name | age | 自增ID | 回滚指针 | 修改ID |
---|---|---|---|---|
tom | 24 | 1 | NULL | NULL |
现在来了一个事物,修改name为Jerry,步骤:
- 给这条记录加排它锁
- 将数据拷贝到undo log,作为旧记录,
- 修改值为Tom,修改的事务ID为1,指针指向在undo log的记录。
- 事物提交后,释放锁
Read View 里面有 当前活跃事物列表 活跃最大事务ID 活跃最小事务ID
在判断某个版本是否可见时:
- 首先比较DB_TRX_ID 小于最小的,则是可见的
- 如果大于最大ID,则不可见
- 如果在活跃的ID里面,是不可见的,如果不在活跃ID中(已经提交),则是可见的。
RC 每次都 重新读 ReadView
RR 读的都是第一个 ReadView