赞
踩
作者:禅与计算机程序设计艺术
随着互联网的蓬勃发展,网站流量越来越大,网站的数据库访问频率也越来越高,而对于数据库服务器来说,一次数据库请求所花费的时间也越来越长。为了解决这个问题,数据库系统设计者们提出了缓存技术,将数据库中的数据存储到内存中,这样就可以减少数据库的访问次数,加快响应速度。
查询缓存(Query Cache)是指当用户执行一条SQL语句时,首先在缓存中查找该条SQL是否已经被缓存过,如果已经被缓存,则直接从缓存中返回查询结果;否则,才会真正去数据库中进行查询。缓存的存在可以极大的提高数据库查询效率。因为相比于每次都需要去数据库中查询,缓存后只需从内存中获取结果,查询速度就会显著地提升。由于缓存通常是内存空间,因此查询缓存不能无限扩大,所以缓存过期、容量限制等方面都需要进行设置。
结果缓存(Result Cache)是指当用户执行一条SELECT语句(即查询语句)时,在查询结束之前,先把结果存放在内存中,直到下次再需要的时候再取出结果并返回给客户端。而非查询语句,例如INSERT、UPDATE、DELETE语句,一般不会执行结果缓存,也就是说即使对同一个表进行操作多次,其结果也不会被缓存起来。
缓存击穿(cache-miss)是指某个热点数据被访问的情况,当某个数据出现在缓存中时,由于某种原因(如缓存过期或缓存空间不足),导致无法及时的更新到缓存中,从而导致缓存中没有该数据,然后用户再次访问该数据时,由于此时缓存中并没有该数据,因此只能从源数据库中读取。这种现象称之为缓存击穿。
缓存穿透(cache-penetration)是指在缓存和数据库中都没有对应的数据,导致用户查询不到想要的数据。缓存穿透是一种性能问题,当缓存和数据库中都没有相应的数据时,查询将会向源数据库发送请求,这种请求量可能会很大,甚至造成系统崩溃。
缓存雪崩(cache-avalanche)是指在某段时间内,缓存集体失效,所有请求都怼到数据库上。由于缓存过期时间短,刚好失效导致大量请求同时访问数据库,引起数据库压力过大,甚至宕机。
查询缓存的基本原理是将查询到的结果保存到缓存中,当下次有相同的查询请求时,就直接从缓存中返回查询结果,避免重新查询,提高查询效率。由于缓存是内存空间,不能无限扩大,因此系统设计者需要设置缓存的过期时间、大小限制等参数。
在执行SQL语句前,需要检查查询缓存中是否已经有缓存。如果缓存命中,则直接从缓存中读取查询结果;如果缓存丢失或者过期,则继续执行SQL语句并将查询结果保存到缓存中。
1.检查SQL文本是否与缓存中的SQL文本一致。如果一致,则表示命中缓存。
2.检查是否已经超过缓存过期时间。如果超过过期时间,则表示缓存过期,需要重新查询。
3.检查查询结果是否已经在缓存中。如果已经在缓存中,则直接从缓存中读取结果。
4.如果查询结果不存在缓存中,则执行SQL语句并将查询结果保存到缓存中。
检查SQL文本匹配规则如下:
1.SQL文本完全匹配。
2.SQL文本与缓存中的SQL文本包含关系。
SQL文本完全匹配时,比较SQL文本完全相同,才认为命中缓存。
SQL文本包含关系时,比较SQL文本是否包含缓存中的SQL文本。例如:
select * from user where id = 1;
该SQL语句中包含id=1
,因此可以命中以下缓存:
select * from user where id = 1 and name='test';
缓存中包含name
字段,但是该缓存不是针对上述SQL语句的,因此并不命中。
当修改数据库中的数据时,如果已经命中的缓存失效,则需要清除掉该缓存,以保证数据的最新性。
1.删除对应的缓存项。
2.刷新缓存中的最近使用列表。
3.如果缓存已满,则清除最近最久未使用的数据。
当修改数据库的数据时,要删除对应的缓存项。具体做法是,首先根据SQL语句生成唯一的key值,然后删除对应的缓存项即可。
缓存中的数据有两种类型:热点数据(经常访问的数据)和冷数据(不经常访问的数据)。维护最近使用的列表,能够快速淘汰缓存中不需要的数据,以节约内存。
刷新最近使用列表的方式有两种:
1.定期扫描缓存,检查哪些数据最近被访问,并将其移到列表头部。
2.当有新数据加入缓存时,自动添加到列表尾部。
当缓存满了之后,需要清除掉最近最久未使用的数据,以腾出缓存空间。具体做法是,首先按最近最久未使用排序,清除最后的一部分数据;也可以选择优先级低的缓存项,将其淘汰掉。
结果缓存的基本原理是将查询结果保存到内存中,当下次需要该结果时,就直接从缓存中返回结果,而不是重新执行查询,提高查询效率。
设置结果缓存一般通过启动参数完成,比如mysqld --query_cache_type=ON 或 my.ini 中的 query_cache_type 参数。
在执行查询语句前,首先检查查询缓存中是否已经有缓存。如果查询缓存已经存在,则直接从缓存中返回查询结果;如果查询缓存不存在,则继续执行查询语句并将查询结果保存到缓存中。
1.检查SQL文本是否与缓存中的SQL文本一致。如果一致,则表示命中缓存。
2.检查缓存中是否已经有查询结果。如果有,则直接返回结果。
3.如果缓存中没有查询结果,则执行SQL语句并将查询结果保存到缓存中。
检查SQL文本匹配规则如下:
1.SQL文本完全匹配。
2.SQL文本与缓存中的SQL文本包含关系。
SQL文本完全匹配时,比较SQL文本完全相同,才认为命中缓存。
SQL文本包含关系时,比较SQL文本是否包含缓存中的SQL文本。例如:
select * from user where id = 1;
该SQL语句中包含id=1
,因此可以命中以下缓存:
select * from user where id = 1 and name='test';
缓存中包含name
字段,但是该缓存不是针对上述SQL语句的,因此并不命中。
查询缓存案例模拟一个数据库系统,其中有两个表user
和product
。为了演示查询缓存的效果,假设设置了查询缓存和热点数据缓存。
-- 创建表 create table if not exists `user`( id int primary key auto_increment, username varchar(20), email varchar(50) unique key ); create table if not exists `product`( id int primary key auto_increment, product_name varchar(20), price decimal(8,2), create_time datetime default current_timestamp ); -- 插入测试数据 insert into user (username,email) values ('Alice','<EMAIL>'); insert into user (username,email) values ('Bob','<EMAIL>'); insert into user (username,email) values ('Charlie','<EMAIL>'); insert into product (product_name,price) values ('iPhone',7999.99); insert into product (product_name,price) values ('MacBook Pro',14999.99); insert into product (product_name,price) values ('iPad Air',6999.99);
为了验证查询缓存的效果,我们进行一下操作:
# 第一次查询,缓存命中,热点数据缓存命中 mysql> select * from user where email='<EMAIL>'; +----+------------+--------------+---------------------+ | id | username | email | password | +----+------------+--------------+---------------------+ | 2 | Charlie | <EMAIL> | xxxxxxxxxxxxxxxxxxxx | +----+------------+--------------+---------------------+ # 第二次查询,缓存命中,热点数据缓存命中 mysql> select * from user where email='<EMAIL>'; +----+------------+----------------------+-------------+ | id | username | email | password | +----+------------+----------------------+-------------+ | 1 | Alice | <EMAIL> | xxxxxxxxxxx | +----+------------+----------------------+-------------+ # 执行DML语句 mysql> update user set username='Tom' where email='<EMAIL>'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 # 第三次查询,缓存失效,热点数据缓存命中 mysql> select * from user where email='<EMAIL>'; +----+----------+-----------------+-------------+ | id | username | email | password | +----+----------+-----------------+-------------+ | 2 | Tom | <EMAIL> | xxxxxxxxxxx | +----+----------+-----------------+-------------+ # 更新缓存 mysql> flush tables with read lock; Query OK, 0 rows affected (0.00 sec) mysql> select * from user where email='<EMAIL>' limit 1 for update; +----+------+-----------------+-------------+ | id | uid | email | password | +----+------+-----------------+-------------+ | 2 | 1 | tom@example.com | xxxxxxxxxxx | +----+------+-----------------+-------------+ mysql> update user set username='Tom' where email='<EMAIL>'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> unlock tables; Query OK, 0 rows affected (0.00 sec)
从上面的例子可以看出,在第二次查询时,查询结果已经被缓存,不会再去执行查询。而且在执行更新操作时,更新的是缓存中的数据,而不是直接去数据库中更新。缓存失效时,要将更新的数据写入缓存,因此效率更高。
结果缓存案例模拟一个微博系统,每隔十分钟更新一次话题排行榜。为了验证结果缓存的效果,我们进行一下操作:
# 没有开启结果缓存的情况下,运行查询,发现耗时较长 mysql> SELECT pid, COUNT(*) AS hot FROM t WHERE status=1 AND created_at BETWEEN DATE_SUB(NOW(), INTERVAL 1 HOUR) AND NOW() GROUP BY pid ORDER BY hot DESC LIMIT 10; +------+-------+ | pid | hot | +------+-------+ | 4 | 20 | | 6 | 15 | | 2 | 15 | | 3 | 10 | | 1 | 10 | | 5 | 9 | | 12 | 7 | | 11 | 5 | | 10 | 5 | | 9 | 5 | +------+-------+ 20 rows in set (3.02 sec) # 通过设置开启结果缓存的参数,运行查询,发现耗时较短 mysql> SET @old_sql_mode=@@sql_mode, sql_mode=(SELECT REPLACE(@@sql_mode,'NO_ENGINE_SUBSTITUTION','')); Query OK, 0 rows affected (0.00 sec) mysql> SELECT @max_stmt_cache:=@@max_statement_history; Query OK, 0 rows affected (0.00 sec) mysql> SET @@global.max_statement_history=2048; Query OK, 0 rows affected (0.00 sec) mysql> SELECT pid, COUNT(*) AS hot FROM t WHERE status=1 AND created_at BETWEEN DATE_SUB(NOW(), INTERVAL 1 HOUR) AND NOW() GROUP BY pid ORDER BY hot DESC LIMIT 10; +------+-------+ | pid | hot | +------+-------+ | 4 | 20 | | 6 | 15 | | 2 | 15 | | 3 | 10 | | 1 | 10 | | 5 | 9 | | 12 | 7 | | 11 | 5 | | 10 | 5 | | 9 | 5 | +------+-------+ 10 rows in set (0.00 sec) # 在第二个查询中,由于命中结果缓存,结果返回速度明显更快 mysql> SELECT pid, COUNT(*) AS hot FROM t WHERE status=1 AND created_at BETWEEN DATE_SUB(NOW(), INTERVAL 1 HOUR) AND NOW() GROUP BY pid ORDER BY hot DESC LIMIT 10; +------+-------+ | pid | hot | +------+-------+ | 4 | 20 | | 6 | 15 | | 2 | 15 | | 3 | 10 | | 1 | 10 | | 5 | 9 | | 12 | 7 | | 11 | 5 | | 10 | 5 | | 9 | 5 | +------+-------+ 10 rows in set (0.00 sec) # 使用SHOW STATUS命令查看结果缓存相关状态 mysql> SHOW STATUS LIKE '%Qcache%'; +-------------------------------------------+-------+ | Variable_name | Value | +-------------------------------------------+-------+ | Qcache_free_memory | 11352 | | Qcache_free_blocks | 0 | | Qcache_total_blocks | 0 | | Qcache_hits | 1 | | Qcache_inserts | 1 | | Qcache_not_cached | 2 | | Qcache_queries_in_cache | 3 | | Queries | 1 | | Qcache_lowmem_prunes | 0 | | Questions | 21 | | Com_select | 2 | | Threads_running | 1 | | Connections | 2 | | Ssl_connections | 0 | | Table_locks_waited | 0 | | Innodb_buffer_pool_wait_free | 2 | | Innodb_data_read | 24 | | Innodb_rows_read | 13 | | Key_reads | 0 | | Open_tables | 21 | | Qcache_deleted | 0 | | Qcache_hitrate | 0.000 | | Query_cache_size | 0 | | Qcache_free_frag_pct | 100.00 | | Created_tmp_disk_tables | 0 | | Created_tmp_files | 0 | | Bytes_received | 52640 | | Uptime | 117 | | Max_used_connections | 1 | | Threads_connected | 1 | | Aborted_connects | 0 | | Table_locks_immediate | 0 | | Slave_open_temp_tables | 0 | | Threads_created | 1 | | Network_wait_timeout | 60 | | Qcache_lowmem_prunes | 0 | | Innodb_buffer_pool_bytes_data | 67901 | | Innodb_buffer_pool_pages_flushed | 1 | | Select_full_join | 0 | | Created_tmp_tables | 0 | | Qcache_queries_in_cache | 3 | | Innodb_row_lock_current_waits | 0 | | Handler_commit | 0 | | Handler_delete | 0 | | Handler_prepare | 0 | | Handler_read_first | 0 | | Handler_read_key | 0 | | Handler_read_next | 0 | | Handler_read_prev | 0 | | Handler_read_rnd | 0 | | Handler_read_rnd_next | 0 | | Handler_rollback | 0 | | Handler_savepoint | 0 | | Handler_savepoint_rollback | 0 | | Handler_update | 0 | | Open_files | 4 | | Table_open_cache_overflows | 0 | | Threads_cached | 1 | | Prepared_stmt_count | 0 | | Table_definition_size | 2501 | | Table_open_cache_instances | 11 | | Table_open_cache_seconds | 117 | | Bytes_sent | 11876 | | COM_COMMIT | 0 | | COM_DELETE | 0 | | COM_INSERT | 0 | | COM_PREPARE | 0 | | COM_ROLLBACK | 0 | | COM_REPLACE | 0 | | COM_SELECT | 2 | | COM_UPDATE | 0 | | Innodb_data_fsyncs | 0 | | Innodb_data_pending_fsyncs | 0 | | Innodb_os_log_fsyncs | 0 | | Ssl_accepts | 0 | | Ssl_accept_renegotiates | 0 | | Ssl_client_connects | 0 | | Ssl_connects | 0 | | Ssl_ctx_verify_depth | 0 | | Ssl_finished_accepts | 0 | | Ssl_session_cache_hits | 0 | | Ssl_session_cache_misses | 0 | | Ssl_session_cache_modes | 0 | | Ssl_ssl_ctx_verify_status | 0 | | Ssl_writes | 0 | | Version | 5.7.25 | | binlog_cache_disk_use | 0 | | binlog_cache_use | 0 | | connection_errors_accept | 0 | | connection_errors_internal | 0 | | connection_errors_max_connections | 0 | | connection_errors_peer_address | 0 | | connection_errors_select | 0 | | connection_errors_tcpwrap | 0 | | connections | 1 | | max_used_connections | 1 | | open_files_limit | 1024 | | qcache_free_blocks | 0 | | qcache_free_memory | 11352 | | qcache_hits | 2 | | qcache_inserts | 2 | | qcache_lowmem_prunes | 0 | | qcache_not_cached | 2 | | qcache_queries_in_cache | 5 | | qcache_total_blocks | 0 | | range_optimizer_max_mem_size | 8388608 | | slave_open_temp_tables | 0 | | sort_merge_passes | 0 | | sort_range | 0 | | sort_rows | 0 | | sort_scan | 0 | | ssl_accepts | 0 | | ssl_accept_renegotiates | 0 | | ssl_callback_cache_hits | 0 | | ssl_cipher | NULL | | ssl_client_connects | 0 | | ssl_connect_renegotiates | 0 | | ssl_ctx_verify_depth | 0 | | ssl_ctx_verify_mode | 0 | | ssl_default_timeout | 0 | | ssl_finished_accepts | 0 | | ssl_sess_accept | 0 | | ssl_sess_accept_good | 0 | | ssl_sess_accept_renegotiate | 0 | | ssl_sess_cache_full | 0 | | ssl_sess_connect | 0 | | ssl_sess_connect_renegotiate | 0 | | ssl_sess_miss | 0 | | ssl_shutdowns | 0 | | ssl_session_cache_hits | 0 | | ssl_session_cache_misses | 0 | | ssl_session_cache_mode | 0 | | ssl_session_cache_overflows | 0 | | ssl_session_cache_size | 4096 | | threads_cached | 1 | | threads_connected | 1 | | uptime | 117 | | wsrep_causal_reads | 0 | | wsrep_cert_deps_distance | 0 | | wsrep_cert_index_size | 0 | | wsrep_cert_interval | 0 | | wsrep_cluster_size | 1 | | wsrep_cluster_state_uuid | | | wsrep_commit_oooe | 0 | | wsrep_commit_window | 0 | | wsrep_desync | 0 | | wsrep_duplicated_cert_transactions | 0 | | wsrep_egress_queue_length | 0 | | wsrep_flow_control_paused | OFF | | wsrep_flow_control_paused_ns | 0 | | wsrep_flow_control_recv | 0 | | wsrep_flow_control_sent | 0 | | wsrep_local_bf_aborts | 0 | | wsrep_local_cert_failures | 0 | | wsrep_local_commits | 0 | | wsrep_local_recv_queue_avglen | 0 | | wsrep_local_recv_queue_minlen | 0 | | wsrep_local_send_queue_avglen | 0 | | wsrep_local_send_queue_minlen | 0 | | wsrep_local_state_comment | | | wsrep_local_state_transferred | 0 | | wsrep_protocol_version | 7 | | wsrep_provider_name | InnoDB | | wsrep_ready | ON | | wsrep_receive_queue_avglen | 0 | | wsrep_receive_queue_minlen | 0 | | wsrep_repl_data_bytes | 0 | | wsrep_repl_keys | 0 | | wsrep_repl_other_bytes | 0 | | wsrep_repl_other_keys | 0 | | wsrep_repl_simultaneous_reps | 0 | | wsrep_replicate_versions | 1 | | wsrep_retries_count | 0 | | wsrep_retry_errno | 0 | | wsrep_rpl_thread_count | 0 | | wsrep_sent_bytes | 11876 | | wsrep_send_queue_avglen | 0 | | wsrep_send_queue_minlen | 0 | | wsrep_service_level | NULL | | wsrep_stalls | 0 | | wsrep_startup_committed_transactions | 0 | | wsrep_startup_commit_position | -1 | | wsrep_startup_complete | ON | | wsrep_sync_queue_avglen | 0 | | wsrep_sync_queue_minlen | 0 | | wsrep_sync_source_index | -1 | | wsrep_total_committed_batches | 0 | | wsrep_total_committed_snapshots | 0 | | wsrep_total_incoming_bytes | 11876 | | wsrep_total_incoming_transmissions | 1 | | wsrep_total_keys | 0 | | wsrep_total_nonSkipped_rows | 0 | | wsrep_total_pack_bytes | 0 | | wsrep_total_queued_bytes | 0 | | wsrep_total_queued_rows | 0 | | wsrep_total_received_bytes | 0 | | wsrep_total_received_msgs | 0 | | wsrep_total_rows | 0 | | wsrep_total_sent_bytes | 0 | | wsrep_total_sent_msgs | 0 | | wsrep_total_skipped_bytes | 0 | | wsrep_total_vco_bytes | 0 | | wsrep_view_queue_avglen | 0 | | wsrep_view_queue_minlen | 0 +----+--------------------+-------------+---------+ Total items shown: 87 out of 106
从以上查询结果可以看出,开启结果缓存后的查询速度较前者提升明显。原因在于结果缓存能够命中缓存中保存的结果,避免了重复计算,加快查询速度。
目前,MySQL查询缓存主要用于缓存查询语句的结果,以提高查询效率。如果想进一步提高查询缓存的应用范围,比如缓存整个表的查询结果,那么就会遇到热点数据的缓存问题。
热点数据的缓存问题是指某一段时间内,缓存命中率很高,缓存占用内存很多的问题。这种问题往往发生在有大量热点数据的环境下,比如电商网站日均订单量最大的几个小时、秒杀活动、秒杀商品购买人数最多的那段时间等。由于缓存命中率高,所以缓存占用内存很多,最终影响到了其他查询请求的响应时间。
解决热点数据的缓存问题,可以从以下几个方面着手:
1.利用Redis等分布式缓存技术。目前很多开源分布式缓存产品,都提供了热点数据缓存功能,可以在这些产品上部署缓存解决方案,降低热点数据的缓存命中率。
2.对于热点数据,采用异步方式处理。对于访问较少的热点数据,可以采用异步的方式处理,将访问操作放入队列中,由后台线程去处理。而对于访问较多的热点数据,可以使用同步的方式处理,确保缓存命中率。
3.缓存数据的有效期。对热点数据设置较短的缓存有效期,使得缓存命中率降低,但不会影响缓存的整体性能。另外,对于一些实时性要求不高的业务,可以适当延长缓存有效期,以达到最优的效果。
随着互联网业务的发展,数据库也在增长。单一的数据库的存储能力已经无法满足需求。比如微信朋友圈的消息记录、手机通讯录、地图导航信息等。
为了解决这个问题,许多公司和组织开始采用分片方案,将数据划分为多个独立的数据库实例,每个实例负责管理其中一部分数据,彻底解决单库存储容量问题。然而,单个分片可能也会面临热点数据缓存的问题,甚至会成为系统性能瓶颈。
如何解决分片缓存问题?有以下几种方案:
1.数据分区。将数据按照某种规则分散到不同的分片中,每个分片的存储能力不同,从而缓解单个分片存储容量过小的问题。另外,可以基于数据特征对分片进行拆分,降低热点数据的影响。
2.异地多活架构。为了避免主备同步延迟带来的性能问题,可以将热点数据同步到多个可用区或区域,以提升系统的访问性能。
3.数据缓存分层。除了使用本地缓存,还可以通过多级缓存方案,将热点数据缓存在各级缓存中,提升系统的访问性能。第一级缓存可以部署在本地,第二级缓存部署在离用户最近的地方,第三级缓存部署在远处。第三级缓存需要依赖于云厂商的服务,比如亚马逊的CloudFront。
1.什么是MySQL查询缓存?
查询缓存是MySQL数据库系统提供的一种优化策略,能够对频繁执行的SELECT语句的结果进行缓存。通过缓存,下一次相同的SELECT语句的执行过程可直接从缓存中获取结果,避免重新计算,提高数据库查询效率。
2.为什么MySQL查询缓存能够提高查询效率?
查询缓存主要用于缓存查询语句的结果,避免重复计算,提高数据库查询效率。由于缓存命中率高,所以缓存占用内存很多,最终影响到了其他查询请求的响应时间。
3.MySQL查询缓存工作原理是什么样的?
MySQL查询缓存的工作原理是,当查询请求到来时,首先在缓存中查找该条SQL是否已经被缓存过,如果已经被缓存,则直接从缓存中返回查询结果;否则,才会真正去数据库中进行查询。缓存的存在可以极大的提高数据库查询效率。
4.查询缓存对什么类型的SQL语句生效?
查询缓存仅对SELECT类型的SQL语句有效。
5.查询缓存中SQL文本的匹配规则是什么?
查询缓存中SQL文本的匹配规则分两类:完全匹配和包含匹配。包含匹配就是将查询语句中的一些关键字包含在缓存的SQL文本中,且顺序相同。完全匹配就是查询语句与缓存的SQL文本完全相同。
6.MySQL查询缓存存在什么问题?
MySQL查询缓存存在以下问题:
1.缓存击穿:缓存击穿是指某个热点数据被访问的情况,当某个数据出现在缓存中时,由于某种原因(如缓存过期或缓存空间不足),导致无法及时的更新到缓存中,从而导致缓存中没有该数据,然后用户再次访问该数据时,由于此时缓存中并没有该数据,因此只能从源数据库中读取。这种现象称之为缓存击穿。
2.缓存穿透:缓存穿透(cache-penetration)是指在缓存和数据库中都没有对应的数据,导致用户查询不到想要的数据。缓存穿透是一种性能问题,当缓存和数据库中都没有相应的数据时,查询将会向源数据库发送请求,这种请求量可能会很大,甚至造成系统崩溃。
3.缓存雪崩:缓存雪崩(cache-avalanche)是指在某段时间内,缓存集体失效,所有请求都怼到数据库上。由于缓存过期时间短,刚好失效导致大量请求同时访问数据库,引起数据库压力过大,甚至宕机。
7.怎么设置MySQL查询缓存的过期时间?
可以使用查询语句:
SET QUERY_CACHE_TYPE = “ON”; //启用查询缓存
SET GLOBAL query_cache_type=“DEMAND”;//设置为"DEMAND"模式,仅对需要使用查询缓存的语句生效,缺省值也是"OFF"。
SET GLOBAL max_query_cache_size=; //设置缓存大小,缺省值为16M。
SET GLOBAL long_query_time=; //设置慢查询阈值,如果查询时间超过该值,则被视为慢查询,会打印到错误日志中。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。