数据库中有读锁(S锁)、写锁(X锁)、表锁、行锁等。S锁与X锁是互斥的,在读的时候不能写,写的时候不能读。表锁和行锁等其实指的是S锁和X锁的作用域,S锁和X锁是作用在行、页、还是整张表。
- 表锁:开销小,加锁快,一般不会出现死索,但是影响并发性能,并发性能差。系统升级,数据迁移时使用表锁 行锁:开销大,加锁慢,可能出现死锁,但是对并发性能影响小,并发性能好。
默认的select语句有锁吗?这个得看数据库引擎的事务的隔离级别。
并发过程中会出现的问题:
- 脏写: 事务中不加隔离级别脏读:事务中加隔离级别不可重复读:事务中加了隔离级别幻读:事务中加了隔离级别
通过事务的隔离级别就能解决上面的问题。事务是通过加锁的方式去解决上面的问题,在事务操作前给受影响的记录加锁,等事务结束的时候释放锁。那么是如果通过S锁和X锁来实现的呢?
怎样查询事务隔离级别和设置事务隔离级别呢?
MySQL的四种事务隔离级别 - 带着梦逃亡 - 博客园
事务的隔离级别与锁的关系:
1.没有隔离级别(不加事务???不对,应该是开启了事务,但是没有隔离级别),这个时候会发生脏写(也叫做 更新丢失)问题: 两个线程操作同一条数据,对其进行更新操作,更新会被覆盖。怎么解决这个问题呢? 应该要通过加锁去解决问题,而且应该是在 Read UnCommit这个隔离级别去解决的
2.Read UnCommit级别(读未提交):这个级别应该是解决了脏写的问题(通过加什么锁解决的? ??这个结论有待确认),但是还有脏读的问题。事务A去更新数据,另外一个并发事务B去读数据,事务B读到了事务A中没有提交的数据(被回滚了),这就是脏读。怎样解决事务B的脏读问题?通过加读锁(S锁)吗? 这其实就是两个并发事务,一个去读,一个去写,才造成了这个问题。
脏写是怎样解决的?锁是怎样加的呢?脏读是怎样造成的呢?
这个时候由于写操作对应的事务加了S锁,所以这个时候,其它并发事务不能再写???
只是在写的时候加了S锁,这样的话,其它任何事务都可以在任何时候读取这个数据,因为可以任意获取S锁,这就造成了脏读。
3.Read Commit: 这个级别解决了脏读的问题(通过加S锁解决的???),但是还是有问题,那就是不可重复读的问题。事务A去更新数据,另外一个并发事务B在更新前去读取数据,然后在事务A提交后,再去读取数据,事务B两次读取的数据不一致,这是不可重复读问题。怎样解决???通过加读锁(S锁)吗? 这其实也是两个并发事务,一个去读,一个去写,才造成了这个问题。
怎样解决脏读问题的?
读操作的事务,在读的瞬间加了读锁(S锁),读完之后立即释放,这样在读的时候就不能写;写事务整个加了X锁,这样在写事务的整个执行过程中,别的事务都不能读,防止了其它事务读取未提交的数据,这样就解决了脏读问题。 读与写两方一起防止脏读。
为什么又会有不可重复读和幻读问题?
4.Repeatable Read: 解决了不可重复读的问题(通过加S 锁实现的????), 但是这个级别还有幻读的问题。事务A要去增加一条数据,并发事务B在A增加前没有读到这条数据,然后事务A增加这条数据,然后事务B读到了这条数据,这条数据对事务B来说,就是突然出现了,这就叫做幻读。另外一种解释,事务B将表清空,然后事务A又插入一条数据,然后事务B发现表中又有数据,造成幻读。怎样解决???通过加读锁(S锁)吗? 这其实也是两个并发事务,一个去读,一个去写,才造成了这个问题。
怎样解决不可重复读问题?
读的时候要全程加读锁(S锁),这样的话,在整个事务过程中,任何其它事务不能写,这样的话,就可以保证两次读到的数据是一致的。当然了,写操作要加写锁,不然的话任何事务都可以做写操作。
5.串行化(Serializable): 可以解决幻读问题,是通过加写锁(X锁)的方式,就是直接给被操作记录加X锁,实现了串行化。但是这样会让事务串行执行,极大的降低并发性能。
为什么会出现幻读?
因为前面加的锁都是行锁,都是针对一行数据的操作,而幻读的问题要放眼于整张表,而不是具体某一行,例如事务A清空某张表,操作的是整张表,而不是具体某一行,这时候行锁对于整张表的操作没有意义,并发事务B可以不受任何限制(肯定不受行锁限制,因为我要插入新的一行,哪里来的行锁???)的随便插入一条数据,这样就造成了幻读。
怎样解决幻读?
在读的时候,整张表加读锁(S锁)
在写的时候,整张表加写锁(X锁)
小总结:脏读、不可重复读、幻读,都是由于并发事务中,一个事务去写数据,一个数据去读数据,脏读和不可重复读是针对具体某行的操作,所以需要加行锁;幻读是针对整张表的操作,所以需要加表锁。
其它知识点:事务的ACID:
仔细阅读下面的两篇文章:
Mysql的select加锁分析 - wintersoft - 博客园
【原创】MySQL(Innodb)索引的原理 - 孤独烟 - 博客园



