資料庫同時更新問題

2021-09-23 19:31:45 字數 3618 閱讀 7587

中國廣東省

深圳市龍華新區民治街道溪山美地

518131

+86 13113668890

+86 755 29812080

文件始創於2010-11-18

文件出處:

$date: 2013-04-10 15:03:49 +0800 (wed, 10 apr 2013) $

我的系列文件

netkiller architect 手札

netkiller developer 手札

netkiller php 手札

netkiller python 手札

netkiller testing 手札

netkiller cryptography 手札

netkiller linux 手札

netkiller centos 手札

netkiller freebsd 手札

netkiller security 手札

netkiller version 手札

netkiller web 手札

netkiller monitoring 手札

netkiller storage 手札

netkiller mail 手札

netkiller shell 手札

netkiller network 手札

netkiller database 手札

netkiller postgresql 手札

netkiller mysql 手札

netkiller nosql 手札

netkiller ldap 手札

netkiller cisco ios 手札

netkiller h3c 手札

netkiller ********** 手札

netkiller docbook 手札

netkiller 開源軟體 手札

create table `account` (

`id` int(10) unsigned not null auto_increment,

`user` varchar(50) not null default '0',

`cash` float not null default '0',

`point` int(10) unsigned not null default '0',

primary key (`id`),

unique index `user` (`user`)

)collate='utf8_general_ci'

engine=innodb;

insert into `test`.`account` (`user`, `cash`,`point`) values ('neo', 10,10);
下面通過account表,我來模擬乙個返點場景,例如電商**經常會用到「返點」,購買一定數量的商品贈送一定的點數,可以通過點數買東西,這樣涉及到點的加於減操作。

表 8.1. 更新丟失演示

session a session b

select point into @point from account where user='neo';

select point into @point from account where user='neo';

update account set point=@point+20 where user='neo';

update account set point=@point+50 where user='neo';
看看最後使用者有多少點?

mysql> select point from account where user='neo';

+-------+

| point |

+-------+

| 30 |

+-------+

1 row in set (0.00 sec)

傻了吧,老闆發火,測試不能重現,運維說這是程式計算錯誤,程式設計師說程式沒有錯誤,這樣的場景國內很多公司都出現過吧?

問題出在**呢?出在併發上,很多web程式設計師很少考慮併發是產生的問題,怎麼解決?很多方案,在我的職業生涯過程就見過很多奇葩方案,都能解決問題但不太完美。

如果更新語句改為 update account set point=@point+50 where user='neo' and point=@point; 會更保險,但仍然不能解決同意時間所產生的更新操作

下面是通過事務與鎖徹底解決上面的問題。

表 8.2. 防止更新丟失加鎖演示

session a session b

begin;

select point into @point from account where user='neo' for update;

begin;

select point into @point from account where user='neo' for update;

執行到此處會掛起

update account set point=@point+20 where user='neo';

commit;

update account set point=@point+50 where user='neo';

commit;

上面解決更新覆蓋問題,但從資料庫設計角度是不應該這樣設計表的。僅供參考

create table `account` (

`id` int(10) unsigned not null auto_increment,

`user` varchar(50) not null default '0',

`cash` float not null default '0',

`point` int(10) not null default '0',

primary key (`id`)

)collate='utf8_general_ci'

engine=innodb;

每一次資料變化新增一條資料

insert into `test`.`account` (`user`, `point`) values ('neo', -10);

insert into `test`.`account` (`user`, `point`) values ('neo', -5);

insert into `test`.`account` (`user`, `point`) values ('neo', 30);

insert into `test`.`account` (`user`, `point`) values ('neo', -20);

計算剩餘點數

select sum(point) as point from account where user='neo';

access資料庫更新問題

今天update access資料庫時,使用了引數化的方式,結果不報錯,但是資料也沒有更新。這問題搞了我好長時間,鬱悶,經過google發現access使用引數化時,引數位置必須和賦值順序相同才行,否則更新時就會出現資料無法更新但是也不報錯的怪現象。例如 update tablename set a...

RecyclerView的資料更新問題

相信很多人都應該知道recyclerecyclerview的基本用法,如果不知道,請參考 概覽 好了,假設你已經基本了解了recyclerview的用法,正如上述文章中講的那樣,recyclerview跟listview不一樣,當我們想要更新資料的時候,有兩種情況 1 dataset為list,也通...

vue 非同步資料更新問題

記錄一下出現的問題,資料翻倍 這是復現問題的 data methods console.log 此時的this.allresult this allresult watch mounted 結果 此時你可以看到第二次的資料時 是 第一次的 2倍 mounted 和 watch 都執行 getmess...