事务
一个数据库事务由一条或多条sql语句构成,形成一个逻辑的工作单元。这些sql语句要么全部执行成功,要么全部执行失败。
事务是保证数据的完整性和一致性的重要手段。
事务是并发控制的基本单位。
事务的类型
DML事务:由一条或者多条DML语句构成(create\alter\drop等),自动commit。
DDL事务:总是由一条DDL语句构成
当自动提交关闭时,事务开始分两种情况
隐式开始:程序的第一条DML语句执行时或者在commit或rollback语句之后执行的第一条DML语句时,自动开始一个新的事务
显式开始:发出start transaction语句,该语句会关闭自动提交,当事务结束后,autocommit恢复到原来的值
DCL事务:总是由一条DCL语句构成(grant\revoke语句),自动commit。
在MySQL中,自动提交系统变量@ @ autocommit默认打开,即任何1条SQL语句都会开始一个事务,语句执行完后事务自动结束。
show variables like "autocommit%"; 查看变量
set @@autocommit=0; 修改变量关闭(只影响当前终端)
set @@autocommit=1; 修改变量打开
事务的控制
commit 提交 --》 数据从内存写入磁盘 --》事务执行成功
rollback 回滚 --》 删除在内存里的数据的修改 --》事务执行失败
其他事务控制语句
savepoint identifier :保存点命令,在事务中做一个标记,专门提供给rollback语句使用。 例 savepoint a
rollback to [savepoint] identifier:回滚到保存点,保存点之后所做的工作全部撤销,并不结束事务。 例rollback to a
并发事务的4个问题
(1)脏读
一个事务读到了另一个事务未提交commit的数据
(2)不可重复读
在同一个事务中,同样的条件读取过的数据再次读取出来时发现值不一样了(数值被修改)
(3)幻读
在同一个事务中,同样的条件,第1次和第2次读出来的记录数不一样(数据新增或删除)
(4)丢失修改
一个事务的修改覆盖了另一个事务的修改
事务的隔离级别 isolation level
(1)REPEATABLE READ 可重复读(mysql默认)
不允许脏读、不可重复读、幻读问题;允许丢失修改问题;
(2)read committed 读已提交
不允许脏读问题;允许不可重复读、幻读、丢失修改问题
(3)read uncommutted 读未提交
允许脏读、
(4)SERIALIZABLE serializable 串行化
不允许脏读、不可重复读、幻读、丢失修改问题
●查看数据库当前会话的事务隔离级别
show variables like "tx_isolation";
select @@ GLOBAL.tx_isolation, @@ tx_isolation; GLOABL指全局变量
●设置事务隔离级别
set GLOBAL tx_isolation='REPEATABLE-READ'; 全局数据库
set SESSION tx_isolation='SERIALIZABLE'; 当前会话
事务的ACID特性
●原子性
一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
●一致性
事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
●隔离性
一个事务执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
●持久性/永久性
一个事务一旦提交,则它对数据库中数据的改变是永久性的。
锁 lock
解决事务问题的办法
mysql允许客户端会话显式的获得一个表锁,以防止其他会话被修改。
lock tbale t1 kock_type[READ][WRITE]
lock tables语句会自动commit 前面的所有内容
unlock tables 释放当前会话持有的所有表锁(一释放其他会话立即可以写入)
锁的分类
● 行锁 ---- 对某些行锁定
● 表锁 ---- 对整个表锁定
● 读锁 ----- READ 当前会话和其他会话可以读表,但是不能修改表(lock table t1 READ)
● 写锁 ----- WRITE 当前会话可以读写表,但是其他会话既不能读也不能写( lock table t1 WRITE)
● 共享锁
对查询到的行加共享锁,其他会话将不能修改它们,除非结束事务释放锁。
select * from t1 where id = 3 lock in share mode;
● 排他锁
对查询得到行及相关的索引加排他锁。其他事务将不能修改它们。不能加锁。
select * from t1 where id = 3 for update;
● 其他锁
死锁
有两个事务A和B,A持有资源a等待b资源,B持有资源b等待a资源,两个进程都在等待另一个资源的同时不释放资源,就形成死锁。
解决死锁
1、抢占资源。
从一个或多个进程中抢占足够数量的资源,分配给死锁进程,以解除死锁状态。
2、终止(撤销)进程
将一个或多个进程终止(撤销),直至打破循环环路,使系统从死锁状态解脱。
预防死锁
破坏请求和保持条件:
1.一次性的申请所有资源。之后不再申请资源,如果不满足资源条件则得不到资源分配。
2.只获得初期资源运行,之后将运行完的资源释放。请求新的资源
被坏不可抢占占条件:
当一个进程获得某种不可抢占资源,提出新的资源申请,若不能满足,则释放所有资源。以后需要,再次重新申请。
破坏循环等待条件:
对资源进行排号,按照序号递增的顺序请求资源。若进程获得序号高的资源想要获取序号低的资源,就需要先释放序号高的资源。
活锁
有多个事务都想对数据进行操作,T1先获取资源封锁了数据,于是T2等待,T3又封锁了数据,于是T2又等待,T2一直获取不到资源。