当前位置:首页 » 数据仓库 » 数据库高并发写入
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

数据库高并发写入

发布时间: 2023-06-26 05:05:39

‘壹’ 一直在说的高并发,多少QPS才算高并发

首先是无状态前端机器不足以承载请求流量,需要进行水平扩展,一般QPS是千级。 然后是关系型数据库无法承载读取或写入峰值,需要数据库横向扩展或引入nosql,一般是千到万级。 之后是单机nosql无法承载,需要nosql横向扩展,一般是十万到百万QPS。

高并发通常是指我们提供的系统服务能够同时并行处理很多请求。并发是指,某个时刻有多少个访问同时到来。QPS是指秒钟响应的请求数量。那么这里就肯容易推算出一个公式:QPS = 并发数 / 平均响应时间

如果你发现自己高并发,一定要及时就医,寻求正规医生的帮助。

‘贰’ 怎么提高数据库高峰时访问的并发能力

1:首先需要有非常良好的网络带宽,若有上万人同时录入数据的普通的Web信息管理系统,至少需要10M左右的网络带宽,而且网通、电信的主干网都有接入比较好,否则全国各地的网络情况都不太一样,有的城市录入数据时可能会遇到网络非常缓慢的情况,甚至到无法忍受的程度。

2:须有一台牛X的Web服务器 + 一台牛X的数据库服务器(备注接近顶配的奢侈硬件服务器非个人PC),由于是需要录入1000万条以上数据,最好采用Oracle数据库比较理想一些,经得起考验一些。

3:需要进行适当的内存缓存优化策略,不能所有的数据库都依靠SQL数据库的方式把压力放在数据库服务器上,尽量多使用内存的方式处理数据。

4:需要一个牛X的,经得起考验的数据库访问层,因为每秒都有可能成千上万的人在访问,若是质量不良好的数据库访问组件、或者不稳定的数据库访问组件,更容易导致系统崩溃、或者占用非常庞大的内存,最后容易导致整个系统的崩溃。

5:需要优化分页存取数据功能,应为有可能会有1000万条数据,若分页读取数据的功能没能优化到最高,也很容易导致系统的崩溃,因为上万人万一在同一时间,或者接近同一时间点了查询某页数据时,那系统就真崩溃了,分页存取数据一定需要做到极致才可以。

6:需要进行数据库索引优化,有索引和没索引的性能差距有时候会是100倍,大数据量时可能会有1000倍都有可能,数据库索引优化到极致了更容易得到运行顺畅的信息管理系统。

7:严谨高效的数据库事务处理,由于高并发,并且有些单据是需要同时写入多个表,需要保证数据库的一致性,要么全部成功,要么全部失败重新录入数据,所以需要一个高效的数据库事务处理机制的配合。

8:所有的系统的操作日志、异常信息都需要完整的记录下来,当系统发生一些故障时,可以快速排查问题,对正确诊断系统发生的故障的原因做分析参考用。

9:需要经常检测系统的各项指标、例如各服务器的内存使用情况、CPU使用情况、网络带宽使用情况,高峰时的各个参数是什么情况、系统不繁忙时的情况等,若服务器快承受不了压力了,就得马上增加负载均衡的服务器,网络带宽不够了需要增加等等,总不能等系统崩溃了再去做这些事情。

10:每个页面的HTML、JS都进行优化,若某个页面多余发了100个字符的垃圾HTML代码,那1万人每天获得100次,那得占用多少网络带宽,100×100×1万个字符的多余HTML被网络上传输了,要知道接入主干网的网络资源是多么宝贵,费用是多么昂贵。

11:HTML、JS等都可以考虑用压缩模式传输,那样网络传输效率会更高一些。

12:由于全国各地上万人,会有各种各样的人,这些人也未必全是好人,可能某些人心情不好,或者其他什么的,可能就会攻击我们的软件系统破坏数据,这些也可能是由于好奇心导致的,所以系统需要有严格的权限管理控制,不应该进入的页面绝对不能进入,不应该看的数据绝对不让看,不能操作的功能绝对不让多操作,一方面防止没必要的多余的麻烦,另一方面也可以减少系统被攻击破坏的可能性。

‘叁’ 关系型数据库的局限性有哪些难以满足高并发读写的需求

随着互联网web2.0网站的兴起,非关系型的数据库现在成了一个极其热门的新领域,非关系数据库产品的发展非常迅速。而传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,例如:

1、High performance——对数据库高并发读写的需求

Web2.0网站要根据用户个性化信息来实时生成动态页面和提供动态信息,所以基本上无法使用动态页面静态化技术,因此数据库并发负载非常高,往往要达到每秒上万次读写请求。关系数据库应付上万次SQL查询还勉强顶得住,但是应付上万次SQL写数据请求,硬盘IO就已经无法承受了。其实对于普通的BBS网站,往往也存在对高并发写请求的需求,例如像JavaEye网站的实时统计在线用户状态,记录热门帖子的点击次数,投票计数等,因此这是一个相当普遍的需求。

2、Huge Storage——对海量数据的高效率存储和访问的需求

类似Facebook,twitter,Friendfeed这样的SNS网站,每天用户产生海量的用户动态,以Friendfeed为例,一个月就达到了2.5亿条用户动态,对于关系数据库来说,在一张2.5亿条记录的表里面进行SQL查询,效率是极其低下乃至不可忍受的。再例如大型web网站的用户登录系统,例如腾讯,盛大,动辄数以亿计的帐号,关系数据库也很难应付。

3、High Scalability && High Availability——对数据库的高可扩展性和高可用性的需求

在基于web的架构当中,数据库是最难进行横向扩展的,当一个应用系统的用户量和访问量与日俱增的时候,你的数据库却没有办法像web server和app server那样简单的通过添加更多的硬件和服务节点来扩展性能和负载能力。对于很多需要提供24小时不间断服务的网站来说,对数据库系统进行升级和扩展是非常痛苦的事情,往往需要停机维护和数据迁移,为什么数据库不能通过不断的添加服务器节点来实现扩展呢?

在上面提到的“三高”需求面前,关系数据库遇到了难以克服的障碍,而对于web2.0网站来说,关系数据库的很多主要特性却往往无用武之地,例如:

1. 数据库事务一致性需求

很多web实时系统并不要求严格的数据库事务,对读一致性的要求很低,有些场合对写一致性要求也不高。因此数据库事务管理成了数据库高负载下一个沉重的负担。

2. 数据库的写实时性和读实时性需求

对关系数据库来说,插入一条数据之后立刻查询,是肯定可以读出来这条数据的,但是对于很多web应用来说,并不要求这么高的实时性,比方说我(JavaEye的robbin)发一条消息之后,过几秒乃至十几秒之后,我的订阅者才看到这条动态是完全可以接受的。

3、对复杂的SQL查询,特别是多表关联查询的需求

任何大数据量的web系统,都非常忌讳多个大表的关联查询,以及复杂的数据分析类型的复杂SQL报表查询,特别是SNS类型的网站,从需求以及产品设计角度,就避免了这种情况的产生。往往更多的只是单表的主键查询,以及单表的简单条件分页查询,SQL的功能被极大的弱化了。

因此,关系数据库在这些越来越多的应用场景下显得不那么合适了,为了解决这类问题的非关系数据库应运而生,现在这两年,各种各样非关系数据库,特别是键值数据库(Key-Value Store DB)风起云涌,多得让人眼花缭乱。前不久国外刚刚举办了NoSQL Conference,各路NoSQL数据库纷纷亮相,加上未亮相但是名声在外的,起码有超过10个开源的NoSQLDB,例如:

Redis,Tokyo Cabinet,Cassandra,Voldemort,MongoDB,Dynomite,HBase,CouchDB,Hypertable, Riak,Tin, Flare, Lightcloud, KiokuDB,Scalaris, Kai, ThruDB, ......

这些NoSQL数据库,有的是用C/C++编写的,有的是用Java编写的,还有的是用Erlang编写的,每个都有自己的独到之处,看都看不过来了,我(robbin)也只能从中挑选一些比较有特色,看起来更有前景的产品学习和了解一下。

‘肆’ 高并发下,数据库成最大问题怎么办

一、数据库结构的设计

为了保证数据库的一致性和完整性,在逻辑设计的时候往往会设计过多的表间关联,尽可能的降低数据的冗余。(例如用户表的地区,我们可以把地区另外存放到一个地区表中)如果数据冗余低,数据的完整性容易得到保证,提高了数据吞吐速度,保证了数据的完整性,清楚地表达数据元素之间的关系。不要用自增属性字段作为主键与子表关联。不便于系统的迁移和数据恢复。对外统计系统映射关系丢失。
表的设计具体注意的问题:
1、数据行的长度不要超过8020字节,如果超过这个长度的话在物理页中这条数据会占用两行从而造成存储碎片,降低查询效率。
2、能够用数字类型的字段尽量选择数字类型而不用字符串类型的(电话号码),这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接回逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
3、对于不可变字符类型char和可变字符类型varchar都是8000字节,char查询快,但是耗存储空间,varchar查询相对慢一些但是节省存储空间。在设计字段的时候可以灵活选择,例如用户名、密码等长度变化不大的字段可以选择CHAR,对于评论等长度变化大的字段可以选择VARCHAR。
4、字段的长度在最大限度的满足可能的需要的前提下,应该尽可能的设得短一些,这样可以提高查询的效率,而且在建立索引的时候也可以减少资源的消耗。

二、查询的优化

在数据窗口使用SQL时,尽量把使用的索引放在选择的首列;算法的结构尽量简单;
在查询时,不要过多地使用通配符如SELECT* FROM T1语句,要用到几列就选择几列如:SELECT COL1,COL2 FROMT1;在可能的情况下尽量限制尽量结果集行数如:SELECT TOP 300 COL1,COL2,COL3 FROMT1,因为某些情况下用户是不需要那么多的数据的。
在没有建索引的情况下,数据库查找某一条数据,就必须进行全表扫描了,对所有数据进行一次遍历,查找出符合条件的记录。在数据量比较小的情况下,也许看不出明显的差别,但是当数据量大的情况下,这种情况就是极为糟糕的了。
SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会被SQLSERVER误解。比如:
select * from table1 where name='zhangsan' and tID >10000和执行:
select * from table1 where tID > 10000 andname='zhangsan'
一些人不知道以上两条语句的执行效率是否一样,因为如果简单的从语句先后上看,这两个语句的确是不一样,如果tID是一个聚合索引,那么后一句仅仅从表的10000条以后的记录中查找就行了;而前一句则要先从全表中查找看有几个name='zhangsan'的,而后再根据限制条件条件tID>10000来提出查询结果。
事实上,这样的担心是不必要的。SQLSERVER中有一个“查询分析优化器”,它可以计算出where子句中的搜索条件并确定哪个索引能缩小表扫描的搜索空间,也就是说,它能实现自动优化。虽然查询优化器可以根据where子句自动的进行查询优化,但有时查询优化器就会不按照您的本意进行快速查询。

所以,优化查询最重要的就是,尽量使语句符合查询优化器的规则避免全表扫描而使用索引查询。
具体要注意的:
1.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:

select id from t where num is null

可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:

select id from t where num=0
2.应尽量避免在 where子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。优化器将无法通过索引来确定将要命中的行数,因此需要搜索该表的所有行。
3.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:

select id from t where num=10 or num=20

可以这样查询:

select id from t where num=10
union all
select id from t where num=20s
4.in 和 not in 也要慎用,因为IN会使系统无法使用索引,而只能直接搜索表中的数据。如:

select id from t where num in(1,2,3)
对于连续的数值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
6.必要时强制查询优化器使用某个索引,如在 where子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:

select id from t where num=@num
可以改为强制查询使用索引:
select id from t with(index(索引名)) where num=@num
7.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:

SELECT * FROM T1 WHERE F1/2=100
应改为:
SELECT * FROM T1 WHERE F1=100*2
SELECT * FROM RECORD WHERESUBSTRING(CARD_NO,1,4)=’5378’
应改为:
SELECT * FROM RECORD WHERE CARD_NO LIKE ‘5378%’
SELECT member_number, first_name, last_name FROMmembers
WHERE DATEDIFF(yy,datofbirth,GETDATE()) >21
应改为:
SELECT member_number, first_name, last_name FROMmembers
WHERE dateofbirth <DATEADD(yy,-21,GETDATE())
即:任何对列的操作都将导致表扫描,它包括数据库函数、计算表达式等等,查询时要尽可能将操作移至等号右边。
8.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:

select id from t wheresubstring(name,1,3)='abc'--name以abc开头的id
select id from t wheredatediff(day,createdate,'2005-11-30')=0--‘2005-11-30’生成的id
应改为:
select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' andcreatedate<'2005-12-1'
9.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
10.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
11.很多时候用 exists是一个好的选择:

elect num from a where num in(select num from b)
用下面的语句替换:
select num from a where exists(select 1 from b where num=a.num)
但是后者的效率显然要高于前者。因为后者不会产生大量锁定的表扫描或是索引扫描。
如果你想校验表里是否存在某条纪录,不要用count(*)那样效率很低,而且浪费服务器资源。可以用EXISTS代替。如:
IF (SELECT COUNT(*) FROM table_name WHERE column_name ='xxx')
可以写成:
IF EXISTS (SELECT * FROM table_name WHERE column_name = 'xxx')
12.尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。
13.避免频繁创建和删除临时表,以减少系统表资源的消耗。
14.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。
15.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。
16.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table,这样可以避免系统表的较长时间锁定。
17.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。
18.尽量避免大事务操作,提高系统并发能力。
19.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。

20.避免使用不兼容的数据类型。例如float和int、char和varchar、binary和varbinary是不兼容的。数据类型的不兼容可能使优化器无法执行一些本来可以进行的优化操作。例如:

SELECT name FROM employee WHERE salary >60000
在这条语句中,如salary字段是money型的,则优化器很难对其进行优化,因为60000是个整型数。我们应当在编程时将整型转化成为钱币型,而不要等到运行时转化。

23、能用DISTINCT的就不用GROUP BY

SELECT OrderID FROM Details WHERE UnitPrice > 10 GROUP BYOrderID
可改为:
SELECT DISTINCT OrderID FROM Details WHERE UnitPrice > 10
24.能用UNION ALL就不要用UNION

UNION ALL不执行SELECTDISTINCT函数,这样就会减少很多不必要的资源

35.尽量不要用SELECT INTO语句。

SELECT INOT 语句会导致表锁定,阻止其他用户访问该表。

四、建立高效的索引
创建索引一般有以下两个目的:维护被索引列的唯一性和提供快速访问表中数据的策略。
大型数据库有两种索引即簇索引和非簇索引,一个没有簇索引的表是按堆结构存储数据,所有的数据均添加在表的尾部,而建立了簇索引的表,其数据在物理上会按照簇索引键的顺序存储,一个表只允许有一个簇索引,因此,根据B树结构,可以理解添加任何一种索引均能提高按索引列查询的速度,但会降低插入、更新、删除操作的性能,尤其是当填充因子(FillFactor)较大时。所以对索引较多的表进行频繁的插入、更新、删除操作,建表和索引时因设置较小的填充因子,以便在各数据页中留下较多的自由空间,减少页分割及重新组织的工作。
索引是从数据库中获取数据的最高效方式之一。95%的数据库性能问题都可以采用索引技术得到解决。作为一条规则,我通常对逻辑主键使用唯一的成组索引,对系统键(作为存储过程)采用唯一的非成组索引,对任何外键列[字段]采用非成组索引。不过,索引就象是盐,太多了菜就咸了。你得考虑数据库的空间有多大,表如何进行访问,还有这些访问是否主要用作读写。
实际上,您可以把索引理解为一种特殊的目录。微软的SQL SERVER提供了两种索引:聚集索引(clusteredindex,也称聚类索引、簇集索引)和非聚集索引(nonclusteredindex,也称非聚类索引、非簇集索引)。
聚集索引和非聚集索引的区别:
其实,我们的汉语字典的正文本身就是一个聚集索引。比如,我们要查“安”字,就会很自然地翻开字典的前几页,因为“安”的拼音是“an”,而按照拼音排序汉字的字典是以英文字母“a”开头并以“z”结尾的,那么“安”字就自然地排在字典的前部。如果您翻完了所有以“a”开头的部分仍然找不到这个字,那么就说明您的字典中没有这个字;同样的,如果查“张”字,那您也会将您的字典翻到最后部分,因为“张”的拼音是“zhang”。也就是说,字典的正文部分本身就是一个目录,您不需要再去查其他目录来找到您需要找的内容。
我们把这种正文内容本身就是一种按照一定规则排列的目录称为“聚集索引”。
如果您认识某个字,您可以快速地从自动中查到这个字。但您也可能会遇到您不认识的字,不知道它的发音,这时候,您就不能按照刚才的方法找到您要查的字,而需要去根据“偏旁部首”查到您要找的字,然后根据这个字后的页码直接翻到某页来找到您要找的字。但您结合“部首目录”和“检字表”而查到的字的排序并不是真正的正文的排序方法,比如您查“张”字,我们可以看到在查部首之后的检字表中“张”的页码是672页,检字表中“张”的上面是“驰”字,但页码却是63页,“张”的下面是“弩”字,页面是390页。很显然,这些字并不是真正的分别位于“张”字的上下方,现在您看到的连续的“驰、张、弩”三字实际上就是他们在非聚集索引中的排序,是字典正文中的字在非聚集索引中的映射。我们可以通过这种方式来找到您所需要的字,但它需要两个过程,先找到目录中的结果,然后再翻到您所需要的页码。

‘伍’ 如何处理高并发

处理高并发的六种方法

1:系统拆分,将一个系统拆分为多个子系统,用bbo来搞。然后每个系统连一个数据库,这样本来就一个库,现在多个数据库,这样就可以抗高并发。

2:缓存,必须得用缓存。大部分的高并发场景,都是读多写少,那你完全可以在数据库和缓存里都写一份,然后读的时候大量走缓存不就得了。毕竟人家redis轻轻松松单机几万的并发啊。没问题的。所以你可以考的虑考虑你的项目里,那些承载主要请求读场景,怎么用缓存来抗高并发。

3:MQ(消息队列),必须得用MQ。可能你还是会出现高并发写的场景,比如说一个业务操作里要频繁搞数据库几十次,增删改增删改,疯了。那高并发绝对搞挂你的系统,人家是缓存你要是用redis来承载写那肯定不行,数据随时就被LRU(淘汰掉最不经常使用的)了,数据格式还无比简单,没有事务支持。所以该用mysql还得用mysql啊。那你咋办?用MQ吧,大量的写请求灌入MQ里,排队慢慢玩儿,后边系统消费后慢慢写,控制在mysql承载范围之内。所以你得考虑考虑你的项目里,那些承载复杂写业务逻辑的场景里,如何用MQ来异步写,提升并发性。MQ单机抗几万并发也是ok的。

4:分库分表,可能到了最后数据库层面还是免不了抗高并发的要求,好吧,那么就将一个数据库拆分为多个库,多个库来抗更高的并发;然后将一个表拆分为多个表,每个表的数据量保持少一点,提高sql跑的性能。

5:读写分离,这个就是说大部分时候数据库可能也是读多写少,没必要所有请求都集中在一个库上吧,可以搞个主从架构,主库写入,从库读取,搞一个读写分离。读流量太多的时候,还可以加更多的从库。

6:solrCloud:
SolrCloud(solr 云)是Solr提供的分布式搜索方案,可以解决海量数据的 分布式全文检索,因为搭建了集群,因此具备高可用的特性,同时对数据进行主从备份,避免了单点故障问题。可以做到数据的快速恢复。并且可以动态的添加新的节点,再对数据进行平衡,可以做到负载均衡:

‘陆’ 高并发下数据库插入重复数据,有什么好方法

MySql避免重复插入记录的几种方法
本文章来给大家提供三种在mysql中避免重复插入记录方法,主要是讲到了ignore,Replace,ON DUPLICATE KEY UPDATE三种方法,有需要的朋友可以参考一下

方案一:使用ignore关键字
如果是用主键primary或者唯一索引unique区分了记录的唯一性,避免重复插入记录可以使用:
复制代码 代码如下:

INSERT IGNORE INTO `table_name` (`email`, `phone`, `user_id`) VALUES ('[email protected]', '99999', '9999');

这样当有重复记录就会忽略,执行后返回数字0

还有个应用就是复制表,避免重复记录:
复制代码 代码如下:

INSERT IGNORE INTO `table_1` (`name`) SELECT `name` FROM `table_2`;

方案二:使用Replace

语法格式:
复制代码 代码如下:

REPLACE INTO `table_name`(`col_name`, ...) VALUES (...);
REPLACE INTO `table_name` (`col_name`, ...) SELECT ...;
REPLACE INTO `table_name` SET `col_name`='value',

...算法说明:
REPLACE的运行与INSERT很相像,但是如果旧记录与新记录有相同的值,则在新记录被插入之前,旧记录被删除,即:

尝试把新行插入到表中
当因为对于主键或唯一关键字出现重复关键字错误而造成插入失败时:
从表中删除含有重复关键字值的冲突行
再次尝试把新行插入到表中
旧记录与新记录有相同的值的判断标准就是:
表有一个PRIMARY KEY或UNIQUE索引,否则,使用一个REPLACE语句没有意义。该语句会与INSERT相同,因为没有索引被用于确定是否新行复制了其它的行。
返回值:
REPLACE语句会返回一个数,来指示受影响的行的数目。该数是被删除和被插入的行数的和
受影响的行数可以容易地确定是否REPLACE只添加了一行,或者是否REPLACE也替换了其它行:检查该数是否为1(添加)或更大(替换)。
示例:
# eg:(phone字段为唯一索引)
复制代码 代码如下:

REPLACE INTO `table_name` (`email`, `phone`, `user_id`) VALUES ('test569', '99999', '123');

另外,在 SQL Server 中可以这样处理:

复制代码 代码如下:

if not exists (select phone from t where phone= '1') insert into t(phone, update_time) values('1', getdate()) else update t set update_time = getdate() where phone= '1'

更多信息请看:http://dev.mysql.com/doc/refman/5.1/zh/sql-syntax.html#replace

方案三:ON DUPLICATE KEY UPDATE
如‍上所写,你也可以在INSERT INTO…..后面加上 ON DUPLICATE KEY UPDATE方法来实现。如果您指定了ON DUPLICATE KEY UPDATE,并且插入行后会导致在一个UNIQUE索引或PRIMARY KEY中出现重复值,则执行旧行UPDATE。
例如,如果列a被定义为UNIQUE,并且包含值1,则以下两个语句具有相同的效果:
复制代码 代码如下:

INSERT INTO `table` (`a`, `b`, `c`) VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE `c`=`c`+1;
UPDATE `table` SET `c`=`c`+1 WHERE `a`=1;

如果行作为新记录被插入,则受影响行的值为1;如果原有的记录被更新,则受影响行的值为2。

注释:如果列b也是唯一列,则INSERT与此UPDATE语句相当:
复制代码 代码如下:

UPDATE `table` SET `c`=`c`+1 WHERE `a`=1 OR `b`=2 LIMIT 1;

如果a=1 OR b=2与多个行向匹配,则只有一个行被更新。通常,您应该尽量避免对带有多个唯一关键字的表使用ON DUPLICATE KEY子句。

您可以在UPDATE子句中使用VALUES(col_name)函数从INSERT…UPDATE语句的INSERT部分引用列值。换句话说,如果没有发生重复关键字冲突,则UPDATE子句中的VALUES(col_name)可以引用被插入的col_name的值。本函数特别适用于多行插入。VALUES()函数只在INSERT…UPDATE语句中有意义,其它时候会返回NULL。
复制代码 代码如下:

INSERT INTO `table` (`a`, `b`, `c`) VALUES (1, 2, 3), (4, 5, 6) ON DUPLICATE KEY UPDATE `c`=VALUES(`a`)+VALUES(`b`);

本语句与以下两个语句作用相同:

复制代码 代码如下:

INSERT INTO `table` (`a`, `b`, `c`) VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE `c`=3;
INSERT INTO `table` (`a`, `b`, `c`) VALUES (4, 5, 6) ON DUPLICATE KEY UPDATE c=9;

注释:当您使用ON DUPLICATE KEY UPDATE时,DELAYED选项被忽略。

示例:
这个例子是我在实际项目中用到的:是将一个表的数据导入到另外一个表中,数据的重复性就得考虑(如下),唯一索引为:email:
复制代码 代码如下:

INSERT INTO `table_name1` (`title`, `first_name`, `last_name`, `email`, `phone`, `user_id`, `role_id`, `status`, `campaign_id`)
SELECT '', '', '', `table_name2`.`email`, `table_name2`.`phone`, NULL, NULL, 'pending', 29 FROM `table_name2`
WHERE `table_name2`.`status` = 1
ON DUPLICATE KEY UPDATE `table_name1`.`status`='pending'

再贴一个例子:

复制代码 代码如下:

INSERT INTO `class` SELECT * FROM `class1` ON DUPLICATE KEY UPDATE `class`.`course`=`class1`.`course`

其它关键:DELAYED 做为快速插入,并不是很关心失效性,提高插入性能。
IGNORE 只关注主键对应记录是不存在,无则添加,有则忽略。

特别说明:在MYSQL中UNIQUE索引将会对null字段失效,也就是说(a字段上建立唯一索引):
复制代码 代码如下:

INSERT INTO `test` (`a`) VALUES (NULL);

是可以重复插入的(联合唯一索引也一样)。

‘柒’ 数据库高并发写入,怎么降低数据库的压力

主要通过架构设计来减少高并发对数据库的压力;
比如 在数据库和应用程序之间,增加 DAL层,通过代理,连接池等,保证数据库与业务程序由一定的缓冲和关系梳理;
在数据库前面,加一个缓存层,让大部分数据访问,都直接在缓存层获取数据,不用访问到后端的MySQL数据库;

‘捌’ 高并发,写入频繁的评论系统有必要加缓存么

如果并发真到几万的话,缓存肯定是要加的。
具体加缓存的策略,看想要什么效果,可以对查询最频繁的一类请求先加缓存。
保证mongo处于一个合理的负载。

‘玖’ java多用户同时访问和数据库进行交互,如何能够高并发

我觉得1万的数据并发量并不大,想oracle数据库,mysql承载这些并发是没有问题的

我觉得,主要的问题在于你GPS是一直在修改的,因为车辆在不断的行驶,这样的话,可能会影响数据库的性能
我觉得,你可以用一个内存行的数据库,比如,redis,用这个来存放GPS信息,redis是基于内存的,读写要比关系数据库速度快(忽略网络因素),你可能要问GPS入库怎么弄,可以做一个定时任务,每隔多少时间来将redis的数据写入到数据库中,当然,redis也支持一些算法,比如LRU,来设置何时将数据同步到数据库