先做好准備,創建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; //發現被阻塞,行鎖邊表鎖
一定要注意索引的合理利用!~~