推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习
1.事务是什么
事务就是从一种一致性状态到达另一种一致性状态。
语句
- START TRANSACTION | BEGIN
- COMMIT
- ROLLBACK
- SAVEPOINT identifier
- ROLLBACK TO SAVEPOIN
2.ACID特性
原子性(A)
事务提交要么都做,要么都不做。
一致性(C)
一个事务单元只有在提交事务后才能被其他事务可见。
隔离性(I)
多条连接同时处理数据,互相不影响。为了提高性能,通过粒度锁,设置不同的隔离级别。
持久性(D)
DML操作进行持久化,即便宕机,根据日志可以找回数据。
3.隔离级别
READ UNCOMMITTED
读未提交,该级别下读不加锁,写加排它锁,写锁在事务提交或回滚后释放锁。
READ COMMITTED
读已提交RC,从该级别后支持MVCC,也就是提供一致性非锁定读;此时读取历史快照数据;该隔离级别下读取历史版本最新数据,所以读取的是已提交的数据。
REPEATABLE READ
可重复读RR,支持MVCC,此时读取操作读取事务开始的版本数据。
SERIALIZABLE
串行化,支持MVCC,隔离级别最高。
命令:
–设置级别隔离
SET GLOBAL |SESSION TRANSACTION ISOLATION LEVE REPEATABLE READ;
SET @@tx_isolation=‘REPEATABLE READ’;
SET @@global.tx_isolaction =‘REPEATABLE READ’;
–查看全局级别隔离
SELECT @@global.tx_isolation;
–查看当前级别隔离
SELECT @@session.tx_isolation;
SELECT @@tx_isolation;
–手动给读加S读锁
SELECT … LOCK IN SHARE MODE;
–手动给读加X写锁
SELECT …FOR UPDATE;
–查看当前锁信息
SELECT &FROM information_schema.innodb_locks;
S共享锁:
事务读操作加的锁,对每一行加锁,只有串行化会默认加S锁。
x排它锁:
事务删除或者更新加的锁,对某一行加的锁。四种隔离级别都加了这个锁。
IS意向共享锁:
意向锁就是告诉其他事务,本表正在使用。作用排除表锁读。插入时先加IS,再加X。间接使用排他锁。
IX意向排它锁:
意向锁和全表级别的读写锁才会冲突,意向所只会和行锁冲突,行锁才会和行锁冲突。
GAP LOCK间隙锁和NEXT-KEY 锁这两个锁只有在READ REPEATE 级别下存在。间隙锁锁定一个范围,但不包记录本身,全开区间NEXT-KEY 是记录锁+间隙锁,锁定一个范围并且记录本身,左开右闭区间。这两个锁经常造成死锁。
INSERT INTENTION LOCK,比如要在1,7行插入,有插入意向锁就可以同时并发插入3,4。提升插入间隙的并发性能。
AUTO INCR-LOCK 自增锁较低概率造成B+树的分裂,提升了自增长值插入性能。
脏读
事务A读到了另一个事务未提交的事务。
不可重复读
事务A可以读到事务B提交的数据,通常发生在一个事务中读到了事务不一样的数据。
幻读
两次读取同一范围的数据,结果集(多了或者数据不一样了)不一样。不可重复读指的是行数据,幻读指的是范围。
事务开始前加锁是持续锁,事务提交或回滚时才释放锁。
丢失更新
两个事务都是写,分为提交覆盖和回滚覆盖。回滚覆盖已经被数据库拒绝。
查看死锁
–开启标准监控
- CREATE TABLE innodb_monitor(a INT) ENGINE=INNODB;
–关闭标准监控 - DROP TABLE innodb_monitorl
–开启锁监控 - CREATE TABLE innodb_lock_monitor ( INT ) ENGINE=INNOB;
–关闭锁监控 - DROP TABLE innodb_lock_monitor
–开启标准监控
- set GLOBAL innodb_status_output_ON;
–关闭标准监控 - set GLOBAL innodb_status_status_output=OFF;
–开启锁监控 - set GLOBAL innodb_status_outpus_locks=ON;
–关闭锁监控 - set GLOBAL innodb_status_output_locks=OFF;
–将死锁信息记录在错误日志中 - set GLOBAL innodb_print_all_deadlocks=ON;