標籤:
比如 一張表 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’會阻塞。
關於mysql 的for update