mysql的事务
一、什么是事务?
保证数据的一致性。例如:A向B转账500,A账户减少500,B账户增加500,这两个操作是同时成功或者失败。
二、事物的语法
开启事务 begin 或 start transaction 或 begin work
事务回滚 rollback
事务提交 commit
还原点 savepoint (不经常使用)
三、事务应该具备的4个属性:原子性、一致性、隔离性、持久性。通常称为ACID
原子性:一个事务为一个不可分割的最小单位,里面的所有操作都是同时的。例如:转账必须同时成功。
一致性:事务必须从一个一致性的状态变到另外一个一致性的状态。例如:转账前后AB的总额是不变的。
隔离性:一个事务不能被其他的事务所干扰。各自操作各自的事务。
持久性:一个事务被提交,就会永久的保存到数据库当中,对数据库的改变是永久的。
四、事务并发造成的问题
脏读:A事务读取B事务更新的数据,然后B回滚,A读取的数据就是脏数据。
不可重复读:A事务多次读取同一数据,事务在此过程中对数据进行了更新并提交,导致A事务多次多去数据时,结果不一样。
幻读:事务A对表进行数据的修改,事务B提交了一条数据,导致有一个数据没有修改过来。
不可重复读侧重于修改,幻读侧重于新增或删除。
解决不可重复读锁住选中的行(行锁),解决幻读进行锁表(表锁)。
五、事务的隔离级别:
未提交读(read uncommitted)会产生脏读。
已提交读(read committed)不会产生脏读的数据,会产生不可重复读。
可重复读(repeatable read)不会产生脏读的数据、不可重复读。产生幻读
可串行化(serializable)不会产生脏读的数据、不可重复读、幻读
-- 查询事务的隔离级别
SHOW VARIABLES LIKE 'tx_isolation';
-- 设置事务的隔离级别为 未提交读
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
1:未提交读:开启A事务,执行更新,但是没有提交。在B事务内查询数据,就会出现脏读。
2:已提交读:开始A事务,执行更新,没有提交。在B事务查询数据,不会出现脏读。但是A事务提交的时候,B事务再去查询就会更新数据,导致了不可重复读。
3:可重复读 :开启A事务,增加一条数据,没有提交,在B事务也增加一条数据,会出现等待,直到A事务提交的时候才能提交。B事务在去查询就会出现两条数据。就会出现幻读。(可重复读会出现读锁)
4:可串行化:开启A事务,增加一条数据,没有提交。B事务查询会等待,知道等到A事务提交,新增数据也是会等待。不会出现幻读,可重复读,脏读。(串行化会锁住整张表)
六、总结
mysql的隔离级别为可重复读,如果有索引的时候,以索引为条件更新数据,会存在间隙锁、行锁、页锁等问题,锁住一些行。
如果没有索引,更新数据会锁住整张表。没有索引的时候,就会使行锁升级为表锁。
1:更新索引的数据时,会出现行锁。 更新没有索引的数据时,不会等待。
2:没有索引的时候for update,会锁住整张表,会自动升级为表锁。更新都会等待。
隔离级别越高,越能保证数据一致性,对并发性能影响也越大,对多数程序,可以优先把数据库的隔离级别设为read committed。