比如 一张表 user (id,name) 在 id主键上建有检索。
测试:
1.建一张表users
Create Table: CREATE TABLE `users` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
插入数据:
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | b |
+----+------+
2.测试代码:
new Thread() {
public void run() {
try {
Connection conn = getConn();
conn.setAutoCommit(false);
PreparedStatement ps = conn
.prepareStatement("select * from users where id=1 for update");
ResultSet rs=ps.executeQuery();
rs.next();
String name=rs.getString("name");
TimeUnit.SECONDS.sleep(30);
if(name.equals("a"))
ps.execute("update users set name='线程1' where id=1");
conn.commit();
conn.close();
} catch (Exception e) {
// TODO: handle exception
}finally{
}
};
}.start();
new Thread() {
public void run() {
try {
Connection conn = getConn();
conn.setAutoCommit(false);
PreparedStatement ps = conn
.prepareStatement("update users set name='线程2' where id=1");
ps.execute();
conn.commit();
conn.close();
} catch (Exception e) {
// TODO: handle exception
}
};
}.start();
说明 :1)当线程1 不用 for update 锁住id=1 记录 结果name=线程1 。
2)当线程1 使用 for update锁住id=1记录 ,线程2 在执行ps.execute();会阻塞 ,等待获取锁,说明 记录被锁住时候,不能写入。
总结 :
(1)线程1执行‘select * from users where id=1 for update’ 锁住该行 ,线程2执行‘update users set name='线程2' where id=1’,更改这条记录时候会阻塞,需要等带 线程1 commmit 该事物。补充 如果线程执行 查询((不加for update)) 则不会被阻塞(select * from users where id=1)。
(2)id=1记录被锁住,线程2 可以更新其他记录。
(3)如果改为‘select * from users where for update’ 则是table lock。则需要等待commmit 其他线程才可以更新 其中任何记录。其他线程查询(不加for update)不受影响。其他线程查询(加for update),如‘select * from users for update’会阻塞。