首页
关于
Search
1
给你10个市场数据调研报告的免费下载网站!以后竞品数据就从这里找!
182 阅读
2
php接口优化 使用curl_multi_init批量请求
144 阅读
3
《从菜鸟到大师之路 ElasticSearch 篇》
107 阅读
4
2024年备考系统架构设计师
104 阅读
5
PHP 文件I/O
92 阅读
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
登录
Search
标签搜索
php函数
php语法
性能优化
安全
错误和异常处理
问题
vue
Composer
Session
缓存
框架
Swoole
api
并发
异步
正则表达式
php-fpm
mysql 索引
开发规范
协程
dafenqi
累计撰写
786
篇文章
累计收到
28
条评论
首页
栏目
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
副业
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
页面
关于
搜索到
72
篇与
的结果
2023-08-12
MYSQL[快问快答系列]
[MYSQL[快问快答系列]](https://learnku.com/articles/75347)4 核 16GB 内存 1TB 固态硬盘,请给我 mysql8.0 的最优配置 my.cnf[mysqld]基本设置port = 3306user = mysqldefault_storage_engine = InnoDBsocket = /var/lib/mysql/mysql.sockpid-file = /var/lib/mysql/mysql.pid日志文件设置log-error = /var/log/mysql/error.logslow_query_log = 1slow_query_log_file = /var/log/mysql/mysql-slow.loglong_query_time = 2log_queries_not_using_indexes = 1缓存设置thread_cache_size = 128table_open_cache = 2048table_definition_cache = 2048table_open_cache_instances = 64query_cache_type = 1query_cache_size = 64Mquery_cache_limit = 4MInnoDB存储引擎设置innodb_buffer_pool_size = 12G //缓冲池大小innodb_log_file_size = 2G //事务日志文件大小innodb_flush_log_at_trx_commit = 1 //2为异步,有风险;1为同步,性能较差innodb_file_per_table = 1 //每个InnoDB表创建单独的数据文件。innodb_flush_method = O_DIRECT //指定InnoDB使用的磁盘刷新方法。O_DIRECT参数表示数据被直接写入磁盘而不是被缓存到操作系统缓存中。innodb_io_capacity = 2000 //指定InnoDB磁盘IO容量的预估值。innodb_io_capacity_max = 4000 //指定InnoDB磁盘IO容量的上限值。线程和连接设置max_connections = 500 //允许的最大客户端连接数max_user_connections = 1000 //每个mysql用户允许的最大连接数。如果没有单独设置,则使用全局max_connections值。thread_stack = 512K //线程分配的堆栈空间thread_cache_size = 128 //MySQL线程缓存的大小。wait_timeout = 600 //连接在没有活动操作时被关闭之前的等待时间。interactive_timeout = 600connect_timeout = 60其他设置character_set_server = utf8mb4collation_server = utf8mb4_unicode_ci执行一条 select 语句,期间发生了什么?Mysql 客户端与 Mysql 服务端通过三次握手建立 TCP 连接验证账号密码查询缓存,如果命中直接返回 (MySQL 8.0 版本直接将查询缓存删掉了)解析器阶段,进行词法分析,生成语法树预处理阶段,检查 SQL 语句中的表或者字段是否存在,将 select 中的 符号扩展为表上的所有列优化器阶段,基于查询成本的考虑,决定使用什么索引执行器阶段,开始与存储引擎交互,从存储引擎读取记录,返回给客户端如何查看 MySQL 服务被多少个客户端连接了?show processlist;空闲连接会一直占用着吗?MySQL 定义了空闲连接的最大空闲时长,由 wait_timeout 参数控制的,默认值是 8 小时(28880 秒),如果空闲连接超过了这个时间,连接器就会自动将它断开。mysql> show variables like 'wait_timeout';Variable_nameValuewait_timeout28800MySQL 的连接数有限制吗?最大连接数由 max_connections 参数控制,超过这个值,系统就会拒绝接下来的连接请求,并报错提示 “Too many connections”。mysql> show variables like 'max_connections';Variable_nameValuemax_connections500怎么解决长连接占用内存的问题?定期断开长连接客户端主动重置连接explain 命令possible_keys 字段表示可能用到的索引key 字段表示实际用的索引,如果这一项为 NULL,说明没有使用索引;key_len 表示索引的长度,根据 key_len 长度来分析联合索引使用了几个rows 表示扫描的数据行数。type 表示数据扫描类型extra 额外信息type 执行效率从低到高的顺序为:All 全表扫描index 全索引扫描 比全表扫描好一些,好处是不用再排序range 索引范围扫描 尽量让 SQL 查询可以使用到 range 这一级别及以上的 type 访问方式ref 非唯一索引扫描eq_ref 主键或唯一索引扫描,通常使用在多表联查中const 结果只有一条的主键或唯一索引扫描extra:覆盖索引 Extra:Using index 效率不错索引下推 Extra:Using index condition文件排序 Extra:Using filesort 常见于 group by 操作 效率低临时表 Extra:Using temporary 常见于 group by/order by 操作 效率低查询一次数据最多需要多少次 IOB+Tree 存储千万级的数据只需要 3-4 层高度就可以满足,即使在数据量很大的情况,查询一个数据的磁盘 I/O 依然维持在 3-4 次什么是回表先检二级索引中的 B+Tree 的索引值,找到对应的叶子节点,然后获取主键值,然后再通过主键索引中的 B+Tree 树查询到对应的叶子节点,然后获取整行数据。这个过程叫回表,也就是说要查两个 B+Tree 才能查到数据。什么是覆盖索引在二级索引的 B+Tree 就能查询到结果的过程就叫作覆盖索引,不需要回表。什么是索引下推MySQL 5.6 引入的索引下推优化, 可以在联合索引遍历过程中,对联合索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。字符集 utf8,utf8mb4,ascii 一个字符分别占用多少字节?utf8 3 个utf8mb4 4 个 允许存储 emoji 表情ascii 1 个怎么提高这条 SQL 效率select * from order where status = 1 order by create_time asc建立 status,create_time 联合索引,避免文件排序什么时候使用索引字段有唯一性限制的经常用于 WHERE 查询条件的字段经常用于 GROUP BY 和 ORDER BY 的字段什么时候不使用索引WHERE 条件,GROUP BY,ORDER BY 里用不到的字段字段中存在大量重复数据,不需要创建索引表数据太少的时候,不需要创建索引经常更新的字段不用创建索引索引列为什么最好设置为 Not Null索引列存在 NULL 就会导致优化器在做索引选择的时候更加复杂,更加难以优化NULL 值是一个没意义的值,但是它会占用物理空间,至少每行都会用 1 字节空间存储 NULL 值列表索引什么时候失效like % xx 或者 like % xx%对索引列做了计算、函数、类型转换操作没有按照最左优先的方式进行索引的匹配在 WHERE 子句中,如果在 OR 前的条件列是索引列,而在 OR 后的条件列不是索引列Innodb 为什么选择 B+treeHashHash 在做等值查询的时候效率贼快,搜索复杂度为 O (1)。但是 Hash 表不适合做范围查询,它更适合做等值的查询二叉树数据量越大,二叉树高越高,磁盘 IO 越多,B+Tree 再千万级别的数据量下只用 3-4 层B Tree相同数据量时,B+Tree 树高比 BTree 低,磁盘 IO 次数更少B+Tree 叶子节点用双向链表串起来,适合范围查询,BTree 无法做到这点如何添加测试数据CREATE TABLE person(id int NOT NULL AUTO_INCREMENT PRIMARY KEY comment '主键', person_id tinyint not null comment '用户id', person_name VARCHAR(200) comment '用户名称', gmt_create datetime comment '创建时间', gmt_modified datetime comment '修改时间') comment '人员信息表';添加一条数据insert into person values(1, 1,'user_1', NOW(), now());以下 sql 执行 20 次 约等于 100 万条数据执行 24 次 1600 万条数据INSERT INTO person ( person_id, person_name, gmt_create, gmt_modified ) SELECT LEFT( rand()* 10, 10 ) AS person_id,concat( 'user_', LEFT ( rand()* 10, 10 ) % 2048 ),date_add( gmt_create, INTERVAL + @i cast( rand() 100 AS signed ) SECOND ),date_add(date_add( gmt_modified, INTERVAL + @i * cast( rand()* 100 AS signed ) SECOND ), INTERVAL + cast( rand()* 1000000 AS signed ) SECOND ) FROMperson;MySQL 单表为什么最好不要超过 2000W超过了这个值可能会导致 B + 树层级更高,影响查询性能。MySQL 使用 like “% x“,索引一定会失效吗?不一定,如果扫描了二级索引就能得到结果,就不用回表,直接返回数据,这个时候 explain 的 type 是 indexcount (*) 和 count (1) 有什么区别?哪个性能最好?count() 执行过程跟 count (1) 执行过程基本一样的,性能没有什么差异。而且 MySQL 会对 count () 和 count (1) 有个优化,如果有多个二级索引的时候,优化器会使用 key_len 最小的二级索引进行扫描。只有当没有二级索引的时候,才会采用主键索引来进行统计。如何优化 count (*)?近似值explain select count(*) from t_order会返回一个近似值 rows额外表保存计数值插入一条记录的同时,将计数表字段 + 1, 新增和删除的时候需要额外维护这个计数器,存在 redis 也行事务有哪些特性?原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成一致性(Consistency):事务操作前和操作后,数据满足完整性约束,数据库保持一致性状态。隔离性(Isolation):每个事务都有一个完整的数据空间,对其他并发事务是隔离的。持久性(Durability):事务处理结束后,对数据的修改就是永久的InnoDB 引擎通过什么技术来保证事务的这四个特性的呢?持久性是通过 redo log (重做日志)来保证的;原子性是通过 undo log(回滚日志) 来保证的;隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的;一致性则是通过持久性 + 原子性 + 隔离性来保证;事务的隔离级别有哪些?读未提交(read uncommitted),指一个事务还没提交时,它做的变更就能被其他事务看到;读提交(read committed),指一个事务提交之后,它做的变更才能被其他事务看到;可重复读(repeatable read),指一个事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,MySQL InnoDB 引擎的默认隔离级别;串行化(serializable );会对记录加上读写锁,在多个事务对这条记录进行读写操作时,如果发生了读写冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行;MySQL InnoDB 怎么避免幻读现象?针对快照读(普通 select 语句),是通过 MVCC 方式解决了幻读,因为可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。针对当前读(select … for update 等语句),是通过 next-key lock(记录锁 + 间隙锁)方式解决了幻读,因为当执行 select … for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。快照读和当前读有什么区别?MySQL 里除了普通查询是快照读,其他都是当前读,比如 update、insert、delete,这些语句执行前都会查询最新版本的数据。另外,select ... for update 这种查询语句是当前读,每次执行的时候都是读取最新的数据。既然备份数据库数据的时候,使用全局锁会影响业务,那有什么其他方式可以避免?在使用 mysqldump 时加上 –single-transaction 参数的时候,就会在备份数据库之前先开启事务。因为在可重复读的隔离级别下,即使其他事务更新了表的数据,也不会影响备份数据库时的 Read View,这就是事务四大特性中的隔离性,这样备份期间备份的数据一直是在开启事务时的数据。MySQL 死锁了,怎么办?设置事务等待锁的超时时间,当一个事务的等待时间超过该值后,就对这个事务进行回滚,于是锁就释放了,另一个事务就可以继续执行了。在 InnoDB 中,参数 innodb_lock_wait_timeout 是用来设置超时时间的,默认值时 50 秒。开启主动死锁检测。主动死锁检测在发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑,默认就开启。分析产生死锁的业务逻辑,考虑怎么去掉 select …for update 导致产生的死锁为什么需要 undo log?实现事务回滚,保障事务的原子性。。实现 MVCC(多版本并发控制)关键因素之一。为什么需要 缓冲池 Buffer Pool?当读取数据时,如果数据存在于 Buffer Pool 中,客户端就会直接读取 Buffer Pool 中的数据,否则再去磁盘中读取。当修改数据时,如果数据存在于 Buffer Pool 中,那直接修改 Buffer Pool 中数据所在的页,然后将其页设置为脏页,为了减少磁盘 I/O,不会立即将脏页写入磁盘,后续由后台线程选择一个合适的时机将脏页写入到磁盘Buffer Pool 除了缓存「索引页」和「数据页」,还包括了 Undo 页,插入缓存、自适应哈希索引、锁信息等等。查询一条记录,就只需要缓冲一条记录吗?不对,当我们查询一条记录时,InnoDB 是会把整个页的数据加载到 Buffer Pool 中为什么需要 redo log ?为了防止断电导致数据丢失的问题,当有一条记录需要更新的时候,InnoDB 引擎就会先更新内存(同时标记为脏页),然后将本次对这个页的修改以 redo log 的形式记录下来当系统崩溃时,虽然脏页数据没有持久化,但是 redo log 已经持久化,接着 MySQL 重启后,可以根据 redo log 的内容,将所有数据恢复到最新的状态。redo log 和 undo log 区别在哪?redo log 记录了此次事务「完成后」的数据状态,记录的是更新之后的值;undo log 记录了此次事务「开始前」的数据状态,记录的是更新之前的值;事务提交之前发生了崩溃,重启后会通过 undo log 回滚事务,事务提交之后发生了崩溃,重启后会通过 redo log 恢复事务,如下图:redo log 什么时候刷盘?MySQL 正常关闭时;当 redo log buffer 中记录的写入量大于 redo log buffer 内存空间的一半时,会触发落盘;InnoDB 的后台线程每隔 1 秒,将 redo log buffer 持久化到磁盘。每次事务提交时都将缓存在 redo log buffer 里的 redo log 直接持久化到磁盘(这个策略可由 innodb_flush_log_at_trx_commit 参数控制,下面会说)。为什么需要 binlog ?binlog 文件是记录了所有数据库表结构变更和表数据修改的日志,不会记录查询类的操作,比如 SELECT 和 SHOW 操作。redo log 和 binlog 有什么区别?binlog 是 MySQL 的 Server 层实现的日志,所有存储引擎都可以使用,用于备份恢复、主从复制;redo log 是 Innodb 存储引擎实现的日志,用于掉电等故障恢复。如果不小心整个数据库的数据被删除了,能使用 redo log 文件恢复数据吗?不可以使用 redo log 文件恢复,只能使用 binlog 文件恢复。主从复制是怎么实现?写入 Binlog:主库写 binlog 日志,提交事务,并更新本地存储数据。同步 Binlog:把 binlog 复制到所有从库上,每个从库把 binlog 写到暂存日志中。回放 Binlog:回放 binlog,并更新存储引擎中的数据。从库是不是越多越好?不是的。因为从库数量增加,从库连接上来的 I/O 线程也比较多,主库也要创建同样多的 log dump 线程来处理复制的请求,对主库资源消耗比较高,同时还受限于主库的网络带宽。所以在实际使用中,一个主库一般跟 2~3 个从库(1 套数据库,1 主 2 从 1 备主),这就是一主多从的 MySQL 集群结构。为什么需要两阶段提交?MySQL 会同时维护 binlog 日志与 InnoDB 的 redo log,为了保证这两个日志的一致性,MySQL 使用了内部 XA 事务MySQL 磁盘 I/O 很高,有什么优化的方法?设置组提交的两个参数: binlog_group_commit_sync_delay 和 binlog_group_commit_sync_no_delay_count 参数,延迟 binlog 刷盘的时机,从而减少 binlog 的刷盘次数。这个方法是基于 “额外的故意等待” 来实现的,因此可能会增加语句的响应时间,但即使 MySQL 进程中途挂了,也没有丢失数据的风险,因为 binlog 早被写入到 page cache 了,只要系统没有宕机,缓存在 page cache 里的 binlog 就会被持久化到磁盘。将 sync_binlog 设置为大于 1 的值(比较常见是 100~1000),表示每次提交事务都 write,但累积 N 个事务后才 fsync,相当于延迟了 binlog 刷盘的时机。但是这样做的风险是,主机掉电时会丢 N 个事务的 binlog 日志。将 innodb_flush_log_at_trx_commit 设置为 2。表示每次事务提交时,都只是缓存在 redo log buffer 里的 redo log 写到 redo log 文件,注意写入到「 redo log 文件」并不意味着写入到了磁盘,因为操作系统的文件系统中有个 Page Cache,专门用来缓存文件数据的,所以写入「 redo log 文件」意味着写入到了操作系统的文件缓存,然后交由操作系统控制持久化到磁盘的时机。但是这样做的风险是,主机掉电的时候会丢数据。你知道 mysql 主从延迟吗?有些时候延迟的时间还会很长。遇到这种情况咋么办?多线程复制确保使用了多线程复制,并且已经按照手册查看了如何调整各种选项以从中获得最佳效率。调整 binlog 格式调整为 statement 减小 binlog 容量临时降低持久化要求可以临时设置sync_binlog=0,innodb_flush_log_at_trx_commit=0以提高复制速度。怎么定位运行中的 MySQL 使用哪个配置文件which mysqld/usr/sbin/mysqld/usr/sbin/mysqld --verbose --help | grep -A 1 'Default options'Default options are read from the following files in the given order:/etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf 为什么不建议字段格式为 null如果查询中包含可为 NULL 的列,对 MySQL 来说更难优化,因为可为 NULL 的列使得索引、索引统计和值比较都更复杂。可为 NULL 的列会使用更多的存储空间,在 MySQL 里也需要特殊处理。储存财务数据,BIGINT 还是 DECIMAL假设要存储财务数据并精确到万分之一分,则可以把所有金额乘以一百万然后将结果存储在 BIGINT 里,这样可以同时避免浮点存储计算不精确和 DECIMAL 精确计算代价高的问题。VARCHAR 和 CHAR 的区别VARCHARVARCHAR 需要额外使用 1 或 2 字节在每行数据前记录字符串的长度:如果最大长度 <=255 字节,则只使用 1 字节表示,否则使用 2 字节。VARCHAR 节省了存储空间,所以对性能也有帮助。但是,由于行是可变长度的,在更新时可能会增长,这会导致 InnoDB 需要分割页面来容纳行,InnoDB 将过长的 VARCHAR 值存储为 BLOBCHAR当存储 CHAR 值时,MySQL 删除所有尾随空格。如果需要进行比较,值会用空格填充。CHAR 适合存储用户密码的 MD5 值。对于经常修改的数据,CHAR 也比 VARCHAR 更好,因为固定长度的行不容易出现碎片。对于非常短的列,CHAR 也比 VARCHAR 更高效;设计为只保存 Y 和 N 的值的 CHAR(1)在单字节字符集 [1] 中只使用 1 字节,但 VARCHAR(1)需要 2 字节如何查询各个数据表储存大小mysql> select table_schema as '数据库', table_name as '表名', table_rows as '记录数', truncate(data_length/1024/1024, 2) as '数据容量(MB)', truncate(index_length/1024/1024, 2) as '索引容量(MB)' from information_schema.tables where table_schema='test' order by data_length desc, index_length desc;数据库表名记录数数据容量(MB)索引容量(MB)testwd_admin_log3830.200.01DATETIME 还是 TIMESTAMPDATETIME可以保存大范围的数值,从 1000 年到 9999 年,精度为 1 微秒。它以 YYYYMMDDHHMMSS 格式存储压缩成整数的日期和时间,且与时区无关。这需要 8 字节的存储空间。TIMESTAMP存储自 1970 年 1 月 1 日格林尼治标准时间(GMT)午夜以来经过的秒数,只使用 4 字节的存储空间,只能表示从 1970 年到 2038 年 1 月 19 日,MySQL 提供 FROM_UNIXTIME () 函数来将 UNIX 时间戳转换为日期,并提供了 UNIX_TIMESTAMP () 函数将日期转换为 UNIX 时间戳。结论使用带符号的 32 位 INT,可以表达直到 2038 年的时间。使用无符号的 32 位 INT,可以表达直到 2106 年的时间。如果使用 64 位,还可以超出这些范围。这一做法越来越流行。可以对保存 md5 (),sha1 (),uuid () 的列做索引吗?这些函数生成的新值会任意分布在很大的空间内,这会减慢INSERT 和某些类型的 SELECT 查询的速度因为插入的值会写到索引的随机位置,所以会使得 INSERT 查询变慢。这会导致页分裂、磁盘随机访问,以及对于聚簇存储引擎产生聚簇索引碎片。SELECT 查询也会变慢,因为逻辑上相邻的行会广泛分布在磁盘和内存中。IPV4 地址用什么数据类型?用过函数转成 int 然后用 unsigned int 存储MySQL schema 设计中的有什么骚操作 (错误示范)?太多的列MySQL 的存储引擎 API 通过在服务器和存储引擎之间以行缓冲区格式复制行来工作,InnoDB 的行格式总是需要转换的。这种转换的成本取决于列数。太多的联接MySQL 限制每个联接有 61 个表全能的枚举如何不停机不锁表地更新表结构?pt-online-schema-change: 原理是使用触发器,对已经使用触发器的表不太兼容gh-ost: 原理是使用 binlog, 对使用外键的表不太兼容怎么选择如果你正在运行许多已存在外键的旧数据库,并且删除外键是很困难的,那么会发现 pt-online-schema-change 已经尝试对外键提供更广泛的支持,但你必须承担为数据完整性和正常运行时间选择最安全选项的认知负担。此外,gh-ost 利用 binlog 来完成其工作,因此如果由于某种原因无法访问这些日志,pt-online-schema-change 仍然是一个可行的选项。INNODB 自适应哈希索引特性?当 InnoDB 发现某些索引值被非常频繁地被访问时,它会在原有的 B-tree 索引之上,在内存中再构建一个哈希索引。这就可以实现非常快速的哈希查找。这个过程是完全自动化的,用户可以通过参数关闭这个特性。如何减少索引和数据的碎片通过执行 OPTIMIZE TABLE 或者导出再导入的方式来重新整理数据。联接查询怎么优化?确保 ON 或者 USING 子句中的列上有索引。确保任何 GROUP BY 和 ORDER BY 中的表达式只涉及一个表中的列,这样 MySQL 才有可能使用索引来优化这个过程。怎么优化大表 limit offset错误示范select id,description from film order by title limit 50, 5正确示范select id,description from film inner join (select id from film order by title limit 50,5) as lim using (id)复制如何工作主库把数据更改记录到 binlog从库启动线程 1 把主库的 binlog 复制到自己的中继日志从库启动线程 2 重放中继日志binlog_format 有多少种日志格式?STATEMENT表示在 binlog 文件中只记录 SQL 语句。这是默认值,优点是简单紧凑容量小,其最大的弊端则在于会遇到某些具有 “不确定性” 的 SQL 语句问题ROW表示在 binlog 文件中只记录受影响的行。在这种格式下,MySQL 会将对数据的更改记录为行级别的操作。这种格式可以更准确地记录数据更改,但会导致 binlog 文件更大。MIXED表示在 binlog 文件中既记录 SQL 语句,又记录受影响的行。MySQL 会自动选择适当的格式来记录数据更改。这是最常用的格式,因为它可以平衡可读性和性能。结论我们 (高性能 MYSQL 第四版) 建议坚持使用基于行的复制 ROW,除非某些场景下明确需要临时使用基于语句的复制。基于行的复制提供了最安全的数据复制方法。怎么保证崩溃后的复制安全保证每个undo log都被同步地写到磁盘,增加磁盘写入操作频次,确保数据持久性innodb_flush_log_at_trx_commit=1每次事务执行的时候都会把二进制日志同步写入磁盘。增加磁盘写入操作频次,防止丢失事务sync_binlog=1使用 InnoDB 存储引擎存储中继日志信息,提供更好的可靠性和性能。relay_log_info_repository=TABLE在复制过程中发生错误时自动尝试使用中继日志进行恢复relay_log_recovery=ON延迟复制有什么用想象一下这样的场景,你正在处理大量数据,突然意外地做了一些变更:删除了一个表。从备份中恢复可能需要几个小时。如果使用了延迟复制的副本,则可以找到 DROP TABLE 语句对应的 GTID,使副本服务器的复制运行到表被删除之前的时间点,这会大大减少修复时间。什么是多线程复制?最新的 MySQL 版本则提供了多线程复制能力,可以在副本端运行多个 SQL 线程,从而加快本地中继日志的应用。什么是半同步复制?在半同步复制中,主服务器会等待至少一个从服务器将更新成功复制后,才会返回客户端。确保至少一个从服务器成功复制了更新,降低故障恢复的成本,缺点是会影响主服务器的性能
2023年08月12日
12 阅读
0 评论
0 点赞
2023-08-08
php中mysql数据库异步查询实现
php中mysql数据库异步查询实现问题通常一个web应用的性能瓶颈在数据库。因为,通常情况下php中mysql查询是串行的。也就是说,如果指定两条sql语句时,第二条sql语句会等到第一条sql语句执行完毕再去执行。这个时候,如果执行2条sql语句,每条执行时间为50ms,全部执行完毕可能需要100ms。既然,主要原因是sql的串行执行导致。那我们是不是可以改变执行方式来提高性能呢?答案是,可以的。我们可以通过异步执行的方式来提高性能。异步如果通过异步的方式去执行,可能性能会有很大提升。如果是采用异步的方式,两条sql语句会并发执行,可能就需要60ms就可以执行完毕。实现mysqli + mysqlnd。php官方实现的mysqlnd中提供了异步查询的方法。分别是:mysqlnd_async_query 发送查询请求mysqlnd_reap_async_query 获取查询结果这样就可以不必每次发送完查询请求后,一直阻塞等待查询结果了。实现代码如下:1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677<?php$host = '127.0.0.1';$user = 'root';$password = '';$database = 'test';/**期望得到额结果array(1 => int,2 => int,3 => int) */$result = array(1=>0, 2=>0, 3=>0);//异步方式[并发请求]$time_start = microtime(true);$links = array();foreach ($result as $key=>$value) {$obj = new mysqli($host, $user, $password, $database); $links[spl_object_hash($obj)] = array('value'=>$key, 'link'=>$obj);}$done = 0;$total = count($links);foreach ($links as $value) {$value['link']->query("SELECT COUNT(*) AS `total` FROM `demo` WHERE `value`={$value['value']}", MYSQLI_ASYNC);}do {$tmp = array(); foreach ($links as $value) { $tmp[] = $value['link']; } $read = $errors = $reject = $tmp; $re = mysqli_poll($read, $errors, $reject, 1); if (false === $re) { die('mysqli_poll failed'); } elseif ($re < 1) { continue; } foreach ($read as $link) { $sql_result = $link->reap_async_query(); if (is_object($sql_result)) { $sql_result_array = $sql_result->fetch_array(MYSQLI_ASSOC);//只有一行 $sql_result->free(); $hash = spl_object_hash($link); $key_in_result = $links[$hash]['value']; $result[$key_in_result] = $sql_result_array['total']; } else { echo $link->error, "\n"; } $done++; } foreach ($errors as $link) { echo $link->error, "1\n"; $done++; } foreach ($reject as $link) { printf("server is busy, client was rejected.\n", $link->connect_error, $link->error); //这个地方别再$done++了。 }} while ($done<$total);var_dump($result);echo "ASYNC_QUERY_TIME:", microtime(true)-$time_start, "\n";$link = end($links);$link = $link['link'];echo "\n";结语mysql数据库对于每个查询请求都是单独启动一个线程进行处理。如果mysql服务器启动线程过多,必然会造成线程切换引起系统负载过高。如果在mysql数据库负载不高的情况下,使用异步查询还是不错的选择。
2023年08月08日
7 阅读
0 评论
0 点赞
2023-08-08
PHP实现真正的异步MySQL
PHP实现真正的异步MySQLnode.js之类的语言可以实现异步的数据库查询功能,执行SQL语句之后不必等待数据库返回结果。继续去执行其他的代码,当数据库返回结果是再对数据进行处理,如渲染页面,并将HTML页面发送给客户端。这样应用程序完全不需要阻塞等待。这种方式运行效率非常高。PHP中是否可以实现类似的异步非阻塞MySQL查询呢?使用github搜索发现一个项目貌似是做此功能的,https://github.com/kaja47/async-mysql,查看代码是基于React.PHP.的。但并不是真正的异步SQL。实现的原理是设置一个定时器,每0.02秒轮询一次。虽然也可以用,但这样很浪费CPU资源。不是真正的异步MYSQL。现在Swoole1.6.2提供了swoole_event_add和swoole_get_mysqli_sock 2个新的函数,使用它完全可以实现真正的PHP异步MySQL。下面讲一下具体的实现。代码:$db = new mysqli; $db->connect('127.0.0.1', 'root', 'root', 'test'); $db->query("show tables", MYSQLI_ASYNC); swoole_event_add(swoole_get_mysqli_sock($db), function($db_sock) { global $db; $res = $db->reap_async_query(); var_dump($res->fetch_all(MYSQLI_ASSOC)); swoole_event_exit(); });首先连接mysql,连接成功后执行SQL语句,要在第二个参数指定MYSQLI_ASYNC。表示此查询为异步。query函数会立即返回,这时候并没有得到mysqli_result。然后调用swoole_get_mysqli_sock函数取到mysql连接的socket,并调用swoole_event_add将它加入到swoole的epoll事件循环中。当数据库返回结果是会回调我们刚才制定的函数。这时候再调用mysqli_reap_async_query得到result,调用fetch_all函数得到数据。这个过程是完全异步非阻塞的,不存在任何浪费CPU的代码。这个代码还可以用在服务器端程序上,具体代码实现后续会再写一篇文章详细介绍。
2023年08月08日
12 阅读
0 评论
0 点赞
2023-08-08
PHP异步并发访问mysql简单实现
PHP异步并发访问mysql简单实现在实际的开发过程中,我们常常会遇到需要操作多张表,多个库的情况。有时因为一些限制我们不能进行连表(例如,异地数据库),所以只能用php串行访问后再在php里进行合并,有时还需要模拟mysql对合并后的结果进行排序、归并等。这里产生的一个问题就是串行带来的访问时间问题。由于传统的串行访问方式,我们只能等到一条sql执行完毕后才可以执行下一条,所以执行时间是累加的。PHP官方手册提供了一种可以异步并发访问mysql的方式,详见:http://php.net/manual/zh/mysqli.poll.php,参考资料:https://svn.osgeo.org/mapguide/sandbox/rfc94/Oem/php/ext/mysqli/tests/mysqli_poll.phpt,使用此种方式,我们可以对Mysql进行异步并发访问,访问时间不再是串行累加,而是取决于执行时间最长的sql。项目地址:https://github.com/huyanping/async-mysql-phpshow you the code: try{ $async_mysql = new \Jenner\Mysql\Async(); $async_mysql->attach( ['host' => '127.0.0.1', 'user' => 'root', 'password' => '', 'database' => 'test'], 'select * from stu' ); $async_mysql->attach( ['host' => '127.0.0.1', 'user' => 'root', 'password' => '', 'database' => 'test'], 'select * from stu limit 0, 3' ); $result = $async_mysql->execute(); print_r($result); }catch (Exception $e){ echo $e->getMessage(); }async_mysql对象对mysql进行异步并发访问,attach方法接收每个请求必须的配置信息,execute方法为执行入口,其返回值是每条sql执行结果的数组,顺序与attach调用顺序一致。当任何一个连接mysql出错或执行任何一条sql出错,都会引起异常抛出。这样设计主要是基于完整性的考虑,我们把所有需要执行的sql看做是一个整体事务,任何一个执行失败,则认为该事务失败。composer信息:"require":{ "jenner/async-mysql-php": "v0.1" }或者直接引入/path/to/async-mysql-php/autoload.php文件最后在阿里云上做了一个简单的测试,测试结果如下:# 同步 [root@iZ942077c78Z async-mysql-php]# php tests/performance_sync.php ------------------------------------------ mark:[total diff] time:4.2648551464081s memory_real:18944KB memory_emalloc:18377.171875KB memory_peak_real:28416KB memory_peak_emalloc:27560.3828125KB [root@iZ942077c78Z async-mysql-php]# php tests/performance_sync.php ------------------------------------------ mark:[total diff] time:4.2285549640656s memory_real:18944KB memory_emalloc:18377.171875KB memory_peak_real:28416KB memory_peak_emalloc:27560.3828125KB [root@iZ942077c78Z async-mysql-php]# php tests/performance_async.php ------------------------------------------ mark:[total diff] time:1.455677986145s memory_real:38144KB memory_emalloc:32574.015625KB memory_peak_real:66816KB memory_peak_emalloc:65709.7734375KB # 异步 [root@iZ942077c78Z async-mysql-php]# php tests/performance_async.php ------------------------------------------ mark:[total diff] time:1.8936941623688s memory_real:38144KB memory_emalloc:32574.015625KB memory_peak_real:66816KB memory_peak_emalloc:65709.7734375KB [root@iZ942077c78Z async-mysql-php]# php tests/performance_async.php ------------------------------------------ mark:[total diff] time:1.5208158493042s memory_real:38144KB memory_emalloc:32574.015625KB memory_peak_real:66816KB memory_peak_emalloc:65709.7734375KB实际上以上测试结果并没有太大意义。因为理论上这种异步并发的访问方式会绝对优于传统的串行访问方式,再次需要说明的是,访问数据库的时间接近执行时间最长的SQL。由于同一时间要处理多个SQL返回的结果,程序需要连续申请多个内存空间用于存储SQL的返回结果。所以使用这种方式会造成内存翻倍。从下面的测试结果来看,内存基本位置在两倍以内(测试程序执行了两条SQL)。到了这一步,我们已经可以实现对mysql进行异步并发访问了。如果我们还需要做多个数组的归并,可以使用《PHP模拟SQL的GROUP BY算法》中介绍的方法。其中提供的归并方式非常灵活,更胜mysql原生的group by。如果还需要对合并后的结果做排序,可以使用https://github.com/huyanping/Zebra-Tools/blob/master/src/Jenner/Zebra/Tools/CommonArray.php#L90这段代码实现,非常方便。改函数来源于php手册http://php.net/manual/zh/function.array-multisort.php
2023年08月08日
9 阅读
0 评论
0 点赞
2023-08-07
PHP —-MySQL 数据库
PHP —-MySQL 数据库MySQL数据库操作1.创建数据库.在MySQL中应用 create database 语句创建数据库.格式如下:create database db_name;db_name 为数据库名,必须为合法名称.规定如下:a.不能与其他数据库重名.b.名字可以是任意的字母,阿拉伯数字,下划线或者"$"组成.可以使用以上任意的字符开头,但不能是使用单独的数字,哪样会造成与数字混淆.c.名字最长可由64个字符组成(包括表,列和索引),而别名最多可长达256个字符.d.不能使用MySQL关键字作为数据库名称和表名.ps: 执行过程:在创建数据库时,首先连接MySQL服务器,用户名是root,密码也是root,然后编写"create database db_name;" sql语句,数据库创建成功.2.选择数据库.use 语句用于选择一个数据库,使其成为当前默认数据库.格式如下:use db_name;3.删除数据库.删除数据库使用 drop database 语句.格式如下:drop database db_nameps.对于删除数据库的操作应该谨慎使用.一旦删除数据库中的所有结构和数据都将会被删除,没有恢复的可能,除非数据库中有备份.MySQL 数据库表上面将完数据库的操作,下面讲一下数据库中,对表的操作.MySQL 数据库表的操作包括 创建,查看,修改,重命名和删除.1.创建表.创建表使用 create table 语句.格式如下:create [temporary] table [if not exists] 数据表名 [(create_definition,...)][table_options][select_statement]a. temporary ,如果使用该关键字,表示创建一个临时表.b. if not exists ,该关键字用于避免创建表时,表存在时 MySQL报告的错误.c. create_definition,这是表的列表属性部分.MySQL要求在创建表时,表至少要包含一列.create_deifnition 格式如下:col_name type [not null] [default default_value] [auto_increment] [primary key] [reference_definition]col_name:字段名. type:字段类型. not null|null:指出该列是否允许空值.not null 表示不允许空值.default default_value:表示默认值.auto_increament:表示默认值.primary key:表示是否为主键,一个表中只能有一个primary key.如果没有primary key ,而某些应用要求primary key,服务器将返回第一个没有null 列的unique 键作为primary key.d. table_option, 表的一些特性参数.e. select_statement,select语句描述部分,用它可以快速地创建表.2.查看表.对于创建成功的表,使用 show columns 语句或 describe 语句查看指定数据表的表结构.格式如下:show columns 语句:show [full] columns from 数据表名 [from 数据库名]; 或者 show [full] columns from 数据表名.数据库名;describe 语句,describe 可以简写成DESC.describe 数据表名; 或者 describe 数据表名 列名;3.修改表.修改表结构使用 alter table 语句.其中,修改表结构的操作又包括:增加或者删除字段,修改字段名称或者字段类型,设置/取消主键或者外键,设置/取消索引以及修改表的注释等.格式如下:alter [ignore] TABLE 数据表名 alter_spec[,alter_spec]....如果指定参数 ignore,当出现重复行时,则只执行一行,其他重复行将被删除.其中alter_spec 子句定义要修改的内容,格式如下:alter_specification: add [column] create_definition [FIRST | AFTER column_name],//添加新字段 add index [index_name] (index_col_name,....),//添加索引名称 add primary key (index_col_name,...),//添加主键名称 add unique [index_name] (index_col_name,...),//添加唯一的索引 alter [column] col_name {SET DEFAULT literal | DROP DEFAULT},//修改字段名称 change [column] old_col_name create_definition //修改字段类型 modify [column] create_definition,//修改字句定义的字段 drop [column] col_name ,//删除字段名称 drop primary key,//删除主键名称 drop indEX index_name, //删除索引名称 rename [AS] new_tbl_name,//更改表名 table_optionsalter table 语句允许制定多个动作,其动作使用逗号分隔,每个动作表示对表的一个修改.通过alter 修改表列的前提是必须将表中的数据全部删除.4. 重命名表.重命名表使用rename table 语句.格式如下:rename table 数据表名1 to 数据表名2;//rename table 语句可以同时对多个数据表进行重命名,多个表之间以逗号分隔.5. 删除表删除数据表使用语句 drop table .格式如下:drop table 数据表名; 或者 drop table if exists 数据表名; //防止删除不存在的表,导致的报错.删除数据表,将同样导致没有备份的数据无法恢复.ps:在执行create table,alter table和drop table中的任何操作时,首先必须选择数据库,否则将无法对数据表进行操作.MySQL 数据表中的数据下面总结数据表中的数据.如何更好的操作和使用这些数据才是使用MySQL数据库的根本.1.添加(插入)数据.创建完数据库和数据表后,要向表中添加数据.添加数据主要有三种语法方式:a.列出所有新添加数据的所有的值.insert into table_name values(value1,value2,.....);//语句缺点 当列过多的时候,不易明确知道匹配值.b.给出要赋值的列,然后再给出值.insert into table_name (column_name1,column_name2,...) values ( value1,value2,....);//缺点同上c.用col_name =value 的形式给出列和值.insert into table_name set column_name1 = value1 ,column_name2 = value2 , ....;//弥补以上缺点,但导致语句过长.批量添加数据begin 数据的批量添加使用 load data 和MySQLimport 语句实现.load data 通过大量读取本地文件系统上的文件,可以将大量数据添加到数据库中.格式如下:load data local infile "filename.txt" into table table_name;MySQLimport语句实现程序直接从文件读取批量数据.它相当于load data 语句的一个接口.格式如下:%MySQLimport -local table_name filename.txt;MySQLimport可以自动生成一个load data 语句,该语句把filename.txt 文件中的数据装入table_name 表.MySQLimport 将文件名中第一个圆点前的的字符作为新的表名,并且将文件中的数据导入到新表中.如 文件名 com.youfilename.txt. 那么将会将数据导入到表com 中.2.修改数据.修改数据使用update语句.格式如下:update table_name set column_name1=new_Value1,column_name2 =new_value2,... where condition;condition 为条件语句,如user_name='张三'. 必须保证condition条件的准确性,否则将会导致破坏表中的数据.3.删除数据.删除数据使用 delete 语句.格式如下:delete from table_name where condition;psa.删除某条数据时,一般选择该数据的id 作为条件,以避免产生不必要的错误.b.当到删除整个表的数据,因效率问题,不推荐使用delete操作.可以使用truncate 语句,它可以很快的删除表中的所有内容.4.查询数据.从数据库表中查询数据用与操作以及显示,是对数据进行操作比较重要的一环.下面将会作详细的解释.首先,对MySql数据库表进行数据查询用到select 语句.格式如下:select selection_list //要查询的内容,选择查询的列. from table_list //从何表中查询,从何处选择行. where primaryz_constraint //查询时,需要满足的条件. group by grouping_columns //如何对查询结果进行分组. order by sorting_columns //如何对结果进行排序 having secondary_constraint //查询时满足的第二条件. limit count //限定输出的结果.a. select_list 表示要查询的内容.如果要查询表中所有的列,可以用" * "表示.如果查询多列,可以直接输入列名,并使用" , "分隔.b. table_list 从指定的表中查询.既可以从一个表中查询;也可以从多个表中查询,多表查询使用 " ," 分隔,并且在where 字句中使用连接运算符号来确定表与表之间的关系.当使用多表查询的使用,如果表中有相同的字段,为了告诉服务器要显示的那个表中的字段信息,需要在字段前加上表名.格式如下:table_name.columns_name; //表名.字段名.使用 " = "符号将表连接起来,叫做等同连接.比如.tb_student.name = tb_gradeOne.name ;如果不使用等号连接,那么产生的结果将是两个表的笛卡尔积,叫做全连接.c.where 条件语句用于通过相应条件获取对应信息.格式为 columns_name 比较运算符 value.d. group by 实现对查询得到的数据进行划分并加以分组,从而实现分组查询.在查询时,所查询的列必须包含在分组的列中,目的是使查询到的数据没有矛盾.在与avg() 或则sum()函数一起使用时,group by 语句能够发挥最大的作用.e.使用distinct 在结果中去除重复行.f.order by.使用order by 可以对结果进行升序和降序(DESC),在默认情况下,order by 按照升序输出结果.如果要降序可以使用DESC 来实现.当对含有null值的列进行排序时,升序,null值排在最前,降序,null 排在最后.g.like 模糊查询. like 属于较常用的运算符,通过它可以实现模糊查询,他有两种通配符,即"%"和下划线"_"."%"可以实现匹配一个或多个字符,而"_"只匹配一个字符.h. 使用concat 联合多列.使用concat 函数可以联合多个字段,从而构成一个总的字符串.例如把书名与价格合并,并使用as 为字段起一个别名.select id ,concat(bookname,":",price) as bookInfo form tb_mkbook;i.使用limit 限定结果函数.使用limit字句可以对结果的记录条数进行限定,从而控制它输出的行数. 例如:limit 3 --表示显示3条数据.limit 5,10---表示从编号为5的记录开始,往下读10条数据用于显示.j.函数表达式.常用的统计函数有:avg(columns_name);//获取指定列的平均值.count(columns_name);//统计出制定列的非空记录的条数. 加distinct限定关键字,则统计不同值的条数,相同值的被认为为一条记录.count(*),则统计包含空记录的数目.max(columns_name) 或者 min(columns_name);//获取指定字段的最大/最小值.std(columns_name) 或者 stdtev(columns_name);//指定字段的标准背离值.sum(columns_name);//指定字段所有记录的值的和.ps.常见的数据类型有 数字类型,字符串类型,时间和日期类型.详细情况,请参考php相关知料与文档.MySQL 数据库的操作步骤以上对mysql数据库结构层次总结如下,下面介绍对数据库的操作步骤.1.连接到mysql服务器.使用mysql_connect()函数创建与MySQL服务器连接.方法格式如下:<?php $conn = mysql_connect('hostname' , 'username' , ' password ') or die( "数据库服务器连接失败".mysql_error()); //hostname: mysql服务器的主机名或者ip.如果省略端口号,则默认为3306; //username:登陆mysql数据库服务器的名称 //password: mysql服务器的用户密码. //改函数的返回值表示对这个数据库的连接,如果成功,则返回一个资源. if($conn){ //服务器连接成功 } ?>从上可以知道,可以指定非本机的机器名作为数据库服务器,这样就为数据库的异地存储和数据库的的安全隔离提供了保障.外界用户往往通过www服务器的直接访问权限,如果数据库直接放在www服务器上,就会给MySQL数据库带来安全隐患;如果为数据库系统安装防火墙,那么php可以直接通过局域网访问数据库,而局域网的计算机对外部不可见,这样保证了s数据库不受外来攻击.为了方便查询数据库连接错误,可以加上die()函数进行屏蔽的错误处理机制.mysql_error()用于提取错误文本信息,如果没有出错则返回空字符;如果出错,连兰奇上将会显示错误信息.ps.对于用户而言,建议在mysql_connect()前面添加@符号,用于屏蔽错误信息,这样做是为了让用户看到一堆莫名其妙的错误信息.但是对于开发者而言,在调试的过程中,不使用@能让我们快速定位错误信息.2.选择MySQL数据库.使用mysql_select_db()函数选择MySQL数据库服务器上的数据库,并与数据库创建连接.格式如下:mysql_select_db(string 数据库名 [,resource link_identifier]); //string 数据库名:要选择的MySQL数据库名称 //resource link_identifier: MySQL服务器的连接标识.//例子,同上一步. <?php if($conn){ $selected = sql_select_db("db_webBookStore",$conn); if($selected){ //数据库连接成功; } } ?>3.执行sql语句.使用mysql_query()函数执行sql语句.sql语句操作在前面已经讲过,此处不在阐述.主要介绍mysql_query()函数的用法,格式如下:$result = mysql_query(string sql [,resource link_identifier]); //如果sql语句为查询语句,成功则返回结果集合,否则返回false //如果sql语句为插入,删除或更新,成功则返回true,否则返回false. //ps.改函数也可以用于选择数据库,和设置数据库编码格式. //如:mysql_query('user db_database13',$conn); // mysql_query(' set names utf8');提高: mysql_unbuffered_query() ,顾名思义改函数为不缓存结果查询.它仅向服务器发送一条sql查询语句,但不获取和缓存结果的行.它不像mysql_query哪样自动获取并缓存结果集.优点在于,当处理很大的结果集时,会节省客观的内存;另一方面,可以在获取第一行数据后立即对结果集进行操作,而不用等到整个SQL语句都执行完毕.mysql_fetch_array()函数,用于将结果集合返回到数组中.格式为:$array = mysql_fetch_array(resource result [,int result_type]); //resource result:资源类型的参数,要传入的是由mysql_query()返回的资源数据指针. //int result_type:可选项,要传入的整型参数,可以是:mysql_assoc(关联索引),mysql_num(数字索引),mysql_both(同时包含前两者).默认为mysql_both. //注意,本函数返回的字段名区分大小写. mysql_fetch_row()函数,从结果集中获取一行来作为枚举数组.格式为: $array = mysql_fetch_row(resource result); //根据所获取的行数据,生成数组.如果没有更多的行,则返回false. //数组偏移量下标从0开始. //本函数返回的字段名区分大小写. 本函数只能使用数字索引,而mysql_fetch_array()两者都可使用.如:数字索引:$array[0],关联索引:$array[type]; mysql_num_rows()函数,用于获取查询结果集中的记录数.格式为: int mysql_num_rows(resource result); //返回结果集中行的数目.此命令只对select语句有效.要获取其他sql语句的操作所影响的数据集行数目,需要使用mysql_affected_rows()4.数据执行完后,需要关闭结果集,以释放资源.语法如下:mysql_free_result(resource result);如果在网页中要频繁的对数据库进行访问,可以通过创建与服务器数据库持续连接来提高效率.这样就避免了,每次连接服务器请求多带来的长时间请求和较大的资源开销.持续连接数据库使用mysql_pconnect()函数来替换mysql_connect()函数.创建的持续连接,在程序结束前将不会调用mysql_close()来关闭数据库请求.当再次调用mysql_pconnect()去连接数据库的时,服务器将返回已经创建的持续连接的ID号,而不去重新创建数据库连接.5.关闭MySQL服务器.每次使用mysql_connect()和mysql_query(),都会消耗系统资源.在少量用户访问web网站时候问题还不大,但当大量用户连接超过一定的数量,就会造成系统性能的下降,甚至死机.为了避免这种情况,在完成数据库操作后,应调用改函数来关闭与MySQL服务器的连接,以节省系统的资源.格式如下:mysql_close($conn);ps.php中与数据库的连接是非持久连接,系统会自动回收,一般不用设置关闭.但如果一次性返回的结果集比较大,或者网站访问量比较多,则最好使用改函数手动释放.提高:数据库乱码问题,使用mysql_query()函数设置数据库编码. 编码格式建议使用utf-8 .如果使用gbk2312,如果用户没有安装中文编码(如一些美洲,欧洲用户的机器查看中文网站),则在输出时将会导致乱码.utf-8 的使用返回更广,可移植性更高,也更被国际化支持.
2023年08月07日
14 阅读
0 评论
0 点赞
1
...
9
10
11
...
15