MySQL主从复制与读写分离( 主从复制原理 、读写分离原理 、配置 MySQL 主从复制 、配置 MySQL 读写分离)_mysql主从复制,主从复制的原理,读写分离,读写分离的原理,mysql优化-程序员宅基地

技术标签: 数据库主从同步与读写分离  linux  mysql  数据库  

一、 MySQL主从复制与读写分离简介

在实际的生产环境中,如果对数据库的读和写都在同一个数据库服务器中操作,无论是在安全性、高可用性还是高并发等各个方面都是完全不能满足实际需求的。因此,一般来说 都是通过主从复制(Master-Slave)来同步数据,再通过读写分离来提升数据库并发负载能力的方案来进行部署与实施。

MySQL数据库自身提供的主从复制功能可以方便的实现数据的多处自动备份,实现数据库的拓展。多个数据备份不仅可以加强数据的安全性,通过实现读写分离还能进一步提升数据库的负载性能。

如图所示,一台主 MySQL 服务器带两台从 MySQL 服务器做数据复制,前端应用在进行数据库写操作时,对主服务器进行操作,在进行数据库读操作时,对两台从服务器进行操作,这样大量减轻了对主服务器的压力(图片来源于网络)。
在这里插入图片描述

二、 MySQL主从复制原理

MySQL 的主从复制和 MySQL 的读写分离两者有着紧密联系,首先要部署主从复制,只有主从复制完成了,才能在此基础上进行数据的读写分离。

2.1 MySQL 支持的复制类型

  1. 基于语句的复制。在主服务器上执行的 SQL 语句,在从服务器上执行同样的语句。MySQL 默认采用基于语句的复制,效率比较高。
  2. 基于行的复制。把改变的内容复制过去,而不是把命令在从服务器上执行一遍。
  3. 混合类型的复制。默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。
  4. 全局事务标识符 GTID(Global Transaction Identifier,GTID)

基于SQL语句的方式是最直接的方式,也是目前默认的复制方式,后来的三种是MySQL 5以后才出现的复制方式。

2.2 MySQL复制的工作过程

在这里插入图片描述

  1. 在每个事务更新数据完成之前,Master 将这些改变记录进二进制日志。写入二进制日志完成后,Master 通知存储引擎提交事务。
  2. Slave 将 Master 的 Binary log 复制到其中继日志(Relay log)。首先,Slave 开始一个工作线程——I/O 线程,I/O 线程在 Master 上打开一个普通的连接,然后开始 Binlog dump process。Binlog dump process 从 Master 的二进制日志中读取事件,如果已经跟上 Master,它会睡眠并等待 Master 产生新的事件。I/O 线程将这些事件写入中继日志。
  3. SQLslave thread(SQL 从线程)处理该过程的最后一步。SQL 线程从中继日志读取事件,并重放其中的事件而更新 Slave 数据,使其与 Master 中的数据保持一致。只要该线程与 I/O 线程保持一致,中继日志通常会位于 OS 的缓存中,所以中继日志的开销很小。 复制过程有一个很重要的限制,即复制在 Slave 上是串行化的,也就是说 Master 上的并行更新操作不能在 Slave 上并行操作。

三、 配置MySQL主从复制

实验目的

实现MySQL数据库之间的主从复制

实验环境

VMware虚拟机中三台centos7.6虚拟机

实验参数

MySQL数据库版本5.7.17
master:14.0.0.7 server-id 10
slave1:14.0.0.17 server-id 20
slave2:14.0.0.27 server-id 30

实验过程

1.手工编译安装MySQL5.7.17

首先在三台虚拟机中都装上mysql,一定要手工编译安装。
手工编译安装MySQL5.7.17脚本如下

---------------------安装软件环境包----------------------------------------------------
yum install ncurses ncurses-devel bison  gcc gcc-c++ cmake -y
 cd /opt   ##将软件包拷贝到当前目录下
tar xzvf mysql-5.7.17.tar.gz  -C /opt
tar xvzf boost_1_59_0.tar.gz -C /usr/local/

useradd -s /sbin/nologin mysql    ##创建数据库管理用户

cd /usr/local/
mv boost_1_59_0/ boost     ##改名方便使用
----------------------------手工编译安装配置----------------------------------------------
cd /opt/mysql-5.7.17/      ##和安装5.7.20的区别在于,5.7.20的boost是集成了一个包,cmake的路径和5.7.17有区别
 cmake \
 -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
 -DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \
 -DSYSCONFDIR=/etc \
 -DSYSTEMD_PID_DIR=/usr/local/mysql \
 -DDEFAULT_CHARSET=utf8 \
 -DDEFAULT_COLLATION=utf8_general_ci \
 -DWITH_INNOBASE_STORAGE_ENGINE=1 \
 -DWITH_ARCHIVE_STORAGE_ENGINE=1 \
 -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
 -DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \
 -DMYSQL_DATADIR=/usr/local/mysql/data \
 -DWITH_BOOST=/usr/local/boost \
 -DWITH_SYSTEMD=1

-------------------编译安装-------------------------------------
make 
make install

-------------------进行mysql设置-------------------------------
chown -R mysql.mysql /usr/local/mysql/    ##将mysql的属主、属组设置为mysql方便管理
 
-------------------------配置mysql文件-------------------------------------
vim /etc/my.cnf
[client]
port = 3306
default-character-set=utf8
socket = /usr/local/mysql/mysql.sock
[mysql]
port = 3306
default-character-set=utf8
socket = /usr/local/mysql/mysql.sock

[mysqld]
user = mysql
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
port = 3306
character_set_server=utf8
pid-file = /usr/local/mysql/mysqld.pid
socket = /usr/local/mysql/mysql.sock
server-id = 1
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,PIPES_AS_CONCAT,ANSI_QUOTES 
 
chown mysql.mysql /etc/my.cnf

--------------------------------声明环境变量--------------------------
echo 'PATH=/usr/local/mysql/bin/:/usr/local/mysql/lib:$PATH' >> /etc/profile
echo 'export PATH' >> /etc/profile
source /etc/profile
----------------------------初始化数据库---------------------------------
cd /usr/local/mysql/
bin/mysqld \
  --initialize-insecure \
  --user=mysql \
  --basedir=/usr/local/mysql \
  --datadir=/usr/local/mysql/data

cp /usr/local/mysql/usr/lib/systemd/system/mysqld.service  /usr/lib/systemd/system   ##将启动脚本放到systemd目录下被管理
systemctl daemon-reload    ##重新加载
systemctl start mysqld
mysql数据库默认为3306端口
---------------------------管理数据库-------------------------------------------
mysqladmin -u root -p password "abc123"    ##创建数据库管理用户并设置密码
Enter password:     ##原密码为空
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.

mysql -u root -p   ##登录数据库

所有权限放给数据库中的所有表格,允许root账户从任何终端(@指定终端)登录,登录密码设置为abc123
grant all privileges on *.* to 'root'@'%' identified by 'abc123' with grant option;
show database;   ##查看数据库中的内容
flush privileges;
bye或者quit退出数据库

2. MySQL主服务器设置

修改配置文件
[root@localhost ~]# systemctl stop firewalld.service 
[root@localhost ~]# setenforce 0
[root@localhost ~]# vim /etc/my.cnf
server-id = 10
log-bin=master-bin
log-slave-updates=true

在这里插入图片描述

[root@localhost mysql]# systemctl restart mysqld

为从服务器创建一个账户,便于从服务器从主服务器进行日志同步。

[root@localhost mysql]# mysql -uroot -pabc123   ##登录数据库
mysql> grant replication slave on *.* to 'myslave'@'14.0.0.%' identified by '123123';   ##创建账户,并放通权限
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> show master status;   ##查看主服务器的状态。在这个状态下就尽量不要再进行操作,否则回导致位置点变化,发生错位
+-------------------+----------+--------------+------------------+-------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000001 |      447 |              |                  |                   |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

3. 从服务器设置

两台从服务器进行的操作都是一样的,只有server-id 不一样,所以以server-id =20 为例子,server-id =30 的从服务器就不演示了。

[root@localhost ~]# systemctl stop firewalld.service 
[root@localhost ~]# setenforce 0
[root@localhost ~]# vim /etc/my.cnf
server-id = 20
relay-log=relay-log-bin  ##从主服务器上同步日志文件记录到本地
relay-log-index=slave-relay-bin-index    ##定义relay-log的位置和名称

在这里插入图片描述

[root@localhost ~]# systemctl restart mysqld
mysql> change master to master_host='14.0.0.7',master_user='myslave',master_password='123123',master_log_file='master-bin.000001',master_log_pos=447;   ##在从服务器上设置到哪里去同步日志文件,使用的账户与密码,以及同步的位置点
Query OK, 0 rows affected, 2 warnings (0.02 sec)
mysql> start slave;    ##开启从服务器同步功能
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status\G;    ##查看状态
            Slave_IO_Running: Yes    ##这两个线程一定要处于开启状态
            Slave_SQL_Running: Yes

在这里插入图片描述

4. 测试主从同步

在主服务器上创建一个新的数据库home

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.01 sec)

mysql> create database home;
Query OK, 1 row affected (0.01 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| home               |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

在这里插入图片描述
在两台从服务器上查看是否同步
在这里插入图片描述
在这里插入图片描述

四、 MySQL读写分离原理

读写分离就是只在主服务器上写,只在从服务器上读。基本的原理是让主数据库处理事务性查询,而从数据库处理 select 查询。数据库复制被用来把主数据库上事务性查询导致的变更同步到集群中的从数据库。

在这里插入图片描述
目前较为常见的 MySQL 读写分离分为两种。

  1. 基于程序代码内部实现
    在代码中根据 select、 insert 进行路由分类,这类方法也是目前生产环境应用最广泛的。
    优点是性能较好,因为在程序代码中实现,不需要增加额外的设备作为硬件开支;
    缺点是需要开发人员来实现,运维人员无从下手。
  2. 基于中间代理层实现
    代理一般位于客户端和服务器之间,代理服务器接到客户端请求后通过判断后转发到后端数据库,有两个代表性程序。
  • MySQL-Proxy。MySQL-Proxy 为 MySQL 开源项目,通过其自带的 lua 脚本进行 SQL 判断,虽然是 MySQL 官方产品,但是 MySQL 官方并不建议将 MySQL-Proxy 用到生产环境。
  • Amoeba。 Java 语言开发,阿里巴巴将其用于生产环境。它不支持事务和存储过程。

通过程序代码实现 MySQL 读写分离自然是一个不错的选择,但是并不是所有的应用都适合在程序代码中实现读写分离,像一些大型复杂的 Java 应用,如果在程序代码中实现读写分离对代码改动就较大。

五、 搭建MySQL读写分离

Amoeba(变形虫)项目开源框架于 2008 年发布一款 AmoebaforMySQL 软件。这个软件致力于 MySQL 的分布式数据库前端代理层,它主要为应用层访问 MySQL 的时候充当 SQL 路由功能,并具有负载均衡、高可用性、SQL 过滤、读写分离、可路由到相关的目标 数据库、可并发请求多台数据库。通过 Amoeba 能够完成多数据源的高可用、负载均衡、 数据切片的功能。

实验目的

实现MySQL的读写分离

实验环境

基于上述的MySQL主从复制,再加一台虚拟机作为Amoeba服务器

实验参数

Amoeba服务器:14.0.0.37

实验过程

1. 在主机 Amoeba 上安装 Java 环境

Amoeba 基于是 jdk1.5 开发的,所以官方推荐使用 jdk1.5 或 1.6 版本,高版本不建议使用。

[root@localhost ~]# cd /opt    ##将软件包拷贝到/opt目录下
[root@localhost opt]# ls
amoeba-mysql-binary-2.2.0.tar.gz  mysql-5.7.17
boost_1_59_0.tar.gz               mysql-5.7.17.tar.gz
jdk-6u14-linux-x64.bin            rh
[root@localhost opt]# cp jdk-6u14-linux-x64.bin /usr/local/   ##将jdk文件直接复制到/usr/local下
[root@localhost opt]# cd /usr/local/
[root@localhost local]# ls
bin    etc    include                 lib    libexec  sbin   src
boost  games  jdk-6u14-linux-x64.bin  lib64  mysql    share
[root@localhost local]# chmod +x jdk-6u14-linux-x64.bin   ##赋予执行权限
[root@localhost local]# ./jdk-6u14-linux-x64.bin    ##执行安装
省略部分过程
Do you agree to the above license terms? [yes or no]
yes     ##选择yes
省略部分过程
Press Enter to continue.....   ##单击回车

 
Done.

配置jdk环境变量
[root@localhost local]# mv jdk1.6.0_14/ jdk1.6
[root@localhost local]# vim /etc/profile

在这里插入图片描述

[root@localhost local]# source /etc/profile   ##加载环境变量

安装amoeba

[root@localhost local]# mkdir /usr/local/amoeba 
[root@localhost local]# cd /opt
[root@localhost opt]# tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba
[root@localhost opt]# chmod -R 755 /usr/local/amoeba/   ##给amoeba提权
[root@localhost opt]#  /usr/local/amoeba/bin/amoeba   ##执行命令
amoeba start|stop    ##说明amoeba可以正常使用了

2. 分别在主、从服务器上提权

mysql> grant all on *.* to test@'14.0.0.%' identified by '123123';   ##让三台mysql服务器通过test用户来访问amoeba服务器
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

3.配置amoeba配置文件

[root@localhost opt]# cd /usr/local/amoeba/conf/
[root@localhost conf]# vim amoeba.xml 
在配置文件的第30行设置客户端通过amoeba用户和123123密码访问amoeba服务器
  <property name="user">amoeba</property>
  <property name="password">123123</property>
然后到117行,开启读写功能池设定
  <property name="defaultPool">master</property>
  <property name="writePool">master</property>
  <property name="readPool">slaves</property>

在这里插入图片描述
在这里插入图片描述

4. 配置数据库服务配置文件

设置amoeba访问mysql数据库的用户和密码
<!-- mysql schema -->
  <property name="schema">mysql</property>

<!-- mysql user -->
  <property name="user">test</property>

<!--  mysql password -->
  <property name="password">123123</property>

分别配置三个服务器对应的三个节点
<dbServer name="master"  parent="abstractServer">                  <factoryConfig>                          <!-- mysql ip -->                          <property name="ipAddress">14.0.0.7</property>                  </factoryConfig>          </dbServer>                              
          <dbServer name="slave1"  parent="abstractServer">
                  <factoryConfig>
                          <!-- mysql ip -->
                          <property name="ipAddress">14.0.0.17</property>
                  </factoryConfig>
          </dbServer>
  
          <dbServer name="slave2"  parent="abstractServer">
                  <factoryConfig>
                          <!-- mysql ip -->                          <property name="ipAddress">14.0.0.27</property>
                  </factoryConfig>
          </dbServer>

在配置文件的末尾指除三个节点的对应关系

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

5. 在后台启动amoeba服务

[root@localhost conf]# /usr/local/amoeba/bin/amoeba start &
[1] 30856
[root@localhost conf]# log4j:WARN log4j config load completed from file:/usr/local/amoeba/conf/log4j.xml
2020-08-29 00:47:26,851 INFO  context.MysqlRuntimeContext - Amoeba for Mysql current versoin=5.1.45-mysql-amoeba-proxy-2.2.0
log4j:WARN ip access config load completed from file:/usr/local/amoeba/conf/access_list.conf
2020-08-29 00:47:30,014 INFO  net.ServerableConnectionManager - Amoeba for Mysql listening on 0.0.0.0/0.0.0.0:8066.
2020-08-29 00:47:30,019 INFO  net.ServerableConnectionManager - Amoeba Monitor Server listening on /127.0.0.1:20915.

6. 再开一台虚拟机进行验证

测试机的客户机可以使用yum方式安装mysql

[root@localhost ~]# iptables -F 
[root@localhost ~]# setenforce 0
[root@localhost ~]# yum install mysql -y
[root@localhost ~]# mysql -uamoeba -p123123 -h14.0.0.37 -P8066
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 1884603565
Server version: 5.1.45-mysql-amoeba-proxy-2.2.0 Source distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| home               |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

MySQL [(none)]> create database hello;
Query OK, 1 row affected (0.01 sec)

在三台mysql服务器分别查看,是否有hello这个数据库
在这里插入图片描述
在这里插入图片描述

7. 停止主从同步,验证读写分离

在主服务器上的home数据库中创建一张表info,并定义表结构
mysql> use home;
Database changed
mysql> create table info(id int(3),name char(10));
Query OK, 0 rows affected (0.02 sec)

mysql> show tables;
+----------------+
| Tables_in_home |
+----------------+
| info           |
+----------------+
1 row in set (0.00 sec)

这时候这张表的结构应该会同步到两个从服务器上,这时候我们在从服务器上停止slave服务

mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)

在这里插入图片描述
在客户端mysql的home数据库中info表中插入数据‘

MySQL [home]> insert into info values(1,'zhangsan');
Query OK, 1 row affected (0.01 sec)

分别在主和从服务器上查看这张表是否被插入数据

在这里插入图片描述
在这里插入图片描述

主服务器(14.0.0.7
mysql> insert into info values(1,'lisi');
Query OK, 1 row affected (0.00 sec)

mysql> select * from info;
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
|    1 | lisi     |
+------+----------+
2 rows in set (0.00 sec)
从服务器slave1(14.0.0.17
mysql> insert into info values(2,'lisi');
Query OK, 1 row affected (0.00 sec)

mysql> select * from info;
+------+------+
| id   | name |
+------+------+
|    2 | lisi |
+------+------+
1 row in set (0.00 sec)
从服务器slave2(14.0.0.27
mysql> insert into info values(3,'lisi');
Query OK, 1 row affected (0.00 sec)

mysql> select * from info;
+------+------+
| id   | name |
+------+------+
|    3 | lisi |
+------+------+
1 row in set (0.00 sec)

最后在客户机14.0.0.47上查看,发现只能查看到从服务器上的内容,采用轮询的方式,看不到主服务器上的内容,所以读写分离验证成功。

MySQL [home]> select * from info;
+------+------+
| id   | name |
+------+------+
|    3 | lisi |
+------+------+
1 row in set (0.00 sec)

MySQL [home]> select * from info;
+------+------+
| id   | name |
+------+------+
|    2 | lisi |
+------+------+
1 row in set (0.01 sec)

MySQL [home]> select * from info;
+------+------+
| id   | name |
+------+------+
|    3 | lisi |
+------+------+
1 row in set (0.00 sec)

MySQL [home]> select * from info;
+------+------+
| id   | name |
+------+------+
|    2 | lisi |
+------+------+
1 row in set (0.01 sec)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/kimowinter/article/details/108257289

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include&lt;stdio.h&gt;#include&lt;string.h&gt;#include&lt;stdlib.h&gt;#include&lt;malloc.h&gt;#include&lt;iostream&gt;#include&lt;stack&gt;#include&lt;queue&gt;using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签