表锁、行锁
表锁:偏向于myisam 锁的粒度大,速度快,开销小,无死锁,发生锁冲突频率高
myisam 偏读
lock table table_name read/write //锁表 读锁和写锁
unlock table_name //解锁
show open tables; //查看状态, in_use = 0 表示正常
读锁、写锁
读锁共享
写锁排他
读锁
session1 | session2 |
---|---|
获取读锁 lock table table_name read | |
可以读该表 不可以读其他的没有加锁的表(报错) | 可以读该表,可以读其他的表 |
不可以插入和更新该表(报错) | 不可以修改该表(阻塞),seesion1进行unlock后完成修改 |
不可以修改或其他的表(报错) | 可以修改或更新其他未锁定的表 |
写锁
session1 | session2 |
---|---|
获取写锁 lock table table_name write | |
可以对锁定的表正常的读写操作, | 其他session对锁定的表查询更新阻塞,需要等待释放锁 |
不可以查其他未锁定的表 |
读锁会阻塞写,不会阻塞读;写锁会把读和写都阻塞
行锁
偏向innodb存储引擎,开销大,加锁慢,会出现死锁,锁的粒度最小,发生锁冲突的概率最小
innodb与myisom的区别:1.支持事务;2.采用了行级锁。
事务
事务是由一组sql语句组成的逻辑处理单元,有一下4个属性,简称ACID
1.原子性 (atomicity) : 事务是一个原子操作单元,对数据的修改,要么全都执行,要么全都不执行。
2.一致性 (consisten): 在事务开始和完成时,数据都必须保持一致状态。这意味着所有相关的数据规则都必须应用于事务的修改,以保持事务的完整性;事务结束时,所有的内保部数据结果(如B数索引或双向链表,也都必须是正确的)
3.隔离性 (isolation): 数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行,这意为着事务处理过程中的中间 状态对外部是不可见的,反之亦然。
4.持久性 (durable) : 事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持
数据库的隔离级别
1.读未提交 read_uncommit
2.读已提交 read_commit -可解决脏读
3.可重复读 repeatable_read -可解决不可重复读
4.序列化 serializable -可解决幻读
并发事务处理的问题
1.更新丢失
2.脏读
3.不可重复读
4.幻读
1.更新丢失
当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生更新丢失的问题,最后 的更新覆盖了由其他事务所做的更新
如果在一个事务完成并提交事务之前,另一个事务不能访问同一行数据,则可以避免此问题
2.脏读
事务A读取了事务B已修改但尚未提交的数据,此时如果事务B回滚,事务A读取的数据无效
3.不可重复读
事务A读取数据后,再次读取时读到了事务B已经提交的修改数据,导致两次读取的数据不一致,不符合隔离性
4.幻读
事务A读取数据后,再次读取时读到了事务B已经提交的新增数据,导致两次读取的数据不一致,不符合隔离性
行锁
mysql在更新并且没有commit之前会锁定该行记录
mysql默认的隔离级别可重复读
set autocommit = 0; //设置手动提交
update tab set a= 1 wher a =2;
commit
会话2可以正常查,但是更新会阻塞,等待会话1commit
在更新的时候,where条件要匹配索引,才会锁一行
索引失效会导致行锁变为表锁, 会话1未使用索引更新未提交时,会锁整表的数据
锁定一行
begin
select * from table where id = 3 for update;
#do it ......
commit
行锁的优化建议
1.尽可能的所有数据检索都通过索引来完成,避免无索引行锁升级为表锁
2.合理设计索引,尽量缩小锁的范围
3.尽可能较少检索条件,避免间隙锁
4.尽量控制事务大小,较小锁定资源量和时间长度
5.尽可能低级别事务隔离