事务有以下4个特性:
(1)原子性:事务中所有的操作视为一个原子单元,即对于事务所进行的数据修改等操作只能是完全提交或者完全回滚。
(2)一致性:事务在完成时,必须使所有的数据从一种一致性状态变更为另外一种一致性状态,所有的变更都必须要应用于事务的修改,以确保数据的完整性。
(3)隔离性:一个事务中的操作语句所做的修改必须与其他事务所做的修改相隔离。在进行事务查看数据时数据所处的状态,要么是被另一并发事务修改之前的状态,要么是被另一个并发事务修改之后的状态,即当前事务不会查看另一个并发事务正在修改的数据,这种特性通过锁机制实现。
(4)持久性:事务完成之后,所做的修改对数据的影响是永久的,即使系统重启或者出现系统故障数据仍可以恢复。
事务隔离级别:
可以通过以下语句设置事务隔离级别:
(1)未提交读
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
(2)提交读
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
(3)可重复读
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
(4)可串行化
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
未提交读(READ UNCOMMITTED)
在此隔离级别,所有事务都可以看到其他未提交事务的结果,他会导致脏读
脏读:事务A会读取事务B未提交的内容
同时开启事务A和B,在B事务·更新但是未提交之前,A事务读取到了更新后的数据,但由于事务B回滚,A事务出现脏读。
提交读( COMMITTED)
一个事务从开始到提交之前所做的改变都是不可见的,事务只能看见已经提交的事务所做的改变,这种隔离级别也支持所谓的不可重复读,因为同一事物的其他势力在该实例处理期间可能会有新的数据提交导致数据改变,所以同一查询可能返回不同结果。
不可重复读:同时开启事务A和事务B,在B事务更新并提交后,A事务读取到了更新后的数据,此时处于同一A事务的查询出现了不同的查询结果,即不可重复读现象。
可重复读(REPEATABLE READ)
这是mysql的默认隔离事务级别,能确保同一事物的多个实例在并发读取数据时,会看到同样的数据行,理论上会导致另一问题,幻读 。例如第一个事务对一个表中的数据进行了修改,这种修改设计表中的全部数据行。同时,第二个事务也修改了这个表中的数据,这种修改是向表中插入一行新数据,那么以后就会发生操作第一个事务的用户发现表中还没有修改的数据行。
可串行化(SERIALIZABLE)
这是最高的隔离级别,通过强制事务排序,使之不可能发生冲突,从而解决幻读问题,是在每个读的数据行上加上共享锁实现,在这个级别,可能会导致大量的超时现象和锁竞争,一般不同意使用
锁的类型
(1)共享锁(S)
共享锁的锁粒度是行或者元组(多个行)。一个事务获取了共享锁之后,可以对锁定范围的数据执行读操作。
(2)排他锁(X)
排他锁的粒度与共享锁相同,也是行或者元组,一个事务获取了排他锁后,可以对锁定范围的数据进行写操作。
如有两个事务A和B,如果事务A获取了一个元组的共享锁,事务B还可以立即获取这个元组的共享锁,但不能立即获取这个元组的排他锁,必须等到事务A释放共享锁之后。
如果事务A获取了一个元组的排他锁,事务B不能立即获取这个元组的共享锁,也不能立即获取这个元组的排他锁,必须等到A释放了排他锁。
(3)意向锁
意向锁是一种表锁,锁定的是整张表,别分为意向排他锁(IX)和意向共享锁(IS)两类,意向共享锁表示一个事务有意对数据上共享锁或排他锁。“有意”是指事务想执行但还没有真正执行,锁与锁之间要么是相容的,要么互斥。
相容:操作一组数据时,如果事务1获取了锁a,另一个事务2还可以获取锁b。
互斥:操作一组数据时,如果事务1获取了锁a,里一个事务2在事务1释放了锁a之前无法获取锁b。
图片转自:https://www.cnblogs.com/olinux/p/5174235.html
锁粒度:
锁粒度主要分为表锁和行锁。
表锁管理锁的开销最小,同时允许的并发量也是最小的锁机制。MyISAM存储引擎使用该锁机制。当要写入数据时,把整个表记录被锁,此时其他读/写动作一律等待,同时一些特定的动作,如ALTER TABLE执行时使用的也是表锁。
行锁支持最大的并发。InnoDB存储引擎使用该锁机制,如果要支持并发/读写,建议采用InnoDB存储引擎,因为采用行级锁,可以获得更多性能。