MySQL InnoDB之事件与锁详解[MySQL防范]
本文“MySQL InnoDB之事件与锁详解[MySQL防范]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
引题:为什么引入事件?
1>.数据完好性
2>.数据安全性
3>.充分操纵系统资源,提高系统并发处理的本领
1. 事件的特点
事件具有四个特点:原子性(Atomiocity)、一致性(Consistency)、断绝性(Isolation)和长期性(Durability),这四个特点简称ACID特点.
1.1原子性
事件是数据库的逻辑工作单位,事件中包含的全部操作要末都做,要末都不做.
1.2 一致性
事件履行的后果必须是使数据库从一个一致性的状况变到别的一个一致性状况.
1.3 断绝性
一个事件的履行不能被其他事件干扰.即一个事件内部的操作及利用的数据对其他
事件是断绝的,并发履行的各个事件之间彼此不干扰.
1.4 长期性
一个事件一旦成功提交,对数据库中数据的改正就是长期性的.接下来其他的其他
操作或弊端不该该对其履行后果有任何影响.
2. MySQL的InnoDB引擎中事物与锁
2.1 SELECT …… LOCK IN SHARE MODE
会话事件中查找的数据,加上一个同享锁.若会话事件中查找的数据已经被其他会话事件加上独占锁的话,同享锁会等候其完毕再加,若等候时间太长就会显示事件需求的锁等候超时.
2.2 SELECT ….. FOR UPDATE
会话事件中查找的数据,加上一个读更新琐,其他会话事件将无法再加其他锁,必须等候其完毕.
2.3 INSERT、UPDATE、DELETE
会话事件会对DML语句操作的数据加上一个独占锁,其他会话的事件都将会等候其释放独占锁.
2.4 gap and next key lock(间隙锁)
InnoDB引擎会自动给会话事件中的同享锁、更新琐以及独占锁,需求加到一个区间值域的时刻,再加上个间隙锁(或称范围锁),对不存在的数据也锁住,避免呈现幻写.
备注:
以上2.1,2.2,2.3,2.4中描写的情形,跟MySQL所设置的事件断绝级别也有关系.
3.四种事件断绝情势
3.1 READ UNCOMMITED
SELECT的时刻答应脏读,即SELECT会读取其他事件改正而还没有提交的数据.
3.2 READ COMMITED
SELECT的时刻无法反复读,即同一个事件中两次履行一样的查询语句,若在第一次与第二次查询之间时间段,其他事件又刚好改正了其查询的数据且提交了,则两次读到的数据不一致.
3.3 REPEATABLE READ
SELECT的时刻可以反复读,即同一个事件中两次履行一样的查询语句,得到的数据始终都是一致的.
3.4 SERIALIZABLE
与可反复读的唯一辨别是,默许把普通的SELECT语句改成SELECT …. LOCK IN SHARE MODE.即为查询语句触及到的数据加上同享琐,阻塞其他事件改正真实数据.
4. 考证事件与锁定示例
接下来,我们将以MySQL中的InnoDB引擎,注释其若何实现ACID特点,差别断绝级别下事件与事件之间的影响.示例表构造:
CREATE TABLE `account ` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`VACCOUNT_ID` varchar(32) NOT NULL,
`GMT_CREATE` datetime NOT NULL,
PRIMARY KEY (`ID`),
KEY `idx_VACCOUNT_PARAMETER_VACCOUNTID ` (`VACCOUNT_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;
然后向表account中写入10W条成立日期分布公道的帐号数据,以便利测试之用.
tx_isolation:SET GLOBAL tx_isolation='read-uncommitted' | ||||
ID | 事件1 | 事件1输出 | 事件2 | 事件2输出 |
1 | START TRANSACTION; | |||
2 | SELECT VACCOUNT_ID from account where ID =1001; | caimao101510 | ||
START TRANSACTION; | ||||
3 | UPDATE account set VACCOUNT_ID='uncommitted' where ID =1001; | |||
4 | SELECT VACCOUNT_ID from account where ID =1001; | uncommitted | ||
5 | SELECT VACCOUNT_ID from account where ID =1001; | uncommitted | ||
6 | ROLLBACK; | |||
7 | SELECT VACCOUNT_ID from account where ID =1001; | caimao101510 | ||
8 | COMMIT; |
tx_isolation:SET GLOBAL tx_isolation='read-committed' | ||||
ID | 事件1 | 事件1输出 | 事件2 | 事件2输出 |
1 | START TRANSACTION; | |||
2 | SELECT VACCOUNT_ID from account where ID =1001; | caimao101510 | ||
3 | START TRANSACTION; | |||
4 | UPDATE account set VACCOUNT_ID='uncommitted' where ID =1001; | |||
5 | SELECT VACCOUNT_ID from account where ID =1001; | uncommitted | ||
6 | SELECT VACCOUNT_ID from account where ID =1001; | caimao101510 | ||
7 | COMMIT; | |||
8 | SELECT VACCOUNT_ID from account where ID =1001; | uncommitted | ||
9 | COMMIT; |
tx_isolation:SET GLOBAL tx_isolation='REPEATABLE-READ' | ||||
ID | 事件1 | 事件1输出 | 事件2 | 事件2输出 |
1 | START TRANSACTION; | |||
2 | SELECT VACCOUNT_ID from account where ID =1001; | caimao101510 | ||
3 | START TRANSACTION; | |||
4 | UPDATE account set VACCOUNT_ID='uncommitted' where ID =1001; | |||
5 | SELECT VACCOUNT_ID from account where ID =1001; | uncommitted | ||
6 | SELECT VACCOUNT_ID from account where ID =1001; | caimao101510 | ||
7 | COMMIT; | |||
8 | SELECT VACCOUNT_ID from account where ID =1001; | caimao101510 | ||
9 | COMMIT; |
tx_isolation:SET GLOBAL tx_isolation='SERIALIZABLE' | ||||
ID | 事件1 | 事件1输出 | 事件2 | 事件2输出 |
1 | START TRANSACTION; | |||
2 | SELECT VACCOUNT_ID from account where ID =1001; | caimao101510 | ||
3 | START TRANSACTION; | |||
4 | UPDATE account set VACCOUNT_ID='uncommitted' where ID =1001; | STATE: Updating | ||
5 | SELECT VACCOUNT_ID from account where ID =1001; | caimao101510 | ||
事件2超时 | ||||
6 | COMMIT; | |||
7 | START TRANSACTION; | |||
8 | UPDATE account set VACCOUNT_ID='uncommitted' where ID =1001; | |||
9 | START TRANSACTION; | |||
10 | SELECT VACCOUNT_ID from account where ID =1001; | STATE:statistics | ||
11 | 事件2超时 | |||
12 | commit; |
tx_isolation:SET GLOBAL tx_isolation='REPEATABLE-READ' | ||||
ID | 事件1 | 事件1输出 | 事件2 | 事件2输出 |
1 | START TRANSACTION; | |||
2 | select max(ID) FROM account; | 124999 | ||
3 | START TRANSACTION; | |||
4 | UPDATE account set gmt_create=date_add(gmt_create,interval +1 day) WHERE ID >=124999; | |||
5 | insert into account(VACCOUNT_ID,gmt_create) values(‘eugene',now()); | STATE:update | ||
6 | 事件2超时 | |||
7 | START TRANSACTION; | |||
8 | SELECT * FROM account WHERE ID =124998; | 2007-10-20 13:47 | ||
9 | UPDATE account set gmt_create=date_add(gmt_create,interval +1 day) WHERE ID =124998; | 履行成功 | ||
10 | SELECT * FROM account WHERE ID =124998; | 2007-10-21 13:47 | ||
11 | COMMIT; | |||
12 | COMMIT; | |||
1 | START TRANSACTION; | |||
2 | UPDATE account set gmt_create=date_add(gmt_create,interval -1 day) WHERE gmt_create >'2009-07-01′; | |||
3 | START TRANSACTION; | |||
4 | SELECT * FROM account WHERE gmt_create>'2009-07-10′ LIMIT 1; | 2009-10-2 13:47 | ||
5 | SELECT * FROM account WHERE gmt_create>'2009-07-10′ LIMIT 1; | 2009-10-1 13:47 | STATE:update | |
6 | insert into account(VACCOUNT_ID,gmt_create) values(‘gmt_create_test',now()); | |||
7 | 事件2超时 | |||
8 | COMMIT; | |||
9 | SELECT * FROM account WHERE gmt_create>'2009-07-10′ LIMIT 1; | 2009-10-1 13:47 | ||
无索引条件更新事件 | ||||
1 | START TRANSACTION; | |||
UPDATE account set gmt_create=date_add(gmt_create,interval -1 day) WHERE gmt_create >'2009-07-01′ AND gmt_create <'2009-07-10′; | ||||
START TRANSACTION; | ||||
insert into account(VACCOUNT_ID,gmt_create) values(‘gmt_create_interval',now()); | ||||
事件2超时 | ||||
COMMIT; |
本文地址: | 与您的QQ/BBS好友分享! |