事务:transaction 一系列sql语句的逻辑单元 类似于java 中的线程
事务特性:ACID
A:atomicity 原子性:操作的一致性
C:consistant 一致性: 数据的一致性
I:isolation 隔离性:和别的事务隔离
D:durable 持久性
多事务并发问题:
脏写:最后一个事务的更新覆盖了前面事务的更新;
脏读:读取到了为提交的事务,回滚后出现脏数据;
不可重复读:同一个事务中,相同查询语句查出来的数据不一致;
幻读:本事务对其他事务 更改后的语句(insert delete update)提交后,进行更新,会出现别的事务操作的数据;
解决办法1:数据库的隔离级别
查询当前数据的隔离级别 show variables like 'tx_isolation';
设置隔离级别:set tx_isolation='repeatable-read' 设置了只对本客户端生效。
脏读 | 不可重复读 | 幻读 | 理解(操作是指 insert update delete) | |
读未提交(read-uncommitted) | 可能发生 | 可能发生 | 可能发生 | 查询和操作公用相同的数据,不同事务更改数据后其他事务可通过查询看到。事务提交后全部更新到公共缓存 |
读已提交(read-committed) | 解决 | 可能发生 | 可能发生 | 读取是当前事务中缓存的数据,操作数据在公共数据中操作 或者更改完数据同步到公共缓存中,操作完后更新本事务中的缓存数据。事务提交后全部更新到公共缓存 |
可重复读(repeatable-read) | 解决 | 解决 | 可能发生 | 默认是本级别。读取和操作数据都在事务缓存中,如果操作不在本缓存中的数据 需要到公共缓存中,update 数据后 更新到当前缓存中,事务提交后全部更新到公共缓存 |
串行化(serializable) | 解决 | 解决 | 解决 | 对本事务中的查询语句 在公共缓存中进行加锁,其他事务不可操作,保证数据的一致性。效率极低一般不采用 |
解决办法2 锁
操作颗粒度区分:
行锁:给数据行加锁。每次操作锁住一行数据。开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度最高。InnoDB与MYISAM的最大不同有两点:InnoDB支持事务(TRANSACTION)InnoDB支持行级锁
表锁:给整张表加锁,主要用于myisam 引擎,或者串行化中 无索引的条件字段 采用表锁。每次操作锁住整张表。开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;一般用在整表数据迁移的场景。
增加表锁
lock table tablename read(write);
查询当前加锁的表:show open tables;
解锁:unlock tables;
加行锁:sql语句后面 for update(排它锁 其余事务不能进行操作该语句查出来的数据) 若条件字段不是索引则锁全表
lock in share mode(共享锁)
读(select) | 操作(insert update delete) | 解释 | |||
当前session | other session | 当前session | other session | ||
表写锁 | 可 | 阻塞 | 可 | 阻塞 | |
表读锁 | 可 | 可 | 报错 | 阻塞 | |
行锁 | 可 | 可 | 可 | 阻塞 | InnoDB的行锁是针对索引加的锁,不是针对记录加的锁。并且该索引不能失效,否则都会从行锁升级为表锁。 |
间隙锁(gap lock) | 可 | 可 | 可 | 阻塞 | 就是锁两个值之间的间隙 |
for update(排它锁) | 可 | 可 | 可 | 阻塞 | 同行锁,手动增加的行锁,其他事务可以增加排斥锁 |
lock in share mode(共享锁) | 可 | 可 | 可 | 阻塞 | 同行锁,手动增加的行锁,其他事务可以增加共享锁 |
innodb | 不加锁(非串行隔离级别) | 加行锁 | |||
myisam | 加表读 | 加表写 |
那么间隙就有id为(3,10),(10,20),(20,正无穷)这三个区间,在Session_1下面执行updateaccountsetname='zhuge'whereid>8andid<18;,
则其他Session没法在这个范围所包含的所有行记录(包括间隙行记录)以及行记录所在的间隙里插入或修改任何数据,即id在(3,20]区间都无法修改数据,注意最后那个20也是包含在内的。间隙锁是在可重复读隔离级别下才会生效。
临键锁(Next-keyLocks):Next-KeyLocks是行锁与间隙锁的组合。像上面那个例子里的这个(3,20]的整个区间可以叫做临键锁。
性能上区分:
乐观锁:根据版本区分更新
悲观锁:
数据库的操作类型上区分 都属于悲观锁
读锁:共享锁,S锁(Shared)):针对同一份数据,多个读操作可以同时进行而不会互相影响
写锁:排它锁,X锁(eXclusive)):当前写操作没有完成前,它会阻断其他写锁和读锁
操作:
查询行锁的情况
对各个状态量的说明如下:
Innodb_row_lock_current_waits:当前正在等待锁定的数量
Innodb_row_lock_time:从系统启动到现在锁定总时间长度
Innodb_row_lock_time_avg:每次等待所花平均时间
Innodb_row_lock_time_max:从系统启动到现在等待最长的一次所花时间
Innodb_row_lock_waits:系统启动后到现在总共等待的次数
select * from information_schema.INNODB_TRX; 查看所有事务详情;
show PROCESSLIST; 查看连接的线程
select * from information_schema.INNODB_LOCKS; 查看拥有锁 并且等待这把锁的事务
select * from information_schema.INNODB_LOCK_WAITS; 查看等待的事务
show engine innodb status \G; 查看锁日志
结束进程:kill 线程id;