MySQL InnoDB 锁 - For Update 加锁分析:

1. InnoDB锁 简单介绍

2. 当前读加锁分析:REPEATABLE-READ 可重复读、READ-COMMITTED 读已提交

3. 锁模式说明及8.0的data_locks表

一、InnoDB锁

1、全局锁

全局读锁,flush tables with read lock,整库处于只读状态。全局锁的一个典型场景:全库逻辑备份,--single-transaction实现一致性读。

2、表级锁

表锁,lock tables…read/write,主动在表上加读锁或写锁;

元数据锁(meta data lock,MDL),访问表时自动加上,防止DDL和DML并发的冲突,保证读写正确性;

自增锁,表中auto_increment字段的自增值生成控制,内存自增计数器,8.0之后通过redo进行持久化;

意向锁,只会和表级锁发生冲突,不会阻止除表锁请求之外的锁,表明有事务即将、或正锁定某N行;

  1. 意向共享锁(IS):SELECT ... LOCK IN SHARE MODE,在对应记录行上加锁之前,在表上加意向共享锁;

  2. 意向排它锁(IX):SELECT .. FOR UPDATE,悲观锁,对表所有扫描过的行都会被加上意向排它锁,若扫描行其中有行锁,则会被阻塞;对SELECT索引加排它锁,阻塞其他事务修改或SELECT ... FOR SHARE(在8.0新增的方式);

3、行锁

行锁,事务锁,只有发生行锁冲突,才会出现事务锁的排队等待。

两阶段锁协议:行锁在需要时加上,事务结束时释放。

行锁的3种算法:record lock、gap lock、next-key lock

  1. 记录锁 record lock:添加在索引上,表中没有索引时会默认添加在默认创建的聚集索引上;

  2. 间隙锁 gap lock:锁定一个范围,可重复读 隔离级别下,行锁会变成gap锁(范围锁),降低并发性,当前读(dml、select for update),若where条件列上有索引,加gap lock在索引上,实现可重复读;

  3. Next-Key Lock:Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身;

    ① 唯一索引或主键,Next-Key Lock 降为 Record Lock,即仅锁住索引本身,而不是范围。

    ② 辅助索引(二级索引),默认使用Next-Key Locking加锁,锁定范围是前一个索引到后一个索引之间范围,左开右闭。

### session 1
root@test 15:51 > begin; root@test 15:51 > show create table student;
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| student | CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`birthday` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `ix_name` (`name`),
KEY `ix_birthday` (`birthday`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ root@test 15:52 > select * from student;
+----+-------+---------------------+
| id | name | birthday |
+----+-------+---------------------+
| 1 | abcd | 1995-06-27 00:00:00 |
| 2 | abef | 1995-01-24 00:00:00 |
| 3 | abg | 1995-07-26 00:00:00 |
| 4 | cdmn | 1995-06-13 00:00:00 |
+----+-------+---------------------+ root@test 15:52 > select * from student where birthday > '1995-06-27 00:00:00' and birthday < '1995-07-26 00:00:00' for update;
Empty set (0.02 sec) ### session 2
root@test 15:51 > begin; # 左开
root@test 15:54 > update student set name = 'abcd' where birthday = "1995-06-27 00:00:00"; # 右闭(阻塞更新)
root@test 15:55 > update student set name = 'abg' where birthday = '1995-07-26 00:00:00';
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

二、当前读加锁分析

分析不同隔离级别,当前读(dml、select … for update)的加锁情况

1、REPEATABLE-READ 可重复读

root@test 15:06 > show global variables like "%iso%";
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
| tx_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1.1、表无显式主键和索引
root@test 15:30 > show create table t_student;
+-----------+----------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-----------+----------------------------------------------------------------------------------------------------------------------------+
| t_student | CREATE TABLE `t_student` (
`id` int(11) NOT NULL,
`name` varchar(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-----------+----------------------------------------------------------------------------------------------------------------------------+ root@test 15:30 > begin; root@test 15:31 > select * from t_student for update;
+----+-------+
| id | name |
+----+-------+
| 1 | jack |
| 2 | kuzma |
| 3 | linda |
+----+-------+

如上,可重复读,表上没有主键(会自动生成隐式主键聚集组织表),也没有索引,全表SELECT的当前读的加锁情况:

  ① 对表添加 IX 锁

  ② 在"supremum"上添加 Next-Key Lock(supremum表示高于表中任何一个索引的值),即最大索引值之后的间隙锁住

  ③ 在三条记录上分别添加 Next-Key Lock

root@test 16:08 > begin;

# where上带条件 id = 3
root@test 16:08 > select * from t_student where id = 3 for update;
+----+-------+
| id | name |
+----+-------+
| 3 | linda |
+----+-------+ root@test 16:09 > show engine innodb status\G
# 锁信息如上,表上IX,supremum 和 三条记录上添加 Next-Key Lock # 另开一个session
root@test 16:09 > begin; root@test 16:13 > insert into t_student values(2,"tom");
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
root@test 16:15 > insert into t_student values(4,"tom");
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

如上,insert为什么会被阻塞呢?delete呢?update呢?

每次插入记录时,所生成的聚集索引(DB_ROW_ID)是自增的,每次都会在表的最后插入,因此就有可能插入id=10这条记录,所以需要添加"supremum pseudo-record"防止数据插入。

---TRANSACTION 582122, ACTIVE 3874 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 6 row lock(s)
MySQL thread id 12529, OS thread handle 123145486712832, query id 94463 localhost root update
insert into t_student values(5,"tom")
Trx read view will not see trx with id >= 582123, sees < 582121
------- TRX HAS BEEN WAITING 3 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 168 page no 3 n bits 72 index GEN_CLUST_INDEX of table `test`.`t_student` trx id 582122 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;; ------------------
TABLE LOCK table `test`.`t_student` trx id 582122 lock mode IX
RECORD LOCKS space id 168 page no 3 n bits 72 index GEN_CLUST_INDEX of table `test`.`t_student` trx id 582122 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;

即使是不满足where条件的记录上,也会添加Next-Key Lock,目的是为了防止幻读。因此的,其他会话事务执行delete或者update都会造成幻读,也就被阻塞的。

---TRANSACTION 582122, ACTIVE 3788 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 5 row lock(s)
MySQL thread id 12529, OS thread handle 123145486712832, query id 94461 localhost root updating
update t_student set name = "linda" where id = 3
Trx read view will not see trx with id >= 582123, sees < 582121
------- TRX HAS BEEN WAITING 14 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 168 page no 3 n bits 72 index GEN_CLUST_INDEX of table `test`.`t_student` trx id 582122 lock_mode X waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 6; hex 00000000090a; asc ;;
1: len 6; hex 00000008e1c8; asc ;;
2: len 7; hex f4000001e40110; asc ;;
3: len 4; hex 80000001; asc ;;
4: len 4; hex 6a61636b; asc jack;; ------------------
TABLE LOCK table `test`.`t_student` trx id 582122 lock mode IX
RECORD LOCKS space id 168 page no 3 n bits 72 index GEN_CLUST_INDEX of table `test`.`t_student` trx id 582122 lock_mode X waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 6; hex 00000000090a; asc ;;
1: len 6; hex 00000008e1c8; asc ;;
2: len 7; hex f4000001e40110; asc ;;
3: len 4; hex 80000001; asc ;;
4: len 4; hex 6a61636b; asc jack;;
1.2、表有显式主键无索引
  1. 不带where条件,表上IX,主键最大索引值之后的间隙锁住,表所有记录对应主键加上记录锁

  2. where条件是主键,表上IX,主键添加记录锁(X,REC_NOT_GAP),并且只锁住条件记录,因为主键保证唯一,不需要间隙锁

---TRANSACTION 582139, ACTIVE 12 sec
2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 12528, OS thread handle 123145486434304, query id 94472 localhost root
TABLE LOCK table `test`.`t_student` trx id 582139 lock mode IX
RECORD LOCKS space id 169 page no 3 n bits 72 index PRIMARY of table `test`.`t_student` trx id 582139 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 4; hex 80000002; asc ;;
1: len 6; hex 00000008e1c8; asc ;;
2: len 7; hex f4000001e4011f; asc ;;
3: len 5; hex 6b757a6d61; asc kuzma;;
1.3、表无显式主键有索引
  1. 不带where条件,表上IX,id最大索引值之后的间隙锁住,表所有记录对应索引加上记录锁

  2. where条件是普通索引字段

root@test 22:01 > show create table t_student;
+-----------+--------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-----------+--------------------------------------------------------------------------------------------------------------------------------------------------+
| t_student | CREATE TABLE `t_student` (
`id` int(11) NOT NULL,
`name` varchar(10) DEFAULT NULL,
KEY `ix_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-----------+--------------------------------------------------------------------------------------------------------------------------------------------------+ root@test 22:10 > begin; root@test 22:11 > select * from t_student where id = 2 for update;
+----+-------+
| id | name |
+----+-------+
| 2 | kuzma |
+----+-------+ root@test 22:11 > show engine innodb status\G
---TRANSACTION 582176, ACTIVE 14 sec
4 lock struct(s), heap size 1136, 3 row lock(s)
MySQL thread id 12534, OS thread handle 123145487269888, query id 94485 localhost root
TABLE LOCK table `test`.`t_student` trx id 582176 lock mode IX
RECORD LOCKS space id 170 page no 4 n bits 72 index ix_id of table `test`.`t_student` trx id 582176 lock_mode X
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 4; hex 80000002; asc ;;
1: len 6; hex 000000000912; asc ;; RECORD LOCKS space id 170 page no 3 n bits 72 index GEN_CLUST_INDEX of table `test`.`t_student` trx id 582176 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 6; hex 000000000912; asc ;;
1: len 6; hex 00000008e200; asc ;;
2: len 7; hex be00000146011f; asc F ;;
3: len 4; hex 80000002; asc ;;
4: len 5; hex 6b757a6d61; asc kuzma;; RECORD LOCKS space id 170 page no 4 n bits 72 index ix_id of table `test`.`t_student` trx id 582176 lock_mode X locks gap before rec
Record lock, heap no 4 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 4; hex 80000003; asc ;;
1: len 6; hex 000000000913; asc ;;

如上,过滤一个普通索引时的加锁情况是:

  ① 对表添加 IX锁

  ② 对id=2对应的索引添加 Next-Key Lock锁,区间是(-∞, 2]

  ③ 对索引对应的聚集索引添加 X记录锁

  ④ 为防止幻读(因为是普通索引,可重复插入id=2的记录),对索引记录区间(2,3)添加间隙锁(lock_mode X locks gap before rec)

也就是说,(测试用例有些许不恰当)如果说放大到10~20~30测试,id直到29之间的记录插入都会被阻塞,而插入id=30因为不在间隙锁范围,不会被阻塞。

1.4、表有显式主键和索引
  1. 无where条件,如1.2.1描述

  2. 有where条件,其实,无论是主键,还是唯一键索引,只要能准确定位的,都是表上IX,主键或唯一键添加记录锁(X,REC_NOT_GAP),并且只锁住条件记录

2、READ-COMMITTED 读已提交

root@test 23:57 > show global variables like "tx_isolation";
+---------------+----------------+
| Variable_name | Value |
+---------------+----------------+
| tx_isolation | READ-COMMITTED |
+---------------+----------------+
2.1、表无显式主键和索引
root@test 23:57 > show create table t_people;
+----------+-------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+----------+-------------------------------------------------------------------------------------------------------------------------------+
| t_people | CREATE TABLE `t_people` (
`id` int(11) DEFAULT NULL,
`name` varchar(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+----------+-------------------------------------------------------------------------------------------------------------------------------+ root@test 23:58 > select * from t_people;
+------+-------+
| id | name |
+------+-------+
| 1 | jack |
| 2 | kuzma |
| 3 | linda |
+------+-------+

如下,表t_people上加 IX意向排它锁,表中所有行的隐藏主键上(行格式里第三个就是隐藏主键,在表中没有显示主键的时候自动生成用于组织表数据)加 X记录锁,只锁定记录本身,非范围间隙锁。

如果带上where条件呢?

root@test 00:44 > begin;

root@test 00:45 > select * from t_people where id = 2 for update;
+------+-------+
| id | name |
+------+-------+
| 2 | kuzma |
+------+-------+ root@test 00:45 > show engine innodb status;
......
---TRANSACTION 582053, ACTIVE 4 sec
2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 12521, OS thread handle 123145487269888, query id 94339 localhost root
TABLE LOCK table `test`.`t_people` trx id 582053 lock mode IX
RECORD LOCKS space id 166 page no 3 n bits 72 index GEN_CLUST_INDEX of table `test`.`t_people` trx id 582053 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 6; hex 000000000908; asc ;;
1: len 6; hex 00000008e19e; asc ;;
2: len 7; hex d2000001580110; asc X ;;
3: len 4; hex 80000002; asc ;;
4: len 5; hex 6b757a6d61; asc kuzma;;
......
# 只是在 id = 2 的记录上加了X记录锁
2.2、表有显式主键无索引
  1. 不带where条件,如上的,表中所有行上加 X记录锁,不锁定范围

  2. where条件是主键字段时,对表加 IX锁,对主键添加记录锁(X, REC_NOTGAP),where了主键,主键已经保证唯一,非范围锁,锁加在具体的记录上

root@test 00:49 > show engine innodb  status;
---TRANSACTION 582071, ACTIVE 7 sec
2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 12521, OS thread handle 123145487269888, query id 94353 localhost root
TABLE LOCK table `test`.`t_people` trx id 582071 lock mode IX
RECORD LOCKS space id 167 page no 3 n bits 72 index PRIMARY of table `test`.`t_people` trx id 582071 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 4; hex 80000002; asc ;;
1: len 6; hex 00000008e19e; asc ;;
2: len 7; hex d2000001580110; asc X ;;
3: len 5; hex 6b757a6d61; asc kuzma;;
  1. where条件包含主键字段和非主键字段,和上面是一样的,因为主键已经定位了加锁。

2.3、表无显示主键有索引
  1. 不带where条件,同样的,表中所有行上加 X记录锁,不锁定范围

  2. where条件是普通索引字段,唯一索引亦如是

root@test 20:24 > show create table t_student;
+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------+
| t_student | CREATE TABLE `t_student` (
`id` int(11) NOT NULL,
`name` varchar(10) DEFAULT NULL,
KEY `ix_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------+ root@test 20:25 > begin; root@test 20:27 > select * from t_student where name = 'kuzma' for update;
+----+-------+
| id | name |
+----+-------+
| 2 | kuzma |
+----+-------+ root@test 20:27 > show engine innodb status;
---TRANSACTION 582093, ACTIVE 57 sec
3 lock struct(s), heap size 1136, 2 row lock(s)
MySQL thread id 12525, OS thread handle 123145486712832, query id 94388 localhost root
TABLE LOCK table `test`.`t_student` trx id 582093 lock mode IX
RECORD LOCKS space id 168 page no 4 n bits 72 index ix_name of table `test`.`t_student` trx id 582093 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 5; hex 6b757a6d61; asc kuzma;;
1: len 6; hex 00000000090b; asc ;; RECORD LOCKS space id 168 page no 3 n bits 72 index GEN_CLUST_INDEX of table `test`.`t_student` trx id 582093 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 6; hex 00000000090b; asc ;;
1: len 6; hex 00000008e1c8; asc ;;
2: len 7; hex f4000001e4011f; asc ;;
3: len 4; hex 80000002; asc ;;
4: len 5; hex 6b757a6d61; asc kuzma;;

如上,当where条件上是普通索引字段时,加锁情况如下:

  ① 表上加 IX,意向排它锁

  ② name='kuzma' 对应的索引上添加 X 记录锁

  ③ GEN_CLUST_INDEX,对应的(自动生成的)聚集索引上添加 X 记录锁

2.4、表有显式主键有索引
  1. 不带where条件,所有行记录添加记录锁,并没有间隙范围锁

  2. where条件是普通索引或主键索引,如前面的,先是表上加 IX 意向排它锁,然后在对应的普通索引上添加 X 记录锁(如果是主键则无需),最后在对应的聚集索引(主键)上添加 X 记录锁

三、锁模式说明及8.0的data_locks表

3.1、锁模式LOCK_MODE

show engine innodb status中见到的 lock_mode,如下整理说明:

锁模式 说明
IX   意向排它锁
X   Next-Key Lock锁定记录和记录之前的间隙(X)
S   Next-Key Lock锁定记录和记录之前的间隙(S)
X, REC_NOT_GAP   只锁定记录本身(X)
S, REC_NOT_GAP   只锁定记录本身(S)
X, GAP   间隙锁,不锁定记录本身(X)
S, GAP   间隙锁,不锁定记录本身(S)
X, GAP, INSERT_INTENTION   插入意向锁,间隙范围,排它

3.2、8.0的data_locks表

在8.0之前,查看锁信息可以通过设置innodb_status_output_locks=ON,然后在 show engine innodb status的输出里,看到详细的锁信息打印,如前面展示。

8.0之后,performance_schema.data_locks,新增的,记录表加锁情况,可将之前的innodb status锁信息打印更好的以表格的形式记录展示。

For Update 加锁分析的更多相关文章

  1. MySQL的并发控制与加锁分析

    本文主要是针对MySQL/InnoDB的并发控制和加锁技术做一个比较深入的剖析,并且对其中涉及到的重要的概念,如多版本并发控制(MVCC),脏读(dirty read),幻读(phantom read ...

  2. (转)mysql、innodb和加锁分析

    mysql.innodb和加锁分析 原文:https://liuzhengyang.github.io/2016/09/25/mysqlinnodb/ 介绍 本文主要介绍MySQL和InnoDB存储引 ...

  3. MySQL中一条SQL的加锁分析

    MySQL中一条SQL的加锁分析 id主键 + RC id唯一索引 + RC id非唯一索引 + RC id无索引 + RC id主键 + RR id唯一索引 + RR id非唯一索引 + RR id ...

  4. mysql InnoDB加锁分析

    文章转载自:http://www.fanyilun.me/2017/04/20/MySQL%E5%8A%A0%E9%94%81%E5%88%86%E6%9E%90/ 以下实验数据基于MySQL 5.7 ...

  5. select加锁分析(Mysql)

    [原创]惊!史上最全的select加锁分析(Mysql) 前言 大家在面试中有没遇到面试官问你下面六句Sql的区别呢 select * from table where id = ? select * ...

  6. 解决死锁之路3 - 常见 SQL 语句的加锁分析 (转)

    出处:https://www.aneasystone.com/archives/2017/12/solving-dead-locks-three.html 这篇博客将对一些常见的 SQL 语句进行加锁 ...

  7. MySQL加锁分析

    参考:MySQL 加锁处理分析.该文已经讲的很详尽了,也易懂,下面仅仅是个人做的总结. 一. 背景 1.1 隔离级别 1.2 加锁过程 逐条处理,逐条加锁. 1.3 两阶段锁2PL 1.4 gap锁 ...

  8. MyISAM加锁分析

    为什么加锁 你正在读着你喜欢的女孩递给你的信,看到一半的时候,她的好闺蜜过来瞄了一眼(假设她会隐身术,你看不到她),她想把"我很喜欢你"改成"我不喜欢你",刚把 ...

  9. 史上最全的select加锁分析(Mysql)

    引言 大家在面试中有没遇到面试官问你下面六句Sql的区别呢 select * from table where id = ? select * from table where id < ? s ...

随机推荐

  1. nanogui之更新子模块glfw3.3.2踩坑总结

    nanogui源码下载: A . https://github.com/wjakob/nanogui B . https://github.com/dalerank/nanogui B是fork的A, ...

  2. 【LeetCode】965. Univalued Binary Tree 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 BFS DFS 日期 题目地址:https://le ...

  3. 【LeetCode】139. Word Break 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  4. hdu -4325-Flowers(离散化 线段树)

    http://acm.hdu.edu.cn/showproblem.php?pid=4325: 题目意思: 给你N个花开的时间段,然后在有M个时间点,问你在这个时间点有多少花开着. 昨天刚做的一个类似 ...

  5. Robust De-noising by Kernel PCA

    目录 引 主要内容 Takahashi T, Kurita T. Robust De-noising by Kernel PCA[C]. international conference on art ...

  6. JavaScript交互式网页设计 • 【第5章 JavaScript对象】

    全部章节   >>>> 本章目录 5.1 Object 对象和 Date 对象 5.1.1 JavaScript 的内部对象 5.1.2 Object对象 5.1.3 Date ...

  7. Spring进一步学习

    目录 1.beans.xml编写 2.别名 (1)alias (2)name 3.依赖注入(DI) (1)数组注入 (2)List注入 (3)Map注入 (4)set注入 (5)Null注入 (6)p ...

  8. CSS基础 清除浮动

    1.单伪元素清除法:清除浮动 .clearfix::after{             content: '.';             display: block;             c ...

  9. java 封装 总结

    1.前言 老是被问什么是java 封装...很基础的一个问题 ,其实我们一直在写的东西但不知道怎么称呼. 比如 在entity实体类 里面老用到的 getter 和 setter 方法其实就是封装的方 ...

  10. 安装TestNG

    1.启动Eclipse,选择"Help"-->'Install New Software' 2.在谈出的弹框中选择"Add" 3.在弹出的"Ad ...