一.事务及其ACID属性
1.原子性:对数据进行修改时,要么都执行,要么都不执行(强调操作)
2.一致性:事务开启和完成时,数据状态需要一致,所有的数据必须保持完整,和原子性类似(强调数据)
3.隔离性:各个事务间互不干扰
4.持久性:事务完成后,数据的修改不会丢失。
并发事务处理带来的问题
1.脏写(更新丢失)
两个事务同时锁定一条数据,最后的更新覆盖了另一个事务的更新。
2.脏读
AB两个事务同事操作一条数据,A事务更新未提交,B数据读取到了这一条更新未提交的数据,并且在此数据上进行操作,如果A事务回滚,B读取的数据就无效了,不符合一致性。
3.不可重复读
一个事务多次相同查询,结果不一样。
4.幻读
事务A读取到了事务B提交的新增数据,不符合隔离性
事务隔离级别
常看当前数据库的事务隔离级别: show variables like 'tx_isolation';
设置事务隔离级别:
set tx_isolation='REPEATABLE-READ';
Mysql默认的事务隔离级别是可重复读,用Spring开发程序时,如果不设置隔离级别默认用Mysql设置的隔
离级别,如果Spring设置了就用已经设置的隔离级别
二.锁详解
锁分类
从性能上分为
乐观锁
(用版本对比来实现)和
悲观锁
从对数据库操作的类型分,分为
读锁和写锁
(都属于悲观锁)
读锁(共享锁,S锁(
S
hared)):针对同一份数据,多个读操作可以同时进行而不会互相影响
写锁(排它锁,X锁(e
X
clusive)):当前写操作没有完成前,它会阻断其他写锁和读锁
从对数据操作的粒度分,分为
表锁和行锁
表锁
每次操作锁住整张表。开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;
一般用在整表数据迁移的场景。
手动增加表锁
lock table
表名称
read
(
write
),表名称
2
read
(
write
);
查看表上加过的锁
show open
tables;
删除表锁
unlock tables;
读锁: 一个客户端锁住一张表后,其他客户端插入会等待锁释放
写锁: 一个客户端锁住一张表后,其他客户端所有对于这张表操作都会被阻塞
行锁
每次操作锁住一行数据。开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度最
高。
InnoDB与MYISAM的最大不同有两点:
InnoDB支持事务(
TRANSACTION)
InnoDB支持行级锁
一个session开启事务更新不提交,另一个session更新同一条记录会阻塞,更新不同记录不会阻塞
总结:
MyISAM在执行查询语句SELECT前,会自动给涉及的所有表加读锁,在执行update、insert、delete操作会自动给涉及的表加写锁。
InnoDB在执行查询语句SELECT时(非串行隔离级别),不会加锁。但是update、insert、delete操作会加行
锁。
简而言之,就是
读锁会阻塞写,但是不会阻塞读。而写锁则会把读和写都阻塞
。