1.表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
2.行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度最高。
3.页面锁:开锁和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
mysql> SHOW STATUS LIKE 'table%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Table_locks_immediate | 44571 | | Table_locks_waited | 0 | -- 值越高,争用越大 | Table_open_cache_hits | 16 | | Table_open_cache_misses | 0 | | Table_open_cache_overflows | 0 | +----------------------------+-------+ 5 rows in set (0.08 sec)
LOCK TABLES orders READ LOCAL, order_detail READ LOCAL; -- LOCAL使得表可以并发在表尾插入数据 SELECT sum(total) FROM orders; SELECT sum(subtotal) FROM order_detail; UNLOCK TABLES;NOTE: LOCK TABLES必须同时取得所有涉及表的锁,并且MySQL不支持锁升级,即LOCK TABLES后,只能访问显示加锁的表,不能访问未加锁的表, 自动加锁的情况也差不多如此,因此MyISAM不会出现死锁。
LOCK TABLE users AS u1 READ, users AS u2 READ
mysql> SHOW VARIABLES LIKE 'concurrent%'; +-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | concurrent_insert | AUTO | -- 默认值为1 +-------------------+-------+ 1 row in set (0.00 sec)
1. 通过启动参数low-priority-updates,使MyISAM给予读请求优先的权利。
2. 通过SET LOW_PRIORITY_UPDATES=1, 使当前连接读请求优先。
3. 通过设置INSERT, UPDATE, DELETE的LOW_PRIORITY属性,降低该语句的优先级。
1. 原子性(Atomicity):事务是一个原子操作,要么全都执行,要么全都不执行。
2. 一致性(Consistent):在事务的开始和结束时,数据都必须保持一致状态。
3. 隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境。
4. 持久性(Durable):事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。
1. 更新丢失(Lost Update): 当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新的问题--最后的更新覆盖了由其他事务所做的更新。
2. 脏读(Dirty Reads): 一个事务正在对一条记录做修改,在这个事务完成并提交前,这条记录的数据就处于不一致状态;这时,另一个事务也来读取这条记录,如果不加控制,第二个事务读取了这些"脏"数据,并据此做进一步处理,就会产生未提交的数据依赖关系。
3. 不可重复读(Non-Repeatable Reads): 一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生变化或某些记录已经被删除!这种现象就叫"不可重复读"。
4. 幻读(Phantom Reads): 一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其条件查询的新数据,这种现象就称为"幻读"。
1. 一种是在读取数据前,对其加锁,阻止其他事务对其进行修改。
2. 另一种是不加任何锁,通过一定机制生成一个数据请求访问点的一致性数据快照(Snapshot),并用这个快照来提供一定级别(语句级或事务级),从用户的角度来看,好像是数据库可以提供同一数据的多个版本,因此这种技术叫做数据库多版本并发控制(MultiVersion Concurrentcy Control, 简称MVCC或MCC),也经常称为多版本数据库。
mysql> SHOW STATUS LIKE 'innodb_row_lock%'; +-------------------------------+-------+ | Variable_name | Value | +-------------------------------+-------+ | Innodb_row_lock_current_waits | 0 | | Innodb_row_lock_time | 1 | | Innodb_row_lock_time_avg | 1 | | Innodb_row_lock_time_max | 1 | | Innodb_row_lock_waits | 1 | +-------------------------------+-------+ 5 rows in set (0.16 sec)
SHOW ENGINE INNODB STATUS --显示标准InnoDB Monitor的扩展信息 SHOW ENGINE INNODB MUTEX --显示InnoDB互斥量和读写锁信息 SHOW ENGINE {NDB | NDBCLUSTER} STATUS SHOW ENGINE PERFORMANCE_SCHEMA STATUS详情可参考: http://dev.mysql.com/doc/refman/5.6/en/innodb-monitors.html
InnoDB实现了两种类型的行锁:
为了允许行锁与表锁共存,InnoDB还有两种意向锁:
InnoDB行锁模式兼容性:
SELECT * FROM table WHERE ... LOCK IN SHARE MODE; --共享锁,不要在共享模式下执行写操作,有可能死锁 SELECT * FROM table WHERE ... FOR UPDATE; --排他锁
MySQL的恢复机制主要有以下特点:
1. 当表比较大,且需要更新大部分或全部数据时。
2. 事务涉及多个表,比较复杂,很可能引起死锁,造成大量事务回滚。
SET AUTOCOMMIT=0; LOCK TABLE t1 WRITE, t2 READ, ...; ---do sth to t1 and t2 COMMIT; UNLOCK TABLES;
SHOW ENGINE INNODB STATUS \G SHOW ENGINE INNODB MUTEX \G不吝指正。