先做好準備,建立InnoDB引擎資料表,並新增了相應的索引
DROP TABLE IF EXISTS `innodb_lock`;
CREATE TABLE `innodb_lock` (
`a` int(10) NOT NULL,
`b` varchar(255) NOT NULL DEFAULT '',
KEY `index_a` (`a`),
KEY `index_b` (`b`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Records of innodb_lock
-- ----------------------------
INSERT INTO `innodb_lock` VALUES ('1', 'b2');
INSERT INTO `innodb_lock` VALUES ('3', '3');
INSERT INTO `innodb_lock` VALUES ('4', '4000');
INSERT INTO `innodb_lock` VALUES ('5', '5000');
INSERT INTO `innodb_lock` VALUES ('6', '6000');
INSERT INTO `innodb_lock` VALUES ('7', '7000');
INSERT INTO `innodb_lock` VALUES ('8', '8000');
INSERT INTO `innodb_lock` VALUES ('9', '9000');
INSERT INTO `innodb_lock` VALUES ('1', 'b1');
然後分別開啟兩個Mysql終端,設定autocommit自動提交為0,也就是關閉自動提交功能,事務隔離級別處於可重複讀狀態;檢視一下表資料。
MySQL [test_db]> set autocommit = 0;
MySQL [test_db]> select * from innodb_lock;
+---+------+
| a | b |
+---+------+
| 1 | b2 |
| 3 | 3 |
| 4 | 4000 |
| 5 | 5000 |
| 6 | 6000 |
| 7 | 7000 |
| 8 | 8000 |
| 9 | 9000 |
| 1 | b1 |
+---+------+
接下來在第一個終端執行update語句
MySQL [test_db]> update innodb_lock set b ='4001' where a = 4;
然後第二個終端執行update語句
MySQL [test_db]> update innodb_lock set b = '4004' where a = 4;
發現第二個終端處於阻塞狀態,因為這裡修改的是同一行資料,只有在第一個終端提交之後,鎖被釋放,第二個終端執行完了SQL,最後第二個終端也commit提交之後資料才會更改,b的值為'4004'。
我們繼續
在第一個終端執行update語句
MySQL [test_db]> update innodb_lock set b='4005' where a = 4;
然後第二個終端執行update語句
MySQL [test_db]> update innodb_lock set b = '9001' where a = 9;
發現兩條語句都執行成功了。因為修改的不是同一行資料。然後分別commit提交,再檢視下資料,發現兩行資料都發生了變化。
MySQL [test_db]> select * from innodb_lock;
+---+------+
| a | b |
+---+------+
| 1 | b2 |
| 3 | 3 |
| 4 | 4005 |
| 5 | 5000 |
| 6 | 6000 |
| 7 | 7000 |
| 8 | 8000 |
| 9 | 9001 |
| 1 | b1 |
+---+------+
下面是重點,兩個終端還是分別操作不同的行。
在第一個終端執行update操作
MySQL [test_db]> update innodb_lock set a = 41 where b =4005; //注意這裡的where條件b=4005。要記得當前表的b欄位是字串型別,並且加了索引,加了索引之後如果查詢條件沒加引號會導致失效
然後在第二個終端執行update操作
MySQL [test_db]> update innodb_lock set b='9002' where a = 9; //發現被阻塞,行鎖邊表鎖
一定要注意索引的合理利用!~~