简单博客

dbeaver手动导入驱动

December 7, 2023
DB
Mark

因为直接下载dbeaver的时候,是没有带上驱动文件的,所以需要在使用时下载。

但是,如果刚好安装的环境是无法通网的,那么就需要手动传入驱动并安装。

做法如下:

  1. 现在本地有网环境下载驱动文件

dbeaver下载mysql的驱动,会存放在目录:C:\Users\{用户名}\AppData\Roaming\DBeaverData\drivers\maven\maven-central\mysql.

NOTE: 注意替换{用户名}为你本机实际名称。

  1. 把下好的文件传入到无网机器上,同样放到以上目录。

  2. 打开dbeaver数据库->驱动管理器,添加驱动

选中MySQL,然后点击编辑;在弹出框里切到,将已有内容全部删掉,再点击添加文件夹,然后选择上面驱动存放的目录,即可确定保存。

如此,即可手动导入驱动文件。

Mysql 8.0.33在使用窗口函数的同时不能用count(distinct *)

October 18, 2023
Mysql 8
Mark

Mysql 8.0.33在使用窗口函数的同时不能用count(distinct *)

比如,我想在窗口函数里使用字段apply_unit_id分组,然后求project_id列不重复值的数量:

select distinct apply_unit_id, count(distinct project_id) over (partition by apply_unit_id)
from weia join weiag on weiag.apply_id = weia.id 
;

此时报错:SQL 错误 [1235] [42000]: This version of MySQL doesn't yet support '<window function>(DISTINCT ..)'

怎么办呢? #

使用 dense_rank()间接计算:

select distinct apply_unit_id, dense_rank() over (partition by apply_unit_id order by project_id) 
+ dense_rank() over (partition by apply_unit_id order by project_id desc) 
- 1
from weia join weiag on weiag.apply_id = weia.id 
;

dense_rank() #

Returns the rank of the current row within its partition, without gaps.

– 返回当前行在其分区内的排名,没有间隙。

...

Wezterm极简配置文件

October 17, 2023
Rust, Wezterm
Mark

Wezterm极简配置文件

-- Pull in the wezterm API
local wezterm = require 'wezterm'

-- This table will hold the configuration.
local config = {}

-- In newer versions of wezterm, use the config_builder which will
-- help provide clearer error messages
if wezterm.config_builder then
  config = wezterm.config_builder()
end

-- This is where you actually apply your config choices

-- For example, changing the color scheme:
config.color_scheme = 'AdventureTime'
-- config.color_scheme = 'Batman'

config.enable_tab_bar = true
config.hide_tab_bar_if_only_one_tab = false
config.show_tab_index_in_tab_bar = false
config.tab_bar_at_bottom = true
config.tab_max_width = 25

-- Font
-- config.font = wezterm.font_with_fallback { 'JetBrains Mono' }
config.font_size = 14
config.freetype_load_target = "Light" -- Possible alternatives are `HorizontalLcd`, `Light`, `Mono`, `Normal`, `VerticalLcd`.

config.mouse_bindings = {  -- Paste on right-click
    {
        event = {
            Down = {
                streak = 1,
                button = 'Right'
            }
        },
        mods = 'NONE',
        action = wezterm.action {
            PasteFrom = 'Clipboard'
        }
    }, -- Change the default click behavior so that it only selects
    {
        event = {
            Up = {
                streak = 1,
                button = 'Left'
             }
         },
        mods = 'NONE',
        action = wezterm.action {
            CompleteSelection = 'PrimarySelection'
         }
    }, -- CTRL-Click open hyperlinks
    {
        event = {
            Up = {
                streak = 1,
                button = 'Left'
             }
         },
        mods = 'CTRL',
        action = 'OpenLinkAtMouseCursor'
    }
}

config.keys = {
    -- 使用 Ctrl+n 来新建标签页,而不是 Ctrl+Shift+T
    { key = "n",          mods = "ALT", action = wezterm.action { SpawnTab = "DefaultDomain" } },
    -- 使用 Alt+左右箭头来切换标签页
    { key = "LeftArrow",  mods = "ALT", action = wezterm.action { ActivateTabRelative = -1 } },
    { key = "RightArrow", mods = "ALT", action = wezterm.action { ActivateTabRelative = 1 } },
}

-- 定义 Alt+数字 切换到对应标签页的快捷键
for i = 1, 9 do
    table.insert(config.keys, {
        key = tostring(i),
        mods = 'ALT',
        action = wezterm.action.ActivateTab(i - 1),
    })
end

-- and finally, return the configuration to wezterm
return config

雪花id的时钟回退问题

September 27, 2023
Snowflake, Time
Mark

雪花id由64位二进制组成,转成字符串则长为19. 它依赖于系统时钟,如果出现时钟回退,会导致已经在用的id再次被生成。

怎么办呢?

  1. 记录上次生成时间,在本次生成时比较时间,如果当前时间比上次生成时间要小,则认为时钟回拨,直接报错。也可以一直重试,直到当前时间不小于上次生成时间。

  2. 采用历史时间则天然的不存在时间回拨问题。但是在超高并发情况下,历史的时间很快用完,时间一直保持在最新时间的话,这个时候还是会出现时间回拨。

  3. Go1.9开始,使用单调时钟: time.Now(), time.Since(), time.Until().

// # Monotonic Clocks

//

// Operating systems provide both a “wall clock,” which is subject to

// changes for clock synchronization, and a “monotonic clock,” which is

// not. The general rule is that the wall clock is for telling time and

// the monotonic clock is for measuring time. Rather than split the API,

// in this package the Time returned by time.Now contains both a wall

...

Go escape analysis

September 20, 2023
Go, Escape Analysis
Note

The meaning of escapes to the heap is variables needs to be shared across the function stack frames [between main() and Println()] …

… So globally access variables must be moved to heap as it requires runtime. So the output line 11:2 shows the same as the data variable moved to the heap memory.

From

What are you preparing to do?

September 20, 2023
Do
Note

他想做的事情,与你想他做的事情,与你在做的事情。

这些事情之间是否存在交集,如果一点都没有,那不就是事与愿违了吗?

查找并杀掉运行中事务

September 15, 2023
Mysql
Note

查找并杀掉运行中事务 #

-- 获取线程id然后杀掉
SELECT * FROM information_schema.innodb_trx;
-- 优先找到其中耗时最长的删
kill 36272;
kill 36275;
kill 35971;
kill 35972;

-- 其它
select * from performance_schema.events_statements_current;
show processlist;

查看锁使用情况 #

SELECT object_name, index_name, lock_type, lock_mode, lock_data FROM performance_schema.data_locks;

Windows环境下死锁时重启数据库导致数据库出现“启动后停止” #

后面重启服务器也不行,一直提示:

> net start mysql
MYSQL服务正在启动
MYSQL服务无法启动

服务没有报告任何错误。
请键入 MET HELPMSG 3534 以获得更多的帮助。

解决办法:

将data目录移走,再重新初始化数据库,此时可正常启动数据库;然后停止数据库,将旧data数据库里的数据库和索引文件复制回新的data目录里,再启动数据库。

# 重新初始化数据库
mysqld --initialize-insecure --user=mysql
mysqld -install

# 停止和启动
net stop mysql
net start mysql

参考

其中需要复制的文件有这些:

[数据库目录]
#ib_16384_0.dblwr # Doublewrite Buffer (内存+磁盘), 新的DBLWR以及它如何帮助解决历史上MySQL性能问题
#ib_16384_1.dblwr
auto.cnf # 记录mysql数据库实例的server_uuid,安装的时候初始化,master和slave的server_uuid不能一样
ib_fubber_pool # 缓存池,存放部分最近的查询记录和索引等,可以通过show variables like 'innodb%pool%'查
ibdata1 # innodb表空间,如果采用innodb引擎,会默认10M大小
mysql.ibd # innodb存储引擎的数据文件

双写 #

official

...

Vscode go cannot find GOROOT directory

September 13, 2023
Go, Vscode
Mark

今天发现在windows上的vscode一直提示找不到go:go: cannot find GOROOT directory: c:\msys64\mingw64\lib\go

强制设置了go.goroot也不行,直到查看了GOENV文件(C:\Users\xxx\AppData\Roaming\go\env)之后,才发现里面有一行:GOROOT=c:\msys64\mingw64\lib\go,可能是当时在msys2安装go的时候加上的。

去掉它就恢复正常了。

$ go env
set GOENV=C:\Users\xxx\AppData\Roaming\go\env
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOMODCACHE=C:\Users\xxx\go\pkg\mod
set GOOS=windows
set GOPATH=C:\Users\xxx\go
set GOPRIVATE=
set GOPROXY=https://goproxy.cn,https://goproxy.io,direct
set GOROOT=C:\Program Files\Go

应该是这样的,如果用go env -w 来设置goroot,那么这个值就会保存到GOENV对应的文件里,如果是$env:GOROOT=xxx的方式来设置则不会修改GOENV文件里的内容。这时候,如果vscode是优先从GOENV文件来获取GOROOT的话,就可能会导致与实际的GOROOT不一致。

所以,如果再遇到以上错误,除了echo $env:GOROOT 看一下环境变量值之外,也要看一下GOENV文件。

不同系统之间通过网络对接

September 13, 2023
Go, Vscode
Mark

不同系统之间通过网络对接

数据库事件 #

  1. 可以用个事件表来做,在事务执行过程中添加事件(确保事务完成时事件也存在)。

  2. 在事务提交之后,先尝试做一次事件,如果成功了就把事件状态置为成功;如果失败了也没关系,另外开定时器来扫表进行重试执行。 – 此时不影响正常业务执行

  3. 在事件处理事务里的网络请求里加入超时控制,确保事件不会执行太久,导致接口过慢。

  4. 网络请求支持幂等,防止事件处理事务请求成功了,但是事务挂了导致状态未变更,这种情况下会重复请求多次。

skip locked实现 #

-- 条件字段必须有索引(status, [name, status]),排序字段必须是主键(id),此时刚好是所要锁定的行

start transaction;
-- select * from w_event we where status in (1) order by create_time asc limit 1 for update skip locked; -- 引入create_time作为排序字段时,会将符合条件的行都锁住,`limit 1`不起作用
select * from w_event we where status in (1) order by id asc limit 1 for update skip locked; -- 使用主键字段作排序时,`limit 1`则起作用
select * from w_event we where name = '测试' and status in (1) order by id asc limit 1 for update skip locked; -- 如果有多个字段作为条件,需要建立组合索引
SELECT object_name, index_name, lock_type, lock_mode, lock_data FROM performance_schema.data_locks; -- 查看上锁情况
select * from w_event we where status in (2) order by id asc limit 1 for update skip locked;
select * from w_event we where status in (3) order by id asc limit 1 for update skip locked;
commit;

可打开两个线程来验证上述事务执行,可以看到,当满足条件的记录有两条或以上时,当事务1查到记录1后,事务1未提交时,事务2不会拿到记录1,而是会拿到记录2. 也就实现了有锁则获取下一批数据的效果。

...

do

September 12, 2023
Do

你在做的事情,是在重复已知的东西,还是在探索未知的东西。

这决定了所能达到的高度。