事务和其ACID属性
- Atomicity 原子性
- Consistent 一致性
- Isolation 隔离性
- Dureble 持久性
事务的隔离级别
- read uncommitted
- read committed
- repeatable read(innodb默认级别)
- serializable
并发事务带来的问题
- 丢失更新(需要应用程序使用乐观锁来解决)
- 脏读 (使用read committed 解决)
- 不可重复读 (update引起的问题,使用repeatable read解决)
- 幻读 (insert、delete引起的问题,使用serializable解决)
innodb锁的实现方式
- record lock :行锁是通过给索引项加锁来实现的。给索引加锁。
- gap lock:对索引项之间的“间隙”加锁。(通过锁间隙,来锁即将到来的幻读数据)
- next-key lock:上面两种的组合。
innodb的这种锁实现意味着,如果不是通过索引(任何类型的索引)检索数据(就算使用了索引,但是mysql选择使用全表扫描则就是没使用索引),那么innodb将对表中的所有记录加行锁,效果同表锁。
Multi-Version Concurrency Control 多版本并发控制
在MVCC并发控制中,读操作可以分成两类:快照读 (snapshot read)与当前读 (current read)
- 快照读,读取的是记录的可见版本 (有可能是历史版本),不用加锁。
- 当前读,读取的是记录的最新版本,并且,当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录。
快照读:innodb 下,除了serializable隔离级别时,select 是当前读,加S锁,其他情况都是快照读,不加锁。
select * from table where ?;
(insert into t select * from t1 where 和 create table t select * from t1 where 这两种情况在innodb_locks_unsafe_for_binlog的值为默认“off”时,会使用当前读,为t1表加S锁,保证binlog的正确,使用binlog实现的主从,binlog实现的复制和恢复数据时要注意。推荐不使用以上两个sql,而使用select * from t1 …into outfile 和 load data infile … 实现,就不会给t1表加锁)
当前读:特殊的读操作,插入/更新/删除操作,属于当前读,需要加锁。
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 ?;