mysql并发事务
PDO事务
当脚本结束或连接即将被关闭时,如果尚有一个未完成的事务,那么 PDO 将自动回滚该事务。
这种安全措施有助于在脚本意外终止时避免出现不一致的情况——如果没有显式地提交事务,那么假设是某个地方出错了,所以执行回滚来保证数据安全。
MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。
我们可以使用命令设置MySQL为非autocommit模式:
set autocommit=0;
设置完autocommit后,需要手动控制事务的提交
事务支持四大特性(ACID):
原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)以及持久性(Durability)
原子性:要不全部成功,要不全部撤销
隔离性:事务之间相互独立,互不干扰
一致性:数据库正确地改变状态后,数据库的一致性约束没有被破坏
持久性:事务的提交结果,将持久保存在数据库中
事务并发问题
- 第一类丢失更新:在--没有事务隔离--的情况下,两个事务都同时更新一行数据,但是第二个事务却中途失败退出回滚, 导致对数据的两个修改都失效了,都变回原来数据。
- 脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据
- 不可重复读:是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
- 第二类丢失更新,更新覆盖:不可重复读的特例。有两个并发事务同时读取同一行数据,然后其中一个对它进行修改提交,而另一个也进行了修改提交。这就会造成第一次写操作失效。
- 幻读:是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
不可重复读的重点是修改,同样的条件,你读取过的数据,再次读取出来发现值不一样了
幻读的重点在于新增或者删除,同样的条件,第 1 次和第 2 次读出来的记录数不一样
事务隔离级别,解决什么并发问题,以及存在什么并发问题
- READ_UNCOMMITTED read_uncommitted
这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。
解决第一类丢失更新的问题,但是会出现脏读、不可重复读、第二类丢失更新的问题,幻读。
- READ_COMMITTED read_committed
保证一个事务修改的数据提交后才能被另外一个事务读取,即另外一个事务不能读取该事务未提交的数据。
解决第一类丢失更新和脏读的问题,会出现不可重复读、第二类丢失更新的问题,幻读问题
- REPEATABLE_READ repeatable_read --Mysql默认的事务隔离级别
保证一个事务相同条件下前后两次获取的数据是一致的
解决第一类丢失更新,脏读、不可重复读、第二类丢失更新的问题,但会出幻读。
事物结束前其他事物可以读到原来的数据-》需要修改读的数据-》读时加写锁。
select * from bingfa where id = :id for update 其他事务可以查询数据,不能修改。
- SERIALIZABLE serializable
事务被处理为顺序执行。其它事务不能读写。解决所有问题
SQL查询命令
查看锁表状态
Table_locks_waited与Table_locks_immediate的比值较大,则说明我们的表锁造成的阻塞比较严重
Innodb_row_lock_waits较大,则说明Innodb的行锁也比较严重,且影响了其他线程的正常处理。同样需要查找出原因并解决。造成Innodb行锁严重的原因可能是Query语句所利用的索引不够合理(Innodb行锁是基于索引来锁定的),造成间隙锁过大。也可能是系统本身处理能力有限,则需要从其他方面来考虑解决。
show processlist 查询进程
kill 188
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; 正在锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; 等待锁的事务
select @@tx_isolation; 会话隔离级别
select @@global.tx_isolation; 系统当前隔离级别
当前会话隔离级别-测试无效
set session transaction isolation level repeatable read;
设置系统当前隔离级别
set global transaction isolation level repeatable read;