[Todo] 乐观悲观锁,自旋互斥锁等等
樂觀鎖、悲觀鎖、要實踐
http://chenzhou123520.iteye.com/blog/1860954 《mysql悲觀鎖總結和實踐》
http://chenzhou123520.iteye.com/blog/1863407 《mysql樂觀鎖總結和實踐》
http://outofmemory.cn/sql/optimistic-lock-and-pessimistic-lock
?
注意,以下的表里面的列名,一定要用 `` 反引號來包括。
mysql> create table `t_goods` ( -> `id` bigint(11) NOT NULL AUTO_INCREMENT, -> `status` bigint(11) DEFAULT 0, -> `name` varchar(32) DEFAULT NULL, -> `version` bigint(11) DEFAULT 1, -> PRIMARY KEY (`id`) -> ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; Query OK, 0 rows affected (0.13 sec)?
mysql> insert into t_goods (`name`) values ('weapon'); Query OK, 1 row affected (0.07 sec)mysql> insert into t_goods (`name`) values ('equipment'); Query OK, 1 row affected (0.10 sec)mysql> select * from t_goods;
+----+--------+-----------+---------+
| id | status | name | version |
+----+--------+-----------+---------+
| 1 | 0 | weapon | 1 |
| 2 | 0 | equipment | 1 |
+----+--------+-----------+---------+
2 rows in set (0.00 sec)
?
實驗1,select for update 指定主鍵,只鎖行:
首先要關閉autocommit:
mysql> set autocommit=0; Query OK, 0 rows affected (0.00 sec)mysql> show variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | OFF | +---------------+-------+ 1 row in set (0.00 sec)如果不關閉,經過實驗,的確不會相互影響。
關閉autocommit之后,普通的sql不放在事務里面也可以。
console A:mysql> select * from t_goods where id = 1 for update; +----+--------+--------+---------+ | id | status | name | version | +----+--------+--------+---------+ | 1 | 0 | weapon | 1 | +----+--------+--------+---------+ 1 row in set (0.00 sec)console B: mysql> select * from t_goods where id = 1; +----+--------+--------+---------+ | id | status | name | version | +----+--------+--------+---------+ | 1 | 0 | weapon | 1 | +----+--------+--------+---------+ 1 row in set (0.00 sec)mysql> select * from t_goods where id = 2 for update; +----+--------+-----------+---------+ | id | status | name | version | +----+--------+-----------+---------+ | 2 | 0 | equipment | 1 | +----+--------+-----------+---------+ 1 row in set (0.00 sec)mysql> select * from t_goods where id = 1 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction?
可以看出,不加for update不影響,加了for update不是同一行,不影響(僅對于主鍵查詢有關)。
?
實驗2,select for update 指定非主鍵,鎖全部:
Console A: mysql> select * from t_goods where name = 'weapon' for update; +----+--------+--------+---------+ | id | status | name | version | +----+--------+--------+---------+ | 1 | 0 | weapon | 1 | +----+--------+--------+---------+ 1 row in set (0.00 sec)Console B: mysql> select * from t_goods; +----+--------+-----------+---------+ | id | status | name | version | +----+--------+-----------+---------+ | 1 | 0 | weapon | 1 | | 2 | 0 | equipment | 1 | +----+--------+-----------+---------+ 2 rows in set (0.00 sec)mysql> select * from t_goods where name = 'equipment' for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactionmysql> select * from t_goods where id = 2 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction?
實驗3,查詢主鍵沒查到,不鎖:
Console A: mysql> select * from t_goods where id=3 for update; Empty set (0.01 sec)Console B: mysql> select * from t_goods for update; +----+--------+-----------+---------+ | id | status | name | version | +----+--------+-----------+---------+ | 1 | 0 | weapon | 1 | | 2 | 0 | equipment | 1 | +----+--------+-----------+---------+ 2 rows in set (0.00 sec)說明,主鍵沒查到數據,不加鎖。
?
實驗4,查詢非主鍵,沒查到,鎖全部,table lock.
Console A: mysql> select * from t_goods where name = 'abc' for update; Empty set (0.00 sec)Console B: mysql> select * from t_goods for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactionmysql> select * from t_goods where id = 1 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction?
實驗5:查詢主鍵不明確,為范圍,大于小于,只鎖相關的行;
Console A: mysql> select * from t_goods where id > 1 for update; +----+--------+-----------+---------+ | id | status | name | version | +----+--------+-----------+---------+ | 2 | 0 | equipment | 1 | +----+--------+-----------+---------+ 1 row in set (0.00 sec)Console B: mysql> select * from t_goods where id = 1 for update; +----+--------+--------+---------+ | id | status | name | version | +----+--------+--------+---------+ | 1 | 0 | weapon | 1 | +----+--------+--------+---------+ 1 row in set (0.00 sec)mysql> select * from t_goods where id = 2 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction?
實驗5:查詢主鍵不明確,!=或者<>,鎖全部;
Console A: mysql> select * from t_goods where id != 1 for update; +----+--------+-----------+---------+ | id | status | name | version | +----+--------+-----------+---------+ | 2 | 0 | equipment | 1 | +----+--------+-----------+---------+ 1 row in set (0.00 sec)Console B: mysql> select * from t_goods where id = 1 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactionConsole A: mysql> select * from t_goods where id <> 1 for update; +----+--------+-----------+---------+ | id | status | name | version | +----+--------+-----------+---------+ | 2 | 0 | equipment | 1 | +----+--------+-----------+---------+ 1 row in set (0.00 sec)Console B: mysql> select * from t_goods where id = 1 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction?
實驗6,對于普通索引,也類似于主鍵的效果:
未加索引之前,鎖全表: console A: mysql> select * from t_goods where status = 1 for update; +----+--------+--------+---------+ | id | status | name | version | +----+--------+--------+---------+ | 1 | 1 | weapon | 1 | +----+--------+--------+---------+ 1 row in set (0.00 sec)console B: mysql> select * from t_goods where id = 2 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction加了索引之后,只鎖行: console A: mysql> alter table t_goods add index index_name(`status`); Query OK, 0 rows affected (0.15 sec) Records: 0 Duplicates: 0 Warnings: 0mysql> select * from t_goods where status = 1 for update; +----+--------+--------+---------+ | id | status | name | version | +----+--------+--------+---------+ | 1 | 1 | weapon | 1 | +----+--------+--------+---------+ 1 row in set (0.00 sec)console B: mysql> select * from t_goods where id = 2 for update; +----+--------+-----------+---------+ | id | status | name | version | +----+--------+-----------+---------+ | 2 | 0 | equipment | 1 | +----+--------+-----------+---------+ 1 row in set (0.00 sec)mysql> select * from t_goods where id = 1 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction?
樂觀鎖:
從業務層面加鎖,一般是加上version字段,然后sql以如下形式處理:
update t_goods set status=2,version=version+1 where id=#{id} and version=#{version};?
自旋鎖與互斥鎖
http://blog.csdn.net/a675311/article/details/49096435
自旋鎖就是不聽的忙檢測,拿不到鎖就返回。
pthread中提供的鎖有:pthread_mutex_t, pthread_spinlock_t, pthread_rwlock_t。pthread_mutex_t是互斥鎖,同一瞬間只能有一個線程能夠獲取鎖,其他線程在等待獲取鎖的時候會進入休眠狀態。因此pthread_mutex_t消耗的CPU資源很小,但是性能不高,因為會引起線程切換。 pthread_spinlock_t是自旋鎖,同一瞬間也只能有一個線程能夠獲取鎖,不同的是,其他線程在等待獲取鎖的過程中并不進入睡眠狀態,而是在CPU上進入“自旋”等待。自旋鎖的性能很高,但是只適合對很小的代碼段加鎖(或短期持有的鎖),自旋鎖對CPU的占用相對較高。 pthread_rwlock_t是讀寫鎖,同時可以有多個線程獲得讀鎖,同時只允許有一個線程獲得寫鎖。其他線程在等待鎖的時候同樣會進入睡眠。讀寫鎖在互斥鎖的基礎上,允許多個線程“讀”,在某些場景下能提高性能。 諸如pthread中的pthread_cond_t, pthread_barrier_t, semaphone等,更像是一種同步原語,不屬于單純的鎖。http://www.cnblogs.com/hdflzh/p/3716156.html
http://blog.csdn.net/pi9nc/article/details/39177343
?
Java鎖相關
http://blog.csdn.net/Evankaka/article/details/44153709 (這一篇要重點看,講了Thread Runnable等)
http://blog.csdn.net/Evankaka/article/details/51866242(Java鎖技術內幕上)
http://blog.csdn.net/evankaka/article/details/51932044(Java鎖技術內幕中)
?
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的[Todo] 乐观悲观锁,自旋互斥锁等等的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: You third iOS app,这
- 下一篇: log4net日志插件的使用