一、InnoDB中的锁与事务
InnoDB中是支持事务的。
首先InnoDB中不只有行锁,也是有表锁的。
二、pt-online-schema-change
我们在修改表结构的时候,上的就是表的写锁,所以修改表结构,尤其是大表时,要尤其注意。
pt-online-schema-change可以在不阻塞写入的情况下改动数据表,其原理如下:
- 首先创建一个和你要执行的alter操作的表一样的空的表结构。
- 执行我们赋予的表结构的修改,然后copy原表中数据到新表里面。
- 在原表上创建一个触发器在数据copy的过程中,将原表的更新数据的操作全部更新到新的表中来。这个理特别注意,如果原表中已经定义了触发器,那么工具就不能工作了,因为工具使用的数据库的触发器。
- copy完成之后,用rename table新表来代替原表,默认删除原表。
三、事务的特性
ACID,原子性,一致性,隔离性,持久性。
四、并发事务带来的问题
- 更新丢失。ABA问题。
- 脏读:读到了其他事务未提交的内容。不符合一致性。
- 不可重复度:事务中前后读到的内容不一致。不符合隔离性。
- 幻读:事务中,后来读到的内容比之前的内容多。不符合隔离性。
五、事务的隔离级别
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
未提交读 | 可能 | 可能 | 可能 |
已提交读 | 不可能 | 可能 | 可能 |
可重复读 | 不可能 | 不可能 | 可能 |
序列化 | 不可能 | 不可能 | 不可能 |
五、查看与设置事务的隔离级别
#常看当前数据库的事务隔离级别
show variables like 'tx_isolation';
#查看当前会话隔离级别
select @@tx_isolation;
#设置为读未提交
set tx_isolation='read-uncommitted';
#设置为读已提交
set tx_isolation='read-committed';
#设置为可重复读
set tx_isolation='REPEATABLE-READ';
#设置为串行化
set tx_isolation='SERIALIZABLE';
六、不可重复读中的机制
开启两个事务,一个事务更改并提交后的数据,在另一个事务中查询不到,但是如果在这个事务中更改却是会以最新的数据为依据的,且在更改后,在本事务中继续查询,就可以查到新的数据了,
这是使用MVCC机制,也就是快照的模式:
- select不会更新版本号,是快照读(历史版本)。
- insert、update、delete会更新版本号,是当前读(当前版本)。
关于幻读,并不是开启两个事务,一个事务中提交的新增记录一定会体现在另一个事务中,而是只有在这个事务需要修改这条新增记录时,这个事务才会查出来这条新增记录。
关于幻读,可以通过间隙锁的方式间接解决,就是当我们不想要我们的数据被别的事务新增时,那么我们就把我们的数据加上间隙锁,从而让其他的事务无法新增数据。
七、行锁分析命令
通过检查InnoDB_row_lock状态变量来分析系统上的行锁的争夺情况:
show status like 'innodb_row_lock%';
查询出来的变量的意义如下:
- Innodb_row_lock_current_waits:当前正在等待锁定的数量
- Innodb_row_lock_time:从系统启动到现在锁定总时间长度
- Innodb_row_lock_time_avg:每次等待所花平均时间
- Innodb_row_lock_time_max:从系统启动到现在等待最长的一次所花时间
- Innodb_row_lock_waits:系统启动后到现在总共等待的次数
八、上升表锁的情况
for update,或者是增删改的条件有以下情况发生:
- 我们在索引上操作是行锁。
- 在无索引的字段上操作上的是表锁。
- 索引字段上的范围查询,以及模糊查询给表上的都是表锁。
我们一定要注意,避免行锁上升为表锁。