由于thinkphp只对Mysql有INSERT IGNORE方法,PostgreSQL是ON CONFLICT DO NOTHING方法,但是thinkphp orm一直没有支持,只能暂时在model用这个方法.
public static function insertIgnore(array $data, string $conflictTarget = null): int
{
$rawSql = static::fetchSql(true)->insert($data);
if ($conflictTarget) {
$rawSql = "{$rawSql} ON CONFLICT {$conflictTarget} DO NOTHING";
}
return Db::execute($rawSql);
}
前段时间看到老冯的公众号推送pgclone这玩意想搞来用一下 https://vonng.com/pg/pg-clone/
翻了下文档要求磁盘分区必须支持reflink才可以, 这就意味着ext4没法玩耍了, 必须XFS Btrfs ZFS分区格式才能玩.
public(公开):外部、内部、子类全通车
protected(受保护):家族内可用
private(私有):仅当前类可用
基础类class
abstract 抽象类,做基础架构、只能继承不能修改,extends后才能new实例化,做model之类的定义
final 最终完美类, 不能extends,可以new实例化
trait 代码复用,不能new初始化,只能class use引入
interface 接口类,不能被 new实例化,使用 implements 来实现接口, 一个类只能继承(extends)一个父类,但可以同时实现(implements)多个接口。
int 整数类型
string 字符串
float 浮点型 带小数点的
bool 布尔型 true或false
array 数组
object 对象
callable 可调用 只能是一个函数、闭包或者方法名
void 空
mixed 混合,任何类型(字符串、数字、数组、对象、甚至 null)
(int|string $id) 联合类型
function 函数
return 直接返回
用女人拍擦边性暗示的视频推广卖男装是我见过最愚蠢的精致营销。
买衣服要穿着合身和舒适, 其次才是好看。
即使我这种好色的老色批看这种营销内容都能感到满满的生理厌恶。
安装postgresql-18
apt install -y postgresql-common
/usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
install -d /usr/share/postgresql-common/pgdg
curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
apt update
apt install postgresql-18
主库配置
USER="replica"
PASSWORD=$(openssl rand -base64 24)
NETWOKR="0.0.0.0/0" //从库IP段
IP="1.1.1.1" #主库IP
#主库
cat>>/etc/postgresql/18/main/postgresql.conf<<EOF
listen_addresses = '*'
wal_level = replica
max_wal_senders = 10
max_replication_slots = 10
wal_keep_size = 1GB
archive_mode = off
#archive_command = 'cp %p /var/lib/postgresql/wal_archive/%f'
EOF
#archive_mode归档模式很占空间
echo "host replication $USER $NETWOKR md5" >>/etc/postgresql/18/main/pg_hba.conf
# 创建用户(幂等)
sudo -u postgres psql -tc "SELECT 1 FROM pg_roles WHERE rolname='$USER'" | grep -q 1 || \
sudo -u postgres psql -c "CREATE ROLE $USER WITH REPLICATION LOGIN PASSWORD '$PASSWORD';"
systemctl restart postgresql
echo "REPL $USER PASSWORD: $PASSWORD"
echo -e "\n\n从库快速导入备份bash shell:"
echo -e "USER=$USER\nPASSWORD=$PASSWORD"
echo "sudo -u postgres pg_basebackup -h $IP -U $USER -D /home/postgresql/18/main -P -R -X stream -v"
从库配置
IP="1.1.1.1" #主库IP
#rm -rf /var/lib/postgresql/18/main/*
cat>>/etc/postgresql/18/main/postgresql.conf<<EOF
listen_addresses = '*'
#recovery_min_apply_delay='24h' #延迟24小时同步
hot_standby = on
wal_keep_size = 2GB
max_wal_senders = 10
EOF
systemctl stop postgresql
mkdir /home/postgresql
chown -R postgres:postgres /home/postgresql
chmod 700 /home/postgresql
sudo -u postgres pg_basebackup -h $IP -U $USER -D /home/postgresql/18/main -P -R -X stream -v
systemctl start postgresql
建议修改/etc/postgresql/18/main/postgresql.conf的data_directory和max_connections参数
data_directory = '/home/postgresql/18/main'
#从库的设置小于主库的max_connections会无法启动
从库自动连接配置文件 /var/lib/postgresql/18/main/postgresql.auto.conf
检查核验配置
tail -n 100 /var/log/postgresql/postgresql-18-main.log
#验证主库
sudo -u postgres psql -c "SELECT client_addr,state FROM pg_stat_replication;"
#验证从库
sudo -u postgres psql -c "SELECT pg_is_in_recovery();"
/etc/postgresql/18/main/conf.d/ 目录存放配置文件可以覆盖主配置
https://www.dnswatch.info/dns/dnslookup?la=en&host=164.210.103.in-addr.arpa&type=NS&submit=Resolve
两三年前刷过,老是重复出现看过的视频, 现在还是一点都没变。。。。。。
真是shi。。。。。。。。 shift
worker和swoole直接常驻内存运行抛弃fpm直接高效运行, 官方提供了现成的静态编译php文件,拿来直接可以运行,不用再自己吭哧吭哧再去编译,直接带上nginx就可以跑,如果将php打包成二进制文件会更简单。
几个相关项目发布地址
https://github.com/swoole/swoole-cli/releases
https://github.com/dixyes/phpmicro
https://github.com/crazywhalecc/static-php-cli
https://www.swoole.com/download
https://www.workerman.net/download
swoole-cli静态php
wget -O - https://github.com/swoole/swoole-cli/releases/download/v6.1.4.0/swoole-cli-v6.1.4-linux-x64.tar.xz | tar -xJ
install swoole-cli /usr/bin/swoole
workerman官方静态php
wget https://www.workerman.net/download/php/php-8.4-linux-x86_64.tar.gz| tar -xz
phpmicro可以打包php为二进制文件
swoole启动fpm
swoole-cli -P -h
# 运行 FPM
swoole-cli -P --fpm-config /opt/php-8.1/etc/php-fpm.conf -p /opt/php-8.1/var
# 关闭守护进程
swoole-cli -P --fpm-config /opt/php-8.1/etc/php-fpm.conf -p /opt/php-8.1/var -F
# 使用 root 账户启动
swoole-cli -P --fpm-config /opt/php-8.1/etc/php-fpm.conf -p /opt/php-8.1/var -F -R
https://github.com/stalwartlabs/stalwart/releases
https://github.com/mjl-/mox/releases
统计CPU
ps -u postgres -o %cpu | awk '{s+=$1} END {print "Postgres Total CPU: " s "%"}'
查看活跃查询
SELECT pid, now() - query_start AS duration, query, state FROM pg_stat_activity WHERE state = 'active' ORDER BY duration DESC;
SELECT pid, now() - query_start AS duration, query, state FROM pg_stat_activity WHERE state = 'active' ORDER BY duration DESC LIMIT 5;
查看连接IP和查询语句
SELECT pid, now() - query_start AS 执行时间, usename AS 用户名,
client_addr AS 连接IP, state AS 状态, query AS 查询语句
FROM pg_stat_activity WHERE
pid <> pg_backend_pid() ORDER BY 执行时间 DESC;
查看扫表
SELECT
relname AS 表名,
seq_scan AS 全表扫描次数,
seq_tup_read AS 全表扫描读取行数,
idx_scan AS 索引扫描次数,
idx_tup_fetch AS 索引提取行数
FROM pg_stat_user_tables
WHERE seq_scan > 0
ORDER BY seq_tup_read DESC
LIMIT 10;
启用插件
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
重置自动增续ID
SELECT setval('tag_id_seq', (SELECT MAX(id) FROM tag));
给浏览器浏览器返回头
$file=decode($url);
header("X-Accel-Redirect: /privatefiles/$file");
nginx配置
location /privatefiles {
internal; #内部访问
alias /var/www/html/xaccel/restrictedfiles;
}
将文件名url加密, 然后接收解密,通过X-Accel-Redirect再转给nginx返回数据。
为什么要这么做? 一些文件路径在某些原因下不想暴露真实路径,又不通过程序再去读一遍问题直接转交个nginx响应。
转载自:https://dev.to/gbhorwood/nginx-serving-private-files-with-x-accel-redirect-57dl
DROP FUNCTION IF EXISTS public.table_msg(varchar) CASCADE;
DROP FUNCTION IF EXISTS public.table_msg(varchar, varchar) CASCADE;
DROP FUNCTION IF EXISTS public.pgsql_type(varchar) CASCADE;
DROP TYPE IF EXISTS public.tablestruct CASCADE;
CREATE OR REPLACE FUNCTION public.pgsql_type(a_type character varying) RETURNS character varying AS
$BODY$
DECLARE
v_type character varying;
BEGIN
CASE a_type
WHEN 'int8' THEN
v_type := 'bigint';
WHEN 'int4' THEN
v_type := 'integer';
WHEN 'int2' THEN
v_type := 'smallint';
WHEN 'bpchar' THEN
v_type := 'char';
ELSE
v_type := a_type;
END CASE;
RETURN v_type;
END;
$BODY$
LANGUAGE plpgsql;
-- 2. tablestruct 类型
CREATE TYPE public.tablestruct AS (
fields_key_name varchar(100),
fields_name varchar(200),
fields_type varchar(20),
fields_length bigint,
fields_not_null varchar(10),
fields_default varchar(500),
fields_comment varchar(1000)
);
-- 3. table_msg 函数(带 schema 参数)
CREATE OR REPLACE FUNCTION public.table_msg(a_schema_name varchar, a_table_name varchar)
RETURNS SETOF public.tablestruct AS
$body$
DECLARE
v_ret tablestruct;
v_oid oid;
v_sql varchar;
v_rec record;
v_key varchar;
BEGIN
-- 获取表 oid
SELECT c.oid INTO v_oid
FROM pg_class c
INNER JOIN pg_namespace n ON c.relnamespace = n.oid AND lower(n.nspname) = lower(a_schema_name)
WHERE c.relname = a_table_name;
IF NOT FOUND THEN
RETURN;
END IF;
-- 构造动态查询
v_sql := '
SELECT
a.attname AS fields_name,
a.attnum AS fields_index,
pgsql_type(t.typname::varchar) AS fields_type,
a.atttypmod - 4 AS fields_length,
CASE WHEN a.attnotnull THEN ''not null'' ELSE '''' END AS fields_not_null,
pg_get_expr(ad.adbin, ad.adrelid) AS fields_default,
d.description AS fields_comment
FROM pg_attribute a
INNER JOIN pg_class c ON a.attrelid = c.oid
INNER JOIN pg_type t ON a.atttypid = t.oid
LEFT JOIN pg_attrdef ad ON ad.adrelid = c.oid AND ad.adnum = a.attnum
LEFT JOIN pg_description d ON d.objoid = c.oid AND d.objsubid = a.attnum
WHERE a.attnum > 0 AND a.attisdropped = false AND c.oid = ' || v_oid || '
ORDER BY a.attnum;
';
-- 遍历字段
FOR v_rec IN EXECUTE v_sql LOOP
v_ret.fields_name := v_rec.fields_name;
v_ret.fields_type := v_rec.fields_type;
IF v_rec.fields_length > 0 THEN
v_ret.fields_length := v_rec.fields_length;
ELSE
v_ret.fields_length := NULL;
END IF;
v_ret.fields_not_null := v_rec.fields_not_null;
v_ret.fields_default := v_rec.fields_default;
v_ret.fields_comment := v_rec.fields_comment;
SELECT constraint_name INTO v_key
FROM information_schema.key_column_usage
WHERE table_schema = a_schema_name
AND table_name = a_table_name
AND column_name = v_rec.fields_name;
IF FOUND THEN
v_ret.fields_key_name := v_key;
ELSE
v_ret.fields_key_name := '';
END IF;
RETURN NEXT v_ret;
END LOOP;
RETURN;
END;
$body$
LANGUAGE plpgsql VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;
COMMENT ON FUNCTION public.table_msg(a_schema_name varchar, a_table_name varchar) IS '获得表信息';
-- 4. table_msg 函数(简化版,只传 table_name)
CREATE OR REPLACE FUNCTION public.table_msg(a_table_name varchar)
RETURNS SETOF public.tablestruct AS
$body$
DECLARE
v_ret tablestruct;
BEGIN
FOR v_ret IN SELECT * FROM public.table_msg('public', a_table_name) LOOP
RETURN NEXT v_ret;
END LOOP;
RETURN;
END;
$body$
LANGUAGE plpgsql VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;
COMMENT ON FUNCTION public.table_msg(a_table_name varchar) IS '获得表信息';
dracut --force #强制更新initramfs
#dracut --force /boot/initramfs-$(uname -r).img $(uname -r)
#grubby --set-default /boot/vmlinuz-5.19.0-ml.x86_64 #设置指定内核
grubby --set-default 0 #设置启动第一个内核
grubby --default-kernel #查看启动内核
现安装golang https://go.dev/dl/
go install github.com/beego/bee/v2@latest
export PATH=$PATH:$(go env GOPATH)/bin
bee new app
cd app
go mod tidy
bee run
- 1
- 2
- 3
- 4
- ...
- 68
- »