Mysql的四大特性
- 原子性(Atomicity),事务要么全部做完,要么就全部不做,一旦事务的某一个环节出了差错,则把数据回滚。也就是说先化学里的原子一样,是不可分割的整体,同生共死。
- 一致性(Consistency),事务的完整性约束不能被破坏,也就是假如说转账,A的账户被扣除了钱,那么B的账户就一定会增加钱。
- 隔离性(Isolation),同一时间内,只允许一个事务去访问同一数据,而不同的事务之间彼此不干扰。
- 持久性(Durability),事务完成后,事务对于数据库的更新将被保存到数据库,不能回滚。
脏读,不可重复读,和幻读
脏读
线程A在读取数据库的数据的时候,线程B修改了数据库里的数据失败并回滚了,而这个时候线程A读取到了修改后回滚前的脏数据,这个就叫脏读。
小明去餐厅吃饭,点了一碗面,小刚拿错了面还加了辣椒吃了几口,但是小刚发现拿错了,于是把面吐了回去给小明,这时小明拿到的就是脏的面。然后小刚心里愧疚又叫了厨师做了一模一样的面放着。
不可重复读
线程A读取了数据库两次,当时线程B这个时候修改了数据库并提交,导致线程A两次读取的数据不一样,就叫不可重复读。
穆斯林小明去面馆吃面,看见顾客小刚在吃牛肉面,于是小明也想吃牛肉面,这个时候趁着小明不注意,小刚偷偷把牛肉换成了猪肉这样看你怎么学我啊。小明很疑惑不知道自己看见的牛肉面还是猪肉面。
幻读
线程A在获取了两次数据库里的信息时,线程B又往表里增添了一条数据并提交,导致线程A获取到的两个结果集合是不一样的,就叫做幻读。
小明去面馆吃面,顾客小刚在吃牛肉面,小刚趁着小明不注意,多加了一碗猪肉面,桌子上变成了两碗面,小明就很奇怪,为啥一转眼一碗面就变两碗面了。
数据库的隔离级别
读未提交
事务可以看见其他事务未提交的数据,安全性是最低,不可以避免脏读,不可重复度,幻读问题
读已提交
事务只能读取已经提交的数据,可以避免脏读,但是不能避免不可重复度和幻读。
可重复读
事务在并发读取数据的时候会读取到相同的数据,可以避免脏读和不可重复读,不能避免幻读
串行化
最高的安全等级,可以避免脏读,不可重复度和幻读,当时效率是最低的。
锁
行锁&表锁
只有指定了主键才会执行行锁,否则会支持表锁
select * from user where id=10 指定了主键,用行锁
select * from user where name='Tom' 主键模糊,使用表锁
select * from user where id=-1 主键不存在,没有锁
锁的机制
行锁机制
Record Lock(普通行锁)
- 键值对在条件范围内,精准命中
- 记录存在
Gap Lock
- 键值条件不明确,叫做间隙,引擎会将间隙加锁。
- 遵循左开右闭规则,例如查找1-4的资源,则会将234锁住,防止脏读和不可重复读。
例如查找主键1-3范围的数据,那么会将2,3锁住,防止幻读。
Next-Key-Lock
- 精准命中索引的范围,会触发,这个锁会把查询出来的记录都锁住,同时也会将间隙也锁住
- 这个锁是InnoDB引擎的默认锁
表锁
-
意向锁(升级)
当带着表锁的事务去访问一个被行锁锁住的资源的时候,行锁会升级成为意向锁。 -
自增锁
事务插入自增类型的列时,获得自增锁,其他事务必须等待。
共享锁和排它锁
- 共享锁(读锁)
共享锁又被称为读锁,一旦给资源上了共享锁,则该资源后续只能被上读锁,而不能上写锁,这样保证了在并发读取时数据无法被修改,但是可以被读取,防止了不可重复读。 - 排它锁(写锁)
排它锁又被称作写锁,一旦上了写锁,该资源后续无法上任何的锁,不能读取,也不能修改。避免了脏数据和脏读。