众所周知,MySQL的存储引擎有MyISAM和InnoDB,锁粒度分别是表锁和行锁。
后者的出现从某种程度上是弥补前者的不足,比如:MyISAM不支持事务,InnoDB支持事务。表锁虽然开销小,锁表快,但高并发下性能低。行锁虽然开销大,锁表慢,但高并发下相比之下性能更高。事务和行锁都是在确保数据准确的基础上提高并发的处理能力。下面分别进行介绍:
行锁
行锁的劣势:
- 开销大;
- 加锁慢;
- 会出现死锁
行锁的优势:
- 锁的粒度小,发生锁冲突的概率低;
- 处理并发的能力强
加锁的方式:
- 自动加锁:对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁;
- 无锁:对于普通SELECT语句,InnoDB不会加任何锁;当然我们也可以显示的加锁:
- 共享锁:select * from tableName where ... + lock in share more
- 排他锁:select * from tableName where ... + for update
InnoDB和MyISAM的最大不同点有两个:
- InnoDB支持事务(transaction);
- 默认采用行级锁。
加锁可以保证事务的一致性,下面我们来学习一下MySQL的事务知识.
MySQL 事务属性
事务是由一组SQL语句组成的逻辑处理单元,事务具有ACID属性。 原子性(Atomicity):事务是一个原子操作单元。在当时原子是不可分割的最小元素,其对数据的修改,要么全部成功,要么全部都不成功。 一致性(Consistent):事务开始到结束的时间段内,数据都必须保持一致状态。 隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的"独立"环境执行。 持久性(Durable):事务完成后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。
事务常见问题
更新丢失(Lost Update) 原因:当多个事务选择同一行操作,并且都是基于最初选定的值,由于每个事务都不知道其他事务的存在,就会发生更新覆盖的问题。类比github提交冲突。
脏读(Dirty Reads) 原因:事务A读取了事务B已经修改但尚未提交的数据。若事务B回滚数据,事务A的数据存在不一致性的问题。
不可重复读(Non-Repeatable Reads) 原因:事务A第一次读取最初数据,第二次读取事务B已经提交的修改或删除数据。导致两次读取数据不一致。不符合事务的隔离性。
幻读(Phantom Reads) 原因:事务A根据相同条件第二次查询到事务B提交的新增数据,两次数据结果集不一致。不符合事务的隔离性。
幻读和脏读有点类似 脏读是事务B里面修改了数据, 幻读是事务B里面新增了数据。
事务的隔离级别
数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大。这是因为事务隔离实质上是将事务在一定程度上"串行"进行,这显然与"并发"是矛盾的。根据自己的业务逻辑,权衡能接受的最大副作用。从而平衡了"隔离" 和 "并发"的问题。MySQL默认隔离级别是可重复读。 脏读,不可重复读,幻读,其实都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决。
+------------------------------+---------------------+--------------+-----